A fake command line interface written in p5.js and Processing 3 https://www.victorgiers.com/cwi
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

p5.js 921KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195151961519715198151991520015201152021520315204152051520615207152081520915210152111521215213152141521515216152171521815219152201522115222152231522415225152261522715228152291523015231152321523315234152351523615237152381523915240152411524215243152441524515246152471524815249152501525115252152531525415255152561525715258152591526015261152621526315264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532315324153251532615327153281532915330153311533215333153341533515336153371533815339153401534115342153431534415345153461534715348153491535015351153521535315354153551535615357153581535915360153611536215363153641536515366153671536815369153701537115372153731537415375153761537715378153791538015381153821538315384153851538615387153881538915390153911539215393153941539515396153971539815399154001540115402154031540415405154061540715408154091541015411154121541315414154151541615417154181541915420154211542215423154241542515426154271542815429154301543115432154331543415435154361543715438154391544015441154421544315444154451544615447154481544915450154511545215453154541545515456154571545815459154601546115462154631546415465154661546715468154691547015471154721547315474154751547615477154781547915480154811548215483154841548515486154871548815489154901549115492154931549415495154961549715498154991550015501155021550315504155051550615507155081550915510155111551215513155141551515516155171551815519155201552115522155231552415525155261552715528155291553015531155321553315534155351553615537155381553915540155411554215543155441554515546155471554815549155501555115552155531555415555155561555715558155591556015561155621556315564155651556615567155681556915570155711557215573155741557515576155771557815579155801558115582155831558415585155861558715588155891559015591155921559315594155951559615597155981559915600156011560215603156041560515606156071560815609156101561115612156131561415615156161561715618156191562015621156221562315624156251562615627156281562915630156311563215633156341563515636156371563815639156401564115642156431564415645156461564715648156491565015651156521565315654156551565615657156581565915660156611566215663156641566515666156671566815669156701567115672156731567415675156761567715678156791568015681156821568315684156851568615687156881568915690156911569215693156941569515696156971569815699157001570115702157031570415705157061570715708157091571015711157121571315714157151571615717157181571915720157211572215723157241572515726157271572815729157301573115732157331573415735157361573715738157391574015741157421574315744157451574615747157481574915750157511575215753157541575515756157571575815759157601576115762157631576415765157661576715768157691577015771157721577315774157751577615777157781577915780157811578215783157841578515786157871578815789157901579115792157931579415795157961579715798157991580015801158021580315804158051580615807158081580915810158111581215813158141581515816158171581815819158201582115822158231582415825158261582715828158291583015831158321583315834158351583615837158381583915840158411584215843158441584515846158471584815849158501585115852158531585415855158561585715858158591586015861158621586315864158651586615867158681586915870158711587215873158741587515876158771587815879158801588115882158831588415885158861588715888158891589015891158921589315894158951589615897158981589915900159011590215903159041590515906159071590815909159101591115912159131591415915159161591715918159191592015921159221592315924159251592615927159281592915930159311593215933159341593515936159371593815939159401594115942159431594415945159461594715948159491595015951159521595315954159551595615957159581595915960159611596215963159641596515966159671596815969159701597115972159731597415975159761597715978159791598015981159821598315984159851598615987159881598915990159911599215993159941599515996159971599815999160001600116002160031600416005160061600716008160091601016011160121601316014160151601616017160181601916020160211602216023160241602516026160271602816029160301603116032160331603416035160361603716038160391604016041160421604316044160451604616047160481604916050160511605216053160541605516056160571605816059160601606116062160631606416065160661606716068160691607016071160721607316074160751607616077160781607916080160811608216083160841608516086160871608816089160901609116092160931609416095160961609716098160991610016101161021610316104161051610616107161081610916110161111611216113161141611516116161171611816119161201612116122161231612416125161261612716128161291613016131161321613316134161351613616137161381613916140161411614216143161441614516146161471614816149161501615116152161531615416155161561615716158161591616016161161621616316164161651616616167161681616916170161711617216173161741617516176161771617816179161801618116182161831618416185161861618716188161891619016191161921619316194161951619616197161981619916200162011620216203162041620516206162071620816209162101621116212162131621416215162161621716218162191622016221162221622316224162251622616227162281622916230162311623216233162341623516236162371623816239162401624116242162431624416245162461624716248162491625016251162521625316254162551625616257162581625916260162611626216263162641626516266162671626816269162701627116272162731627416275162761627716278162791628016281162821628316284162851628616287162881628916290162911629216293162941629516296162971629816299163001630116302163031630416305163061630716308163091631016311163121631316314163151631616317163181631916320163211632216323163241632516326163271632816329163301633116332163331633416335163361633716338163391634016341163421634316344163451634616347163481634916350163511635216353163541635516356163571635816359163601636116362163631636416365163661636716368163691637016371163721637316374163751637616377163781637916380163811638216383163841638516386163871638816389163901639116392163931639416395163961639716398163991640016401164021640316404164051640616407164081640916410164111641216413164141641516416164171641816419164201642116422164231642416425164261642716428164291643016431164321643316434164351643616437164381643916440164411644216443164441644516446164471644816449164501645116452164531645416455164561645716458164591646016461164621646316464164651646616467164681646916470164711647216473164741647516476164771647816479164801648116482164831648416485164861648716488164891649016491164921649316494164951649616497164981649916500165011650216503165041650516506165071650816509165101651116512165131651416515165161651716518165191652016521165221652316524165251652616527165281652916530165311653216533165341653516536165371653816539165401654116542165431654416545165461654716548165491655016551165521655316554165551655616557165581655916560165611656216563165641656516566165671656816569165701657116572165731657416575165761657716578165791658016581165821658316584165851658616587165881658916590165911659216593165941659516596165971659816599166001660116602166031660416605166061660716608166091661016611166121661316614166151661616617166181661916620166211662216623166241662516626166271662816629166301663116632166331663416635166361663716638166391664016641166421664316644166451664616647166481664916650166511665216653166541665516656166571665816659166601666116662166631666416665166661666716668166691667016671166721667316674166751667616677166781667916680166811668216683166841668516686166871668816689166901669116692166931669416695166961669716698166991670016701167021670316704167051670616707167081670916710167111671216713167141671516716167171671816719167201672116722167231672416725167261672716728167291673016731167321673316734167351673616737167381673916740167411674216743167441674516746167471674816749167501675116752167531675416755167561675716758167591676016761167621676316764167651676616767167681676916770167711677216773167741677516776167771677816779167801678116782167831678416785167861678716788167891679016791167921679316794167951679616797167981679916800168011680216803168041680516806168071680816809168101681116812168131681416815168161681716818168191682016821168221682316824168251682616827168281682916830168311683216833168341683516836168371683816839168401684116842168431684416845168461684716848168491685016851168521685316854168551685616857168581685916860168611686216863168641686516866168671686816869168701687116872168731687416875168761687716878168791688016881168821688316884168851688616887168881688916890168911689216893168941689516896168971689816899169001690116902169031690416905169061690716908169091691016911169121691316914169151691616917169181691916920169211692216923169241692516926169271692816929169301693116932169331693416935169361693716938169391694016941169421694316944169451694616947169481694916950169511695216953169541695516956169571695816959169601696116962169631696416965169661696716968169691697016971169721697316974169751697616977169781697916980169811698216983169841698516986169871698816989169901699116992169931699416995169961699716998169991700017001170021700317004170051700617007170081700917010170111701217013170141701517016170171701817019170201702117022170231702417025170261702717028170291703017031170321703317034170351703617037170381703917040170411704217043170441704517046170471704817049170501705117052170531705417055170561705717058170591706017061170621706317064170651706617067170681706917070170711707217073170741707517076170771707817079170801708117082170831708417085170861708717088170891709017091170921709317094170951709617097170981709917100171011710217103171041710517106171071710817109171101711117112171131711417115171161711717118171191712017121171221712317124171251712617127171281712917130171311713217133171341713517136171371713817139171401714117142171431714417145171461714717148171491715017151171521715317154171551715617157171581715917160171611716217163171641716517166171671716817169171701717117172171731717417175171761717717178171791718017181171821718317184171851718617187171881718917190171911719217193171941719517196171971719817199172001720117202172031720417205172061720717208172091721017211172121721317214172151721617217172181721917220172211722217223172241722517226172271722817229172301723117232172331723417235172361723717238172391724017241172421724317244172451724617247172481724917250172511725217253172541725517256172571725817259172601726117262172631726417265172661726717268172691727017271172721727317274172751727617277172781727917280172811728217283172841728517286172871728817289172901729117292172931729417295172961729717298172991730017301173021730317304173051730617307173081730917310173111731217313173141731517316173171731817319173201732117322173231732417325173261732717328173291733017331173321733317334173351733617337173381733917340173411734217343173441734517346173471734817349173501735117352173531735417355173561735717358173591736017361173621736317364173651736617367173681736917370173711737217373173741737517376173771737817379173801738117382173831738417385173861738717388173891739017391173921739317394173951739617397173981739917400174011740217403174041740517406174071740817409174101741117412174131741417415174161741717418174191742017421174221742317424174251742617427174281742917430174311743217433174341743517436174371743817439174401744117442174431744417445174461744717448174491745017451174521745317454174551745617457174581745917460174611746217463174641746517466174671746817469174701747117472174731747417475174761747717478174791748017481174821748317484174851748617487174881748917490174911749217493174941749517496174971749817499175001750117502175031750417505175061750717508175091751017511175121751317514175151751617517175181751917520175211752217523175241752517526175271752817529175301753117532175331753417535175361753717538175391754017541175421754317544175451754617547175481754917550175511755217553175541755517556175571755817559175601756117562175631756417565175661756717568175691757017571175721757317574175751757617577175781757917580175811758217583175841758517586175871758817589175901759117592175931759417595175961759717598175991760017601176021760317604176051760617607176081760917610176111761217613176141761517616176171761817619176201762117622176231762417625176261762717628176291763017631176321763317634176351763617637176381763917640176411764217643176441764517646176471764817649176501765117652176531765417655176561765717658176591766017661176621766317664176651766617667176681766917670176711767217673176741767517676176771767817679176801768117682176831768417685176861768717688176891769017691176921769317694176951769617697176981769917700177011770217703177041770517706177071770817709177101771117712177131771417715177161771717718177191772017721177221772317724177251772617727177281772917730177311773217733177341773517736177371773817739177401774117742177431774417745177461774717748177491775017751177521775317754177551775617757177581775917760177611776217763177641776517766177671776817769177701777117772177731777417775177761777717778177791778017781177821778317784177851778617787177881778917790177911779217793177941779517796177971779817799178001780117802178031780417805178061780717808178091781017811178121781317814178151781617817178181781917820178211782217823178241782517826178271782817829178301783117832178331783417835178361783717838178391784017841178421784317844178451784617847178481784917850178511785217853178541785517856178571785817859178601786117862178631786417865178661786717868178691787017871178721787317874178751787617877178781787917880178811788217883178841788517886178871788817889178901789117892178931789417895178961789717898178991790017901179021790317904179051790617907179081790917910179111791217913179141791517916179171791817919179201792117922179231792417925179261792717928179291793017931179321793317934179351793617937179381793917940179411794217943179441794517946179471794817949179501795117952179531795417955179561795717958179591796017961179621796317964179651796617967179681796917970179711797217973179741797517976179771797817979179801798117982179831798417985179861798717988179891799017991179921799317994179951799617997179981799918000180011800218003180041800518006180071800818009180101801118012180131801418015180161801718018180191802018021180221802318024180251802618027180281802918030180311803218033180341803518036180371803818039180401804118042180431804418045180461804718048180491805018051180521805318054180551805618057180581805918060180611806218063180641806518066180671806818069180701807118072180731807418075180761807718078180791808018081180821808318084180851808618087180881808918090180911809218093180941809518096180971809818099181001810118102181031810418105181061810718108181091811018111181121811318114181151811618117181181811918120181211812218123181241812518126181271812818129181301813118132181331813418135181361813718138181391814018141181421814318144181451814618147181481814918150181511815218153181541815518156181571815818159181601816118162181631816418165181661816718168181691817018171181721817318174181751817618177181781817918180181811818218183181841818518186181871818818189181901819118192181931819418195181961819718198181991820018201182021820318204182051820618207182081820918210182111821218213182141821518216182171821818219182201822118222182231822418225182261822718228182291823018231182321823318234182351823618237182381823918240182411824218243182441824518246182471824818249182501825118252182531825418255182561825718258182591826018261182621826318264182651826618267182681826918270182711827218273182741827518276182771827818279182801828118282182831828418285182861828718288182891829018291182921829318294182951829618297182981829918300183011830218303183041830518306183071830818309183101831118312183131831418315183161831718318183191832018321183221832318324183251832618327183281832918330183311833218333183341833518336183371833818339183401834118342183431834418345183461834718348183491835018351183521835318354183551835618357183581835918360183611836218363183641836518366183671836818369183701837118372183731837418375183761837718378183791838018381183821838318384183851838618387183881838918390183911839218393183941839518396183971839818399184001840118402184031840418405184061840718408184091841018411184121841318414184151841618417184181841918420184211842218423184241842518426184271842818429184301843118432184331843418435184361843718438184391844018441184421844318444184451844618447184481844918450184511845218453184541845518456184571845818459184601846118462184631846418465184661846718468184691847018471184721847318474184751847618477184781847918480184811848218483184841848518486184871848818489184901849118492184931849418495184961849718498184991850018501185021850318504185051850618507185081850918510185111851218513185141851518516185171851818519185201852118522185231852418525185261852718528185291853018531185321853318534185351853618537185381853918540185411854218543185441854518546185471854818549185501855118552185531855418555185561855718558185591856018561185621856318564185651856618567185681856918570185711857218573185741857518576185771857818579185801858118582185831858418585185861858718588185891859018591185921859318594185951859618597185981859918600186011860218603186041860518606186071860818609186101861118612186131861418615186161861718618186191862018621186221862318624186251862618627186281862918630186311863218633186341863518636186371863818639186401864118642186431864418645186461864718648186491865018651186521865318654186551865618657186581865918660186611866218663186641866518666186671866818669186701867118672186731867418675186761867718678186791868018681186821868318684186851868618687186881868918690186911869218693186941869518696186971869818699187001870118702187031870418705187061870718708187091871018711187121871318714187151871618717187181871918720187211872218723187241872518726187271872818729187301873118732187331873418735187361873718738187391874018741187421874318744187451874618747187481874918750187511875218753187541875518756187571875818759187601876118762187631876418765187661876718768187691877018771187721877318774187751877618777187781877918780187811878218783187841878518786187871878818789187901879118792187931879418795187961879718798187991880018801188021880318804188051880618807188081880918810188111881218813188141881518816188171881818819188201882118822188231882418825188261882718828188291883018831188321883318834188351883618837188381883918840188411884218843188441884518846188471884818849188501885118852188531885418855188561885718858188591886018861188621886318864188651886618867188681886918870188711887218873188741887518876188771887818879188801888118882188831888418885188861888718888188891889018891188921889318894188951889618897188981889918900189011890218903189041890518906189071890818909189101891118912189131891418915189161891718918189191892018921189221892318924189251892618927189281892918930189311893218933189341893518936189371893818939189401894118942189431894418945189461894718948189491895018951189521895318954189551895618957189581895918960189611896218963189641896518966189671896818969189701897118972189731897418975189761897718978189791898018981189821898318984189851898618987189881898918990189911899218993189941899518996189971899818999190001900119002190031900419005190061900719008190091901019011190121901319014190151901619017190181901919020190211902219023190241902519026190271902819029190301903119032190331903419035190361903719038190391904019041190421904319044190451904619047190481904919050190511905219053190541905519056190571905819059190601906119062190631906419065190661906719068190691907019071190721907319074190751907619077190781907919080190811908219083190841908519086190871908819089190901909119092190931909419095190961909719098190991910019101191021910319104191051910619107191081910919110191111911219113191141911519116191171911819119191201912119122191231912419125191261912719128191291913019131191321913319134191351913619137191381913919140191411914219143191441914519146191471914819149191501915119152191531915419155191561915719158191591916019161191621916319164191651916619167191681916919170191711917219173191741917519176191771917819179191801918119182191831918419185191861918719188191891919019191191921919319194191951919619197191981919919200192011920219203192041920519206192071920819209192101921119212192131921419215192161921719218192191922019221192221922319224192251922619227192281922919230192311923219233192341923519236192371923819239192401924119242192431924419245192461924719248192491925019251192521925319254192551925619257192581925919260192611926219263192641926519266192671926819269192701927119272192731927419275192761927719278192791928019281192821928319284192851928619287192881928919290192911929219293192941929519296192971929819299193001930119302193031930419305193061930719308193091931019311193121931319314193151931619317193181931919320193211932219323193241932519326193271932819329193301933119332193331933419335193361933719338193391934019341193421934319344193451934619347193481934919350193511935219353193541935519356193571935819359193601936119362193631936419365193661936719368193691937019371193721937319374193751937619377193781937919380193811938219383193841938519386193871938819389193901939119392193931939419395193961939719398193991940019401194021940319404194051940619407194081940919410194111941219413194141941519416194171941819419194201942119422194231942419425194261942719428194291943019431194321943319434194351943619437194381943919440194411944219443194441944519446194471944819449194501945119452194531945419455194561945719458194591946019461194621946319464194651946619467194681946919470194711947219473194741947519476194771947819479194801948119482194831948419485194861948719488194891949019491194921949319494194951949619497194981949919500195011950219503195041950519506195071950819509195101951119512195131951419515195161951719518195191952019521195221952319524195251952619527195281952919530195311953219533195341953519536195371953819539195401954119542195431954419545195461954719548195491955019551195521955319554195551955619557195581955919560195611956219563195641956519566195671956819569195701957119572195731957419575195761957719578195791958019581195821958319584195851958619587195881958919590195911959219593195941959519596195971959819599196001960119602196031960419605196061960719608196091961019611196121961319614196151961619617196181961919620196211962219623196241962519626196271962819629196301963119632196331963419635196361963719638196391964019641196421964319644196451964619647196481964919650196511965219653196541965519656196571965819659196601966119662196631966419665196661966719668196691967019671196721967319674196751967619677196781967919680196811968219683196841968519686196871968819689196901969119692196931969419695196961969719698196991970019701197021970319704197051970619707197081970919710197111971219713197141971519716197171971819719197201972119722197231972419725197261972719728197291973019731197321973319734197351973619737197381973919740197411974219743197441974519746197471974819749197501975119752197531975419755197561975719758197591976019761197621976319764197651976619767197681976919770197711977219773197741977519776197771977819779197801978119782197831978419785197861978719788197891979019791197921979319794197951979619797197981979919800198011980219803198041980519806198071980819809198101981119812198131981419815198161981719818198191982019821198221982319824198251982619827198281982919830198311983219833198341983519836198371983819839198401984119842198431984419845198461984719848198491985019851198521985319854198551985619857198581985919860198611986219863198641986519866198671986819869198701987119872198731987419875198761987719878198791988019881198821988319884198851988619887198881988919890198911989219893198941989519896198971989819899199001990119902199031990419905199061990719908199091991019911199121991319914199151991619917199181991919920199211992219923199241992519926199271992819929199301993119932199331993419935199361993719938199391994019941199421994319944199451994619947199481994919950199511995219953199541995519956199571995819959199601996119962199631996419965199661996719968199691997019971199721997319974199751997619977199781997919980199811998219983199841998519986199871998819989199901999119992199931999419995199961999719998199992000020001200022000320004200052000620007200082000920010200112001220013200142001520016200172001820019200202002120022200232002420025200262002720028200292003020031200322003320034200352003620037200382003920040200412004220043200442004520046200472004820049200502005120052200532005420055200562005720058200592006020061200622006320064200652006620067200682006920070200712007220073200742007520076200772007820079200802008120082200832008420085200862008720088200892009020091200922009320094200952009620097200982009920100201012010220103201042010520106201072010820109201102011120112201132011420115201162011720118201192012020121201222012320124201252012620127201282012920130201312013220133201342013520136201372013820139201402014120142201432014420145201462014720148201492015020151201522015320154201552015620157201582015920160201612016220163201642016520166201672016820169201702017120172201732017420175201762017720178201792018020181201822018320184201852018620187201882018920190201912019220193201942019520196201972019820199202002020120202202032020420205202062020720208202092021020211202122021320214202152021620217202182021920220202212022220223202242022520226202272022820229202302023120232202332023420235202362023720238202392024020241202422024320244202452024620247202482024920250202512025220253202542025520256202572025820259202602026120262202632026420265202662026720268202692027020271202722027320274202752027620277202782027920280202812028220283202842028520286202872028820289202902029120292202932029420295202962029720298202992030020301203022030320304203052030620307203082030920310203112031220313203142031520316203172031820319203202032120322203232032420325203262032720328203292033020331203322033320334203352033620337203382033920340203412034220343203442034520346203472034820349203502035120352203532035420355203562035720358203592036020361203622036320364203652036620367203682036920370203712037220373203742037520376203772037820379203802038120382203832038420385203862038720388203892039020391203922039320394203952039620397203982039920400204012040220403204042040520406204072040820409204102041120412204132041420415204162041720418204192042020421204222042320424204252042620427204282042920430204312043220433204342043520436204372043820439204402044120442204432044420445204462044720448204492045020451204522045320454204552045620457204582045920460204612046220463204642046520466204672046820469204702047120472204732047420475204762047720478204792048020481204822048320484204852048620487204882048920490204912049220493204942049520496204972049820499205002050120502205032050420505205062050720508205092051020511205122051320514205152051620517205182051920520205212052220523205242052520526205272052820529205302053120532205332053420535205362053720538205392054020541205422054320544205452054620547205482054920550205512055220553205542055520556205572055820559205602056120562205632056420565205662056720568205692057020571205722057320574205752057620577205782057920580205812058220583205842058520586205872058820589205902059120592205932059420595205962059720598205992060020601206022060320604206052060620607206082060920610206112061220613206142061520616206172061820619206202062120622206232062420625206262062720628206292063020631206322063320634206352063620637206382063920640206412064220643206442064520646206472064820649206502065120652206532065420655206562065720658206592066020661206622066320664206652066620667206682066920670206712067220673206742067520676206772067820679206802068120682206832068420685206862068720688206892069020691206922069320694206952069620697206982069920700207012070220703207042070520706207072070820709207102071120712207132071420715207162071720718207192072020721207222072320724207252072620727207282072920730207312073220733207342073520736207372073820739207402074120742207432074420745207462074720748207492075020751207522075320754207552075620757207582075920760207612076220763207642076520766207672076820769207702077120772207732077420775207762077720778207792078020781207822078320784207852078620787207882078920790207912079220793207942079520796207972079820799208002080120802208032080420805208062080720808208092081020811208122081320814208152081620817208182081920820208212082220823208242082520826208272082820829208302083120832208332083420835208362083720838208392084020841208422084320844208452084620847208482084920850208512085220853208542085520856208572085820859208602086120862208632086420865208662086720868208692087020871208722087320874208752087620877208782087920880208812088220883208842088520886208872088820889208902089120892208932089420895208962089720898208992090020901209022090320904209052090620907209082090920910209112091220913209142091520916209172091820919209202092120922209232092420925209262092720928209292093020931209322093320934209352093620937209382093920940209412094220943209442094520946209472094820949209502095120952209532095420955209562095720958209592096020961209622096320964209652096620967209682096920970209712097220973209742097520976209772097820979209802098120982209832098420985209862098720988209892099020991209922099320994209952099620997209982099921000210012100221003210042100521006210072100821009210102101121012210132101421015210162101721018210192102021021210222102321024210252102621027210282102921030210312103221033210342103521036210372103821039210402104121042210432104421045210462104721048210492105021051210522105321054210552105621057210582105921060210612106221063210642106521066210672106821069210702107121072210732107421075210762107721078210792108021081210822108321084210852108621087210882108921090210912109221093210942109521096210972109821099211002110121102211032110421105211062110721108211092111021111211122111321114211152111621117211182111921120211212112221123211242112521126211272112821129211302113121132211332113421135211362113721138211392114021141211422114321144211452114621147211482114921150211512115221153211542115521156211572115821159211602116121162211632116421165211662116721168211692117021171211722117321174211752117621177211782117921180211812118221183211842118521186211872118821189211902119121192211932119421195211962119721198211992120021201212022120321204212052120621207212082120921210212112121221213212142121521216212172121821219212202122121222212232122421225212262122721228212292123021231212322123321234212352123621237212382123921240212412124221243212442124521246212472124821249212502125121252212532125421255212562125721258212592126021261212622126321264212652126621267212682126921270212712127221273212742127521276212772127821279212802128121282212832128421285212862128721288212892129021291212922129321294212952129621297212982129921300213012130221303213042130521306213072130821309213102131121312213132131421315213162131721318213192132021321213222132321324213252132621327213282132921330213312133221333213342133521336213372133821339213402134121342213432134421345213462134721348213492135021351213522135321354213552135621357213582135921360213612136221363213642136521366213672136821369213702137121372213732137421375213762137721378213792138021381213822138321384213852138621387213882138921390213912139221393213942139521396213972139821399214002140121402214032140421405214062140721408214092141021411214122141321414214152141621417214182141921420214212142221423214242142521426214272142821429214302143121432214332143421435214362143721438214392144021441214422144321444214452144621447214482144921450214512145221453214542145521456214572145821459214602146121462214632146421465214662146721468214692147021471214722147321474214752147621477214782147921480214812148221483214842148521486214872148821489214902149121492214932149421495214962149721498214992150021501215022150321504215052150621507215082150921510215112151221513215142151521516215172151821519215202152121522215232152421525215262152721528215292153021531215322153321534215352153621537215382153921540215412154221543215442154521546215472154821549215502155121552215532155421555215562155721558215592156021561215622156321564215652156621567215682156921570215712157221573215742157521576215772157821579215802158121582215832158421585215862158721588215892159021591215922159321594215952159621597215982159921600216012160221603216042160521606216072160821609216102161121612216132161421615216162161721618216192162021621216222162321624216252162621627216282162921630216312163221633216342163521636216372163821639216402164121642216432164421645216462164721648216492165021651216522165321654216552165621657216582165921660216612166221663216642166521666216672166821669216702167121672216732167421675216762167721678216792168021681216822168321684216852168621687216882168921690216912169221693216942169521696216972169821699217002170121702217032170421705217062170721708217092171021711217122171321714217152171621717217182171921720217212172221723217242172521726217272172821729217302173121732217332173421735217362173721738217392174021741217422174321744217452174621747217482174921750217512175221753217542175521756217572175821759217602176121762217632176421765217662176721768217692177021771217722177321774217752177621777217782177921780217812178221783217842178521786217872178821789217902179121792217932179421795217962179721798217992180021801218022180321804218052180621807218082180921810218112181221813218142181521816218172181821819218202182121822218232182421825218262182721828218292183021831218322183321834218352183621837218382183921840218412184221843218442184521846218472184821849218502185121852218532185421855218562185721858218592186021861218622186321864218652186621867218682186921870218712187221873218742187521876218772187821879218802188121882218832188421885218862188721888218892189021891218922189321894218952189621897218982189921900219012190221903219042190521906219072190821909219102191121912219132191421915219162191721918219192192021921219222192321924219252192621927219282192921930219312193221933219342193521936219372193821939219402194121942219432194421945219462194721948219492195021951219522195321954219552195621957219582195921960219612196221963219642196521966219672196821969219702197121972219732197421975219762197721978219792198021981219822198321984219852198621987219882198921990219912199221993219942199521996219972199821999220002200122002220032200422005220062200722008220092201022011220122201322014220152201622017220182201922020220212202222023220242202522026220272202822029220302203122032220332203422035220362203722038220392204022041220422204322044220452204622047220482204922050220512205222053220542205522056220572205822059220602206122062220632206422065220662206722068220692207022071220722207322074220752207622077220782207922080220812208222083220842208522086220872208822089220902209122092220932209422095220962209722098220992210022101221022210322104221052210622107221082210922110221112211222113221142211522116221172211822119221202212122122221232212422125221262212722128221292213022131221322213322134221352213622137221382213922140221412214222143221442214522146221472214822149221502215122152221532215422155221562215722158221592216022161221622216322164221652216622167221682216922170221712217222173221742217522176221772217822179221802218122182221832218422185221862218722188221892219022191221922219322194221952219622197221982219922200222012220222203222042220522206222072220822209222102221122212222132221422215222162221722218222192222022221222222222322224222252222622227222282222922230222312223222233222342223522236222372223822239222402224122242222432224422245222462224722248222492225022251222522225322254222552225622257222582225922260222612226222263222642226522266222672226822269222702227122272222732227422275222762227722278222792228022281222822228322284222852228622287222882228922290222912229222293222942229522296222972229822299223002230122302223032230422305223062230722308223092231022311223122231322314223152231622317223182231922320223212232222323223242232522326223272232822329223302233122332223332233422335223362233722338223392234022341223422234322344223452234622347223482234922350223512235222353223542235522356223572235822359223602236122362223632236422365223662236722368223692237022371223722237322374223752237622377223782237922380223812238222383223842238522386223872238822389223902239122392223932239422395223962239722398223992240022401224022240322404224052240622407224082240922410224112241222413224142241522416224172241822419224202242122422224232242422425224262242722428224292243022431224322243322434224352243622437224382243922440224412244222443224442244522446224472244822449224502245122452224532245422455224562245722458224592246022461224622246322464224652246622467224682246922470224712247222473224742247522476224772247822479224802248122482224832248422485224862248722488224892249022491224922249322494224952249622497224982249922500225012250222503225042250522506225072250822509225102251122512225132251422515225162251722518225192252022521225222252322524225252252622527225282252922530225312253222533225342253522536225372253822539225402254122542225432254422545225462254722548225492255022551225522255322554225552255622557225582255922560225612256222563225642256522566225672256822569225702257122572225732257422575225762257722578225792258022581225822258322584225852258622587225882258922590225912259222593225942259522596225972259822599226002260122602226032260422605226062260722608226092261022611226122261322614226152261622617226182261922620226212262222623226242262522626226272262822629226302263122632226332263422635226362263722638226392264022641226422264322644226452264622647226482264922650226512265222653226542265522656226572265822659226602266122662226632266422665226662266722668226692267022671226722267322674226752267622677226782267922680226812268222683226842268522686226872268822689226902269122692226932269422695226962269722698226992270022701227022270322704227052270622707227082270922710227112271222713227142271522716227172271822719227202272122722227232272422725227262272722728227292273022731227322273322734227352273622737227382273922740227412274222743227442274522746227472274822749227502275122752227532275422755227562275722758227592276022761227622276322764227652276622767227682276922770227712277222773227742277522776227772277822779227802278122782227832278422785227862278722788227892279022791227922279322794227952279622797227982279922800228012280222803228042280522806228072280822809228102281122812228132281422815228162281722818228192282022821228222282322824228252282622827228282282922830228312283222833228342283522836228372283822839228402284122842228432284422845228462284722848228492285022851228522285322854228552285622857228582285922860228612286222863228642286522866228672286822869228702287122872228732287422875228762287722878228792288022881228822288322884228852288622887228882288922890228912289222893228942289522896228972289822899229002290122902229032290422905229062290722908229092291022911229122291322914229152291622917229182291922920229212292222923229242292522926229272292822929229302293122932229332293422935229362293722938229392294022941229422294322944229452294622947229482294922950229512295222953229542295522956229572295822959229602296122962229632296422965229662296722968229692297022971229722297322974229752297622977229782297922980229812298222983229842298522986229872298822989229902299122992229932299422995229962299722998229992300023001230022300323004230052300623007230082300923010230112301223013230142301523016230172301823019230202302123022230232302423025230262302723028230292303023031230322303323034230352303623037230382303923040230412304223043230442304523046230472304823049230502305123052230532305423055230562305723058230592306023061230622306323064230652306623067230682306923070230712307223073230742307523076230772307823079230802308123082230832308423085230862308723088230892309023091230922309323094230952309623097230982309923100231012310223103231042310523106231072310823109231102311123112231132311423115231162311723118231192312023121231222312323124231252312623127231282312923130231312313223133231342313523136231372313823139231402314123142231432314423145231462314723148231492315023151231522315323154231552315623157231582315923160231612316223163231642316523166231672316823169231702317123172231732317423175231762317723178231792318023181231822318323184231852318623187231882318923190231912319223193231942319523196231972319823199232002320123202232032320423205232062320723208232092321023211232122321323214232152321623217232182321923220232212322223223232242322523226232272322823229232302323123232232332323423235232362323723238232392324023241232422324323244232452324623247232482324923250232512325223253232542325523256232572325823259232602326123262232632326423265232662326723268232692327023271232722327323274232752327623277232782327923280232812328223283232842328523286232872328823289232902329123292232932329423295232962329723298232992330023301233022330323304233052330623307233082330923310233112331223313233142331523316233172331823319233202332123322233232332423325233262332723328233292333023331233322333323334233352333623337233382333923340233412334223343233442334523346233472334823349233502335123352233532335423355233562335723358233592336023361233622336323364233652336623367233682336923370233712337223373233742337523376233772337823379233802338123382233832338423385233862338723388233892339023391233922339323394233952339623397233982339923400234012340223403234042340523406234072340823409234102341123412234132341423415234162341723418234192342023421234222342323424234252342623427234282342923430234312343223433234342343523436234372343823439234402344123442234432344423445234462344723448234492345023451234522345323454234552345623457234582345923460234612346223463234642346523466234672346823469234702347123472234732347423475234762347723478234792348023481234822348323484234852348623487234882348923490234912349223493234942349523496234972349823499235002350123502235032350423505235062350723508235092351023511235122351323514235152351623517235182351923520235212352223523235242352523526235272352823529235302353123532235332353423535235362353723538235392354023541235422354323544235452354623547235482354923550235512355223553235542355523556235572355823559235602356123562235632356423565235662356723568235692357023571235722357323574235752357623577235782357923580235812358223583235842358523586235872358823589235902359123592235932359423595235962359723598235992360023601236022360323604236052360623607236082360923610236112361223613236142361523616236172361823619236202362123622236232362423625236262362723628236292363023631236322363323634236352363623637236382363923640236412364223643236442364523646236472364823649236502365123652236532365423655236562365723658236592366023661236622366323664236652366623667236682366923670236712367223673236742367523676236772367823679236802368123682236832368423685236862368723688236892369023691236922369323694236952369623697236982369923700237012370223703237042370523706237072370823709237102371123712237132371423715237162371723718237192372023721237222372323724237252372623727237282372923730237312373223733237342373523736237372373823739237402374123742237432374423745237462374723748237492375023751237522375323754237552375623757237582375923760237612376223763237642376523766237672376823769237702377123772237732377423775237762377723778237792378023781237822378323784237852378623787237882378923790237912379223793237942379523796237972379823799238002380123802238032380423805238062380723808238092381023811238122381323814238152381623817238182381923820238212382223823238242382523826238272382823829238302383123832238332383423835238362383723838238392384023841238422384323844238452384623847238482384923850238512385223853238542385523856238572385823859238602386123862238632386423865238662386723868238692387023871238722387323874238752387623877238782387923880238812388223883238842388523886238872388823889238902389123892238932389423895238962389723898238992390023901239022390323904239052390623907239082390923910239112391223913239142391523916239172391823919239202392123922239232392423925239262392723928239292393023931239322393323934239352393623937239382393923940239412394223943239442394523946239472394823949239502395123952239532395423955239562395723958239592396023961239622396323964239652396623967239682396923970239712397223973239742397523976239772397823979239802398123982239832398423985239862398723988239892399023991239922399323994239952399623997239982399924000240012400224003240042400524006240072400824009240102401124012240132401424015240162401724018240192402024021240222402324024240252402624027240282402924030240312403224033240342403524036240372403824039240402404124042240432404424045240462404724048240492405024051240522405324054240552405624057240582405924060240612406224063240642406524066240672406824069240702407124072240732407424075240762407724078240792408024081240822408324084240852408624087240882408924090240912409224093240942409524096240972409824099241002410124102241032410424105241062410724108241092411024111241122411324114241152411624117241182411924120241212412224123241242412524126241272412824129241302413124132241332413424135241362413724138241392414024141241422414324144241452414624147241482414924150241512415224153241542415524156241572415824159241602416124162241632416424165241662416724168241692417024171241722417324174241752417624177241782417924180241812418224183241842418524186241872418824189241902419124192241932419424195241962419724198241992420024201242022420324204242052420624207242082420924210242112421224213242142421524216242172421824219242202422124222242232422424225242262422724228242292423024231242322423324234242352423624237242382423924240242412424224243242442424524246242472424824249242502425124252242532425424255242562425724258242592426024261242622426324264242652426624267242682426924270242712427224273242742427524276242772427824279242802428124282242832428424285242862428724288242892429024291242922429324294242952429624297242982429924300243012430224303243042430524306243072430824309243102431124312243132431424315243162431724318243192432024321243222432324324243252432624327243282432924330243312433224333243342433524336243372433824339243402434124342243432434424345243462434724348243492435024351243522435324354243552435624357243582435924360243612436224363243642436524366243672436824369243702437124372243732437424375243762437724378243792438024381243822438324384243852438624387243882438924390243912439224393243942439524396243972439824399244002440124402244032440424405244062440724408244092441024411244122441324414244152441624417244182441924420244212442224423244242442524426244272442824429244302443124432244332443424435244362443724438244392444024441244422444324444244452444624447244482444924450244512445224453244542445524456244572445824459244602446124462244632446424465244662446724468244692447024471244722447324474244752447624477244782447924480244812448224483244842448524486244872448824489244902449124492244932449424495244962449724498244992450024501245022450324504245052450624507245082450924510245112451224513245142451524516245172451824519245202452124522245232452424525245262452724528245292453024531245322453324534245352453624537245382453924540245412454224543245442454524546245472454824549245502455124552245532455424555245562455724558245592456024561245622456324564245652456624567245682456924570245712457224573245742457524576245772457824579245802458124582245832458424585245862458724588245892459024591245922459324594245952459624597245982459924600246012460224603246042460524606246072460824609246102461124612246132461424615246162461724618246192462024621246222462324624246252462624627246282462924630246312463224633246342463524636246372463824639246402464124642246432464424645246462464724648246492465024651246522465324654246552465624657246582465924660246612466224663246642466524666246672466824669246702467124672246732467424675246762467724678246792468024681246822468324684246852468624687246882468924690246912469224693246942469524696246972469824699247002470124702247032470424705247062470724708247092471024711247122471324714247152471624717247182471924720247212472224723247242472524726247272472824729247302473124732247332473424735247362473724738247392474024741247422474324744247452474624747247482474924750247512475224753247542475524756247572475824759247602476124762247632476424765247662476724768247692477024771247722477324774247752477624777247782477924780247812478224783247842478524786247872478824789247902479124792247932479424795247962479724798247992480024801248022480324804248052480624807248082480924810248112481224813248142481524816248172481824819248202482124822248232482424825248262482724828248292483024831248322483324834248352483624837248382483924840248412484224843248442484524846248472484824849248502485124852248532485424855248562485724858248592486024861248622486324864248652486624867248682486924870248712487224873248742487524876248772487824879248802488124882248832488424885248862488724888248892489024891248922489324894248952489624897248982489924900249012490224903249042490524906249072490824909249102491124912249132491424915249162491724918249192492024921249222492324924249252492624927249282492924930249312493224933249342493524936249372493824939249402494124942249432494424945249462494724948249492495024951249522495324954249552495624957249582495924960249612496224963249642496524966249672496824969249702497124972249732497424975249762497724978249792498024981249822498324984249852498624987249882498924990249912499224993249942499524996249972499824999250002500125002250032500425005250062500725008250092501025011250122501325014250152501625017250182501925020250212502225023250242502525026250272502825029250302503125032250332503425035250362503725038250392504025041250422504325044250452504625047250482504925050250512505225053250542505525056250572505825059250602506125062250632506425065250662506725068250692507025071250722507325074250752507625077250782507925080250812508225083250842508525086250872508825089250902509125092250932509425095250962509725098250992510025101251022510325104251052510625107251082510925110251112511225113251142511525116251172511825119251202512125122251232512425125251262512725128251292513025131251322513325134251352513625137251382513925140251412514225143251442514525146251472514825149251502515125152251532515425155251562515725158251592516025161251622516325164251652516625167251682516925170251712517225173251742517525176251772517825179251802518125182251832518425185251862518725188251892519025191251922519325194251952519625197251982519925200252012520225203252042520525206252072520825209252102521125212252132521425215252162521725218252192522025221252222522325224252252522625227252282522925230252312523225233252342523525236252372523825239252402524125242252432524425245252462524725248252492525025251252522525325254252552525625257252582525925260252612526225263252642526525266252672526825269252702527125272252732527425275252762527725278252792528025281252822528325284252852528625287252882528925290252912529225293252942529525296252972529825299253002530125302253032530425305253062530725308253092531025311253122531325314253152531625317253182531925320253212532225323253242532525326253272532825329253302533125332253332533425335253362533725338253392534025341253422534325344253452534625347253482534925350253512535225353253542535525356253572535825359253602536125362253632536425365253662536725368253692537025371253722537325374253752537625377253782537925380253812538225383253842538525386253872538825389253902539125392253932539425395253962539725398253992540025401254022540325404254052540625407254082540925410254112541225413254142541525416254172541825419254202542125422254232542425425254262542725428254292543025431254322543325434254352543625437254382543925440254412544225443254442544525446254472544825449254502545125452254532545425455254562545725458254592546025461254622546325464254652546625467254682546925470254712547225473254742547525476254772547825479254802548125482254832548425485254862548725488254892549025491254922549325494254952549625497254982549925500255012550225503255042550525506255072550825509255102551125512255132551425515255162551725518255192552025521255222552325524255252552625527255282552925530255312553225533255342553525536255372553825539255402554125542255432554425545255462554725548255492555025551255522555325554255552555625557255582555925560255612556225563255642556525566255672556825569255702557125572255732557425575255762557725578255792558025581255822558325584255852558625587255882558925590255912559225593255942559525596255972559825599256002560125602256032560425605256062560725608256092561025611256122561325614256152561625617256182561925620256212562225623256242562525626256272562825629256302563125632256332563425635256362563725638256392564025641256422564325644256452564625647256482564925650256512565225653256542565525656256572565825659256602566125662256632566425665256662566725668256692567025671256722567325674256752567625677256782567925680256812568225683256842568525686256872568825689256902569125692256932569425695256962569725698256992570025701257022570325704257052570625707257082570925710257112571225713257142571525716257172571825719257202572125722257232572425725257262572725728257292573025731257322573325734257352573625737257382573925740257412574225743257442574525746257472574825749257502575125752257532575425755257562575725758257592576025761257622576325764257652576625767257682576925770257712577225773257742577525776257772577825779257802578125782257832578425785257862578725788257892579025791257922579325794257952579625797257982579925800258012580225803258042580525806258072580825809258102581125812258132581425815258162581725818258192582025821258222582325824258252582625827258282582925830258312583225833258342583525836258372583825839258402584125842258432584425845258462584725848258492585025851258522585325854258552585625857258582585925860258612586225863258642586525866258672586825869258702587125872258732587425875258762587725878258792588025881258822588325884258852588625887258882588925890258912589225893258942589525896258972589825899259002590125902259032590425905259062590725908259092591025911259122591325914259152591625917259182591925920259212592225923259242592525926259272592825929259302593125932259332593425935259362593725938259392594025941259422594325944259452594625947259482594925950259512595225953259542595525956259572595825959259602596125962259632596425965259662596725968259692597025971259722597325974259752597625977259782597925980259812598225983259842598525986259872598825989259902599125992259932599425995259962599725998259992600026001260022600326004260052600626007260082600926010260112601226013260142601526016260172601826019260202602126022260232602426025260262602726028260292603026031260322603326034260352603626037260382603926040260412604226043260442604526046260472604826049260502605126052260532605426055260562605726058260592606026061260622606326064260652606626067260682606926070260712607226073260742607526076260772607826079260802608126082260832608426085260862608726088260892609026091260922609326094260952609626097260982609926100261012610226103261042610526106261072610826109261102611126112261132611426115261162611726118261192612026121261222612326124261252612626127261282612926130261312613226133261342613526136261372613826139261402614126142261432614426145261462614726148261492615026151261522615326154261552615626157261582615926160261612616226163261642616526166261672616826169261702617126172261732617426175261762617726178261792618026181261822618326184261852618626187261882618926190261912619226193261942619526196261972619826199262002620126202262032620426205262062620726208262092621026211262122621326214262152621626217262182621926220262212622226223262242622526226262272622826229262302623126232262332623426235262362623726238262392624026241262422624326244262452624626247262482624926250262512625226253262542625526256262572625826259262602626126262262632626426265262662626726268262692627026271262722627326274262752627626277262782627926280262812628226283262842628526286262872628826289262902629126292262932629426295262962629726298262992630026301263022630326304263052630626307263082630926310263112631226313263142631526316263172631826319263202632126322263232632426325263262632726328263292633026331263322633326334263352633626337263382633926340263412634226343263442634526346263472634826349263502635126352263532635426355263562635726358263592636026361263622636326364263652636626367263682636926370263712637226373263742637526376263772637826379263802638126382263832638426385263862638726388263892639026391263922639326394263952639626397263982639926400264012640226403264042640526406264072640826409264102641126412264132641426415264162641726418264192642026421264222642326424264252642626427264282642926430264312643226433264342643526436264372643826439264402644126442264432644426445264462644726448264492645026451264522645326454264552645626457264582645926460264612646226463264642646526466264672646826469264702647126472264732647426475264762647726478264792648026481264822648326484264852648626487264882648926490264912649226493264942649526496264972649826499265002650126502265032650426505265062650726508265092651026511265122651326514265152651626517265182651926520265212652226523265242652526526265272652826529265302653126532265332653426535265362653726538265392654026541265422654326544265452654626547265482654926550265512655226553265542655526556265572655826559265602656126562265632656426565265662656726568265692657026571265722657326574265752657626577265782657926580265812658226583265842658526586265872658826589265902659126592265932659426595265962659726598265992660026601266022660326604266052660626607266082660926610266112661226613266142661526616266172661826619266202662126622266232662426625266262662726628266292663026631266322663326634266352663626637266382663926640266412664226643266442664526646266472664826649266502665126652266532665426655266562665726658266592666026661266622666326664266652666626667266682666926670266712667226673266742667526676266772667826679266802668126682266832668426685266862668726688266892669026691266922669326694266952669626697266982669926700267012670226703267042670526706267072670826709267102671126712267132671426715267162671726718267192672026721267222672326724267252672626727267282672926730267312673226733267342673526736267372673826739267402674126742267432674426745267462674726748267492675026751267522675326754267552675626757267582675926760267612676226763267642676526766267672676826769267702677126772267732677426775267762677726778267792678026781267822678326784267852678626787267882678926790267912679226793267942679526796267972679826799268002680126802268032680426805268062680726808268092681026811268122681326814268152681626817268182681926820268212682226823268242682526826268272682826829268302683126832268332683426835268362683726838268392684026841268422684326844268452684626847268482684926850268512685226853268542685526856268572685826859268602686126862268632686426865268662686726868268692687026871268722687326874268752687626877268782687926880268812688226883268842688526886268872688826889268902689126892268932689426895268962689726898268992690026901269022690326904269052690626907269082690926910269112691226913269142691526916269172691826919269202692126922269232692426925269262692726928269292693026931269322693326934269352693626937269382693926940269412694226943269442694526946269472694826949269502695126952269532695426955269562695726958269592696026961269622696326964269652696626967269682696926970269712697226973269742697526976269772697826979269802698126982269832698426985269862698726988269892699026991269922699326994269952699626997269982699927000270012700227003270042700527006270072700827009270102701127012270132701427015270162701727018270192702027021270222702327024270252702627027270282702927030270312703227033270342703527036270372703827039270402704127042270432704427045270462704727048270492705027051270522705327054270552705627057270582705927060270612706227063270642706527066270672706827069270702707127072270732707427075270762707727078270792708027081270822708327084270852708627087270882708927090270912709227093270942709527096270972709827099271002710127102271032710427105271062710727108271092711027111271122711327114271152711627117271182711927120271212712227123271242712527126271272712827129271302713127132271332713427135271362713727138271392714027141271422714327144271452714627147271482714927150271512715227153271542715527156271572715827159271602716127162271632716427165271662716727168271692717027171271722717327174271752717627177271782717927180271812718227183271842718527186271872718827189271902719127192271932719427195271962719727198271992720027201272022720327204272052720627207272082720927210272112721227213272142721527216272172721827219272202722127222272232722427225272262722727228272292723027231272322723327234272352723627237272382723927240272412724227243272442724527246272472724827249272502725127252272532725427255272562725727258272592726027261272622726327264272652726627267272682726927270272712727227273272742727527276272772727827279272802728127282272832728427285272862728727288272892729027291272922729327294272952729627297272982729927300273012730227303273042730527306273072730827309273102731127312273132731427315273162731727318273192732027321273222732327324273252732627327273282732927330273312733227333273342733527336273372733827339273402734127342273432734427345273462734727348273492735027351273522735327354273552735627357273582735927360273612736227363273642736527366273672736827369273702737127372273732737427375273762737727378273792738027381273822738327384273852738627387273882738927390273912739227393273942739527396273972739827399274002740127402274032740427405274062740727408274092741027411274122741327414274152741627417274182741927420274212742227423274242742527426274272742827429274302743127432274332743427435274362743727438274392744027441274422744327444274452744627447274482744927450274512745227453274542745527456274572745827459274602746127462274632746427465274662746727468274692747027471274722747327474274752747627477274782747927480274812748227483274842748527486274872748827489274902749127492274932749427495274962749727498274992750027501275022750327504275052750627507275082750927510275112751227513275142751527516275172751827519275202752127522275232752427525275262752727528275292753027531275322753327534275352753627537275382753927540275412754227543275442754527546275472754827549275502755127552275532755427555275562755727558275592756027561275622756327564275652756627567275682756927570275712757227573275742757527576275772757827579275802758127582275832758427585275862758727588275892759027591275922759327594275952759627597275982759927600276012760227603276042760527606276072760827609276102761127612276132761427615276162761727618276192762027621276222762327624276252762627627276282762927630276312763227633276342763527636276372763827639276402764127642276432764427645276462764727648276492765027651276522765327654276552765627657276582765927660276612766227663276642766527666276672766827669276702767127672276732767427675276762767727678276792768027681276822768327684276852768627687276882768927690276912769227693276942769527696276972769827699277002770127702277032770427705277062770727708277092771027711277122771327714277152771627717277182771927720277212772227723277242772527726277272772827729277302773127732277332773427735277362773727738277392774027741277422774327744277452774627747277482774927750277512775227753277542775527756277572775827759277602776127762277632776427765277662776727768277692777027771277722777327774277752777627777277782777927780277812778227783277842778527786277872778827789277902779127792277932779427795277962779727798277992780027801278022780327804278052780627807278082780927810278112781227813278142781527816278172781827819278202782127822278232782427825278262782727828278292783027831278322783327834278352783627837278382783927840278412784227843278442784527846278472784827849278502785127852278532785427855278562785727858278592786027861278622786327864278652786627867278682786927870278712787227873278742787527876278772787827879278802788127882278832788427885278862788727888278892789027891278922789327894278952789627897278982789927900279012790227903279042790527906279072790827909279102791127912279132791427915279162791727918279192792027921279222792327924279252792627927279282792927930279312793227933279342793527936279372793827939279402794127942279432794427945279462794727948279492795027951279522795327954279552795627957279582795927960279612796227963279642796527966279672796827969279702797127972279732797427975279762797727978279792798027981279822798327984279852798627987279882798927990279912799227993279942799527996279972799827999280002800128002280032800428005280062800728008280092801028011280122801328014280152801628017280182801928020280212802228023280242802528026280272802828029280302803128032280332803428035280362803728038280392804028041280422804328044280452804628047280482804928050280512805228053280542805528056280572805828059280602806128062280632806428065280662806728068280692807028071280722807328074280752807628077280782807928080280812808228083280842808528086280872808828089280902809128092280932809428095280962809728098280992810028101281022810328104281052810628107281082810928110281112811228113281142811528116281172811828119281202812128122281232812428125281262812728128281292813028131281322813328134281352813628137281382813928140281412814228143281442814528146281472814828149281502815128152281532815428155281562815728158281592816028161281622816328164281652816628167281682816928170281712817228173281742817528176281772817828179281802818128182281832818428185281862818728188281892819028191281922819328194281952819628197281982819928200282012820228203282042820528206282072820828209282102821128212282132821428215282162821728218282192822028221282222822328224282252822628227282282822928230282312823228233282342823528236282372823828239282402824128242282432824428245282462824728248282492825028251282522825328254282552825628257282582825928260282612826228263282642826528266282672826828269282702827128272282732827428275282762827728278282792828028281282822828328284282852828628287282882828928290282912829228293282942829528296282972829828299283002830128302283032830428305283062830728308283092831028311283122831328314283152831628317283182831928320283212832228323283242832528326283272832828329283302833128332283332833428335283362833728338283392834028341283422834328344283452834628347283482834928350283512835228353283542835528356283572835828359283602836128362283632836428365283662836728368283692837028371283722837328374283752837628377283782837928380283812838228383283842838528386283872838828389283902839128392283932839428395283962839728398283992840028401284022840328404284052840628407284082840928410284112841228413284142841528416284172841828419284202842128422284232842428425284262842728428284292843028431284322843328434284352843628437284382843928440284412844228443284442844528446284472844828449284502845128452284532845428455284562845728458284592846028461284622846328464284652846628467284682846928470284712847228473284742847528476284772847828479284802848128482284832848428485284862848728488284892849028491284922849328494284952849628497284982849928500285012850228503285042850528506285072850828509285102851128512285132851428515285162851728518285192852028521285222852328524285252852628527285282852928530285312853228533285342853528536285372853828539285402854128542285432854428545285462854728548285492855028551285522855328554285552855628557285582855928560285612856228563285642856528566285672856828569285702857128572285732857428575285762857728578285792858028581285822858328584285852858628587285882858928590285912859228593285942859528596285972859828599286002860128602286032860428605286062860728608286092861028611286122861328614286152861628617286182861928620286212862228623286242862528626286272862828629286302863128632286332863428635286362863728638286392864028641286422864328644286452864628647286482864928650286512865228653286542865528656286572865828659286602866128662286632866428665286662866728668286692867028671286722867328674286752867628677286782867928680286812868228683286842868528686286872868828689286902869128692286932869428695286962869728698286992870028701287022870328704287052870628707287082870928710287112871228713287142871528716287172871828719287202872128722287232872428725287262872728728287292873028731287322873328734287352873628737287382873928740287412874228743287442874528746287472874828749287502875128752287532875428755287562875728758287592876028761287622876328764287652876628767287682876928770287712877228773287742877528776287772877828779287802878128782287832878428785287862878728788287892879028791287922879328794287952879628797287982879928800288012880228803288042880528806288072880828809288102881128812288132881428815288162881728818288192882028821288222882328824288252882628827288282882928830288312883228833288342883528836288372883828839288402884128842288432884428845288462884728848288492885028851288522885328854288552885628857288582885928860288612886228863288642886528866288672886828869288702887128872288732887428875288762887728878288792888028881288822888328884288852888628887288882888928890288912889228893288942889528896288972889828899289002890128902289032890428905289062890728908289092891028911289122891328914289152891628917289182891928920289212892228923289242892528926289272892828929289302893128932289332893428935289362893728938289392894028941289422894328944289452894628947289482894928950289512895228953289542895528956289572895828959289602896128962289632896428965289662896728968289692897028971289722897328974289752897628977289782897928980289812898228983289842898528986289872898828989289902899128992289932899428995289962899728998289992900029001290022900329004290052900629007290082900929010290112901229013290142901529016290172901829019290202902129022290232902429025290262902729028290292903029031290322903329034290352903629037290382903929040290412904229043290442904529046290472904829049290502905129052290532905429055290562905729058290592906029061290622906329064290652906629067290682906929070290712907229073290742907529076290772907829079290802908129082290832908429085290862908729088290892909029091290922909329094290952909629097290982909929100291012910229103291042910529106291072910829109291102911129112291132911429115291162911729118291192912029121291222912329124291252912629127291282912929130291312913229133291342913529136291372913829139291402914129142291432914429145291462914729148291492915029151291522915329154291552915629157291582915929160291612916229163291642916529166291672916829169291702917129172291732917429175291762917729178291792918029181291822918329184291852918629187291882918929190291912919229193291942919529196291972919829199292002920129202292032920429205292062920729208292092921029211292122921329214292152921629217292182921929220292212922229223292242922529226292272922829229292302923129232292332923429235292362923729238292392924029241292422924329244292452924629247292482924929250292512925229253292542925529256292572925829259292602926129262292632926429265292662926729268292692927029271292722927329274292752927629277292782927929280292812928229283292842928529286292872928829289292902929129292292932929429295292962929729298292992930029301293022930329304293052930629307293082930929310293112931229313293142931529316293172931829319293202932129322293232932429325293262932729328293292933029331293322933329334293352933629337293382933929340293412934229343293442934529346293472934829349293502935129352293532935429355293562935729358293592936029361293622936329364293652936629367293682936929370293712937229373293742937529376293772937829379293802938129382293832938429385293862938729388293892939029391293922939329394293952939629397293982939929400294012940229403294042940529406294072940829409294102941129412294132941429415294162941729418294192942029421294222942329424294252942629427294282942929430294312943229433294342943529436294372943829439294402944129442294432944429445294462944729448294492945029451294522945329454294552945629457294582945929460294612946229463294642946529466294672946829469294702947129472294732947429475294762947729478294792948029481294822948329484294852948629487294882948929490294912949229493294942949529496294972949829499295002950129502295032950429505295062950729508295092951029511295122951329514295152951629517295182951929520295212952229523295242952529526295272952829529295302953129532295332953429535295362953729538295392954029541295422954329544295452954629547295482954929550295512955229553295542955529556295572955829559295602956129562295632956429565295662956729568295692957029571295722957329574295752957629577295782957929580295812958229583295842958529586295872958829589295902959129592295932959429595295962959729598295992960029601296022960329604296052960629607296082960929610296112961229613296142961529616296172961829619296202962129622296232962429625296262962729628296292963029631296322963329634296352963629637296382963929640296412964229643296442964529646296472964829649296502965129652296532965429655296562965729658296592966029661296622966329664296652966629667296682966929670296712967229673296742967529676296772967829679296802968129682296832968429685296862968729688296892969029691296922969329694296952969629697296982969929700297012970229703297042970529706297072970829709297102971129712297132971429715297162971729718297192972029721297222972329724297252972629727297282972929730297312973229733297342973529736297372973829739297402974129742297432974429745297462974729748297492975029751297522975329754297552975629757297582975929760297612976229763297642976529766297672976829769297702977129772297732977429775297762977729778297792978029781297822978329784297852978629787297882978929790297912979229793297942979529796297972979829799298002980129802298032980429805298062980729808298092981029811298122981329814298152981629817298182981929820298212982229823298242982529826298272982829829298302983129832298332983429835298362983729838298392984029841298422984329844298452984629847298482984929850298512985229853298542985529856298572985829859298602986129862298632986429865298662986729868298692987029871298722987329874298752987629877298782987929880298812988229883298842988529886298872988829889298902989129892298932989429895298962989729898298992990029901299022990329904299052990629907299082990929910299112991229913299142991529916299172991829919299202992129922299232992429925299262992729928299292993029931299322993329934299352993629937299382993929940299412994229943299442994529946299472994829949299502995129952299532995429955299562995729958299592996029961299622996329964299652996629967299682996929970299712997229973299742997529976299772997829979299802998129982299832998429985299862998729988299892999029991299922999329994299952999629997299982999930000300013000230003300043000530006300073000830009300103001130012300133001430015300163001730018300193002030021300223002330024300253002630027300283002930030300313003230033300343003530036300373003830039300403004130042300433004430045300463004730048300493005030051300523005330054300553005630057300583005930060300613006230063300643006530066300673006830069300703007130072300733007430075300763007730078300793008030081300823008330084300853008630087300883008930090300913009230093300943009530096300973009830099301003010130102301033010430105301063010730108301093011030111301123011330114301153011630117301183011930120301213012230123301243012530126301273012830129301303013130132301333013430135301363013730138301393014030141301423014330144301453014630147301483014930150301513015230153301543015530156301573015830159301603016130162301633016430165301663016730168301693017030171301723017330174301753017630177301783017930180301813018230183301843018530186301873018830189301903019130192301933019430195301963019730198301993020030201302023020330204302053020630207302083020930210302113021230213302143021530216302173021830219302203022130222302233022430225302263022730228302293023030231302323023330234302353023630237302383023930240302413024230243302443024530246302473024830249302503025130252302533025430255302563025730258302593026030261302623026330264302653026630267302683026930270302713027230273302743027530276302773027830279302803028130282302833028430285302863028730288302893029030291302923029330294302953029630297302983029930300303013030230303303043030530306303073030830309303103031130312303133031430315303163031730318303193032030321303223032330324303253032630327303283032930330303313033230333303343033530336303373033830339303403034130342303433034430345303463034730348303493035030351303523035330354303553035630357303583035930360303613036230363303643036530366303673036830369303703037130372303733037430375303763037730378303793038030381303823038330384303853038630387303883038930390303913039230393303943039530396303973039830399304003040130402304033040430405304063040730408304093041030411304123041330414304153041630417304183041930420304213042230423304243042530426304273042830429304303043130432304333043430435304363043730438304393044030441304423044330444304453044630447304483044930450304513045230453304543045530456304573045830459304603046130462304633046430465304663046730468304693047030471304723047330474304753047630477304783047930480304813048230483304843048530486304873048830489304903049130492304933049430495304963049730498304993050030501305023050330504305053050630507305083050930510305113051230513305143051530516305173051830519305203052130522305233052430525305263052730528305293053030531305323053330534305353053630537305383053930540305413054230543305443054530546305473054830549305503055130552305533055430555305563055730558305593056030561305623056330564305653056630567305683056930570305713057230573305743057530576305773057830579305803058130582305833058430585305863058730588305893059030591305923059330594305953059630597305983059930600306013060230603306043060530606306073060830609306103061130612306133061430615306163061730618306193062030621306223062330624306253062630627306283062930630306313063230633306343063530636306373063830639306403064130642306433064430645306463064730648306493065030651306523065330654306553065630657306583065930660306613066230663306643066530666306673066830669306703067130672306733067430675306763067730678306793068030681306823068330684306853068630687306883068930690306913069230693306943069530696306973069830699307003070130702307033070430705307063070730708307093071030711307123071330714307153071630717307183071930720307213072230723307243072530726307273072830729307303073130732307333073430735307363073730738307393074030741307423074330744307453074630747307483074930750307513075230753307543075530756307573075830759307603076130762307633076430765307663076730768307693077030771307723077330774307753077630777307783077930780307813078230783307843078530786307873078830789307903079130792307933079430795307963079730798307993080030801308023080330804308053080630807308083080930810308113081230813308143081530816308173081830819308203082130822308233082430825308263082730828308293083030831308323083330834308353083630837308383083930840308413084230843308443084530846308473084830849308503085130852308533085430855308563085730858308593086030861308623086330864308653086630867308683086930870308713087230873308743087530876308773087830879308803088130882308833088430885308863088730888308893089030891308923089330894308953089630897308983089930900309013090230903309043090530906309073090830909309103091130912309133091430915309163091730918309193092030921309223092330924309253092630927309283092930930309313093230933309343093530936309373093830939309403094130942309433094430945309463094730948309493095030951309523095330954309553095630957309583095930960309613096230963309643096530966309673096830969309703097130972309733097430975309763097730978309793098030981309823098330984309853098630987309883098930990309913099230993309943099530996309973099830999310003100131002310033100431005310063100731008310093101031011310123101331014310153101631017310183101931020310213102231023310243102531026310273102831029310303103131032310333103431035310363103731038310393104031041310423104331044310453104631047310483104931050310513105231053310543105531056310573105831059310603106131062310633106431065310663106731068310693107031071310723107331074310753107631077310783107931080310813108231083310843108531086310873108831089310903109131092310933109431095310963109731098310993110031101311023110331104311053110631107311083110931110311113111231113311143111531116311173111831119311203112131122311233112431125311263112731128311293113031131311323113331134311353113631137311383113931140311413114231143311443114531146311473114831149311503115131152311533115431155311563115731158311593116031161311623116331164311653116631167311683116931170311713117231173311743117531176311773117831179311803118131182311833118431185311863118731188311893119031191311923119331194311953119631197311983119931200312013120231203312043120531206312073120831209312103121131212312133121431215312163121731218312193122031221312223122331224312253122631227312283122931230312313123231233312343123531236312373123831239312403124131242312433124431245312463124731248312493125031251312523125331254312553125631257312583125931260312613126231263312643126531266312673126831269312703127131272312733127431275312763127731278312793128031281312823128331284312853128631287312883128931290312913129231293312943129531296312973129831299313003130131302313033130431305313063130731308313093131031311313123131331314313153131631317313183131931320313213132231323313243132531326313273132831329313303133131332313333133431335313363133731338313393134031341313423134331344313453134631347313483134931350313513135231353313543135531356313573135831359313603136131362313633136431365313663136731368313693137031371313723137331374313753137631377313783137931380313813138231383313843138531386313873138831389313903139131392313933139431395313963139731398313993140031401314023140331404314053140631407314083140931410314113141231413314143141531416314173141831419314203142131422314233142431425314263142731428314293143031431314323143331434314353143631437314383143931440314413144231443314443144531446314473144831449314503145131452314533145431455314563145731458314593146031461314623146331464314653146631467314683146931470314713147231473314743147531476314773147831479314803148131482314833148431485314863148731488314893149031491314923149331494314953149631497314983149931500315013150231503315043150531506315073150831509315103151131512315133151431515315163151731518315193152031521315223152331524315253152631527315283152931530315313153231533315343153531536315373153831539315403154131542315433154431545315463154731548315493155031551315523155331554315553155631557315583155931560315613156231563315643156531566315673156831569315703157131572315733157431575315763157731578315793158031581315823158331584315853158631587315883158931590315913159231593315943159531596315973159831599316003160131602316033160431605316063160731608316093161031611316123161331614316153161631617316183161931620316213162231623316243162531626316273162831629316303163131632316333163431635316363163731638316393164031641316423164331644316453164631647316483164931650316513165231653316543165531656316573165831659316603166131662316633166431665316663166731668316693167031671316723167331674316753167631677316783167931680316813168231683316843168531686316873168831689316903169131692316933169431695316963169731698316993170031701317023170331704317053170631707317083170931710317113171231713317143171531716317173171831719317203172131722317233172431725317263172731728317293173031731317323173331734317353173631737317383173931740317413174231743317443174531746317473174831749317503175131752317533175431755317563175731758317593176031761317623176331764317653176631767317683176931770317713177231773317743177531776317773177831779317803178131782317833178431785317863178731788317893179031791317923179331794317953179631797317983179931800318013180231803318043180531806318073180831809318103181131812318133181431815318163181731818318193182031821318223182331824318253182631827318283182931830318313183231833318343183531836318373183831839318403184131842318433184431845318463184731848318493185031851318523185331854318553185631857318583185931860318613186231863318643186531866318673186831869318703187131872318733187431875318763187731878318793188031881318823188331884318853188631887318883188931890318913189231893318943189531896318973189831899319003190131902319033190431905319063190731908319093191031911319123191331914319153191631917319183191931920319213192231923319243192531926319273192831929319303193131932319333193431935319363193731938319393194031941319423194331944319453194631947319483194931950319513195231953319543195531956319573195831959319603196131962319633196431965319663196731968319693197031971319723197331974319753197631977319783197931980319813198231983319843198531986319873198831989319903199131992319933199431995319963199731998319993200032001320023200332004320053200632007320083200932010320113201232013320143201532016320173201832019320203202132022320233202432025320263202732028320293203032031320323203332034320353203632037320383203932040320413204232043320443204532046320473204832049320503205132052320533205432055320563205732058320593206032061320623206332064320653206632067320683206932070320713207232073320743207532076320773207832079320803208132082320833208432085320863208732088320893209032091320923209332094320953209632097320983209932100321013210232103321043210532106321073210832109321103211132112321133211432115321163211732118321193212032121321223212332124321253212632127321283212932130321313213232133321343213532136321373213832139321403214132142321433214432145321463214732148321493215032151321523215332154321553215632157321583215932160321613216232163321643216532166321673216832169321703217132172321733217432175321763217732178321793218032181321823218332184321853218632187321883218932190321913219232193321943219532196321973219832199322003220132202322033220432205322063220732208322093221032211322123221332214322153221632217322183221932220322213222232223322243222532226322273222832229322303223132232322333223432235322363223732238322393224032241322423224332244322453224632247322483224932250322513225232253322543225532256322573225832259322603226132262322633226432265322663226732268322693227032271322723227332274322753227632277322783227932280322813228232283322843228532286322873228832289322903229132292322933229432295322963229732298322993230032301323023230332304323053230632307323083230932310323113231232313323143231532316323173231832319323203232132322323233232432325323263232732328323293233032331323323233332334323353233632337323383233932340323413234232343323443234532346323473234832349323503235132352323533235432355323563235732358323593236032361323623236332364323653236632367323683236932370323713237232373323743237532376323773237832379323803238132382323833238432385323863238732388323893239032391323923239332394323953239632397323983239932400324013240232403324043240532406324073240832409324103241132412324133241432415324163241732418324193242032421324223242332424324253242632427324283242932430324313243232433324343243532436324373243832439324403244132442324433244432445324463244732448324493245032451324523245332454324553245632457324583245932460324613246232463324643246532466324673246832469324703247132472324733247432475324763247732478324793248032481324823248332484324853248632487324883248932490324913249232493324943249532496324973249832499325003250132502325033250432505325063250732508325093251032511325123251332514325153251632517325183251932520325213252232523325243252532526325273252832529325303253132532325333253432535325363253732538325393254032541325423254332544325453254632547325483254932550325513255232553325543255532556325573255832559325603256132562325633256432565325663256732568325693257032571325723257332574325753257632577325783257932580325813258232583325843258532586325873258832589325903259132592325933259432595325963259732598325993260032601326023260332604326053260632607326083260932610326113261232613326143261532616326173261832619326203262132622326233262432625
  1. /*! p5.js v0.5.7 February 08, 2017 */
  2. (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.p5 = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
  3. },{}],2:[function(_dereq_,module,exports){
  4. // Run-time checking of preconditions.
  5. 'use strict';
  6. // Precondition function that checks if the given predicate is true.
  7. // If not, it will throw an error.
  8. exports.argument = function(predicate, message) {
  9. if (!predicate) {
  10. throw new Error(message);
  11. }
  12. };
  13. // Precondition function that checks if the given assertion is true.
  14. // If not, it will throw an error.
  15. exports.assert = exports.argument;
  16. },{}],3:[function(_dereq_,module,exports){
  17. // Drawing utility functions.
  18. 'use strict';
  19. // Draw a line on the given context from point `x1,y1` to point `x2,y2`.
  20. function line(ctx, x1, y1, x2, y2) {
  21. ctx.beginPath();
  22. ctx.moveTo(x1, y1);
  23. ctx.lineTo(x2, y2);
  24. ctx.stroke();
  25. }
  26. exports.line = line;
  27. },{}],4:[function(_dereq_,module,exports){
  28. // Glyph encoding
  29. 'use strict';
  30. var cffStandardStrings = [
  31. '.notdef', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', 'ampersand', 'quoteright',
  32. 'parenleft', 'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two',
  33. 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater',
  34. 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
  35. 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore',
  36. 'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
  37. 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', 'exclamdown', 'cent', 'sterling',
  38. 'fraction', 'yen', 'florin', 'section', 'currency', 'quotesingle', 'quotedblleft', 'guillemotleft',
  39. 'guilsinglleft', 'guilsinglright', 'fi', 'fl', 'endash', 'dagger', 'daggerdbl', 'periodcentered', 'paragraph',
  40. 'bullet', 'quotesinglbase', 'quotedblbase', 'quotedblright', 'guillemotright', 'ellipsis', 'perthousand',
  41. 'questiondown', 'grave', 'acute', 'circumflex', 'tilde', 'macron', 'breve', 'dotaccent', 'dieresis', 'ring',
  42. 'cedilla', 'hungarumlaut', 'ogonek', 'caron', 'emdash', 'AE', 'ordfeminine', 'Lslash', 'Oslash', 'OE',
  43. 'ordmasculine', 'ae', 'dotlessi', 'lslash', 'oslash', 'oe', 'germandbls', 'onesuperior', 'logicalnot', 'mu',
  44. 'trademark', 'Eth', 'onehalf', 'plusminus', 'Thorn', 'onequarter', 'divide', 'brokenbar', 'degree', 'thorn',
  45. 'threequarters', 'twosuperior', 'registered', 'minus', 'eth', 'multiply', 'threesuperior', 'copyright',
  46. 'Aacute', 'Acircumflex', 'Adieresis', 'Agrave', 'Aring', 'Atilde', 'Ccedilla', 'Eacute', 'Ecircumflex',
  47. 'Edieresis', 'Egrave', 'Iacute', 'Icircumflex', 'Idieresis', 'Igrave', 'Ntilde', 'Oacute', 'Ocircumflex',
  48. 'Odieresis', 'Ograve', 'Otilde', 'Scaron', 'Uacute', 'Ucircumflex', 'Udieresis', 'Ugrave', 'Yacute',
  49. 'Ydieresis', 'Zcaron', 'aacute', 'acircumflex', 'adieresis', 'agrave', 'aring', 'atilde', 'ccedilla', 'eacute',
  50. 'ecircumflex', 'edieresis', 'egrave', 'iacute', 'icircumflex', 'idieresis', 'igrave', 'ntilde', 'oacute',
  51. 'ocircumflex', 'odieresis', 'ograve', 'otilde', 'scaron', 'uacute', 'ucircumflex', 'udieresis', 'ugrave',
  52. 'yacute', 'ydieresis', 'zcaron', 'exclamsmall', 'Hungarumlautsmall', 'dollaroldstyle', 'dollarsuperior',
  53. 'ampersandsmall', 'Acutesmall', 'parenleftsuperior', 'parenrightsuperior', '266 ff', 'onedotenleader',
  54. 'zerooldstyle', 'oneoldstyle', 'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle', 'sixoldstyle',
  55. 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'commasuperior', 'threequartersemdash', 'periodsuperior',
  56. 'questionsmall', 'asuperior', 'bsuperior', 'centsuperior', 'dsuperior', 'esuperior', 'isuperior', 'lsuperior',
  57. 'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior', 'tsuperior', 'ff', 'ffi', 'ffl',
  58. 'parenleftinferior', 'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall', 'Asmall',
  59. 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall',
  60. 'Msmall', 'Nsmall', 'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall',
  61. 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah', 'Tildesmall', 'exclamdownsmall',
  62. 'centoldstyle', 'Lslashsmall', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall', 'Brevesmall', 'Caronsmall',
  63. 'Dotaccentsmall', 'Macronsmall', 'figuredash', 'hypheninferior', 'Ogoneksmall', 'Ringsmall', 'Cedillasmall',
  64. 'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths', 'seveneighths', 'onethird', 'twothirds',
  65. 'zerosuperior', 'foursuperior', 'fivesuperior', 'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior',
  66. 'zeroinferior', 'oneinferior', 'twoinferior', 'threeinferior', 'fourinferior', 'fiveinferior', 'sixinferior',
  67. 'seveninferior', 'eightinferior', 'nineinferior', 'centinferior', 'dollarinferior', 'periodinferior',
  68. 'commainferior', 'Agravesmall', 'Aacutesmall', 'Acircumflexsmall', 'Atildesmall', 'Adieresissmall',
  69. 'Aringsmall', 'AEsmall', 'Ccedillasmall', 'Egravesmall', 'Eacutesmall', 'Ecircumflexsmall', 'Edieresissmall',
  70. 'Igravesmall', 'Iacutesmall', 'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall', 'Ogravesmall',
  71. 'Oacutesmall', 'Ocircumflexsmall', 'Otildesmall', 'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall',
  72. 'Uacutesmall', 'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall', 'Ydieresissmall', '001.000',
  73. '001.001', '001.002', '001.003', 'Black', 'Bold', 'Book', 'Light', 'Medium', 'Regular', 'Roman', 'Semibold'];
  74. var cffStandardEncoding = [
  75. '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
  76. '', '', '', '', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', 'ampersand', 'quoteright',
  77. 'parenleft', 'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two',
  78. 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater',
  79. 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
  80. 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore',
  81. 'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
  82. 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', '', '', '', '', '', '', '', '',
  83. '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
  84. 'exclamdown', 'cent', 'sterling', 'fraction', 'yen', 'florin', 'section', 'currency', 'quotesingle',
  85. 'quotedblleft', 'guillemotleft', 'guilsinglleft', 'guilsinglright', 'fi', 'fl', '', 'endash', 'dagger',
  86. 'daggerdbl', 'periodcentered', '', 'paragraph', 'bullet', 'quotesinglbase', 'quotedblbase', 'quotedblright',
  87. 'guillemotright', 'ellipsis', 'perthousand', '', 'questiondown', '', 'grave', 'acute', 'circumflex', 'tilde',
  88. 'macron', 'breve', 'dotaccent', 'dieresis', '', 'ring', 'cedilla', '', 'hungarumlaut', 'ogonek', 'caron',
  89. 'emdash', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'AE', '', 'ordfeminine', '', '', '',
  90. '', 'Lslash', 'Oslash', 'OE', 'ordmasculine', '', '', '', '', '', 'ae', '', '', '', 'dotlessi', '', '',
  91. 'lslash', 'oslash', 'oe', 'germandbls'];
  92. var cffExpertEncoding = [
  93. '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
  94. '', '', '', '', 'space', 'exclamsmall', 'Hungarumlautsmall', '', 'dollaroldstyle', 'dollarsuperior',
  95. 'ampersandsmall', 'Acutesmall', 'parenleftsuperior', 'parenrightsuperior', 'twodotenleader', 'onedotenleader',
  96. 'comma', 'hyphen', 'period', 'fraction', 'zerooldstyle', 'oneoldstyle', 'twooldstyle', 'threeoldstyle',
  97. 'fouroldstyle', 'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'colon',
  98. 'semicolon', 'commasuperior', 'threequartersemdash', 'periodsuperior', 'questionsmall', '', 'asuperior',
  99. 'bsuperior', 'centsuperior', 'dsuperior', 'esuperior', '', '', 'isuperior', '', '', 'lsuperior', 'msuperior',
  100. 'nsuperior', 'osuperior', '', '', 'rsuperior', 'ssuperior', 'tsuperior', '', 'ff', 'fi', 'fl', 'ffi', 'ffl',
  101. 'parenleftinferior', '', 'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall', 'Asmall',
  102. 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall',
  103. 'Msmall', 'Nsmall', 'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall',
  104. 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah', 'Tildesmall', '', '', '', '', '', '', '',
  105. '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
  106. 'exclamdownsmall', 'centoldstyle', 'Lslashsmall', '', '', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall',
  107. 'Brevesmall', 'Caronsmall', '', 'Dotaccentsmall', '', '', 'Macronsmall', '', '', 'figuredash', 'hypheninferior',
  108. '', '', 'Ogoneksmall', 'Ringsmall', 'Cedillasmall', '', '', '', 'onequarter', 'onehalf', 'threequarters',
  109. 'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths', 'seveneighths', 'onethird', 'twothirds', '',
  110. '', 'zerosuperior', 'onesuperior', 'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior',
  111. 'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior', 'zeroinferior', 'oneinferior', 'twoinferior',
  112. 'threeinferior', 'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior', 'eightinferior',
  113. 'nineinferior', 'centinferior', 'dollarinferior', 'periodinferior', 'commainferior', 'Agravesmall',
  114. 'Aacutesmall', 'Acircumflexsmall', 'Atildesmall', 'Adieresissmall', 'Aringsmall', 'AEsmall', 'Ccedillasmall',
  115. 'Egravesmall', 'Eacutesmall', 'Ecircumflexsmall', 'Edieresissmall', 'Igravesmall', 'Iacutesmall',
  116. 'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall', 'Ogravesmall', 'Oacutesmall',
  117. 'Ocircumflexsmall', 'Otildesmall', 'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', 'Uacutesmall',
  118. 'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall', 'Ydieresissmall'];
  119. var standardNames = [
  120. '.notdef', '.null', 'nonmarkingreturn', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent',
  121. 'ampersand', 'quotesingle', 'parenleft', 'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash',
  122. 'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less',
  123. 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
  124. 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright',
  125. 'asciicircum', 'underscore', 'grave', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
  126. 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde',
  127. 'Adieresis', 'Aring', 'Ccedilla', 'Eacute', 'Ntilde', 'Odieresis', 'Udieresis', 'aacute', 'agrave',
  128. 'acircumflex', 'adieresis', 'atilde', 'aring', 'ccedilla', 'eacute', 'egrave', 'ecircumflex', 'edieresis',
  129. 'iacute', 'igrave', 'icircumflex', 'idieresis', 'ntilde', 'oacute', 'ograve', 'ocircumflex', 'odieresis',
  130. 'otilde', 'uacute', 'ugrave', 'ucircumflex', 'udieresis', 'dagger', 'degree', 'cent', 'sterling', 'section',
  131. 'bullet', 'paragraph', 'germandbls', 'registered', 'copyright', 'trademark', 'acute', 'dieresis', 'notequal',
  132. 'AE', 'Oslash', 'infinity', 'plusminus', 'lessequal', 'greaterequal', 'yen', 'mu', 'partialdiff', 'summation',
  133. 'product', 'pi', 'integral', 'ordfeminine', 'ordmasculine', 'Omega', 'ae', 'oslash', 'questiondown',
  134. 'exclamdown', 'logicalnot', 'radical', 'florin', 'approxequal', 'Delta', 'guillemotleft', 'guillemotright',
  135. 'ellipsis', 'nonbreakingspace', 'Agrave', 'Atilde', 'Otilde', 'OE', 'oe', 'endash', 'emdash', 'quotedblleft',
  136. 'quotedblright', 'quoteleft', 'quoteright', 'divide', 'lozenge', 'ydieresis', 'Ydieresis', 'fraction',
  137. 'currency', 'guilsinglleft', 'guilsinglright', 'fi', 'fl', 'daggerdbl', 'periodcentered', 'quotesinglbase',
  138. 'quotedblbase', 'perthousand', 'Acircumflex', 'Ecircumflex', 'Aacute', 'Edieresis', 'Egrave', 'Iacute',
  139. 'Icircumflex', 'Idieresis', 'Igrave', 'Oacute', 'Ocircumflex', 'apple', 'Ograve', 'Uacute', 'Ucircumflex',
  140. 'Ugrave', 'dotlessi', 'circumflex', 'tilde', 'macron', 'breve', 'dotaccent', 'ring', 'cedilla', 'hungarumlaut',
  141. 'ogonek', 'caron', 'Lslash', 'lslash', 'Scaron', 'scaron', 'Zcaron', 'zcaron', 'brokenbar', 'Eth', 'eth',
  142. 'Yacute', 'yacute', 'Thorn', 'thorn', 'minus', 'multiply', 'onesuperior', 'twosuperior', 'threesuperior',
  143. 'onehalf', 'onequarter', 'threequarters', 'franc', 'Gbreve', 'gbreve', 'Idotaccent', 'Scedilla', 'scedilla',
  144. 'Cacute', 'cacute', 'Ccaron', 'ccaron', 'dcroat'];
  145. // This is the encoding used for fonts created from scratch.
  146. // It loops through all glyphs and finds the appropriate unicode value.
  147. // Since it's linear time, other encodings will be faster.
  148. function DefaultEncoding(font) {
  149. this.font = font;
  150. }
  151. DefaultEncoding.prototype.charToGlyphIndex = function(c) {
  152. var code = c.charCodeAt(0);
  153. var glyphs = this.font.glyphs;
  154. if (glyphs) {
  155. for (var i = 0; i < glyphs.length; i += 1) {
  156. var glyph = glyphs.get(i);
  157. for (var j = 0; j < glyph.unicodes.length; j += 1) {
  158. if (glyph.unicodes[j] === code) {
  159. return i;
  160. }
  161. }
  162. }
  163. } else {
  164. return null;
  165. }
  166. };
  167. function CmapEncoding(cmap) {
  168. this.cmap = cmap;
  169. }
  170. CmapEncoding.prototype.charToGlyphIndex = function(c) {
  171. return this.cmap.glyphIndexMap[c.charCodeAt(0)] || 0;
  172. };
  173. function CffEncoding(encoding, charset) {
  174. this.encoding = encoding;
  175. this.charset = charset;
  176. }
  177. CffEncoding.prototype.charToGlyphIndex = function(s) {
  178. var code = s.charCodeAt(0);
  179. var charName = this.encoding[code];
  180. return this.charset.indexOf(charName);
  181. };
  182. function GlyphNames(post) {
  183. var i;
  184. switch (post.version) {
  185. case 1:
  186. this.names = exports.standardNames.slice();
  187. break;
  188. case 2:
  189. this.names = new Array(post.numberOfGlyphs);
  190. for (i = 0; i < post.numberOfGlyphs; i++) {
  191. if (post.glyphNameIndex[i] < exports.standardNames.length) {
  192. this.names[i] = exports.standardNames[post.glyphNameIndex[i]];
  193. } else {
  194. this.names[i] = post.names[post.glyphNameIndex[i] - exports.standardNames.length];
  195. }
  196. }
  197. break;
  198. case 2.5:
  199. this.names = new Array(post.numberOfGlyphs);
  200. for (i = 0; i < post.numberOfGlyphs; i++) {
  201. this.names[i] = exports.standardNames[i + post.glyphNameIndex[i]];
  202. }
  203. break;
  204. case 3:
  205. this.names = [];
  206. break;
  207. }
  208. }
  209. GlyphNames.prototype.nameToGlyphIndex = function(name) {
  210. return this.names.indexOf(name);
  211. };
  212. GlyphNames.prototype.glyphIndexToName = function(gid) {
  213. return this.names[gid];
  214. };
  215. function addGlyphNames(font) {
  216. var glyph;
  217. var glyphIndexMap = font.tables.cmap.glyphIndexMap;
  218. var charCodes = Object.keys(glyphIndexMap);
  219. for (var i = 0; i < charCodes.length; i += 1) {
  220. var c = charCodes[i];
  221. var glyphIndex = glyphIndexMap[c];
  222. glyph = font.glyphs.get(glyphIndex);
  223. glyph.addUnicode(parseInt(c));
  224. }
  225. for (i = 0; i < font.glyphs.length; i += 1) {
  226. glyph = font.glyphs.get(i);
  227. if (font.cffEncoding) {
  228. glyph.name = font.cffEncoding.charset[i];
  229. } else {
  230. glyph.name = font.glyphNames.glyphIndexToName(i);
  231. }
  232. }
  233. }
  234. exports.cffStandardStrings = cffStandardStrings;
  235. exports.cffStandardEncoding = cffStandardEncoding;
  236. exports.cffExpertEncoding = cffExpertEncoding;
  237. exports.standardNames = standardNames;
  238. exports.DefaultEncoding = DefaultEncoding;
  239. exports.CmapEncoding = CmapEncoding;
  240. exports.CffEncoding = CffEncoding;
  241. exports.GlyphNames = GlyphNames;
  242. exports.addGlyphNames = addGlyphNames;
  243. },{}],5:[function(_dereq_,module,exports){
  244. // The Font object
  245. 'use strict';
  246. var path = _dereq_('./path');
  247. var sfnt = _dereq_('./tables/sfnt');
  248. var encoding = _dereq_('./encoding');
  249. var glyphset = _dereq_('./glyphset');
  250. // A Font represents a loaded OpenType font file.
  251. // It contains a set of glyphs and methods to draw text on a drawing context,
  252. // or to get a path representing the text.
  253. function Font(options) {
  254. options = options || {};
  255. // OS X will complain if the names are empty, so we put a single space everywhere by default.
  256. this.familyName = options.familyName || ' ';
  257. this.styleName = options.styleName || ' ';
  258. this.designer = options.designer || ' ';
  259. this.designerURL = options.designerURL || ' ';
  260. this.manufacturer = options.manufacturer || ' ';
  261. this.manufacturerURL = options.manufacturerURL || ' ';
  262. this.license = options.license || ' ';
  263. this.licenseURL = options.licenseURL || ' ';
  264. this.version = options.version || 'Version 0.1';
  265. this.description = options.description || ' ';
  266. this.copyright = options.copyright || ' ';
  267. this.trademark = options.trademark || ' ';
  268. this.unitsPerEm = options.unitsPerEm || 1000;
  269. this.ascender = options.ascender;
  270. this.descender = options.descender;
  271. this.supported = true;
  272. this.glyphs = new glyphset.GlyphSet(this, options.glyphs || []);
  273. this.encoding = new encoding.DefaultEncoding(this);
  274. this.tables = {};
  275. }
  276. // Check if the font has a glyph for the given character.
  277. Font.prototype.hasChar = function(c) {
  278. return this.encoding.charToGlyphIndex(c) !== null;
  279. };
  280. // Convert the given character to a single glyph index.
  281. // Note that this function assumes that there is a one-to-one mapping between
  282. // the given character and a glyph; for complex scripts this might not be the case.
  283. Font.prototype.charToGlyphIndex = function(s) {
  284. return this.encoding.charToGlyphIndex(s);
  285. };
  286. // Convert the given character to a single Glyph object.
  287. // Note that this function assumes that there is a one-to-one mapping between
  288. // the given character and a glyph; for complex scripts this might not be the case.
  289. Font.prototype.charToGlyph = function(c) {
  290. var glyphIndex = this.charToGlyphIndex(c);
  291. var glyph = this.glyphs.get(glyphIndex);
  292. if (!glyph) {
  293. // .notdef
  294. glyph = this.glyphs.get(0);
  295. }
  296. return glyph;
  297. };
  298. // Convert the given text to a list of Glyph objects.
  299. // Note that there is no strict one-to-one mapping between characters and
  300. // glyphs, so the list of returned glyphs can be larger or smaller than the
  301. // length of the given string.
  302. Font.prototype.stringToGlyphs = function(s) {
  303. var glyphs = [];
  304. for (var i = 0; i < s.length; i += 1) {
  305. var c = s[i];
  306. glyphs.push(this.charToGlyph(c));
  307. }
  308. return glyphs;
  309. };
  310. Font.prototype.nameToGlyphIndex = function(name) {
  311. return this.glyphNames.nameToGlyphIndex(name);
  312. };
  313. Font.prototype.nameToGlyph = function(name) {
  314. var glyphIndex = this.nametoGlyphIndex(name);
  315. var glyph = this.glyphs.get(glyphIndex);
  316. if (!glyph) {
  317. // .notdef
  318. glyph = this.glyphs.get(0);
  319. }
  320. return glyph;
  321. };
  322. Font.prototype.glyphIndexToName = function(gid) {
  323. if (!this.glyphNames.glyphIndexToName) {
  324. return '';
  325. }
  326. return this.glyphNames.glyphIndexToName(gid);
  327. };
  328. // Retrieve the value of the kerning pair between the left glyph (or its index)
  329. // and the right glyph (or its index). If no kerning pair is found, return 0.
  330. // The kerning value gets added to the advance width when calculating the spacing
  331. // between glyphs.
  332. Font.prototype.getKerningValue = function(leftGlyph, rightGlyph) {
  333. leftGlyph = leftGlyph.index || leftGlyph;
  334. rightGlyph = rightGlyph.index || rightGlyph;
  335. var gposKerning = this.getGposKerningValue;
  336. return gposKerning ? gposKerning(leftGlyph, rightGlyph) :
  337. (this.kerningPairs[leftGlyph + ',' + rightGlyph] || 0);
  338. };
  339. // Helper function that invokes the given callback for each glyph in the given text.
  340. // The callback gets `(glyph, x, y, fontSize, options)`.
  341. Font.prototype.forEachGlyph = function(text, x, y, fontSize, options, callback) {
  342. if (!this.supported) {
  343. return;
  344. }
  345. x = x !== undefined ? x : 0;
  346. y = y !== undefined ? y : 0;
  347. fontSize = fontSize !== undefined ? fontSize : 72;
  348. options = options || {};
  349. var kerning = options.kerning === undefined ? true : options.kerning;
  350. var fontScale = 1 / this.unitsPerEm * fontSize;
  351. var glyphs = this.stringToGlyphs(text);
  352. for (var i = 0; i < glyphs.length; i += 1) {
  353. var glyph = glyphs[i];
  354. callback(glyph, x, y, fontSize, options);
  355. if (glyph.advanceWidth) {
  356. x += glyph.advanceWidth * fontScale;
  357. }
  358. if (kerning && i < glyphs.length - 1) {
  359. var kerningValue = this.getKerningValue(glyph, glyphs[i + 1]);
  360. x += kerningValue * fontScale;
  361. }
  362. }
  363. };
  364. // Create a Path object that represents the given text.
  365. //
  366. // text - The text to create.
  367. // x - Horizontal position of the beginning of the text. (default: 0)
  368. // y - Vertical position of the *baseline* of the text. (default: 0)
  369. // fontSize - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. (default: 72)
  370. // Options is an optional object that contains:
  371. // - kerning - Whether to take kerning information into account. (default: true)
  372. //
  373. // Returns a Path object.
  374. Font.prototype.getPath = function(text, x, y, fontSize, options) {
  375. var fullPath = new path.Path();
  376. this.forEachGlyph(text, x, y, fontSize, options, function(glyph, gX, gY, gFontSize) {
  377. var glyphPath = glyph.getPath(gX, gY, gFontSize);
  378. fullPath.extend(glyphPath);
  379. });
  380. return fullPath;
  381. };
  382. // Draw the text on the given drawing context.
  383. //
  384. // ctx - A 2D drawing context, like Canvas.
  385. // text - The text to create.
  386. // x - Horizontal position of the beginning of the text. (default: 0)
  387. // y - Vertical position of the *baseline* of the text. (default: 0)
  388. // fontSize - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. (default: 72)
  389. // Options is an optional object that contains:
  390. // - kerning - Whether to take kerning information into account. (default: true)
  391. Font.prototype.draw = function(ctx, text, x, y, fontSize, options) {
  392. this.getPath(text, x, y, fontSize, options).draw(ctx);
  393. };
  394. // Draw the points of all glyphs in the text.
  395. // On-curve points will be drawn in blue, off-curve points will be drawn in red.
  396. //
  397. // ctx - A 2D drawing context, like Canvas.
  398. // text - The text to create.
  399. // x - Horizontal position of the beginning of the text. (default: 0)
  400. // y - Vertical position of the *baseline* of the text. (default: 0)
  401. // fontSize - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. (default: 72)
  402. // Options is an optional object that contains:
  403. // - kerning - Whether to take kerning information into account. (default: true)
  404. Font.prototype.drawPoints = function(ctx, text, x, y, fontSize, options) {
  405. this.forEachGlyph(text, x, y, fontSize, options, function(glyph, gX, gY, gFontSize) {
  406. glyph.drawPoints(ctx, gX, gY, gFontSize);
  407. });
  408. };
  409. // Draw lines indicating important font measurements for all glyphs in the text.
  410. // Black lines indicate the origin of the coordinate system (point 0,0).
  411. // Blue lines indicate the glyph bounding box.
  412. // Green line indicates the advance width of the glyph.
  413. //
  414. // ctx - A 2D drawing context, like Canvas.
  415. // text - The text to create.
  416. // x - Horizontal position of the beginning of the text. (default: 0)
  417. // y - Vertical position of the *baseline* of the text. (default: 0)
  418. // fontSize - Font size in pixels. We scale the glyph units by `1 / unitsPerEm * fontSize`. (default: 72)
  419. // Options is an optional object that contains:
  420. // - kerning - Whether to take kerning information into account. (default: true)
  421. Font.prototype.drawMetrics = function(ctx, text, x, y, fontSize, options) {
  422. this.forEachGlyph(text, x, y, fontSize, options, function(glyph, gX, gY, gFontSize) {
  423. glyph.drawMetrics(ctx, gX, gY, gFontSize);
  424. });
  425. };
  426. // Validate
  427. Font.prototype.validate = function() {
  428. var warnings = [];
  429. var _this = this;
  430. function assert(predicate, message) {
  431. if (!predicate) {
  432. warnings.push(message);
  433. }
  434. }
  435. function assertStringAttribute(attrName) {
  436. assert(_this[attrName] && _this[attrName].trim().length > 0, 'No ' + attrName + ' specified.');
  437. }
  438. // Identification information
  439. assertStringAttribute('familyName');
  440. assertStringAttribute('weightName');
  441. assertStringAttribute('manufacturer');
  442. assertStringAttribute('copyright');
  443. assertStringAttribute('version');
  444. // Dimension information
  445. assert(this.unitsPerEm > 0, 'No unitsPerEm specified.');
  446. };
  447. // Convert the font object to a SFNT data structure.
  448. // This structure contains all the necessary tables and metadata to create a binary OTF file.
  449. Font.prototype.toTables = function() {
  450. return sfnt.fontToTable(this);
  451. };
  452. Font.prototype.toBuffer = function() {
  453. var sfntTable = this.toTables();
  454. var bytes = sfntTable.encode();
  455. var buffer = new ArrayBuffer(bytes.length);
  456. var intArray = new Uint8Array(buffer);
  457. for (var i = 0; i < bytes.length; i++) {
  458. intArray[i] = bytes[i];
  459. }
  460. return buffer;
  461. };
  462. // Initiate a download of the OpenType font.
  463. Font.prototype.download = function() {
  464. var fileName = this.familyName.replace(/\s/g, '') + '-' + this.styleName + '.otf';
  465. var buffer = this.toBuffer();
  466. window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
  467. window.requestFileSystem(window.TEMPORARY, buffer.byteLength, function(fs) {
  468. fs.root.getFile(fileName, {create: true}, function(fileEntry) {
  469. fileEntry.createWriter(function(writer) {
  470. var dataView = new DataView(buffer);
  471. var blob = new Blob([dataView], {type: 'font/opentype'});
  472. writer.write(blob);
  473. writer.addEventListener('writeend', function() {
  474. // Navigating to the file will download it.
  475. location.href = fileEntry.toURL();
  476. }, false);
  477. });
  478. });
  479. },
  480. function(err) {
  481. throw err;
  482. });
  483. };
  484. exports.Font = Font;
  485. },{"./encoding":4,"./glyphset":7,"./path":10,"./tables/sfnt":25}],6:[function(_dereq_,module,exports){
  486. // The Glyph object
  487. 'use strict';
  488. var check = _dereq_('./check');
  489. var draw = _dereq_('./draw');
  490. var path = _dereq_('./path');
  491. function getPathDefinition(glyph, path) {
  492. var _path = path || { commands: [] };
  493. return {
  494. configurable: true,
  495. get: function() {
  496. if (typeof _path === 'function') {
  497. _path = _path();
  498. }
  499. return _path;
  500. },
  501. set: function(p) {
  502. _path = p;
  503. }
  504. };
  505. }
  506. // A Glyph is an individual mark that often corresponds to a character.
  507. // Some glyphs, such as ligatures, are a combination of many characters.
  508. // Glyphs are the basic building blocks of a font.
  509. //
  510. // The `Glyph` class contains utility methods for drawing the path and its points.
  511. function Glyph(options) {
  512. // By putting all the code on a prototype function (which is only declared once)
  513. // we reduce the memory requirements for larger fonts by some 2%
  514. this.bindConstructorValues(options);
  515. }
  516. Glyph.prototype.bindConstructorValues = function(options) {
  517. this.index = options.index || 0;
  518. // These three values cannnot be deferred for memory optimization:
  519. this.name = options.name || null;
  520. this.unicode = options.unicode || undefined;
  521. this.unicodes = options.unicodes || options.unicode !== undefined ? [options.unicode] : [];
  522. // But by binding these values only when necessary, we reduce can
  523. // the memory requirements by almost 3% for larger fonts.
  524. if (options.xMin) {
  525. this.xMin = options.xMin;
  526. }
  527. if (options.yMin) {
  528. this.yMin = options.yMin;
  529. }
  530. if (options.xMax) {
  531. this.xMax = options.xMax;
  532. }
  533. if (options.yMax) {
  534. this.yMax = options.yMax;
  535. }
  536. if (options.advanceWidth) {
  537. this.advanceWidth = options.advanceWidth;
  538. }
  539. // The path for a glyph is the most memory intensive, and is bound as a value
  540. // with a getter/setter to ensure we actually do path parsing only once the
  541. // path is actually needed by anything.
  542. Object.defineProperty(this, 'path', getPathDefinition(this, options.path));
  543. };
  544. Glyph.prototype.addUnicode = function(unicode) {
  545. if (this.unicodes.length === 0) {
  546. this.unicode = unicode;
  547. }
  548. this.unicodes.push(unicode);
  549. };
  550. // Convert the glyph to a Path we can draw on a drawing context.
  551. //
  552. // x - Horizontal position of the glyph. (default: 0)
  553. // y - Vertical position of the *baseline* of the glyph. (default: 0)
  554. // fontSize - Font size, in pixels (default: 72).
  555. Glyph.prototype.getPath = function(x, y, fontSize) {
  556. x = x !== undefined ? x : 0;
  557. y = y !== undefined ? y : 0;
  558. fontSize = fontSize !== undefined ? fontSize : 72;
  559. var scale = 1 / this.path.unitsPerEm * fontSize;
  560. var p = new path.Path();
  561. var commands = this.path.commands;
  562. for (var i = 0; i < commands.length; i += 1) {
  563. var cmd = commands[i];
  564. if (cmd.type === 'M') {
  565. p.moveTo(x + (cmd.x * scale), y + (-cmd.y * scale));
  566. } else if (cmd.type === 'L') {
  567. p.lineTo(x + (cmd.x * scale), y + (-cmd.y * scale));
  568. } else if (cmd.type === 'Q') {
  569. p.quadraticCurveTo(x + (cmd.x1 * scale), y + (-cmd.y1 * scale),
  570. x + (cmd.x * scale), y + (-cmd.y * scale));
  571. } else if (cmd.type === 'C') {
  572. p.curveTo(x + (cmd.x1 * scale), y + (-cmd.y1 * scale),
  573. x + (cmd.x2 * scale), y + (-cmd.y2 * scale),
  574. x + (cmd.x * scale), y + (-cmd.y * scale));
  575. } else if (cmd.type === 'Z') {
  576. p.closePath();
  577. }
  578. }
  579. return p;
  580. };
  581. // Split the glyph into contours.
  582. // This function is here for backwards compatibility, and to
  583. // provide raw access to the TrueType glyph outlines.
  584. Glyph.prototype.getContours = function() {
  585. if (this.points === undefined) {
  586. return [];
  587. }
  588. var contours = [];
  589. var currentContour = [];
  590. for (var i = 0; i < this.points.length; i += 1) {
  591. var pt = this.points[i];
  592. currentContour.push(pt);
  593. if (pt.lastPointOfContour) {
  594. contours.push(currentContour);
  595. currentContour = [];
  596. }
  597. }
  598. check.argument(currentContour.length === 0, 'There are still points left in the current contour.');
  599. return contours;
  600. };
  601. // Calculate the xMin/yMin/xMax/yMax/lsb/rsb for a Glyph.
  602. Glyph.prototype.getMetrics = function() {
  603. var commands = this.path.commands;
  604. var xCoords = [];
  605. var yCoords = [];
  606. for (var i = 0; i < commands.length; i += 1) {
  607. var cmd = commands[i];
  608. if (cmd.type !== 'Z') {
  609. xCoords.push(cmd.x);
  610. yCoords.push(cmd.y);
  611. }
  612. if (cmd.type === 'Q' || cmd.type === 'C') {
  613. xCoords.push(cmd.x1);
  614. yCoords.push(cmd.y1);
  615. }
  616. if (cmd.type === 'C') {
  617. xCoords.push(cmd.x2);
  618. yCoords.push(cmd.y2);
  619. }
  620. }
  621. var metrics = {
  622. xMin: Math.min.apply(null, xCoords),
  623. yMin: Math.min.apply(null, yCoords),
  624. xMax: Math.max.apply(null, xCoords),
  625. yMax: Math.max.apply(null, yCoords),
  626. leftSideBearing: 0
  627. };
  628. metrics.rightSideBearing = this.advanceWidth - metrics.leftSideBearing - (metrics.xMax - metrics.xMin);
  629. return metrics;
  630. };
  631. // Draw the glyph on the given context.
  632. //
  633. // ctx - The drawing context.
  634. // x - Horizontal position of the glyph. (default: 0)
  635. // y - Vertical position of the *baseline* of the glyph. (default: 0)
  636. // fontSize - Font size, in pixels (default: 72).
  637. Glyph.prototype.draw = function(ctx, x, y, fontSize) {
  638. this.getPath(x, y, fontSize).draw(ctx);
  639. };
  640. // Draw the points of the glyph.
  641. // On-curve points will be drawn in blue, off-curve points will be drawn in red.
  642. //
  643. // ctx - The drawing context.
  644. // x - Horizontal position of the glyph. (default: 0)
  645. // y - Vertical position of the *baseline* of the glyph. (default: 0)
  646. // fontSize - Font size, in pixels (default: 72).
  647. Glyph.prototype.drawPoints = function(ctx, x, y, fontSize) {
  648. function drawCircles(l, x, y, scale) {
  649. var PI_SQ = Math.PI * 2;
  650. ctx.beginPath();
  651. for (var j = 0; j < l.length; j += 1) {
  652. ctx.moveTo(x + (l[j].x * scale), y + (l[j].y * scale));
  653. ctx.arc(x + (l[j].x * scale), y + (l[j].y * scale), 2, 0, PI_SQ, false);
  654. }
  655. ctx.closePath();
  656. ctx.fill();
  657. }
  658. x = x !== undefined ? x : 0;
  659. y = y !== undefined ? y : 0;
  660. fontSize = fontSize !== undefined ? fontSize : 24;
  661. var scale = 1 / this.path.unitsPerEm * fontSize;
  662. var blueCircles = [];
  663. var redCircles = [];
  664. var path = this.path;
  665. for (var i = 0; i < path.commands.length; i += 1) {
  666. var cmd = path.commands[i];
  667. if (cmd.x !== undefined) {
  668. blueCircles.push({x: cmd.x, y: -cmd.y});
  669. }
  670. if (cmd.x1 !== undefined) {
  671. redCircles.push({x: cmd.x1, y: -cmd.y1});
  672. }
  673. if (cmd.x2 !== undefined) {
  674. redCircles.push({x: cmd.x2, y: -cmd.y2});
  675. }
  676. }
  677. ctx.fillStyle = 'blue';
  678. drawCircles(blueCircles, x, y, scale);
  679. ctx.fillStyle = 'red';
  680. drawCircles(redCircles, x, y, scale);
  681. };
  682. // Draw lines indicating important font measurements.
  683. // Black lines indicate the origin of the coordinate system (point 0,0).
  684. // Blue lines indicate the glyph bounding box.
  685. // Green line indicates the advance width of the glyph.
  686. //
  687. // ctx - The drawing context.
  688. // x - Horizontal position of the glyph. (default: 0)
  689. // y - Vertical position of the *baseline* of the glyph. (default: 0)
  690. // fontSize - Font size, in pixels (default: 72).
  691. Glyph.prototype.drawMetrics = function(ctx, x, y, fontSize) {
  692. var scale;
  693. x = x !== undefined ? x : 0;
  694. y = y !== undefined ? y : 0;
  695. fontSize = fontSize !== undefined ? fontSize : 24;
  696. scale = 1 / this.path.unitsPerEm * fontSize;
  697. ctx.lineWidth = 1;
  698. // Draw the origin
  699. ctx.strokeStyle = 'black';
  700. draw.line(ctx, x, -10000, x, 10000);
  701. draw.line(ctx, -10000, y, 10000, y);
  702. // This code is here due to memory optimization: by not using
  703. // defaults in the constructor, we save a notable amount of memory.
  704. var xMin = this.xMin || 0;
  705. var yMin = this.yMin || 0;
  706. var xMax = this.xMax || 0;
  707. var yMax = this.yMax || 0;
  708. var advanceWidth = this.advanceWidth || 0;
  709. // Draw the glyph box
  710. ctx.strokeStyle = 'blue';
  711. draw.line(ctx, x + (xMin * scale), -10000, x + (xMin * scale), 10000);
  712. draw.line(ctx, x + (xMax * scale), -10000, x + (xMax * scale), 10000);
  713. draw.line(ctx, -10000, y + (-yMin * scale), 10000, y + (-yMin * scale));
  714. draw.line(ctx, -10000, y + (-yMax * scale), 10000, y + (-yMax * scale));
  715. // Draw the advance width
  716. ctx.strokeStyle = 'green';
  717. draw.line(ctx, x + (advanceWidth * scale), -10000, x + (advanceWidth * scale), 10000);
  718. };
  719. exports.Glyph = Glyph;
  720. },{"./check":2,"./draw":3,"./path":10}],7:[function(_dereq_,module,exports){
  721. // The GlyphSet object
  722. 'use strict';
  723. var _glyph = _dereq_('./glyph');
  724. // A GlyphSet represents all glyphs available in the font, but modelled using
  725. // a deferred glyph loader, for retrieving glyphs only once they are absolutely
  726. // necessary, to keep the memory footprint down.
  727. function GlyphSet(font, glyphs) {
  728. this.font = font;
  729. this.glyphs = {};
  730. if (Array.isArray(glyphs)) {
  731. for (var i = 0; i < glyphs.length; i++) {
  732. this.glyphs[i] = glyphs[i];
  733. }
  734. }
  735. this.length = (glyphs && glyphs.length) || 0;
  736. }
  737. GlyphSet.prototype.get = function(index) {
  738. if (typeof this.glyphs[index] === 'function') {
  739. this.glyphs[index] = this.glyphs[index]();
  740. }
  741. return this.glyphs[index];
  742. };
  743. GlyphSet.prototype.push = function(index, loader) {
  744. this.glyphs[index] = loader;
  745. this.length++;
  746. };
  747. function glyphLoader(font, index) {
  748. return new _glyph.Glyph({index: index, font: font});
  749. }
  750. /**
  751. * Generate a stub glyph that can be filled with all metadata *except*
  752. * the "points" and "path" properties, which must be loaded only once
  753. * the glyph's path is actually requested for text shaping.
  754. */
  755. function ttfGlyphLoader(font, index, parseGlyph, data, position, buildPath) {
  756. return function() {
  757. var glyph = new _glyph.Glyph({index: index, font: font});
  758. glyph.path = function() {
  759. parseGlyph(glyph, data, position);
  760. var path = buildPath(font.glyphs, glyph);
  761. path.unitsPerEm = font.unitsPerEm;
  762. return path;
  763. };
  764. return glyph;
  765. };
  766. }
  767. function cffGlyphLoader(font, index, parseCFFCharstring, charstring) {
  768. return function() {
  769. var glyph = new _glyph.Glyph({index: index, font: font});
  770. glyph.path = function() {
  771. var path = parseCFFCharstring(font, glyph, charstring);
  772. path.unitsPerEm = font.unitsPerEm;
  773. return path;
  774. };
  775. return glyph;
  776. };
  777. }
  778. exports.GlyphSet = GlyphSet;
  779. exports.glyphLoader = glyphLoader;
  780. exports.ttfGlyphLoader = ttfGlyphLoader;
  781. exports.cffGlyphLoader = cffGlyphLoader;
  782. },{"./glyph":6}],8:[function(_dereq_,module,exports){
  783. // opentype.js
  784. // https://github.com/nodebox/opentype.js
  785. // (c) 2015 Frederik De Bleser
  786. // opentype.js may be freely distributed under the MIT license.
  787. /* global ArrayBuffer, DataView, Uint8Array, XMLHttpRequest */
  788. 'use strict';
  789. var encoding = _dereq_('./encoding');
  790. var _font = _dereq_('./font');
  791. var glyph = _dereq_('./glyph');
  792. var parse = _dereq_('./parse');
  793. var path = _dereq_('./path');
  794. var cmap = _dereq_('./tables/cmap');
  795. var cff = _dereq_('./tables/cff');
  796. var glyf = _dereq_('./tables/glyf');
  797. var gpos = _dereq_('./tables/gpos');
  798. var head = _dereq_('./tables/head');
  799. var hhea = _dereq_('./tables/hhea');
  800. var hmtx = _dereq_('./tables/hmtx');
  801. var kern = _dereq_('./tables/kern');
  802. var loca = _dereq_('./tables/loca');
  803. var maxp = _dereq_('./tables/maxp');
  804. var _name = _dereq_('./tables/name');
  805. var os2 = _dereq_('./tables/os2');
  806. var post = _dereq_('./tables/post');
  807. // File loaders /////////////////////////////////////////////////////////
  808. // Convert a Node.js Buffer to an ArrayBuffer
  809. function toArrayBuffer(buffer) {
  810. var arrayBuffer = new ArrayBuffer(buffer.length);
  811. var data = new Uint8Array(arrayBuffer);
  812. for (var i = 0; i < buffer.length; i += 1) {
  813. data[i] = buffer[i];
  814. }
  815. return arrayBuffer;
  816. }
  817. function loadFromFile(path, callback) {
  818. var fs = _dereq_('fs');
  819. fs.readFile(path, function(err, buffer) {
  820. if (err) {
  821. return callback(err.message);
  822. }
  823. callback(null, toArrayBuffer(buffer));
  824. });
  825. }
  826. function loadFromUrl(url, callback) {
  827. var request = new XMLHttpRequest();
  828. request.open('get', url, true);
  829. request.responseType = 'arraybuffer';
  830. request.onload = function() {
  831. if (request.status !== 200) {
  832. return callback('Font could not be loaded: ' + request.statusText);
  833. }
  834. return callback(null, request.response);
  835. };
  836. request.send();
  837. }
  838. // Public API ///////////////////////////////////////////////////////////
  839. // Parse the OpenType file data (as an ArrayBuffer) and return a Font object.
  840. // If the file could not be parsed (most likely because it contains Postscript outlines)
  841. // we return an empty Font object with the `supported` flag set to `false`.
  842. function parseBuffer(buffer) {
  843. var indexToLocFormat;
  844. var hmtxOffset;
  845. var glyfOffset;
  846. var locaOffset;
  847. var cffOffset;
  848. var kernOffset;
  849. var gposOffset;
  850. // OpenType fonts use big endian byte ordering.
  851. // We can't rely on typed array view types, because they operate with the endianness of the host computer.
  852. // Instead we use DataViews where we can specify endianness.
  853. var font = new _font.Font();
  854. var data = new DataView(buffer, 0);
  855. var version = parse.getFixed(data, 0);
  856. if (version === 1.0) {
  857. font.outlinesFormat = 'truetype';
  858. } else {
  859. version = parse.getTag(data, 0);
  860. if (version === 'OTTO') {
  861. font.outlinesFormat = 'cff';
  862. } else {
  863. throw new Error('Unsupported OpenType version ' + version);
  864. }
  865. }
  866. var numTables = parse.getUShort(data, 4);
  867. // Offset into the table records.
  868. var p = 12;
  869. for (var i = 0; i < numTables; i += 1) {
  870. var tag = parse.getTag(data, p);
  871. var offset = parse.getULong(data, p + 8);
  872. switch (tag) {
  873. case 'cmap':
  874. font.tables.cmap = cmap.parse(data, offset);
  875. font.encoding = new encoding.CmapEncoding(font.tables.cmap);
  876. if (!font.encoding) {
  877. font.supported = false;
  878. }
  879. break;
  880. case 'head':
  881. font.tables.head = head.parse(data, offset);
  882. font.unitsPerEm = font.tables.head.unitsPerEm;
  883. indexToLocFormat = font.tables.head.indexToLocFormat;
  884. break;
  885. case 'hhea':
  886. font.tables.hhea = hhea.parse(data, offset);
  887. font.ascender = font.tables.hhea.ascender;
  888. font.descender = font.tables.hhea.descender;
  889. font.numberOfHMetrics = font.tables.hhea.numberOfHMetrics;
  890. break;
  891. case 'hmtx':
  892. hmtxOffset = offset;
  893. break;
  894. case 'maxp':
  895. font.tables.maxp = maxp.parse(data, offset);
  896. font.numGlyphs = font.tables.maxp.numGlyphs;
  897. break;
  898. case 'name':
  899. font.tables.name = _name.parse(data, offset);
  900. font.familyName = font.tables.name.fontFamily;
  901. font.styleName = font.tables.name.fontSubfamily;
  902. break;
  903. case 'OS/2':
  904. font.tables.os2 = os2.parse(data, offset);
  905. break;
  906. case 'post':
  907. font.tables.post = post.parse(data, offset);
  908. font.glyphNames = new encoding.GlyphNames(font.tables.post);
  909. break;
  910. case 'glyf':
  911. glyfOffset = offset;
  912. break;
  913. case 'loca':
  914. locaOffset = offset;
  915. break;
  916. case 'CFF ':
  917. cffOffset = offset;
  918. break;
  919. case 'kern':
  920. kernOffset = offset;
  921. break;
  922. case 'GPOS':
  923. gposOffset = offset;
  924. break;
  925. }
  926. p += 16;
  927. }
  928. if (glyfOffset && locaOffset) {
  929. var shortVersion = indexToLocFormat === 0;
  930. var locaTable = loca.parse(data, locaOffset, font.numGlyphs, shortVersion);
  931. font.glyphs = glyf.parse(data, glyfOffset, locaTable, font);
  932. hmtx.parse(data, hmtxOffset, font.numberOfHMetrics, font.numGlyphs, font.glyphs);
  933. encoding.addGlyphNames(font);
  934. } else if (cffOffset) {
  935. cff.parse(data, cffOffset, font);
  936. encoding.addGlyphNames(font);
  937. } else {
  938. font.supported = false;
  939. }
  940. if (font.supported) {
  941. if (kernOffset) {
  942. font.kerningPairs = kern.parse(data, kernOffset);
  943. } else {
  944. font.kerningPairs = {};
  945. }
  946. if (gposOffset) {
  947. gpos.parse(data, gposOffset, font);
  948. }
  949. }
  950. return font;
  951. }
  952. // Asynchronously load the font from a URL or a filesystem. When done, call the callback
  953. // with two arguments `(err, font)`. The `err` will be null on success,
  954. // the `font` is a Font object.
  955. //
  956. // We use the node.js callback convention so that
  957. // opentype.js can integrate with frameworks like async.js.
  958. function load(url, callback) {
  959. var isNode = typeof window === 'undefined';
  960. var loadFn = isNode ? loadFromFile : loadFromUrl;
  961. loadFn(url, function(err, arrayBuffer) {
  962. if (err) {
  963. return callback(err);
  964. }
  965. var font = parseBuffer(arrayBuffer);
  966. if (!font.supported) {
  967. return callback('Font is not supported (is this a Postscript font?)');
  968. }
  969. return callback(null, font);
  970. });
  971. }
  972. exports._parse = parse;
  973. exports.Font = _font.Font;
  974. exports.Glyph = glyph.Glyph;
  975. exports.Path = path.Path;
  976. exports.parse = parseBuffer;
  977. exports.load = load;
  978. },{"./encoding":4,"./font":5,"./glyph":6,"./parse":9,"./path":10,"./tables/cff":12,"./tables/cmap":13,"./tables/glyf":14,"./tables/gpos":15,"./tables/head":16,"./tables/hhea":17,"./tables/hmtx":18,"./tables/kern":19,"./tables/loca":20,"./tables/maxp":21,"./tables/name":22,"./tables/os2":23,"./tables/post":24,"fs":1}],9:[function(_dereq_,module,exports){
  979. // Parsing utility functions
  980. 'use strict';
  981. // Retrieve an unsigned byte from the DataView.
  982. exports.getByte = function getByte(dataView, offset) {
  983. return dataView.getUint8(offset);
  984. };
  985. exports.getCard8 = exports.getByte;
  986. // Retrieve an unsigned 16-bit short from the DataView.
  987. // The value is stored in big endian.
  988. exports.getUShort = function(dataView, offset) {
  989. return dataView.getUint16(offset, false);
  990. };
  991. exports.getCard16 = exports.getUShort;
  992. // Retrieve a signed 16-bit short from the DataView.
  993. // The value is stored in big endian.
  994. exports.getShort = function(dataView, offset) {
  995. return dataView.getInt16(offset, false);
  996. };
  997. // Retrieve an unsigned 32-bit long from the DataView.
  998. // The value is stored in big endian.
  999. exports.getULong = function(dataView, offset) {
  1000. return dataView.getUint32(offset, false);
  1001. };
  1002. // Retrieve a 32-bit signed fixed-point number (16.16) from the DataView.
  1003. // The value is stored in big endian.
  1004. exports.getFixed = function(dataView, offset) {
  1005. var decimal = dataView.getInt16(offset, false);
  1006. var fraction = dataView.getUint16(offset + 2, false);
  1007. return decimal + fraction / 65535;
  1008. };
  1009. // Retrieve a 4-character tag from the DataView.
  1010. // Tags are used to identify tables.
  1011. exports.getTag = function(dataView, offset) {
  1012. var tag = '';
  1013. for (var i = offset; i < offset + 4; i += 1) {
  1014. tag += String.fromCharCode(dataView.getInt8(i));
  1015. }
  1016. return tag;
  1017. };
  1018. // Retrieve an offset from the DataView.
  1019. // Offsets are 1 to 4 bytes in length, depending on the offSize argument.
  1020. exports.getOffset = function(dataView, offset, offSize) {
  1021. var v = 0;
  1022. for (var i = 0; i < offSize; i += 1) {
  1023. v <<= 8;
  1024. v += dataView.getUint8(offset + i);
  1025. }
  1026. return v;
  1027. };
  1028. // Retrieve a number of bytes from start offset to the end offset from the DataView.
  1029. exports.getBytes = function(dataView, startOffset, endOffset) {
  1030. var bytes = [];
  1031. for (var i = startOffset; i < endOffset; i += 1) {
  1032. bytes.push(dataView.getUint8(i));
  1033. }
  1034. return bytes;
  1035. };
  1036. // Convert the list of bytes to a string.
  1037. exports.bytesToString = function(bytes) {
  1038. var s = '';
  1039. for (var i = 0; i < bytes.length; i += 1) {
  1040. s += String.fromCharCode(bytes[i]);
  1041. }
  1042. return s;
  1043. };
  1044. var typeOffsets = {
  1045. byte: 1,
  1046. uShort: 2,
  1047. short: 2,
  1048. uLong: 4,
  1049. fixed: 4,
  1050. longDateTime: 8,
  1051. tag: 4
  1052. };
  1053. // A stateful parser that changes the offset whenever a value is retrieved.
  1054. // The data is a DataView.
  1055. function Parser(data, offset) {
  1056. this.data = data;
  1057. this.offset = offset;
  1058. this.relativeOffset = 0;
  1059. }
  1060. Parser.prototype.parseByte = function() {
  1061. var v = this.data.getUint8(this.offset + this.relativeOffset);
  1062. this.relativeOffset += 1;
  1063. return v;
  1064. };
  1065. Parser.prototype.parseChar = function() {
  1066. var v = this.data.getInt8(this.offset + this.relativeOffset);
  1067. this.relativeOffset += 1;
  1068. return v;
  1069. };
  1070. Parser.prototype.parseCard8 = Parser.prototype.parseByte;
  1071. Parser.prototype.parseUShort = function() {
  1072. var v = this.data.getUint16(this.offset + this.relativeOffset);
  1073. this.relativeOffset += 2;
  1074. return v;
  1075. };
  1076. Parser.prototype.parseCard16 = Parser.prototype.parseUShort;
  1077. Parser.prototype.parseSID = Parser.prototype.parseUShort;
  1078. Parser.prototype.parseOffset16 = Parser.prototype.parseUShort;
  1079. Parser.prototype.parseShort = function() {
  1080. var v = this.data.getInt16(this.offset + this.relativeOffset);
  1081. this.relativeOffset += 2;
  1082. return v;
  1083. };
  1084. Parser.prototype.parseF2Dot14 = function() {
  1085. var v = this.data.getInt16(this.offset + this.relativeOffset) / 16384;
  1086. this.relativeOffset += 2;
  1087. return v;
  1088. };
  1089. Parser.prototype.parseULong = function() {
  1090. var v = exports.getULong(this.data, this.offset + this.relativeOffset);
  1091. this.relativeOffset += 4;
  1092. return v;
  1093. };
  1094. Parser.prototype.parseFixed = function() {
  1095. var v = exports.getFixed(this.data, this.offset + this.relativeOffset);
  1096. this.relativeOffset += 4;
  1097. return v;
  1098. };
  1099. Parser.prototype.parseOffset16List =
  1100. Parser.prototype.parseUShortList = function(count) {
  1101. var offsets = new Array(count);
  1102. var dataView = this.data;
  1103. var offset = this.offset + this.relativeOffset;
  1104. for (var i = 0; i < count; i++) {
  1105. offsets[i] = exports.getUShort(dataView, offset);
  1106. offset += 2;
  1107. }
  1108. this.relativeOffset += count * 2;
  1109. return offsets;
  1110. };
  1111. Parser.prototype.parseString = function(length) {
  1112. var dataView = this.data;
  1113. var offset = this.offset + this.relativeOffset;
  1114. var string = '';
  1115. this.relativeOffset += length;
  1116. for (var i = 0; i < length; i++) {
  1117. string += String.fromCharCode(dataView.getUint8(offset + i));
  1118. }
  1119. return string;
  1120. };
  1121. Parser.prototype.parseTag = function() {
  1122. return this.parseString(4);
  1123. };
  1124. // LONGDATETIME is a 64-bit integer.
  1125. // JavaScript and unix timestamps traditionally use 32 bits, so we
  1126. // only take the last 32 bits.
  1127. Parser.prototype.parseLongDateTime = function() {
  1128. var v = exports.getULong(this.data, this.offset + this.relativeOffset + 4);
  1129. this.relativeOffset += 8;
  1130. return v;
  1131. };
  1132. Parser.prototype.parseFixed = function() {
  1133. var v = exports.getULong(this.data, this.offset + this.relativeOffset);
  1134. this.relativeOffset += 4;
  1135. return v / 65536;
  1136. };
  1137. Parser.prototype.parseVersion = function() {
  1138. var major = exports.getUShort(this.data, this.offset + this.relativeOffset);
  1139. // How to interpret the minor version is very vague in the spec. 0x5000 is 5, 0x1000 is 1
  1140. // This returns the correct number if minor = 0xN000 where N is 0-9
  1141. var minor = exports.getUShort(this.data, this.offset + this.relativeOffset + 2);
  1142. this.relativeOffset += 4;
  1143. return major + minor / 0x1000 / 10;
  1144. };
  1145. Parser.prototype.skip = function(type, amount) {
  1146. if (amount === undefined) {
  1147. amount = 1;
  1148. }
  1149. this.relativeOffset += typeOffsets[type] * amount;
  1150. };
  1151. exports.Parser = Parser;
  1152. },{}],10:[function(_dereq_,module,exports){
  1153. // Geometric objects
  1154. 'use strict';
  1155. // A bézier path containing a set of path commands similar to a SVG path.
  1156. // Paths can be drawn on a context using `draw`.
  1157. function Path() {
  1158. this.commands = [];
  1159. this.fill = 'black';
  1160. this.stroke = null;
  1161. this.strokeWidth = 1;
  1162. }
  1163. Path.prototype.moveTo = function(x, y) {
  1164. this.commands.push({
  1165. type: 'M',
  1166. x: x,
  1167. y: y
  1168. });
  1169. };
  1170. Path.prototype.lineTo = function(x, y) {
  1171. this.commands.push({
  1172. type: 'L',
  1173. x: x,
  1174. y: y
  1175. });
  1176. };
  1177. Path.prototype.curveTo = Path.prototype.bezierCurveTo = function(x1, y1, x2, y2, x, y) {
  1178. this.commands.push({
  1179. type: 'C',
  1180. x1: x1,
  1181. y1: y1,
  1182. x2: x2,
  1183. y2: y2,
  1184. x: x,
  1185. y: y
  1186. });
  1187. };
  1188. Path.prototype.quadTo = Path.prototype.quadraticCurveTo = function(x1, y1, x, y) {
  1189. this.commands.push({
  1190. type: 'Q',
  1191. x1: x1,
  1192. y1: y1,
  1193. x: x,
  1194. y: y
  1195. });
  1196. };
  1197. Path.prototype.close = Path.prototype.closePath = function() {
  1198. this.commands.push({
  1199. type: 'Z'
  1200. });
  1201. };
  1202. // Add the given path or list of commands to the commands of this path.
  1203. Path.prototype.extend = function(pathOrCommands) {
  1204. if (pathOrCommands.commands) {
  1205. pathOrCommands = pathOrCommands.commands;
  1206. }
  1207. Array.prototype.push.apply(this.commands, pathOrCommands);
  1208. };
  1209. // Draw the path to a 2D context.
  1210. Path.prototype.draw = function(ctx) {
  1211. ctx.beginPath();
  1212. for (var i = 0; i < this.commands.length; i += 1) {
  1213. var cmd = this.commands[i];
  1214. if (cmd.type === 'M') {
  1215. ctx.moveTo(cmd.x, cmd.y);
  1216. } else if (cmd.type === 'L') {
  1217. ctx.lineTo(cmd.x, cmd.y);
  1218. } else if (cmd.type === 'C') {
  1219. ctx.bezierCurveTo(cmd.x1, cmd.y1, cmd.x2, cmd.y2, cmd.x, cmd.y);
  1220. } else if (cmd.type === 'Q') {
  1221. ctx.quadraticCurveTo(cmd.x1, cmd.y1, cmd.x, cmd.y);
  1222. } else if (cmd.type === 'Z') {
  1223. ctx.closePath();
  1224. }
  1225. }
  1226. if (this.fill) {
  1227. ctx.fillStyle = this.fill;
  1228. ctx.fill();
  1229. }
  1230. if (this.stroke) {
  1231. ctx.strokeStyle = this.stroke;
  1232. ctx.lineWidth = this.strokeWidth;
  1233. ctx.stroke();
  1234. }
  1235. };
  1236. // Convert the Path to a string of path data instructions
  1237. // See http://www.w3.org/TR/SVG/paths.html#PathData
  1238. // Parameters:
  1239. // - decimalPlaces: The amount of decimal places for floating-point values (default: 2)
  1240. Path.prototype.toPathData = function(decimalPlaces) {
  1241. decimalPlaces = decimalPlaces !== undefined ? decimalPlaces : 2;
  1242. function floatToString(v) {
  1243. if (Math.round(v) === v) {
  1244. return '' + Math.round(v);
  1245. } else {
  1246. return v.toFixed(decimalPlaces);
  1247. }
  1248. }
  1249. function packValues() {
  1250. var s = '';
  1251. for (var i = 0; i < arguments.length; i += 1) {
  1252. var v = arguments[i];
  1253. if (v >= 0 && i > 0) {
  1254. s += ' ';
  1255. }
  1256. s += floatToString(v);
  1257. }
  1258. return s;
  1259. }
  1260. var d = '';
  1261. for (var i = 0; i < this.commands.length; i += 1) {
  1262. var cmd = this.commands[i];
  1263. if (cmd.type === 'M') {
  1264. d += 'M' + packValues(cmd.x, cmd.y);
  1265. } else if (cmd.type === 'L') {
  1266. d += 'L' + packValues(cmd.x, cmd.y);
  1267. } else if (cmd.type === 'C') {
  1268. d += 'C' + packValues(cmd.x1, cmd.y1, cmd.x2, cmd.y2, cmd.x, cmd.y);
  1269. } else if (cmd.type === 'Q') {
  1270. d += 'Q' + packValues(cmd.x1, cmd.y1, cmd.x, cmd.y);
  1271. } else if (cmd.type === 'Z') {
  1272. d += 'Z';
  1273. }
  1274. }
  1275. return d;
  1276. };
  1277. // Convert the path to a SVG <path> element, as a string.
  1278. // Parameters:
  1279. // - decimalPlaces: The amount of decimal places for floating-point values (default: 2)
  1280. Path.prototype.toSVG = function(decimalPlaces) {
  1281. var svg = '<path d="';
  1282. svg += this.toPathData(decimalPlaces);
  1283. svg += '"';
  1284. if (this.fill & this.fill !== 'black') {
  1285. if (this.fill === null) {
  1286. svg += ' fill="none"';
  1287. } else {
  1288. svg += ' fill="' + this.fill + '"';
  1289. }
  1290. }
  1291. if (this.stroke) {
  1292. svg += ' stroke="' + this.stroke + '" stroke-width="' + this.strokeWidth + '"';
  1293. }
  1294. svg += '/>';
  1295. return svg;
  1296. };
  1297. exports.Path = Path;
  1298. },{}],11:[function(_dereq_,module,exports){
  1299. // Table metadata
  1300. 'use strict';
  1301. var check = _dereq_('./check');
  1302. var encode = _dereq_('./types').encode;
  1303. var sizeOf = _dereq_('./types').sizeOf;
  1304. function Table(tableName, fields, options) {
  1305. var i;
  1306. for (i = 0; i < fields.length; i += 1) {
  1307. var field = fields[i];
  1308. this[field.name] = field.value;
  1309. }
  1310. this.tableName = tableName;
  1311. this.fields = fields;
  1312. if (options) {
  1313. var optionKeys = Object.keys(options);
  1314. for (i = 0; i < optionKeys.length; i += 1) {
  1315. var k = optionKeys[i];
  1316. var v = options[k];
  1317. if (this[k] !== undefined) {
  1318. this[k] = v;
  1319. }
  1320. }
  1321. }
  1322. }
  1323. Table.prototype.sizeOf = function() {
  1324. var v = 0;
  1325. for (var i = 0; i < this.fields.length; i += 1) {
  1326. var field = this.fields[i];
  1327. var value = this[field.name];
  1328. if (value === undefined) {
  1329. value = field.value;
  1330. }
  1331. if (typeof value.sizeOf === 'function') {
  1332. v += value.sizeOf();
  1333. } else {
  1334. var sizeOfFunction = sizeOf[field.type];
  1335. check.assert(typeof sizeOfFunction === 'function', 'Could not find sizeOf function for field' + field.name);
  1336. v += sizeOfFunction(value);
  1337. }
  1338. }
  1339. return v;
  1340. };
  1341. Table.prototype.encode = function() {
  1342. return encode.TABLE(this);
  1343. };
  1344. exports.Table = Table;
  1345. },{"./check":2,"./types":26}],12:[function(_dereq_,module,exports){
  1346. // The `CFF` table contains the glyph outlines in PostScript format.
  1347. // https://www.microsoft.com/typography/OTSPEC/cff.htm
  1348. // http://download.microsoft.com/download/8/0/1/801a191c-029d-4af3-9642-555f6fe514ee/cff.pdf
  1349. // http://download.microsoft.com/download/8/0/1/801a191c-029d-4af3-9642-555f6fe514ee/type2.pdf
  1350. 'use strict';
  1351. var encoding = _dereq_('../encoding');
  1352. var glyphset = _dereq_('../glyphset');
  1353. var parse = _dereq_('../parse');
  1354. var path = _dereq_('../path');
  1355. var table = _dereq_('../table');
  1356. // Custom equals function that can also check lists.
  1357. function equals(a, b) {
  1358. if (a === b) {
  1359. return true;
  1360. } else if (Array.isArray(a) && Array.isArray(b)) {
  1361. if (a.length !== b.length) {
  1362. return false;
  1363. }
  1364. for (var i = 0; i < a.length; i += 1) {
  1365. if (!equals(a[i], b[i])) {
  1366. return false;
  1367. }
  1368. }
  1369. return true;
  1370. } else {
  1371. return false;
  1372. }
  1373. }
  1374. // Parse a `CFF` INDEX array.
  1375. // An index array consists of a list of offsets, then a list of objects at those offsets.
  1376. function parseCFFIndex(data, start, conversionFn) {
  1377. //var i, objectOffset, endOffset;
  1378. var offsets = [];
  1379. var objects = [];
  1380. var count = parse.getCard16(data, start);
  1381. var i;
  1382. var objectOffset;
  1383. var endOffset;
  1384. if (count !== 0) {
  1385. var offsetSize = parse.getByte(data, start + 2);
  1386. objectOffset = start + ((count + 1) * offsetSize) + 2;
  1387. var pos = start + 3;
  1388. for (i = 0; i < count + 1; i += 1) {
  1389. offsets.push(parse.getOffset(data, pos, offsetSize));
  1390. pos += offsetSize;
  1391. }
  1392. // The total size of the index array is 4 header bytes + the value of the last offset.
  1393. endOffset = objectOffset + offsets[count];
  1394. } else {
  1395. endOffset = start + 2;
  1396. }
  1397. for (i = 0; i < offsets.length - 1; i += 1) {
  1398. var value = parse.getBytes(data, objectOffset + offsets[i], objectOffset + offsets[i + 1]);
  1399. if (conversionFn) {
  1400. value = conversionFn(value);
  1401. }
  1402. objects.push(value);
  1403. }
  1404. return {objects: objects, startOffset: start, endOffset: endOffset};
  1405. }
  1406. // Parse a `CFF` DICT real value.
  1407. function parseFloatOperand(parser) {
  1408. var s = '';
  1409. var eof = 15;
  1410. var lookup = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', 'E', 'E-', null, '-'];
  1411. while (true) {
  1412. var b = parser.parseByte();
  1413. var n1 = b >> 4;
  1414. var n2 = b & 15;
  1415. if (n1 === eof) {
  1416. break;
  1417. }
  1418. s += lookup[n1];
  1419. if (n2 === eof) {
  1420. break;
  1421. }
  1422. s += lookup[n2];
  1423. }
  1424. return parseFloat(s);
  1425. }
  1426. // Parse a `CFF` DICT operand.
  1427. function parseOperand(parser, b0) {
  1428. var b1;
  1429. var b2;
  1430. var b3;
  1431. var b4;
  1432. if (b0 === 28) {
  1433. b1 = parser.parseByte();
  1434. b2 = parser.parseByte();
  1435. return b1 << 8 | b2;
  1436. }
  1437. if (b0 === 29) {
  1438. b1 = parser.parseByte();
  1439. b2 = parser.parseByte();
  1440. b3 = parser.parseByte();
  1441. b4 = parser.parseByte();
  1442. return b1 << 24 | b2 << 16 | b3 << 8 | b4;
  1443. }
  1444. if (b0 === 30) {
  1445. return parseFloatOperand(parser);
  1446. }
  1447. if (b0 >= 32 && b0 <= 246) {
  1448. return b0 - 139;
  1449. }
  1450. if (b0 >= 247 && b0 <= 250) {
  1451. b1 = parser.parseByte();
  1452. return (b0 - 247) * 256 + b1 + 108;
  1453. }
  1454. if (b0 >= 251 && b0 <= 254) {
  1455. b1 = parser.parseByte();
  1456. return -(b0 - 251) * 256 - b1 - 108;
  1457. }
  1458. throw new Error('Invalid b0 ' + b0);
  1459. }
  1460. // Convert the entries returned by `parseDict` to a proper dictionary.
  1461. // If a value is a list of one, it is unpacked.
  1462. function entriesToObject(entries) {
  1463. var o = {};
  1464. for (var i = 0; i < entries.length; i += 1) {
  1465. var key = entries[i][0];
  1466. var values = entries[i][1];
  1467. var value;
  1468. if (values.length === 1) {
  1469. value = values[0];
  1470. } else {
  1471. value = values;
  1472. }
  1473. if (o.hasOwnProperty(key)) {
  1474. throw new Error('Object ' + o + ' already has key ' + key);
  1475. }
  1476. o[key] = value;
  1477. }
  1478. return o;
  1479. }
  1480. // Parse a `CFF` DICT object.
  1481. // A dictionary contains key-value pairs in a compact tokenized format.
  1482. function parseCFFDict(data, start, size) {
  1483. start = start !== undefined ? start : 0;
  1484. var parser = new parse.Parser(data, start);
  1485. var entries = [];
  1486. var operands = [];
  1487. size = size !== undefined ? size : data.length;
  1488. while (parser.relativeOffset < size) {
  1489. var op = parser.parseByte();
  1490. // The first byte for each dict item distinguishes between operator (key) and operand (value).
  1491. // Values <= 21 are operators.
  1492. if (op <= 21) {
  1493. // Two-byte operators have an initial escape byte of 12.
  1494. if (op === 12) {
  1495. op = 1200 + parser.parseByte();
  1496. }
  1497. entries.push([op, operands]);
  1498. operands = [];
  1499. } else {
  1500. // Since the operands (values) come before the operators (keys), we store all operands in a list
  1501. // until we encounter an operator.
  1502. operands.push(parseOperand(parser, op));
  1503. }
  1504. }
  1505. return entriesToObject(entries);
  1506. }
  1507. // Given a String Index (SID), return the value of the string.
  1508. // Strings below index 392 are standard CFF strings and are not encoded in the font.
  1509. function getCFFString(strings, index) {
  1510. if (index <= 390) {
  1511. index = encoding.cffStandardStrings[index];
  1512. } else {
  1513. index = strings[index - 391];
  1514. }
  1515. return index;
  1516. }
  1517. // Interpret a dictionary and return a new dictionary with readable keys and values for missing entries.
  1518. // This function takes `meta` which is a list of objects containing `operand`, `name` and `default`.
  1519. function interpretDict(dict, meta, strings) {
  1520. var newDict = {};
  1521. // Because we also want to include missing values, we start out from the meta list
  1522. // and lookup values in the dict.
  1523. for (var i = 0; i < meta.length; i += 1) {
  1524. var m = meta[i];
  1525. var value = dict[m.op];
  1526. if (value === undefined) {
  1527. value = m.value !== undefined ? m.value : null;
  1528. }
  1529. if (m.type === 'SID') {
  1530. value = getCFFString(strings, value);
  1531. }
  1532. newDict[m.name] = value;
  1533. }
  1534. return newDict;
  1535. }
  1536. // Parse the CFF header.
  1537. function parseCFFHeader(data, start) {
  1538. var header = {};
  1539. header.formatMajor = parse.getCard8(data, start);
  1540. header.formatMinor = parse.getCard8(data, start + 1);
  1541. header.size = parse.getCard8(data, start + 2);
  1542. header.offsetSize = parse.getCard8(data, start + 3);
  1543. header.startOffset = start;
  1544. header.endOffset = start + 4;
  1545. return header;
  1546. }
  1547. var TOP_DICT_META = [
  1548. {name: 'version', op: 0, type: 'SID'},
  1549. {name: 'notice', op: 1, type: 'SID'},
  1550. {name: 'copyright', op: 1200, type: 'SID'},
  1551. {name: 'fullName', op: 2, type: 'SID'},
  1552. {name: 'familyName', op: 3, type: 'SID'},
  1553. {name: 'weight', op: 4, type: 'SID'},
  1554. {name: 'isFixedPitch', op: 1201, type: 'number', value: 0},
  1555. {name: 'italicAngle', op: 1202, type: 'number', value: 0},
  1556. {name: 'underlinePosition', op: 1203, type: 'number', value: -100},
  1557. {name: 'underlineThickness', op: 1204, type: 'number', value: 50},
  1558. {name: 'paintType', op: 1205, type: 'number', value: 0},
  1559. {name: 'charstringType', op: 1206, type: 'number', value: 2},
  1560. {name: 'fontMatrix', op: 1207, type: ['real', 'real', 'real', 'real', 'real', 'real'], value: [0.001, 0, 0, 0.001, 0, 0]},
  1561. {name: 'uniqueId', op: 13, type: 'number'},
  1562. {name: 'fontBBox', op: 5, type: ['number', 'number', 'number', 'number'], value: [0, 0, 0, 0]},
  1563. {name: 'strokeWidth', op: 1208, type: 'number', value: 0},
  1564. {name: 'xuid', op: 14, type: [], value: null},
  1565. {name: 'charset', op: 15, type: 'offset', value: 0},
  1566. {name: 'encoding', op: 16, type: 'offset', value: 0},
  1567. {name: 'charStrings', op: 17, type: 'offset', value: 0},
  1568. {name: 'private', op: 18, type: ['number', 'offset'], value: [0, 0]}
  1569. ];
  1570. var PRIVATE_DICT_META = [
  1571. {name: 'subrs', op: 19, type: 'offset', value: 0},
  1572. {name: 'defaultWidthX', op: 20, type: 'number', value: 0},
  1573. {name: 'nominalWidthX', op: 21, type: 'number', value: 0}
  1574. ];
  1575. // Parse the CFF top dictionary. A CFF table can contain multiple fonts, each with their own top dictionary.
  1576. // The top dictionary contains the essential metadata for the font, together with the private dictionary.
  1577. function parseCFFTopDict(data, strings) {
  1578. var dict = parseCFFDict(data, 0, data.byteLength);
  1579. return interpretDict(dict, TOP_DICT_META, strings);
  1580. }
  1581. // Parse the CFF private dictionary. We don't fully parse out all the values, only the ones we need.
  1582. function parseCFFPrivateDict(data, start, size, strings) {
  1583. var dict = parseCFFDict(data, start, size);
  1584. return interpretDict(dict, PRIVATE_DICT_META, strings);
  1585. }
  1586. // Parse the CFF charset table, which contains internal names for all the glyphs.
  1587. // This function will return a list of glyph names.
  1588. // See Adobe TN #5176 chapter 13, "Charsets".
  1589. function parseCFFCharset(data, start, nGlyphs, strings) {
  1590. var i;
  1591. var sid;
  1592. var count;
  1593. var parser = new parse.Parser(data, start);
  1594. // The .notdef glyph is not included, so subtract 1.
  1595. nGlyphs -= 1;
  1596. var charset = ['.notdef'];
  1597. var format = parser.parseCard8();
  1598. if (format === 0) {
  1599. for (i = 0; i < nGlyphs; i += 1) {
  1600. sid = parser.parseSID();
  1601. charset.push(getCFFString(strings, sid));
  1602. }
  1603. } else if (format === 1) {
  1604. while (charset.length <= nGlyphs) {
  1605. sid = parser.parseSID();
  1606. count = parser.parseCard8();
  1607. for (i = 0; i <= count; i += 1) {
  1608. charset.push(getCFFString(strings, sid));
  1609. sid += 1;
  1610. }
  1611. }
  1612. } else if (format === 2) {
  1613. while (charset.length <= nGlyphs) {
  1614. sid = parser.parseSID();
  1615. count = parser.parseCard16();
  1616. for (i = 0; i <= count; i += 1) {
  1617. charset.push(getCFFString(strings, sid));
  1618. sid += 1;
  1619. }
  1620. }
  1621. } else {
  1622. throw new Error('Unknown charset format ' + format);
  1623. }
  1624. return charset;
  1625. }
  1626. // Parse the CFF encoding data. Only one encoding can be specified per font.
  1627. // See Adobe TN #5176 chapter 12, "Encodings".
  1628. function parseCFFEncoding(data, start, charset) {
  1629. var i;
  1630. var code;
  1631. var enc = {};
  1632. var parser = new parse.Parser(data, start);
  1633. var format = parser.parseCard8();
  1634. if (format === 0) {
  1635. var nCodes = parser.parseCard8();
  1636. for (i = 0; i < nCodes; i += 1) {
  1637. code = parser.parseCard8();
  1638. enc[code] = i;
  1639. }
  1640. } else if (format === 1) {
  1641. var nRanges = parser.parseCard8();
  1642. code = 1;
  1643. for (i = 0; i < nRanges; i += 1) {
  1644. var first = parser.parseCard8();
  1645. var nLeft = parser.parseCard8();
  1646. for (var j = first; j <= first + nLeft; j += 1) {
  1647. enc[j] = code;
  1648. code += 1;
  1649. }
  1650. }
  1651. } else {
  1652. throw new Error('Unknown encoding format ' + format);
  1653. }
  1654. return new encoding.CffEncoding(enc, charset);
  1655. }
  1656. // Take in charstring code and return a Glyph object.
  1657. // The encoding is described in the Type 2 Charstring Format
  1658. // https://www.microsoft.com/typography/OTSPEC/charstr2.htm
  1659. function parseCFFCharstring(font, glyph, code) {
  1660. var c1x;
  1661. var c1y;
  1662. var c2x;
  1663. var c2y;
  1664. var p = new path.Path();
  1665. var stack = [];
  1666. var nStems = 0;
  1667. var haveWidth = false;
  1668. var width = font.defaultWidthX;
  1669. var open = false;
  1670. var x = 0;
  1671. var y = 0;
  1672. function newContour(x, y) {
  1673. if (open) {
  1674. p.closePath();
  1675. }
  1676. p.moveTo(x, y);
  1677. open = true;
  1678. }
  1679. function parseStems() {
  1680. var hasWidthArg;
  1681. // The number of stem operators on the stack is always even.
  1682. // If the value is uneven, that means a width is specified.
  1683. hasWidthArg = stack.length % 2 !== 0;
  1684. if (hasWidthArg && !haveWidth) {
  1685. width = stack.shift() + font.nominalWidthX;
  1686. }
  1687. nStems += stack.length >> 1;
  1688. stack.length = 0;
  1689. haveWidth = true;
  1690. }
  1691. function parse(code) {
  1692. var b1;
  1693. var b2;
  1694. var b3;
  1695. var b4;
  1696. var codeIndex;
  1697. var subrCode;
  1698. var jpx;
  1699. var jpy;
  1700. var c3x;
  1701. var c3y;
  1702. var c4x;
  1703. var c4y;
  1704. var i = 0;
  1705. while (i < code.length) {
  1706. var v = code[i];
  1707. i += 1;
  1708. switch (v) {
  1709. case 1: // hstem
  1710. parseStems();
  1711. break;
  1712. case 3: // vstem
  1713. parseStems();
  1714. break;
  1715. case 4: // vmoveto
  1716. if (stack.length > 1 && !haveWidth) {
  1717. width = stack.shift() + font.nominalWidthX;
  1718. haveWidth = true;
  1719. }
  1720. y += stack.pop();
  1721. newContour(x, y);
  1722. break;
  1723. case 5: // rlineto
  1724. while (stack.length > 0) {
  1725. x += stack.shift();
  1726. y += stack.shift();
  1727. p.lineTo(x, y);
  1728. }
  1729. break;
  1730. case 6: // hlineto
  1731. while (stack.length > 0) {
  1732. x += stack.shift();
  1733. p.lineTo(x, y);
  1734. if (stack.length === 0) {
  1735. break;
  1736. }
  1737. y += stack.shift();
  1738. p.lineTo(x, y);
  1739. }
  1740. break;
  1741. case 7: // vlineto
  1742. while (stack.length > 0) {
  1743. y += stack.shift();
  1744. p.lineTo(x, y);
  1745. if (stack.length === 0) {
  1746. break;
  1747. }
  1748. x += stack.shift();
  1749. p.lineTo(x, y);
  1750. }
  1751. break;
  1752. case 8: // rrcurveto
  1753. while (stack.length > 0) {
  1754. c1x = x + stack.shift();
  1755. c1y = y + stack.shift();
  1756. c2x = c1x + stack.shift();
  1757. c2y = c1y + stack.shift();
  1758. x = c2x + stack.shift();
  1759. y = c2y + stack.shift();
  1760. p.curveTo(c1x, c1y, c2x, c2y, x, y);
  1761. }
  1762. break;
  1763. case 10: // callsubr
  1764. codeIndex = stack.pop() + font.subrsBias;
  1765. subrCode = font.subrs[codeIndex];
  1766. if (subrCode) {
  1767. parse(subrCode);
  1768. }
  1769. break;
  1770. case 11: // return
  1771. return;
  1772. case 12: // flex operators
  1773. v = code[i];
  1774. i += 1;
  1775. switch (v) {
  1776. case 35: // flex
  1777. // |- dx1 dy1 dx2 dy2 dx3 dy3 dx4 dy4 dx5 dy5 dx6 dy6 fd flex (12 35) |-
  1778. c1x = x + stack.shift(); // dx1
  1779. c1y = y + stack.shift(); // dy1
  1780. c2x = c1x + stack.shift(); // dx2
  1781. c2y = c1y + stack.shift(); // dy2
  1782. jpx = c2x + stack.shift(); // dx3
  1783. jpy = c2y + stack.shift(); // dy3
  1784. c3x = jpx + stack.shift(); // dx4
  1785. c3y = jpy + stack.shift(); // dy4
  1786. c4x = c3x + stack.shift(); // dx5
  1787. c4y = c3y + stack.shift(); // dy5
  1788. x = c4x + stack.shift(); // dx6
  1789. y = c4y + stack.shift(); // dy6
  1790. stack.shift(); // flex depth
  1791. p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy);
  1792. p.curveTo(c3x, c3y, c4x, c4y, x, y);
  1793. break;
  1794. case 34: // hflex
  1795. // |- dx1 dx2 dy2 dx3 dx4 dx5 dx6 hflex (12 34) |-
  1796. c1x = x + stack.shift(); // dx1
  1797. c1y = y; // dy1
  1798. c2x = c1x + stack.shift(); // dx2
  1799. c2y = c1y + stack.shift(); // dy2
  1800. jpx = c2x + stack.shift(); // dx3
  1801. jpy = c2y; // dy3
  1802. c3x = jpx + stack.shift(); // dx4
  1803. c3y = c2y; // dy4
  1804. c4x = c3x + stack.shift(); // dx5
  1805. c4y = y; // dy5
  1806. x = c4x + stack.shift(); // dx6
  1807. p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy);
  1808. p.curveTo(c3x, c3y, c4x, c4y, x, y);
  1809. break;
  1810. case 36: // hflex1
  1811. // |- dx1 dy1 dx2 dy2 dx3 dx4 dx5 dy5 dx6 hflex1 (12 36) |-
  1812. c1x = x + stack.shift(); // dx1
  1813. c1y = y + stack.shift(); // dy1
  1814. c2x = c1x + stack.shift(); // dx2
  1815. c2y = c1y + stack.shift(); // dy2
  1816. jpx = c2x + stack.shift(); // dx3
  1817. jpy = c2y; // dy3
  1818. c3x = jpx + stack.shift(); // dx4
  1819. c3y = c2y; // dy4
  1820. c4x = c3x + stack.shift(); // dx5
  1821. c4y = c3y + stack.shift(); // dy5
  1822. x = c4x + stack.shift(); // dx6
  1823. p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy);
  1824. p.curveTo(c3x, c3y, c4x, c4y, x, y);
  1825. break;
  1826. case 37: // flex1
  1827. // |- dx1 dy1 dx2 dy2 dx3 dy3 dx4 dy4 dx5 dy5 d6 flex1 (12 37) |-
  1828. c1x = x + stack.shift(); // dx1
  1829. c1y = y + stack.shift(); // dy1
  1830. c2x = c1x + stack.shift(); // dx2
  1831. c2y = c1y + stack.shift(); // dy2
  1832. jpx = c2x + stack.shift(); // dx3
  1833. jpy = c2y + stack.shift(); // dy3
  1834. c3x = jpx + stack.shift(); // dx4
  1835. c3y = jpy + stack.shift(); // dy4
  1836. c4x = c3x + stack.shift(); // dx5
  1837. c4y = c3y + stack.shift(); // dy5
  1838. if (Math.abs(c4x - x) > Math.abs(c4y - y)) {
  1839. x = c4x + stack.shift();
  1840. } else {
  1841. y = c4y + stack.shift();
  1842. }
  1843. p.curveTo(c1x, c1y, c2x, c2y, jpx, jpy);
  1844. p.curveTo(c3x, c3y, c4x, c4y, x, y);
  1845. break;
  1846. default:
  1847. console.log('Glyph ' + glyph.index + ': unknown operator ' + 1200 + v);
  1848. stack.length = 0;
  1849. }
  1850. break;
  1851. case 14: // endchar
  1852. if (stack.length > 0 && !haveWidth) {
  1853. width = stack.shift() + font.nominalWidthX;
  1854. haveWidth = true;
  1855. }
  1856. if (open) {
  1857. p.closePath();
  1858. open = false;
  1859. }
  1860. break;
  1861. case 18: // hstemhm
  1862. parseStems();
  1863. break;
  1864. case 19: // hintmask
  1865. case 20: // cntrmask
  1866. parseStems();
  1867. i += (nStems + 7) >> 3;
  1868. break;
  1869. case 21: // rmoveto
  1870. if (stack.length > 2 && !haveWidth) {
  1871. width = stack.shift() + font.nominalWidthX;
  1872. haveWidth = true;
  1873. }
  1874. y += stack.pop();
  1875. x += stack.pop();
  1876. newContour(x, y);
  1877. break;
  1878. case 22: // hmoveto
  1879. if (stack.length > 1 && !haveWidth) {
  1880. width = stack.shift() + font.nominalWidthX;
  1881. haveWidth = true;
  1882. }
  1883. x += stack.pop();
  1884. newContour(x, y);
  1885. break;
  1886. case 23: // vstemhm
  1887. parseStems();
  1888. break;
  1889. case 24: // rcurveline
  1890. while (stack.length > 2) {
  1891. c1x = x + stack.shift();
  1892. c1y = y + stack.shift();
  1893. c2x = c1x + stack.shift();
  1894. c2y = c1y + stack.shift();
  1895. x = c2x + stack.shift();
  1896. y = c2y + stack.shift();
  1897. p.curveTo(c1x, c1y, c2x, c2y, x, y);
  1898. }
  1899. x += stack.shift();
  1900. y += stack.shift();
  1901. p.lineTo(x, y);
  1902. break;
  1903. case 25: // rlinecurve
  1904. while (stack.length > 6) {
  1905. x += stack.shift();
  1906. y += stack.shift();
  1907. p.lineTo(x, y);
  1908. }
  1909. c1x = x + stack.shift();
  1910. c1y = y + stack.shift();
  1911. c2x = c1x + stack.shift();
  1912. c2y = c1y + stack.shift();
  1913. x = c2x + stack.shift();
  1914. y = c2y + stack.shift();
  1915. p.curveTo(c1x, c1y, c2x, c2y, x, y);
  1916. break;
  1917. case 26: // vvcurveto
  1918. if (stack.length % 2) {
  1919. x += stack.shift();
  1920. }
  1921. while (stack.length > 0) {
  1922. c1x = x;
  1923. c1y = y + stack.shift();
  1924. c2x = c1x + stack.shift();
  1925. c2y = c1y + stack.shift();
  1926. x = c2x;
  1927. y = c2y + stack.shift();
  1928. p.curveTo(c1x, c1y, c2x, c2y, x, y);
  1929. }
  1930. break;
  1931. case 27: // hhcurveto
  1932. if (stack.length % 2) {
  1933. y += stack.shift();
  1934. }
  1935. while (stack.length > 0) {
  1936. c1x = x + stack.shift();
  1937. c1y = y;
  1938. c2x = c1x + stack.shift();
  1939. c2y = c1y + stack.shift();
  1940. x = c2x + stack.shift();
  1941. y = c2y;
  1942. p.curveTo(c1x, c1y, c2x, c2y, x, y);
  1943. }
  1944. break;
  1945. case 28: // shortint
  1946. b1 = code[i];
  1947. b2 = code[i + 1];
  1948. stack.push(((b1 << 24) | (b2 << 16)) >> 16);
  1949. i += 2;
  1950. break;
  1951. case 29: // callgsubr
  1952. codeIndex = stack.pop() + font.gsubrsBias;
  1953. subrCode = font.gsubrs[codeIndex];
  1954. if (subrCode) {
  1955. parse(subrCode);
  1956. }
  1957. break;
  1958. case 30: // vhcurveto
  1959. while (stack.length > 0) {
  1960. c1x = x;
  1961. c1y = y + stack.shift();
  1962. c2x = c1x + stack.shift();
  1963. c2y = c1y + stack.shift();
  1964. x = c2x + stack.shift();
  1965. y = c2y + (stack.length === 1 ? stack.shift() : 0);
  1966. p.curveTo(c1x, c1y, c2x, c2y, x, y);
  1967. if (stack.length === 0) {
  1968. break;
  1969. }
  1970. c1x = x + stack.shift();
  1971. c1y = y;
  1972. c2x = c1x + stack.shift();
  1973. c2y = c1y + stack.shift();
  1974. y = c2y + stack.shift();
  1975. x = c2x + (stack.length === 1 ? stack.shift() : 0);
  1976. p.curveTo(c1x, c1y, c2x, c2y, x, y);
  1977. }
  1978. break;
  1979. case 31: // hvcurveto
  1980. while (stack.length > 0) {
  1981. c1x = x + stack.shift();
  1982. c1y = y;
  1983. c2x = c1x + stack.shift();
  1984. c2y = c1y + stack.shift();
  1985. y = c2y + stack.shift();
  1986. x = c2x + (stack.length === 1 ? stack.shift() : 0);
  1987. p.curveTo(c1x, c1y, c2x, c2y, x, y);
  1988. if (stack.length === 0) {
  1989. break;
  1990. }
  1991. c1x = x;
  1992. c1y = y + stack.shift();
  1993. c2x = c1x + stack.shift();
  1994. c2y = c1y + stack.shift();
  1995. x = c2x + stack.shift();
  1996. y = c2y + (stack.length === 1 ? stack.shift() : 0);
  1997. p.curveTo(c1x, c1y, c2x, c2y, x, y);
  1998. }
  1999. break;
  2000. default:
  2001. if (v < 32) {
  2002. console.log('Glyph ' + glyph.index + ': unknown operator ' + v);
  2003. } else if (v < 247) {
  2004. stack.push(v - 139);
  2005. } else if (v < 251) {
  2006. b1 = code[i];
  2007. i += 1;
  2008. stack.push((v - 247) * 256 + b1 + 108);
  2009. } else if (v < 255) {
  2010. b1 = code[i];
  2011. i += 1;
  2012. stack.push(-(v - 251) * 256 - b1 - 108);
  2013. } else {
  2014. b1 = code[i];
  2015. b2 = code[i + 1];
  2016. b3 = code[i + 2];
  2017. b4 = code[i + 3];
  2018. i += 4;
  2019. stack.push(((b1 << 24) | (b2 << 16) | (b3 << 8) | b4) / 65536);
  2020. }
  2021. }
  2022. }
  2023. }
  2024. parse(code);
  2025. glyph.advanceWidth = width;
  2026. return p;
  2027. }
  2028. // Subroutines are encoded using the negative half of the number space.
  2029. // See type 2 chapter 4.7 "Subroutine operators".
  2030. function calcCFFSubroutineBias(subrs) {
  2031. var bias;
  2032. if (subrs.length < 1240) {
  2033. bias = 107;
  2034. } else if (subrs.length < 33900) {
  2035. bias = 1131;
  2036. } else {
  2037. bias = 32768;
  2038. }
  2039. return bias;
  2040. }
  2041. // Parse the `CFF` table, which contains the glyph outlines in PostScript format.
  2042. function parseCFFTable(data, start, font) {
  2043. font.tables.cff = {};
  2044. var header = parseCFFHeader(data, start);
  2045. var nameIndex = parseCFFIndex(data, header.endOffset, parse.bytesToString);
  2046. var topDictIndex = parseCFFIndex(data, nameIndex.endOffset);
  2047. var stringIndex = parseCFFIndex(data, topDictIndex.endOffset, parse.bytesToString);
  2048. var globalSubrIndex = parseCFFIndex(data, stringIndex.endOffset);
  2049. font.gsubrs = globalSubrIndex.objects;
  2050. font.gsubrsBias = calcCFFSubroutineBias(font.gsubrs);
  2051. var topDictData = new DataView(new Uint8Array(topDictIndex.objects[0]).buffer);
  2052. var topDict = parseCFFTopDict(topDictData, stringIndex.objects);
  2053. font.tables.cff.topDict = topDict;
  2054. var privateDictOffset = start + topDict['private'][1];
  2055. var privateDict = parseCFFPrivateDict(data, privateDictOffset, topDict['private'][0], stringIndex.objects);
  2056. font.defaultWidthX = privateDict.defaultWidthX;
  2057. font.nominalWidthX = privateDict.nominalWidthX;
  2058. if (privateDict.subrs !== 0) {
  2059. var subrOffset = privateDictOffset + privateDict.subrs;
  2060. var subrIndex = parseCFFIndex(data, subrOffset);
  2061. font.subrs = subrIndex.objects;
  2062. font.subrsBias = calcCFFSubroutineBias(font.subrs);
  2063. } else {
  2064. font.subrs = [];
  2065. font.subrsBias = 0;
  2066. }
  2067. // Offsets in the top dict are relative to the beginning of the CFF data, so add the CFF start offset.
  2068. var charStringsIndex = parseCFFIndex(data, start + topDict.charStrings);
  2069. font.nGlyphs = charStringsIndex.objects.length;
  2070. var charset = parseCFFCharset(data, start + topDict.charset, font.nGlyphs, stringIndex.objects);
  2071. if (topDict.encoding === 0) { // Standard encoding
  2072. font.cffEncoding = new encoding.CffEncoding(encoding.cffStandardEncoding, charset);
  2073. } else if (topDict.encoding === 1) { // Expert encoding
  2074. font.cffEncoding = new encoding.CffEncoding(encoding.cffExpertEncoding, charset);
  2075. } else {
  2076. font.cffEncoding = parseCFFEncoding(data, start + topDict.encoding, charset);
  2077. }
  2078. // Prefer the CMAP encoding to the CFF encoding.
  2079. font.encoding = font.encoding || font.cffEncoding;
  2080. font.glyphs = new glyphset.GlyphSet(font);
  2081. for (var i = 0; i < font.nGlyphs; i += 1) {
  2082. var charString = charStringsIndex.objects[i];
  2083. font.glyphs.push(i, glyphset.cffGlyphLoader(font, i, parseCFFCharstring, charString));
  2084. }
  2085. }
  2086. // Convert a string to a String ID (SID).
  2087. // The list of strings is modified in place.
  2088. function encodeString(s, strings) {
  2089. var sid;
  2090. // Is the string in the CFF standard strings?
  2091. var i = encoding.cffStandardStrings.indexOf(s);
  2092. if (i >= 0) {
  2093. sid = i;
  2094. }
  2095. // Is the string already in the string index?
  2096. i = strings.indexOf(s);
  2097. if (i >= 0) {
  2098. sid = i + encoding.cffStandardStrings.length;
  2099. } else {
  2100. sid = encoding.cffStandardStrings.length + strings.length;
  2101. strings.push(s);
  2102. }
  2103. return sid;
  2104. }
  2105. function makeHeader() {
  2106. return new table.Table('Header', [
  2107. {name: 'major', type: 'Card8', value: 1},
  2108. {name: 'minor', type: 'Card8', value: 0},
  2109. {name: 'hdrSize', type: 'Card8', value: 4},
  2110. {name: 'major', type: 'Card8', value: 1}
  2111. ]);
  2112. }
  2113. function makeNameIndex(fontNames) {
  2114. var t = new table.Table('Name INDEX', [
  2115. {name: 'names', type: 'INDEX', value: []}
  2116. ]);
  2117. t.names = [];
  2118. for (var i = 0; i < fontNames.length; i += 1) {
  2119. t.names.push({name: 'name_' + i, type: 'NAME', value: fontNames[i]});
  2120. }
  2121. return t;
  2122. }
  2123. // Given a dictionary's metadata, create a DICT structure.
  2124. function makeDict(meta, attrs, strings) {
  2125. var m = {};
  2126. for (var i = 0; i < meta.length; i += 1) {
  2127. var entry = meta[i];
  2128. var value = attrs[entry.name];
  2129. if (value !== undefined && !equals(value, entry.value)) {
  2130. if (entry.type === 'SID') {
  2131. value = encodeString(value, strings);
  2132. }
  2133. m[entry.op] = {name: entry.name, type: entry.type, value: value};
  2134. }
  2135. }
  2136. return m;
  2137. }
  2138. // The Top DICT houses the global font attributes.
  2139. function makeTopDict(attrs, strings) {
  2140. var t = new table.Table('Top DICT', [
  2141. {name: 'dict', type: 'DICT', value: {}}
  2142. ]);
  2143. t.dict = makeDict(TOP_DICT_META, attrs, strings);
  2144. return t;
  2145. }
  2146. function makeTopDictIndex(topDict) {
  2147. var t = new table.Table('Top DICT INDEX', [
  2148. {name: 'topDicts', type: 'INDEX', value: []}
  2149. ]);
  2150. t.topDicts = [{name: 'topDict_0', type: 'TABLE', value: topDict}];
  2151. return t;
  2152. }
  2153. function makeStringIndex(strings) {
  2154. var t = new table.Table('String INDEX', [
  2155. {name: 'strings', type: 'INDEX', value: []}
  2156. ]);
  2157. t.strings = [];
  2158. for (var i = 0; i < strings.length; i += 1) {
  2159. t.strings.push({name: 'string_' + i, type: 'STRING', value: strings[i]});
  2160. }
  2161. return t;
  2162. }
  2163. function makeGlobalSubrIndex() {
  2164. // Currently we don't use subroutines.
  2165. return new table.Table('Global Subr INDEX', [
  2166. {name: 'subrs', type: 'INDEX', value: []}
  2167. ]);
  2168. }
  2169. function makeCharsets(glyphNames, strings) {
  2170. var t = new table.Table('Charsets', [
  2171. {name: 'format', type: 'Card8', value: 0}
  2172. ]);
  2173. for (var i = 0; i < glyphNames.length; i += 1) {
  2174. var glyphName = glyphNames[i];
  2175. var glyphSID = encodeString(glyphName, strings);
  2176. t.fields.push({name: 'glyph_' + i, type: 'SID', value: glyphSID});
  2177. }
  2178. return t;
  2179. }
  2180. function glyphToOps(glyph) {
  2181. var ops = [];
  2182. var path = glyph.path;
  2183. ops.push({name: 'width', type: 'NUMBER', value: glyph.advanceWidth});
  2184. var x = 0;
  2185. var y = 0;
  2186. for (var i = 0; i < path.commands.length; i += 1) {
  2187. var dx;
  2188. var dy;
  2189. var cmd = path.commands[i];
  2190. if (cmd.type === 'Q') {
  2191. // CFF only supports bézier curves, so convert the quad to a bézier.
  2192. var _13 = 1 / 3;
  2193. var _23 = 2 / 3;
  2194. // We're going to create a new command so we don't change the original path.
  2195. cmd = {
  2196. type: 'C',
  2197. x: cmd.x,
  2198. y: cmd.y,
  2199. x1: _13 * x + _23 * cmd.x1,
  2200. y1: _13 * y + _23 * cmd.y1,
  2201. x2: _13 * cmd.x + _23 * cmd.x1,
  2202. y2: _13 * cmd.y + _23 * cmd.y1
  2203. };
  2204. }
  2205. if (cmd.type === 'M') {
  2206. dx = Math.round(cmd.x - x);
  2207. dy = Math.round(cmd.y - y);
  2208. ops.push({name: 'dx', type: 'NUMBER', value: dx});
  2209. ops.push({name: 'dy', type: 'NUMBER', value: dy});
  2210. ops.push({name: 'rmoveto', type: 'OP', value: 21});
  2211. x = Math.round(cmd.x);
  2212. y = Math.round(cmd.y);
  2213. } else if (cmd.type === 'L') {
  2214. dx = Math.round(cmd.x - x);
  2215. dy = Math.round(cmd.y - y);
  2216. ops.push({name: 'dx', type: 'NUMBER', value: dx});
  2217. ops.push({name: 'dy', type: 'NUMBER', value: dy});
  2218. ops.push({name: 'rlineto', type: 'OP', value: 5});
  2219. x = Math.round(cmd.x);
  2220. y = Math.round(cmd.y);
  2221. } else if (cmd.type === 'C') {
  2222. var dx1 = Math.round(cmd.x1 - x);
  2223. var dy1 = Math.round(cmd.y1 - y);
  2224. var dx2 = Math.round(cmd.x2 - cmd.x1);
  2225. var dy2 = Math.round(cmd.y2 - cmd.y1);
  2226. dx = Math.round(cmd.x - cmd.x2);
  2227. dy = Math.round(cmd.y - cmd.y2);
  2228. ops.push({name: 'dx1', type: 'NUMBER', value: dx1});
  2229. ops.push({name: 'dy1', type: 'NUMBER', value: dy1});
  2230. ops.push({name: 'dx2', type: 'NUMBER', value: dx2});
  2231. ops.push({name: 'dy2', type: 'NUMBER', value: dy2});
  2232. ops.push({name: 'dx', type: 'NUMBER', value: dx});
  2233. ops.push({name: 'dy', type: 'NUMBER', value: dy});
  2234. ops.push({name: 'rrcurveto', type: 'OP', value: 8});
  2235. x = Math.round(cmd.x);
  2236. y = Math.round(cmd.y);
  2237. }
  2238. // Contours are closed automatically.
  2239. }
  2240. ops.push({name: 'endchar', type: 'OP', value: 14});
  2241. return ops;
  2242. }
  2243. function makeCharStringsIndex(glyphs) {
  2244. var t = new table.Table('CharStrings INDEX', [
  2245. {name: 'charStrings', type: 'INDEX', value: []}
  2246. ]);
  2247. for (var i = 0; i < glyphs.length; i += 1) {
  2248. var glyph = glyphs.get(i);
  2249. var ops = glyphToOps(glyph);
  2250. t.charStrings.push({name: glyph.name, type: 'CHARSTRING', value: ops});
  2251. }
  2252. return t;
  2253. }
  2254. function makePrivateDict(attrs, strings) {
  2255. var t = new table.Table('Private DICT', [
  2256. {name: 'dict', type: 'DICT', value: {}}
  2257. ]);
  2258. t.dict = makeDict(PRIVATE_DICT_META, attrs, strings);
  2259. return t;
  2260. }
  2261. function makePrivateDictIndex(privateDict) {
  2262. var t = new table.Table('Private DICT INDEX', [
  2263. {name: 'privateDicts', type: 'INDEX', value: []}
  2264. ]);
  2265. t.privateDicts = [{name: 'privateDict_0', type: 'TABLE', value: privateDict}];
  2266. return t;
  2267. }
  2268. function makeCFFTable(glyphs, options) {
  2269. var t = new table.Table('CFF ', [
  2270. {name: 'header', type: 'TABLE'},
  2271. {name: 'nameIndex', type: 'TABLE'},
  2272. {name: 'topDictIndex', type: 'TABLE'},
  2273. {name: 'stringIndex', type: 'TABLE'},
  2274. {name: 'globalSubrIndex', type: 'TABLE'},
  2275. {name: 'charsets', type: 'TABLE'},
  2276. {name: 'charStringsIndex', type: 'TABLE'},
  2277. {name: 'privateDictIndex', type: 'TABLE'}
  2278. ]);
  2279. var fontScale = 1 / options.unitsPerEm;
  2280. // We use non-zero values for the offsets so that the DICT encodes them.
  2281. // This is important because the size of the Top DICT plays a role in offset calculation,
  2282. // and the size shouldn't change after we've written correct offsets.
  2283. var attrs = {
  2284. version: options.version,
  2285. fullName: options.fullName,
  2286. familyName: options.familyName,
  2287. weight: options.weightName,
  2288. fontMatrix: [fontScale, 0, 0, fontScale, 0, 0],
  2289. charset: 999,
  2290. encoding: 0,
  2291. charStrings: 999,
  2292. private: [0, 999]
  2293. };
  2294. var privateAttrs = {};
  2295. var glyphNames = [];
  2296. var glyph;
  2297. // Skip first glyph (.notdef)
  2298. for (var i = 1; i < glyphs.length; i += 1) {
  2299. glyph = glyphs.get(i);
  2300. glyphNames.push(glyph.name);
  2301. }
  2302. var strings = [];
  2303. t.header = makeHeader();
  2304. t.nameIndex = makeNameIndex([options.postScriptName]);
  2305. var topDict = makeTopDict(attrs, strings);
  2306. t.topDictIndex = makeTopDictIndex(topDict);
  2307. t.globalSubrIndex = makeGlobalSubrIndex();
  2308. t.charsets = makeCharsets(glyphNames, strings);
  2309. t.charStringsIndex = makeCharStringsIndex(glyphs);
  2310. var privateDict = makePrivateDict(privateAttrs, strings);
  2311. t.privateDictIndex = makePrivateDictIndex(privateDict);
  2312. // Needs to come at the end, to encode all custom strings used in the font.
  2313. t.stringIndex = makeStringIndex(strings);
  2314. var startOffset = t.header.sizeOf() +
  2315. t.nameIndex.sizeOf() +
  2316. t.topDictIndex.sizeOf() +
  2317. t.stringIndex.sizeOf() +
  2318. t.globalSubrIndex.sizeOf();
  2319. attrs.charset = startOffset;
  2320. // We use the CFF standard encoding; proper encoding will be handled in cmap.
  2321. attrs.encoding = 0;
  2322. attrs.charStrings = attrs.charset + t.charsets.sizeOf();
  2323. attrs.private[1] = attrs.charStrings + t.charStringsIndex.sizeOf();
  2324. // Recreate the Top DICT INDEX with the correct offsets.
  2325. topDict = makeTopDict(attrs, strings);
  2326. t.topDictIndex = makeTopDictIndex(topDict);
  2327. return t;
  2328. }
  2329. exports.parse = parseCFFTable;
  2330. exports.make = makeCFFTable;
  2331. },{"../encoding":4,"../glyphset":7,"../parse":9,"../path":10,"../table":11}],13:[function(_dereq_,module,exports){
  2332. // The `cmap` table stores the mappings from characters to glyphs.
  2333. // https://www.microsoft.com/typography/OTSPEC/cmap.htm
  2334. 'use strict';
  2335. var check = _dereq_('../check');
  2336. var parse = _dereq_('../parse');
  2337. var table = _dereq_('../table');
  2338. // Parse the `cmap` table. This table stores the mappings from characters to glyphs.
  2339. // There are many available formats, but we only support the Windows format 4.
  2340. // This function returns a `CmapEncoding` object or null if no supported format could be found.
  2341. function parseCmapTable(data, start) {
  2342. var i;
  2343. var cmap = {};
  2344. cmap.version = parse.getUShort(data, start);
  2345. check.argument(cmap.version === 0, 'cmap table version should be 0.');
  2346. // The cmap table can contain many sub-tables, each with their own format.
  2347. // We're only interested in a "platform 3" table. This is a Windows format.
  2348. cmap.numTables = parse.getUShort(data, start + 2);
  2349. var offset = -1;
  2350. for (i = 0; i < cmap.numTables; i += 1) {
  2351. var platformId = parse.getUShort(data, start + 4 + (i * 8));
  2352. var encodingId = parse.getUShort(data, start + 4 + (i * 8) + 2);
  2353. if (platformId === 3 && (encodingId === 1 || encodingId === 0)) {
  2354. offset = parse.getULong(data, start + 4 + (i * 8) + 4);
  2355. break;
  2356. }
  2357. }
  2358. if (offset === -1) {
  2359. // There is no cmap table in the font that we support, so return null.
  2360. // This font will be marked as unsupported.
  2361. return null;
  2362. }
  2363. var p = new parse.Parser(data, start + offset);
  2364. cmap.format = p.parseUShort();
  2365. check.argument(cmap.format === 4, 'Only format 4 cmap tables are supported.');
  2366. // Length in bytes of the sub-tables.
  2367. cmap.length = p.parseUShort();
  2368. cmap.language = p.parseUShort();
  2369. // segCount is stored x 2.
  2370. var segCount;
  2371. cmap.segCount = segCount = p.parseUShort() >> 1;
  2372. // Skip searchRange, entrySelector, rangeShift.
  2373. p.skip('uShort', 3);
  2374. // The "unrolled" mapping from character codes to glyph indices.
  2375. cmap.glyphIndexMap = {};
  2376. var endCountParser = new parse.Parser(data, start + offset + 14);
  2377. var startCountParser = new parse.Parser(data, start + offset + 16 + segCount * 2);
  2378. var idDeltaParser = new parse.Parser(data, start + offset + 16 + segCount * 4);
  2379. var idRangeOffsetParser = new parse.Parser(data, start + offset + 16 + segCount * 6);
  2380. var glyphIndexOffset = start + offset + 16 + segCount * 8;
  2381. for (i = 0; i < segCount - 1; i += 1) {
  2382. var glyphIndex;
  2383. var endCount = endCountParser.parseUShort();
  2384. var startCount = startCountParser.parseUShort();
  2385. var idDelta = idDeltaParser.parseShort();
  2386. var idRangeOffset = idRangeOffsetParser.parseUShort();
  2387. for (var c = startCount; c <= endCount; c += 1) {
  2388. if (idRangeOffset !== 0) {
  2389. // The idRangeOffset is relative to the current position in the idRangeOffset array.
  2390. // Take the current offset in the idRangeOffset array.
  2391. glyphIndexOffset = (idRangeOffsetParser.offset + idRangeOffsetParser.relativeOffset - 2);
  2392. // Add the value of the idRangeOffset, which will move us into the glyphIndex array.
  2393. glyphIndexOffset += idRangeOffset;
  2394. // Then add the character index of the current segment, multiplied by 2 for USHORTs.
  2395. glyphIndexOffset += (c - startCount) * 2;
  2396. glyphIndex = parse.getUShort(data, glyphIndexOffset);
  2397. if (glyphIndex !== 0) {
  2398. glyphIndex = (glyphIndex + idDelta) & 0xFFFF;
  2399. }
  2400. } else {
  2401. glyphIndex = (c + idDelta) & 0xFFFF;
  2402. }
  2403. cmap.glyphIndexMap[c] = glyphIndex;
  2404. }
  2405. }
  2406. return cmap;
  2407. }
  2408. function addSegment(t, code, glyphIndex) {
  2409. t.segments.push({
  2410. end: code,
  2411. start: code,
  2412. delta: -(code - glyphIndex),
  2413. offset: 0
  2414. });
  2415. }
  2416. function addTerminatorSegment(t) {
  2417. t.segments.push({
  2418. end: 0xFFFF,
  2419. start: 0xFFFF,
  2420. delta: 1,
  2421. offset: 0
  2422. });
  2423. }
  2424. function makeCmapTable(glyphs) {
  2425. var i;
  2426. var t = new table.Table('cmap', [
  2427. {name: 'version', type: 'USHORT', value: 0},
  2428. {name: 'numTables', type: 'USHORT', value: 1},
  2429. {name: 'platformID', type: 'USHORT', value: 3},
  2430. {name: 'encodingID', type: 'USHORT', value: 1},
  2431. {name: 'offset', type: 'ULONG', value: 12},
  2432. {name: 'format', type: 'USHORT', value: 4},
  2433. {name: 'length', type: 'USHORT', value: 0},
  2434. {name: 'language', type: 'USHORT', value: 0},
  2435. {name: 'segCountX2', type: 'USHORT', value: 0},
  2436. {name: 'searchRange', type: 'USHORT', value: 0},
  2437. {name: 'entrySelector', type: 'USHORT', value: 0},
  2438. {name: 'rangeShift', type: 'USHORT', value: 0}
  2439. ]);
  2440. t.segments = [];
  2441. for (i = 0; i < glyphs.length; i += 1) {
  2442. var glyph = glyphs.get(i);
  2443. for (var j = 0; j < glyph.unicodes.length; j += 1) {
  2444. addSegment(t, glyph.unicodes[j], i);
  2445. }
  2446. t.segments = t.segments.sort(function(a, b) {
  2447. return a.start - b.start;
  2448. });
  2449. }
  2450. addTerminatorSegment(t);
  2451. var segCount;
  2452. segCount = t.segments.length;
  2453. t.segCountX2 = segCount * 2;
  2454. t.searchRange = Math.pow(2, Math.floor(Math.log(segCount) / Math.log(2))) * 2;
  2455. t.entrySelector = Math.log(t.searchRange / 2) / Math.log(2);
  2456. t.rangeShift = t.segCountX2 - t.searchRange;
  2457. // Set up parallel segment arrays.
  2458. var endCounts = [];
  2459. var startCounts = [];
  2460. var idDeltas = [];
  2461. var idRangeOffsets = [];
  2462. var glyphIds = [];
  2463. for (i = 0; i < segCount; i += 1) {
  2464. var segment = t.segments[i];
  2465. endCounts = endCounts.concat({name: 'end_' + i, type: 'USHORT', value: segment.end});
  2466. startCounts = startCounts.concat({name: 'start_' + i, type: 'USHORT', value: segment.start});
  2467. idDeltas = idDeltas.concat({name: 'idDelta_' + i, type: 'SHORT', value: segment.delta});
  2468. idRangeOffsets = idRangeOffsets.concat({name: 'idRangeOffset_' + i, type: 'USHORT', value: segment.offset});
  2469. if (segment.glyphId !== undefined) {
  2470. glyphIds = glyphIds.concat({name: 'glyph_' + i, type: 'USHORT', value: segment.glyphId});
  2471. }
  2472. }
  2473. t.fields = t.fields.concat(endCounts);
  2474. t.fields.push({name: 'reservedPad', type: 'USHORT', value: 0});
  2475. t.fields = t.fields.concat(startCounts);
  2476. t.fields = t.fields.concat(idDeltas);
  2477. t.fields = t.fields.concat(idRangeOffsets);
  2478. t.fields = t.fields.concat(glyphIds);
  2479. t.length = 14 + // Subtable header
  2480. endCounts.length * 2 +
  2481. 2 + // reservedPad
  2482. startCounts.length * 2 +
  2483. idDeltas.length * 2 +
  2484. idRangeOffsets.length * 2 +
  2485. glyphIds.length * 2;
  2486. return t;
  2487. }
  2488. exports.parse = parseCmapTable;
  2489. exports.make = makeCmapTable;
  2490. },{"../check":2,"../parse":9,"../table":11}],14:[function(_dereq_,module,exports){
  2491. // The `glyf` table describes the glyphs in TrueType outline format.
  2492. // http://www.microsoft.com/typography/otspec/glyf.htm
  2493. 'use strict';
  2494. var check = _dereq_('../check');
  2495. var glyphset = _dereq_('../glyphset');
  2496. var parse = _dereq_('../parse');
  2497. var path = _dereq_('../path');
  2498. // Parse the coordinate data for a glyph.
  2499. function parseGlyphCoordinate(p, flag, previousValue, shortVectorBitMask, sameBitMask) {
  2500. var v;
  2501. if ((flag & shortVectorBitMask) > 0) {
  2502. // The coordinate is 1 byte long.
  2503. v = p.parseByte();
  2504. // The `same` bit is re-used for short values to signify the sign of the value.
  2505. if ((flag & sameBitMask) === 0) {
  2506. v = -v;
  2507. }
  2508. v = previousValue + v;
  2509. } else {
  2510. // The coordinate is 2 bytes long.
  2511. // If the `same` bit is set, the coordinate is the same as the previous coordinate.
  2512. if ((flag & sameBitMask) > 0) {
  2513. v = previousValue;
  2514. } else {
  2515. // Parse the coordinate as a signed 16-bit delta value.
  2516. v = previousValue + p.parseShort();
  2517. }
  2518. }
  2519. return v;
  2520. }
  2521. // Parse a TrueType glyph.
  2522. function parseGlyph(glyph, data, start) {
  2523. var p = new parse.Parser(data, start);
  2524. glyph.numberOfContours = p.parseShort();
  2525. glyph.xMin = p.parseShort();
  2526. glyph.yMin = p.parseShort();
  2527. glyph.xMax = p.parseShort();
  2528. glyph.yMax = p.parseShort();
  2529. var flags;
  2530. var flag;
  2531. if (glyph.numberOfContours > 0) {
  2532. var i;
  2533. // This glyph is not a composite.
  2534. var endPointIndices = glyph.endPointIndices = [];
  2535. for (i = 0; i < glyph.numberOfContours; i += 1) {
  2536. endPointIndices.push(p.parseUShort());
  2537. }
  2538. glyph.instructionLength = p.parseUShort();
  2539. glyph.instructions = [];
  2540. for (i = 0; i < glyph.instructionLength; i += 1) {
  2541. glyph.instructions.push(p.parseByte());
  2542. }
  2543. var numberOfCoordinates = endPointIndices[endPointIndices.length - 1] + 1;
  2544. flags = [];
  2545. for (i = 0; i < numberOfCoordinates; i += 1) {
  2546. flag = p.parseByte();
  2547. flags.push(flag);
  2548. // If bit 3 is set, we repeat this flag n times, where n is the next byte.
  2549. if ((flag & 8) > 0) {
  2550. var repeatCount = p.parseByte();
  2551. for (var j = 0; j < repeatCount; j += 1) {
  2552. flags.push(flag);
  2553. i += 1;
  2554. }
  2555. }
  2556. }
  2557. check.argument(flags.length === numberOfCoordinates, 'Bad flags.');
  2558. if (endPointIndices.length > 0) {
  2559. var points = [];
  2560. var point;
  2561. // X/Y coordinates are relative to the previous point, except for the first point which is relative to 0,0.
  2562. if (numberOfCoordinates > 0) {
  2563. for (i = 0; i < numberOfCoordinates; i += 1) {
  2564. flag = flags[i];
  2565. point = {};
  2566. point.onCurve = !!(flag & 1);
  2567. point.lastPointOfContour = endPointIndices.indexOf(i) >= 0;
  2568. points.push(point);
  2569. }
  2570. var px = 0;
  2571. for (i = 0; i < numberOfCoordinates; i += 1) {
  2572. flag = flags[i];
  2573. point = points[i];
  2574. point.x = parseGlyphCoordinate(p, flag, px, 2, 16);
  2575. px = point.x;
  2576. }
  2577. var py = 0;
  2578. for (i = 0; i < numberOfCoordinates; i += 1) {
  2579. flag = flags[i];
  2580. point = points[i];
  2581. point.y = parseGlyphCoordinate(p, flag, py, 4, 32);
  2582. py = point.y;
  2583. }
  2584. }
  2585. glyph.points = points;
  2586. } else {
  2587. glyph.points = [];
  2588. }
  2589. } else if (glyph.numberOfContours === 0) {
  2590. glyph.points = [];
  2591. } else {
  2592. glyph.isComposite = true;
  2593. glyph.points = [];
  2594. glyph.components = [];
  2595. var moreComponents = true;
  2596. while (moreComponents) {
  2597. flags = p.parseUShort();
  2598. var component = {
  2599. glyphIndex: p.parseUShort(),
  2600. xScale: 1,
  2601. scale01: 0,
  2602. scale10: 0,
  2603. yScale: 1,
  2604. dx: 0,
  2605. dy: 0
  2606. };
  2607. if ((flags & 1) > 0) {
  2608. // The arguments are words
  2609. component.dx = p.parseShort();
  2610. component.dy = p.parseShort();
  2611. } else {
  2612. // The arguments are bytes
  2613. component.dx = p.parseChar();
  2614. component.dy = p.parseChar();
  2615. }
  2616. if ((flags & 8) > 0) {
  2617. // We have a scale
  2618. component.xScale = component.yScale = p.parseF2Dot14();
  2619. } else if ((flags & 64) > 0) {
  2620. // We have an X / Y scale
  2621. component.xScale = p.parseF2Dot14();
  2622. component.yScale = p.parseF2Dot14();
  2623. } else if ((flags & 128) > 0) {
  2624. // We have a 2x2 transformation
  2625. component.xScale = p.parseF2Dot14();
  2626. component.scale01 = p.parseF2Dot14();
  2627. component.scale10 = p.parseF2Dot14();
  2628. component.yScale = p.parseF2Dot14();
  2629. }
  2630. glyph.components.push(component);
  2631. moreComponents = !!(flags & 32);
  2632. }
  2633. }
  2634. }
  2635. // Transform an array of points and return a new array.
  2636. function transformPoints(points, transform) {
  2637. var newPoints = [];
  2638. for (var i = 0; i < points.length; i += 1) {
  2639. var pt = points[i];
  2640. var newPt = {
  2641. x: transform.xScale * pt.x + transform.scale01 * pt.y + transform.dx,
  2642. y: transform.scale10 * pt.x + transform.yScale * pt.y + transform.dy,
  2643. onCurve: pt.onCurve,
  2644. lastPointOfContour: pt.lastPointOfContour
  2645. };
  2646. newPoints.push(newPt);
  2647. }
  2648. return newPoints;
  2649. }
  2650. function getContours(points) {
  2651. var contours = [];
  2652. var currentContour = [];
  2653. for (var i = 0; i < points.length; i += 1) {
  2654. var pt = points[i];
  2655. currentContour.push(pt);
  2656. if (pt.lastPointOfContour) {
  2657. contours.push(currentContour);
  2658. currentContour = [];
  2659. }
  2660. }
  2661. check.argument(currentContour.length === 0, 'There are still points left in the current contour.');
  2662. return contours;
  2663. }
  2664. // Convert the TrueType glyph outline to a Path.
  2665. function getPath(points) {
  2666. var p = new path.Path();
  2667. if (!points) {
  2668. return p;
  2669. }
  2670. var contours = getContours(points);
  2671. for (var i = 0; i < contours.length; i += 1) {
  2672. var contour = contours[i];
  2673. var firstPt = contour[0];
  2674. var lastPt = contour[contour.length - 1];
  2675. var curvePt;
  2676. var realFirstPoint;
  2677. if (firstPt.onCurve) {
  2678. curvePt = null;
  2679. // The first point will be consumed by the moveTo command,
  2680. // so skip it in the loop.
  2681. realFirstPoint = true;
  2682. } else {
  2683. if (lastPt.onCurve) {
  2684. // If the first point is off-curve and the last point is on-curve,
  2685. // start at the last point.
  2686. firstPt = lastPt;
  2687. } else {
  2688. // If both first and last points are off-curve, start at their middle.
  2689. firstPt = { x: (firstPt.x + lastPt.x) / 2, y: (firstPt.y + lastPt.y) / 2 };
  2690. }
  2691. curvePt = firstPt;
  2692. // The first point is synthesized, so don't skip the real first point.
  2693. realFirstPoint = false;
  2694. }
  2695. p.moveTo(firstPt.x, firstPt.y);
  2696. for (var j = realFirstPoint ? 1 : 0; j < contour.length; j += 1) {
  2697. var pt = contour[j];
  2698. var prevPt = j === 0 ? firstPt : contour[j - 1];
  2699. if (prevPt.onCurve && pt.onCurve) {
  2700. // This is a straight line.
  2701. p.lineTo(pt.x, pt.y);
  2702. } else if (prevPt.onCurve && !pt.onCurve) {
  2703. curvePt = pt;
  2704. } else if (!prevPt.onCurve && !pt.onCurve) {
  2705. var midPt = { x: (prevPt.x + pt.x) / 2, y: (prevPt.y + pt.y) / 2 };
  2706. p.quadraticCurveTo(prevPt.x, prevPt.y, midPt.x, midPt.y);
  2707. curvePt = pt;
  2708. } else if (!prevPt.onCurve && pt.onCurve) {
  2709. // Previous point off-curve, this point on-curve.
  2710. p.quadraticCurveTo(curvePt.x, curvePt.y, pt.x, pt.y);
  2711. curvePt = null;
  2712. } else {
  2713. throw new Error('Invalid state.');
  2714. }
  2715. }
  2716. if (firstPt !== lastPt) {
  2717. // Connect the last and first points
  2718. if (curvePt) {
  2719. p.quadraticCurveTo(curvePt.x, curvePt.y, firstPt.x, firstPt.y);
  2720. } else {
  2721. p.lineTo(firstPt.x, firstPt.y);
  2722. }
  2723. }
  2724. }
  2725. p.closePath();
  2726. return p;
  2727. }
  2728. function buildPath(glyphs, glyph) {
  2729. if (glyph.isComposite) {
  2730. for (var j = 0; j < glyph.components.length; j += 1) {
  2731. var component = glyph.components[j];
  2732. var componentGlyph = glyphs.get(component.glyphIndex);
  2733. if (componentGlyph.points) {
  2734. var transformedPoints = transformPoints(componentGlyph.points, component);
  2735. glyph.points = glyph.points.concat(transformedPoints);
  2736. }
  2737. }
  2738. }
  2739. return getPath(glyph.points);
  2740. }
  2741. // Parse all the glyphs according to the offsets from the `loca` table.
  2742. function parseGlyfTable(data, start, loca, font) {
  2743. var glyphs = new glyphset.GlyphSet(font);
  2744. var i;
  2745. // The last element of the loca table is invalid.
  2746. for (i = 0; i < loca.length - 1; i += 1) {
  2747. var offset = loca[i];
  2748. var nextOffset = loca[i + 1];
  2749. if (offset !== nextOffset) {
  2750. glyphs.push(i, glyphset.ttfGlyphLoader(font, i, parseGlyph, data, start + offset, buildPath));
  2751. } else {
  2752. glyphs.push(i, glyphset.glyphLoader(font, i));
  2753. }
  2754. }
  2755. return glyphs;
  2756. }
  2757. exports.parse = parseGlyfTable;
  2758. },{"../check":2,"../glyphset":7,"../parse":9,"../path":10}],15:[function(_dereq_,module,exports){
  2759. // The `GPOS` table contains kerning pairs, among other things.
  2760. // https://www.microsoft.com/typography/OTSPEC/gpos.htm
  2761. 'use strict';
  2762. var check = _dereq_('../check');
  2763. var parse = _dereq_('../parse');
  2764. // Parse ScriptList and FeatureList tables of GPOS, GSUB, GDEF, BASE, JSTF tables.
  2765. // These lists are unused by now, this function is just the basis for a real parsing.
  2766. function parseTaggedListTable(data, start) {
  2767. var p = new parse.Parser(data, start);
  2768. var n = p.parseUShort();
  2769. var list = [];
  2770. for (var i = 0; i < n; i++) {
  2771. list[p.parseTag()] = { offset: p.parseUShort() };
  2772. }
  2773. return list;
  2774. }
  2775. // Parse a coverage table in a GSUB, GPOS or GDEF table.
  2776. // Format 1 is a simple list of glyph ids,
  2777. // Format 2 is a list of ranges. It is expanded in a list of glyphs, maybe not the best idea.
  2778. function parseCoverageTable(data, start) {
  2779. var p = new parse.Parser(data, start);
  2780. var format = p.parseUShort();
  2781. var count = p.parseUShort();
  2782. if (format === 1) {
  2783. return p.parseUShortList(count);
  2784. }
  2785. else if (format === 2) {
  2786. var coverage = [];
  2787. for (; count--;) {
  2788. var begin = p.parseUShort();
  2789. var end = p.parseUShort();
  2790. var index = p.parseUShort();
  2791. for (var i = begin; i <= end; i++) {
  2792. coverage[index++] = i;
  2793. }
  2794. }
  2795. return coverage;
  2796. }
  2797. }
  2798. // Parse a Class Definition Table in a GSUB, GPOS or GDEF table.
  2799. // Returns a function that gets a class value from a glyph ID.
  2800. function parseClassDefTable(data, start) {
  2801. var p = new parse.Parser(data, start);
  2802. var format = p.parseUShort();
  2803. if (format === 1) {
  2804. // Format 1 specifies a range of consecutive glyph indices, one class per glyph ID.
  2805. var startGlyph = p.parseUShort();
  2806. var glyphCount = p.parseUShort();
  2807. var classes = p.parseUShortList(glyphCount);
  2808. return function(glyphID) {
  2809. return classes[glyphID - startGlyph] || 0;
  2810. };
  2811. }
  2812. else if (format === 2) {
  2813. // Format 2 defines multiple groups of glyph indices that belong to the same class.
  2814. var rangeCount = p.parseUShort();
  2815. var startGlyphs = [];
  2816. var endGlyphs = [];
  2817. var classValues = [];
  2818. for (var i = 0; i < rangeCount; i++) {
  2819. startGlyphs[i] = p.parseUShort();
  2820. endGlyphs[i] = p.parseUShort();
  2821. classValues[i] = p.parseUShort();
  2822. }
  2823. return function(glyphID) {
  2824. var l = 0;
  2825. var r = startGlyphs.length - 1;
  2826. while (l < r) {
  2827. var c = (l + r + 1) >> 1;
  2828. if (glyphID < startGlyphs[c]) {
  2829. r = c - 1;
  2830. } else {
  2831. l = c;
  2832. }
  2833. }
  2834. if (startGlyphs[l] <= glyphID && glyphID <= endGlyphs[l]) {
  2835. return classValues[l] || 0;
  2836. }
  2837. return 0;
  2838. };
  2839. }
  2840. }
  2841. // Parse a pair adjustment positioning subtable, format 1 or format 2
  2842. // The subtable is returned in the form of a lookup function.
  2843. function parsePairPosSubTable(data, start) {
  2844. var p = new parse.Parser(data, start);
  2845. // This part is common to format 1 and format 2 subtables
  2846. var format = p.parseUShort();
  2847. var coverageOffset = p.parseUShort();
  2848. var coverage = parseCoverageTable(data, start + coverageOffset);
  2849. // valueFormat 4: XAdvance only, 1: XPlacement only, 0: no ValueRecord for second glyph
  2850. // Only valueFormat1=4 and valueFormat2=0 is supported.
  2851. var valueFormat1 = p.parseUShort();
  2852. var valueFormat2 = p.parseUShort();
  2853. var value1;
  2854. var value2;
  2855. if (valueFormat1 !== 4 || valueFormat2 !== 0) return;
  2856. var sharedPairSets = {};
  2857. if (format === 1) {
  2858. // Pair Positioning Adjustment: Format 1
  2859. var pairSetCount = p.parseUShort();
  2860. var pairSet = [];
  2861. // Array of offsets to PairSet tables-from beginning of PairPos subtable-ordered by Coverage Index
  2862. var pairSetOffsets = p.parseOffset16List(pairSetCount);
  2863. for (var firstGlyph = 0; firstGlyph < pairSetCount; firstGlyph++) {
  2864. var pairSetOffset = pairSetOffsets[firstGlyph];
  2865. var sharedPairSet = sharedPairSets[pairSetOffset];
  2866. if (!sharedPairSet) {
  2867. // Parse a pairset table in a pair adjustment subtable format 1
  2868. sharedPairSet = {};
  2869. p.relativeOffset = pairSetOffset;
  2870. var pairValueCount = p.parseUShort();
  2871. for (; pairValueCount--;) {
  2872. var secondGlyph = p.parseUShort();
  2873. if (valueFormat1) value1 = p.parseShort();
  2874. if (valueFormat2) value2 = p.parseShort();
  2875. // We only support valueFormat1 = 4 and valueFormat2 = 0,
  2876. // so value1 is the XAdvance and value2 is empty.
  2877. sharedPairSet[secondGlyph] = value1;
  2878. }
  2879. }
  2880. pairSet[coverage[firstGlyph]] = sharedPairSet;
  2881. }
  2882. return function(leftGlyph, rightGlyph) {
  2883. var pairs = pairSet[leftGlyph];
  2884. if (pairs) return pairs[rightGlyph];
  2885. };
  2886. }
  2887. else if (format === 2) {
  2888. // Pair Positioning Adjustment: Format 2
  2889. var classDef1Offset = p.parseUShort();
  2890. var classDef2Offset = p.parseUShort();
  2891. var class1Count = p.parseUShort();
  2892. var class2Count = p.parseUShort();
  2893. var getClass1 = parseClassDefTable(data, start + classDef1Offset);
  2894. var getClass2 = parseClassDefTable(data, start + classDef2Offset);
  2895. // Parse kerning values by class pair.
  2896. var kerningMatrix = [];
  2897. for (var i = 0; i < class1Count; i++) {
  2898. var kerningRow = kerningMatrix[i] = [];
  2899. for (var j = 0; j < class2Count; j++) {
  2900. if (valueFormat1) value1 = p.parseShort();
  2901. if (valueFormat2) value2 = p.parseShort();
  2902. // We only support valueFormat1 = 4 and valueFormat2 = 0,
  2903. // so value1 is the XAdvance and value2 is empty.
  2904. kerningRow[j] = value1;
  2905. }
  2906. }
  2907. // Convert coverage list to a hash
  2908. var covered = {};
  2909. for (i = 0; i < coverage.length; i++) covered[coverage[i]] = 1;
  2910. // Get the kerning value for a specific glyph pair.
  2911. return function(leftGlyph, rightGlyph) {
  2912. if (!covered[leftGlyph]) return;
  2913. var class1 = getClass1(leftGlyph);
  2914. var class2 = getClass2(rightGlyph);
  2915. var kerningRow = kerningMatrix[class1];
  2916. if (kerningRow) {
  2917. return kerningRow[class2];
  2918. }
  2919. };
  2920. }
  2921. }
  2922. // Parse a LookupTable (present in of GPOS, GSUB, GDEF, BASE, JSTF tables).
  2923. function parseLookupTable(data, start) {
  2924. var p = new parse.Parser(data, start);
  2925. var lookupType = p.parseUShort();
  2926. var lookupFlag = p.parseUShort();
  2927. var useMarkFilteringSet = lookupFlag & 0x10;
  2928. var subTableCount = p.parseUShort();
  2929. var subTableOffsets = p.parseOffset16List(subTableCount);
  2930. var table = {
  2931. lookupType: lookupType,
  2932. lookupFlag: lookupFlag,
  2933. markFilteringSet: useMarkFilteringSet ? p.parseUShort() : -1
  2934. };
  2935. // LookupType 2, Pair adjustment
  2936. if (lookupType === 2) {
  2937. var subtables = [];
  2938. for (var i = 0; i < subTableCount; i++) {
  2939. subtables.push(parsePairPosSubTable(data, start + subTableOffsets[i]));
  2940. }
  2941. // Return a function which finds the kerning values in the subtables.
  2942. table.getKerningValue = function(leftGlyph, rightGlyph) {
  2943. for (var i = subtables.length; i--;) {
  2944. var value = subtables[i](leftGlyph, rightGlyph);
  2945. if (value !== undefined) return value;
  2946. }
  2947. return 0;
  2948. };
  2949. }
  2950. return table;
  2951. }
  2952. // Parse the `GPOS` table which contains, among other things, kerning pairs.
  2953. // https://www.microsoft.com/typography/OTSPEC/gpos.htm
  2954. function parseGposTable(data, start, font) {
  2955. var p = new parse.Parser(data, start);
  2956. var tableVersion = p.parseFixed();
  2957. check.argument(tableVersion === 1, 'Unsupported GPOS table version.');
  2958. // ScriptList and FeatureList - ignored for now
  2959. parseTaggedListTable(data, start + p.parseUShort());
  2960. // 'kern' is the feature we are looking for.
  2961. parseTaggedListTable(data, start + p.parseUShort());
  2962. // LookupList
  2963. var lookupListOffset = p.parseUShort();
  2964. p.relativeOffset = lookupListOffset;
  2965. var lookupCount = p.parseUShort();
  2966. var lookupTableOffsets = p.parseOffset16List(lookupCount);
  2967. var lookupListAbsoluteOffset = start + lookupListOffset;
  2968. for (var i = 0; i < lookupCount; i++) {
  2969. var table = parseLookupTable(data, lookupListAbsoluteOffset + lookupTableOffsets[i]);
  2970. if (table.lookupType === 2 && !font.getGposKerningValue) font.getGposKerningValue = table.getKerningValue;
  2971. }
  2972. }
  2973. exports.parse = parseGposTable;
  2974. },{"../check":2,"../parse":9}],16:[function(_dereq_,module,exports){
  2975. // The `head` table contains global information about the font.
  2976. // https://www.microsoft.com/typography/OTSPEC/head.htm
  2977. 'use strict';
  2978. var check = _dereq_('../check');
  2979. var parse = _dereq_('../parse');
  2980. var table = _dereq_('../table');
  2981. // Parse the header `head` table
  2982. function parseHeadTable(data, start) {
  2983. var head = {};
  2984. var p = new parse.Parser(data, start);
  2985. head.version = p.parseVersion();
  2986. head.fontRevision = Math.round(p.parseFixed() * 1000) / 1000;
  2987. head.checkSumAdjustment = p.parseULong();
  2988. head.magicNumber = p.parseULong();
  2989. check.argument(head.magicNumber === 0x5F0F3CF5, 'Font header has wrong magic number.');
  2990. head.flags = p.parseUShort();
  2991. head.unitsPerEm = p.parseUShort();
  2992. head.created = p.parseLongDateTime();
  2993. head.modified = p.parseLongDateTime();
  2994. head.xMin = p.parseShort();
  2995. head.yMin = p.parseShort();
  2996. head.xMax = p.parseShort();
  2997. head.yMax = p.parseShort();
  2998. head.macStyle = p.parseUShort();
  2999. head.lowestRecPPEM = p.parseUShort();
  3000. head.fontDirectionHint = p.parseShort();
  3001. head.indexToLocFormat = p.parseShort(); // 50
  3002. head.glyphDataFormat = p.parseShort();
  3003. return head;
  3004. }
  3005. function makeHeadTable(options) {
  3006. return new table.Table('head', [
  3007. {name: 'version', type: 'FIXED', value: 0x00010000},
  3008. {name: 'fontRevision', type: 'FIXED', value: 0x00010000},
  3009. {name: 'checkSumAdjustment', type: 'ULONG', value: 0},
  3010. {name: 'magicNumber', type: 'ULONG', value: 0x5F0F3CF5},
  3011. {name: 'flags', type: 'USHORT', value: 0},
  3012. {name: 'unitsPerEm', type: 'USHORT', value: 1000},
  3013. {name: 'created', type: 'LONGDATETIME', value: 0},
  3014. {name: 'modified', type: 'LONGDATETIME', value: 0},
  3015. {name: 'xMin', type: 'SHORT', value: 0},
  3016. {name: 'yMin', type: 'SHORT', value: 0},
  3017. {name: 'xMax', type: 'SHORT', value: 0},
  3018. {name: 'yMax', type: 'SHORT', value: 0},
  3019. {name: 'macStyle', type: 'USHORT', value: 0},
  3020. {name: 'lowestRecPPEM', type: 'USHORT', value: 0},
  3021. {name: 'fontDirectionHint', type: 'SHORT', value: 2},
  3022. {name: 'indexToLocFormat', type: 'SHORT', value: 0},
  3023. {name: 'glyphDataFormat', type: 'SHORT', value: 0}
  3024. ], options);
  3025. }
  3026. exports.parse = parseHeadTable;
  3027. exports.make = makeHeadTable;
  3028. },{"../check":2,"../parse":9,"../table":11}],17:[function(_dereq_,module,exports){
  3029. // The `hhea` table contains information for horizontal layout.
  3030. // https://www.microsoft.com/typography/OTSPEC/hhea.htm
  3031. 'use strict';
  3032. var parse = _dereq_('../parse');
  3033. var table = _dereq_('../table');
  3034. // Parse the horizontal header `hhea` table
  3035. function parseHheaTable(data, start) {
  3036. var hhea = {};
  3037. var p = new parse.Parser(data, start);
  3038. hhea.version = p.parseVersion();
  3039. hhea.ascender = p.parseShort();
  3040. hhea.descender = p.parseShort();
  3041. hhea.lineGap = p.parseShort();
  3042. hhea.advanceWidthMax = p.parseUShort();
  3043. hhea.minLeftSideBearing = p.parseShort();
  3044. hhea.minRightSideBearing = p.parseShort();
  3045. hhea.xMaxExtent = p.parseShort();
  3046. hhea.caretSlopeRise = p.parseShort();
  3047. hhea.caretSlopeRun = p.parseShort();
  3048. hhea.caretOffset = p.parseShort();
  3049. p.relativeOffset += 8;
  3050. hhea.metricDataFormat = p.parseShort();
  3051. hhea.numberOfHMetrics = p.parseUShort();
  3052. return hhea;
  3053. }
  3054. function makeHheaTable(options) {
  3055. return new table.Table('hhea', [
  3056. {name: 'version', type: 'FIXED', value: 0x00010000},
  3057. {name: 'ascender', type: 'FWORD', value: 0},
  3058. {name: 'descender', type: 'FWORD', value: 0},
  3059. {name: 'lineGap', type: 'FWORD', value: 0},
  3060. {name: 'advanceWidthMax', type: 'UFWORD', value: 0},
  3061. {name: 'minLeftSideBearing', type: 'FWORD', value: 0},
  3062. {name: 'minRightSideBearing', type: 'FWORD', value: 0},
  3063. {name: 'xMaxExtent', type: 'FWORD', value: 0},
  3064. {name: 'caretSlopeRise', type: 'SHORT', value: 1},
  3065. {name: 'caretSlopeRun', type: 'SHORT', value: 0},
  3066. {name: 'caretOffset', type: 'SHORT', value: 0},
  3067. {name: 'reserved1', type: 'SHORT', value: 0},
  3068. {name: 'reserved2', type: 'SHORT', value: 0},
  3069. {name: 'reserved3', type: 'SHORT', value: 0},
  3070. {name: 'reserved4', type: 'SHORT', value: 0},
  3071. {name: 'metricDataFormat', type: 'SHORT', value: 0},
  3072. {name: 'numberOfHMetrics', type: 'USHORT', value: 0}
  3073. ], options);
  3074. }
  3075. exports.parse = parseHheaTable;
  3076. exports.make = makeHheaTable;
  3077. },{"../parse":9,"../table":11}],18:[function(_dereq_,module,exports){
  3078. // The `hmtx` table contains the horizontal metrics for all glyphs.
  3079. // https://www.microsoft.com/typography/OTSPEC/hmtx.htm
  3080. 'use strict';
  3081. var parse = _dereq_('../parse');
  3082. var table = _dereq_('../table');
  3083. // Parse the `hmtx` table, which contains the horizontal metrics for all glyphs.
  3084. // This function augments the glyph array, adding the advanceWidth and leftSideBearing to each glyph.
  3085. function parseHmtxTable(data, start, numMetrics, numGlyphs, glyphs) {
  3086. var advanceWidth;
  3087. var leftSideBearing;
  3088. var p = new parse.Parser(data, start);
  3089. for (var i = 0; i < numGlyphs; i += 1) {
  3090. // If the font is monospaced, only one entry is needed. This last entry applies to all subsequent glyphs.
  3091. if (i < numMetrics) {
  3092. advanceWidth = p.parseUShort();
  3093. leftSideBearing = p.parseShort();
  3094. }
  3095. var glyph = glyphs.get(i);
  3096. glyph.advanceWidth = advanceWidth;
  3097. glyph.leftSideBearing = leftSideBearing;
  3098. }
  3099. }
  3100. function makeHmtxTable(glyphs) {
  3101. var t = new table.Table('hmtx', []);
  3102. for (var i = 0; i < glyphs.length; i += 1) {
  3103. var glyph = glyphs.get(i);
  3104. var advanceWidth = glyph.advanceWidth || 0;
  3105. var leftSideBearing = glyph.leftSideBearing || 0;
  3106. t.fields.push({name: 'advanceWidth_' + i, type: 'USHORT', value: advanceWidth});
  3107. t.fields.push({name: 'leftSideBearing_' + i, type: 'SHORT', value: leftSideBearing});
  3108. }
  3109. return t;
  3110. }
  3111. exports.parse = parseHmtxTable;
  3112. exports.make = makeHmtxTable;
  3113. },{"../parse":9,"../table":11}],19:[function(_dereq_,module,exports){
  3114. // The `kern` table contains kerning pairs.
  3115. // Note that some fonts use the GPOS OpenType layout table to specify kerning.
  3116. // https://www.microsoft.com/typography/OTSPEC/kern.htm
  3117. 'use strict';
  3118. var check = _dereq_('../check');
  3119. var parse = _dereq_('../parse');
  3120. // Parse the `kern` table which contains kerning pairs.
  3121. function parseKernTable(data, start) {
  3122. var pairs = {};
  3123. var p = new parse.Parser(data, start);
  3124. var tableVersion = p.parseUShort();
  3125. check.argument(tableVersion === 0, 'Unsupported kern table version.');
  3126. // Skip nTables.
  3127. p.skip('uShort', 1);
  3128. var subTableVersion = p.parseUShort();
  3129. check.argument(subTableVersion === 0, 'Unsupported kern sub-table version.');
  3130. // Skip subTableLength, subTableCoverage
  3131. p.skip('uShort', 2);
  3132. var nPairs = p.parseUShort();
  3133. // Skip searchRange, entrySelector, rangeShift.
  3134. p.skip('uShort', 3);
  3135. for (var i = 0; i < nPairs; i += 1) {
  3136. var leftIndex = p.parseUShort();
  3137. var rightIndex = p.parseUShort();
  3138. var value = p.parseShort();
  3139. pairs[leftIndex + ',' + rightIndex] = value;
  3140. }
  3141. return pairs;
  3142. }
  3143. exports.parse = parseKernTable;
  3144. },{"../check":2,"../parse":9}],20:[function(_dereq_,module,exports){
  3145. // The `loca` table stores the offsets to the locations of the glyphs in the font.
  3146. // https://www.microsoft.com/typography/OTSPEC/loca.htm
  3147. 'use strict';
  3148. var parse = _dereq_('../parse');
  3149. // Parse the `loca` table. This table stores the offsets to the locations of the glyphs in the font,
  3150. // relative to the beginning of the glyphData table.
  3151. // The number of glyphs stored in the `loca` table is specified in the `maxp` table (under numGlyphs)
  3152. // The loca table has two versions: a short version where offsets are stored as uShorts, and a long
  3153. // version where offsets are stored as uLongs. The `head` table specifies which version to use
  3154. // (under indexToLocFormat).
  3155. function parseLocaTable(data, start, numGlyphs, shortVersion) {
  3156. var p = new parse.Parser(data, start);
  3157. var parseFn = shortVersion ? p.parseUShort : p.parseULong;
  3158. // There is an extra entry after the last index element to compute the length of the last glyph.
  3159. // That's why we use numGlyphs + 1.
  3160. var glyphOffsets = [];
  3161. for (var i = 0; i < numGlyphs + 1; i += 1) {
  3162. var glyphOffset = parseFn.call(p);
  3163. if (shortVersion) {
  3164. // The short table version stores the actual offset divided by 2.
  3165. glyphOffset *= 2;
  3166. }
  3167. glyphOffsets.push(glyphOffset);
  3168. }
  3169. return glyphOffsets;
  3170. }
  3171. exports.parse = parseLocaTable;
  3172. },{"../parse":9}],21:[function(_dereq_,module,exports){
  3173. // The `maxp` table establishes the memory requirements for the font.
  3174. // We need it just to get the number of glyphs in the font.
  3175. // https://www.microsoft.com/typography/OTSPEC/maxp.htm
  3176. 'use strict';
  3177. var parse = _dereq_('../parse');
  3178. var table = _dereq_('../table');
  3179. // Parse the maximum profile `maxp` table.
  3180. function parseMaxpTable(data, start) {
  3181. var maxp = {};
  3182. var p = new parse.Parser(data, start);
  3183. maxp.version = p.parseVersion();
  3184. maxp.numGlyphs = p.parseUShort();
  3185. if (maxp.version === 1.0) {
  3186. maxp.maxPoints = p.parseUShort();
  3187. maxp.maxContours = p.parseUShort();
  3188. maxp.maxCompositePoints = p.parseUShort();
  3189. maxp.maxCompositeContours = p.parseUShort();
  3190. maxp.maxZones = p.parseUShort();
  3191. maxp.maxTwilightPoints = p.parseUShort();
  3192. maxp.maxStorage = p.parseUShort();
  3193. maxp.maxFunctionDefs = p.parseUShort();
  3194. maxp.maxInstructionDefs = p.parseUShort();
  3195. maxp.maxStackElements = p.parseUShort();
  3196. maxp.maxSizeOfInstructions = p.parseUShort();
  3197. maxp.maxComponentElements = p.parseUShort();
  3198. maxp.maxComponentDepth = p.parseUShort();
  3199. }
  3200. return maxp;
  3201. }
  3202. function makeMaxpTable(numGlyphs) {
  3203. return new table.Table('maxp', [
  3204. {name: 'version', type: 'FIXED', value: 0x00005000},
  3205. {name: 'numGlyphs', type: 'USHORT', value: numGlyphs}
  3206. ]);
  3207. }
  3208. exports.parse = parseMaxpTable;
  3209. exports.make = makeMaxpTable;
  3210. },{"../parse":9,"../table":11}],22:[function(_dereq_,module,exports){
  3211. // The `name` naming table.
  3212. // https://www.microsoft.com/typography/OTSPEC/name.htm
  3213. 'use strict';
  3214. var encode = _dereq_('../types').encode;
  3215. var parse = _dereq_('../parse');
  3216. var table = _dereq_('../table');
  3217. // NameIDs for the name table.
  3218. var nameTableNames = [
  3219. 'copyright', // 0
  3220. 'fontFamily', // 1
  3221. 'fontSubfamily', // 2
  3222. 'uniqueID', // 3
  3223. 'fullName', // 4
  3224. 'version', // 5
  3225. 'postScriptName', // 6
  3226. 'trademark', // 7
  3227. 'manufacturer', // 8
  3228. 'designer', // 9
  3229. 'description', // 10
  3230. 'manufacturerURL', // 11
  3231. 'designerURL', // 12
  3232. 'licence', // 13
  3233. 'licenceURL', // 14
  3234. 'reserved', // 15
  3235. 'preferredFamily', // 16
  3236. 'preferredSubfamily', // 17
  3237. 'compatibleFullName', // 18
  3238. 'sampleText', // 19
  3239. 'postScriptFindFontName', // 20
  3240. 'wwsFamily', // 21
  3241. 'wwsSubfamily' // 22
  3242. ];
  3243. // Parse the naming `name` table
  3244. // Only Windows Unicode English names are supported.
  3245. // Format 1 additional fields are not supported
  3246. function parseNameTable(data, start) {
  3247. var name = {};
  3248. var p = new parse.Parser(data, start);
  3249. name.format = p.parseUShort();
  3250. var count = p.parseUShort();
  3251. var stringOffset = p.offset + p.parseUShort();
  3252. var unknownCount = 0;
  3253. for (var i = 0; i < count; i++) {
  3254. var platformID = p.parseUShort();
  3255. var encodingID = p.parseUShort();
  3256. var languageID = p.parseUShort();
  3257. var nameID = p.parseUShort();
  3258. var property = nameTableNames[nameID];
  3259. var byteLength = p.parseUShort();
  3260. var offset = p.parseUShort();
  3261. // platformID - encodingID - languageID standard combinations :
  3262. // 1 - 0 - 0 : Macintosh, Roman, English
  3263. // 3 - 1 - 0x409 : Windows, Unicode BMP (UCS-2), en-US
  3264. if (platformID === 3 && encodingID === 1 && languageID === 0x409) {
  3265. var codePoints = [];
  3266. var length = byteLength / 2;
  3267. for (var j = 0; j < length; j++, offset += 2) {
  3268. codePoints[j] = parse.getShort(data, stringOffset + offset);
  3269. }
  3270. var str = String.fromCharCode.apply(null, codePoints);
  3271. if (property) {
  3272. name[property] = str;
  3273. }
  3274. else {
  3275. unknownCount++;
  3276. name['unknown' + unknownCount] = str;
  3277. }
  3278. }
  3279. }
  3280. if (name.format === 1) {
  3281. name.langTagCount = p.parseUShort();
  3282. }
  3283. return name;
  3284. }
  3285. function makeNameRecord(platformID, encodingID, languageID, nameID, length, offset) {
  3286. return new table.Table('NameRecord', [
  3287. {name: 'platformID', type: 'USHORT', value: platformID},
  3288. {name: 'encodingID', type: 'USHORT', value: encodingID},
  3289. {name: 'languageID', type: 'USHORT', value: languageID},
  3290. {name: 'nameID', type: 'USHORT', value: nameID},
  3291. {name: 'length', type: 'USHORT', value: length},
  3292. {name: 'offset', type: 'USHORT', value: offset}
  3293. ]);
  3294. }
  3295. function addMacintoshNameRecord(t, recordID, s, offset) {
  3296. // Macintosh, Roman, English
  3297. var stringBytes = encode.STRING(s);
  3298. t.records.push(makeNameRecord(1, 0, 0, recordID, stringBytes.length, offset));
  3299. t.strings.push(stringBytes);
  3300. offset += stringBytes.length;
  3301. return offset;
  3302. }
  3303. function addWindowsNameRecord(t, recordID, s, offset) {
  3304. // Windows, Unicode BMP (UCS-2), US English
  3305. var utf16Bytes = encode.UTF16(s);
  3306. t.records.push(makeNameRecord(3, 1, 0x0409, recordID, utf16Bytes.length, offset));
  3307. t.strings.push(utf16Bytes);
  3308. offset += utf16Bytes.length;
  3309. return offset;
  3310. }
  3311. function makeNameTable(options) {
  3312. var t = new table.Table('name', [
  3313. {name: 'format', type: 'USHORT', value: 0},
  3314. {name: 'count', type: 'USHORT', value: 0},
  3315. {name: 'stringOffset', type: 'USHORT', value: 0}
  3316. ]);
  3317. t.records = [];
  3318. t.strings = [];
  3319. var offset = 0;
  3320. var i;
  3321. var s;
  3322. // Add Macintosh records first
  3323. for (i = 0; i < nameTableNames.length; i += 1) {
  3324. if (options[nameTableNames[i]] !== undefined) {
  3325. s = options[nameTableNames[i]];
  3326. offset = addMacintoshNameRecord(t, i, s, offset);
  3327. }
  3328. }
  3329. // Then add Windows records
  3330. for (i = 0; i < nameTableNames.length; i += 1) {
  3331. if (options[nameTableNames[i]] !== undefined) {
  3332. s = options[nameTableNames[i]];
  3333. offset = addWindowsNameRecord(t, i, s, offset);
  3334. }
  3335. }
  3336. t.count = t.records.length;
  3337. t.stringOffset = 6 + t.count * 12;
  3338. for (i = 0; i < t.records.length; i += 1) {
  3339. t.fields.push({name: 'record_' + i, type: 'TABLE', value: t.records[i]});
  3340. }
  3341. for (i = 0; i < t.strings.length; i += 1) {
  3342. t.fields.push({name: 'string_' + i, type: 'LITERAL', value: t.strings[i]});
  3343. }
  3344. return t;
  3345. }
  3346. exports.parse = parseNameTable;
  3347. exports.make = makeNameTable;
  3348. },{"../parse":9,"../table":11,"../types":26}],23:[function(_dereq_,module,exports){
  3349. // The `OS/2` table contains metrics required in OpenType fonts.
  3350. // https://www.microsoft.com/typography/OTSPEC/os2.htm
  3351. 'use strict';
  3352. var parse = _dereq_('../parse');
  3353. var table = _dereq_('../table');
  3354. var unicodeRanges = [
  3355. {begin: 0x0000, end: 0x007F}, // Basic Latin
  3356. {begin: 0x0080, end: 0x00FF}, // Latin-1 Supplement
  3357. {begin: 0x0100, end: 0x017F}, // Latin Extended-A
  3358. {begin: 0x0180, end: 0x024F}, // Latin Extended-B
  3359. {begin: 0x0250, end: 0x02AF}, // IPA Extensions
  3360. {begin: 0x02B0, end: 0x02FF}, // Spacing Modifier Letters
  3361. {begin: 0x0300, end: 0x036F}, // Combining Diacritical Marks
  3362. {begin: 0x0370, end: 0x03FF}, // Greek and Coptic
  3363. {begin: 0x2C80, end: 0x2CFF}, // Coptic
  3364. {begin: 0x0400, end: 0x04FF}, // Cyrillic
  3365. {begin: 0x0530, end: 0x058F}, // Armenian
  3366. {begin: 0x0590, end: 0x05FF}, // Hebrew
  3367. {begin: 0xA500, end: 0xA63F}, // Vai
  3368. {begin: 0x0600, end: 0x06FF}, // Arabic
  3369. {begin: 0x07C0, end: 0x07FF}, // NKo
  3370. {begin: 0x0900, end: 0x097F}, // Devanagari
  3371. {begin: 0x0980, end: 0x09FF}, // Bengali
  3372. {begin: 0x0A00, end: 0x0A7F}, // Gurmukhi
  3373. {begin: 0x0A80, end: 0x0AFF}, // Gujarati
  3374. {begin: 0x0B00, end: 0x0B7F}, // Oriya
  3375. {begin: 0x0B80, end: 0x0BFF}, // Tamil
  3376. {begin: 0x0C00, end: 0x0C7F}, // Telugu
  3377. {begin: 0x0C80, end: 0x0CFF}, // Kannada
  3378. {begin: 0x0D00, end: 0x0D7F}, // Malayalam
  3379. {begin: 0x0E00, end: 0x0E7F}, // Thai
  3380. {begin: 0x0E80, end: 0x0EFF}, // Lao
  3381. {begin: 0x10A0, end: 0x10FF}, // Georgian
  3382. {begin: 0x1B00, end: 0x1B7F}, // Balinese
  3383. {begin: 0x1100, end: 0x11FF}, // Hangul Jamo
  3384. {begin: 0x1E00, end: 0x1EFF}, // Latin Extended Additional
  3385. {begin: 0x1F00, end: 0x1FFF}, // Greek Extended
  3386. {begin: 0x2000, end: 0x206F}, // General Punctuation
  3387. {begin: 0x2070, end: 0x209F}, // Superscripts And Subscripts
  3388. {begin: 0x20A0, end: 0x20CF}, // Currency Symbol
  3389. {begin: 0x20D0, end: 0x20FF}, // Combining Diacritical Marks For Symbols
  3390. {begin: 0x2100, end: 0x214F}, // Letterlike Symbols
  3391. {begin: 0x2150, end: 0x218F}, // Number Forms
  3392. {begin: 0x2190, end: 0x21FF}, // Arrows
  3393. {begin: 0x2200, end: 0x22FF}, // Mathematical Operators
  3394. {begin: 0x2300, end: 0x23FF}, // Miscellaneous Technical
  3395. {begin: 0x2400, end: 0x243F}, // Control Pictures
  3396. {begin: 0x2440, end: 0x245F}, // Optical Character Recognition
  3397. {begin: 0x2460, end: 0x24FF}, // Enclosed Alphanumerics
  3398. {begin: 0x2500, end: 0x257F}, // Box Drawing
  3399. {begin: 0x2580, end: 0x259F}, // Block Elements
  3400. {begin: 0x25A0, end: 0x25FF}, // Geometric Shapes
  3401. {begin: 0x2600, end: 0x26FF}, // Miscellaneous Symbols
  3402. {begin: 0x2700, end: 0x27BF}, // Dingbats
  3403. {begin: 0x3000, end: 0x303F}, // CJK Symbols And Punctuation
  3404. {begin: 0x3040, end: 0x309F}, // Hiragana
  3405. {begin: 0x30A0, end: 0x30FF}, // Katakana
  3406. {begin: 0x3100, end: 0x312F}, // Bopomofo
  3407. {begin: 0x3130, end: 0x318F}, // Hangul Compatibility Jamo
  3408. {begin: 0xA840, end: 0xA87F}, // Phags-pa
  3409. {begin: 0x3200, end: 0x32FF}, // Enclosed CJK Letters And Months
  3410. {begin: 0x3300, end: 0x33FF}, // CJK Compatibility
  3411. {begin: 0xAC00, end: 0xD7AF}, // Hangul Syllables
  3412. {begin: 0xD800, end: 0xDFFF}, // Non-Plane 0 *
  3413. {begin: 0x10900, end: 0x1091F}, // Phoenicia
  3414. {begin: 0x4E00, end: 0x9FFF}, // CJK Unified Ideographs
  3415. {begin: 0xE000, end: 0xF8FF}, // Private Use Area (plane 0)
  3416. {begin: 0x31C0, end: 0x31EF}, // CJK Strokes
  3417. {begin: 0xFB00, end: 0xFB4F}, // Alphabetic Presentation Forms
  3418. {begin: 0xFB50, end: 0xFDFF}, // Arabic Presentation Forms-A
  3419. {begin: 0xFE20, end: 0xFE2F}, // Combining Half Marks
  3420. {begin: 0xFE10, end: 0xFE1F}, // Vertical Forms
  3421. {begin: 0xFE50, end: 0xFE6F}, // Small Form Variants
  3422. {begin: 0xFE70, end: 0xFEFF}, // Arabic Presentation Forms-B
  3423. {begin: 0xFF00, end: 0xFFEF}, // Halfwidth And Fullwidth Forms
  3424. {begin: 0xFFF0, end: 0xFFFF}, // Specials
  3425. {begin: 0x0F00, end: 0x0FFF}, // Tibetan
  3426. {begin: 0x0700, end: 0x074F}, // Syriac
  3427. {begin: 0x0780, end: 0x07BF}, // Thaana
  3428. {begin: 0x0D80, end: 0x0DFF}, // Sinhala
  3429. {begin: 0x1000, end: 0x109F}, // Myanmar
  3430. {begin: 0x1200, end: 0x137F}, // Ethiopic
  3431. {begin: 0x13A0, end: 0x13FF}, // Cherokee
  3432. {begin: 0x1400, end: 0x167F}, // Unified Canadian Aboriginal Syllabics
  3433. {begin: 0x1680, end: 0x169F}, // Ogham
  3434. {begin: 0x16A0, end: 0x16FF}, // Runic
  3435. {begin: 0x1780, end: 0x17FF}, // Khmer
  3436. {begin: 0x1800, end: 0x18AF}, // Mongolian
  3437. {begin: 0x2800, end: 0x28FF}, // Braille Patterns
  3438. {begin: 0xA000, end: 0xA48F}, // Yi Syllables
  3439. {begin: 0x1700, end: 0x171F}, // Tagalog
  3440. {begin: 0x10300, end: 0x1032F}, // Old Italic
  3441. {begin: 0x10330, end: 0x1034F}, // Gothic
  3442. {begin: 0x10400, end: 0x1044F}, // Deseret
  3443. {begin: 0x1D000, end: 0x1D0FF}, // Byzantine Musical Symbols
  3444. {begin: 0x1D400, end: 0x1D7FF}, // Mathematical Alphanumeric Symbols
  3445. {begin: 0xFF000, end: 0xFFFFD}, // Private Use (plane 15)
  3446. {begin: 0xFE00, end: 0xFE0F}, // Variation Selectors
  3447. {begin: 0xE0000, end: 0xE007F}, // Tags
  3448. {begin: 0x1900, end: 0x194F}, // Limbu
  3449. {begin: 0x1950, end: 0x197F}, // Tai Le
  3450. {begin: 0x1980, end: 0x19DF}, // New Tai Lue
  3451. {begin: 0x1A00, end: 0x1A1F}, // Buginese
  3452. {begin: 0x2C00, end: 0x2C5F}, // Glagolitic
  3453. {begin: 0x2D30, end: 0x2D7F}, // Tifinagh
  3454. {begin: 0x4DC0, end: 0x4DFF}, // Yijing Hexagram Symbols
  3455. {begin: 0xA800, end: 0xA82F}, // Syloti Nagri
  3456. {begin: 0x10000, end: 0x1007F}, // Linear B Syllabary
  3457. {begin: 0x10140, end: 0x1018F}, // Ancient Greek Numbers
  3458. {begin: 0x10380, end: 0x1039F}, // Ugaritic
  3459. {begin: 0x103A0, end: 0x103DF}, // Old Persian
  3460. {begin: 0x10450, end: 0x1047F}, // Shavian
  3461. {begin: 0x10480, end: 0x104AF}, // Osmanya
  3462. {begin: 0x10800, end: 0x1083F}, // Cypriot Syllabary
  3463. {begin: 0x10A00, end: 0x10A5F}, // Kharoshthi
  3464. {begin: 0x1D300, end: 0x1D35F}, // Tai Xuan Jing Symbols
  3465. {begin: 0x12000, end: 0x123FF}, // Cuneiform
  3466. {begin: 0x1D360, end: 0x1D37F}, // Counting Rod Numerals
  3467. {begin: 0x1B80, end: 0x1BBF}, // Sundanese
  3468. {begin: 0x1C00, end: 0x1C4F}, // Lepcha
  3469. {begin: 0x1C50, end: 0x1C7F}, // Ol Chiki
  3470. {begin: 0xA880, end: 0xA8DF}, // Saurashtra
  3471. {begin: 0xA900, end: 0xA92F}, // Kayah Li
  3472. {begin: 0xA930, end: 0xA95F}, // Rejang
  3473. {begin: 0xAA00, end: 0xAA5F}, // Cham
  3474. {begin: 0x10190, end: 0x101CF}, // Ancient Symbols
  3475. {begin: 0x101D0, end: 0x101FF}, // Phaistos Disc
  3476. {begin: 0x102A0, end: 0x102DF}, // Carian
  3477. {begin: 0x1F030, end: 0x1F09F} // Domino Tiles
  3478. ];
  3479. function getUnicodeRange(unicode) {
  3480. for (var i = 0; i < unicodeRanges.length; i += 1) {
  3481. var range = unicodeRanges[i];
  3482. if (unicode >= range.begin && unicode < range.end) {
  3483. return i;
  3484. }
  3485. }
  3486. return -1;
  3487. }
  3488. // Parse the OS/2 and Windows metrics `OS/2` table
  3489. function parseOS2Table(data, start) {
  3490. var os2 = {};
  3491. var p = new parse.Parser(data, start);
  3492. os2.version = p.parseUShort();
  3493. os2.xAvgCharWidth = p.parseShort();
  3494. os2.usWeightClass = p.parseUShort();
  3495. os2.usWidthClass = p.parseUShort();
  3496. os2.fsType = p.parseUShort();
  3497. os2.ySubscriptXSize = p.parseShort();
  3498. os2.ySubscriptYSize = p.parseShort();
  3499. os2.ySubscriptXOffset = p.parseShort();
  3500. os2.ySubscriptYOffset = p.parseShort();
  3501. os2.ySuperscriptXSize = p.parseShort();
  3502. os2.ySuperscriptYSize = p.parseShort();
  3503. os2.ySuperscriptXOffset = p.parseShort();
  3504. os2.ySuperscriptYOffset = p.parseShort();
  3505. os2.yStrikeoutSize = p.parseShort();
  3506. os2.yStrikeoutPosition = p.parseShort();
  3507. os2.sFamilyClass = p.parseShort();
  3508. os2.panose = [];
  3509. for (var i = 0; i < 10; i++) {
  3510. os2.panose[i] = p.parseByte();
  3511. }
  3512. os2.ulUnicodeRange1 = p.parseULong();
  3513. os2.ulUnicodeRange2 = p.parseULong();
  3514. os2.ulUnicodeRange3 = p.parseULong();
  3515. os2.ulUnicodeRange4 = p.parseULong();
  3516. os2.achVendID = String.fromCharCode(p.parseByte(), p.parseByte(), p.parseByte(), p.parseByte());
  3517. os2.fsSelection = p.parseUShort();
  3518. os2.usFirstCharIndex = p.parseUShort();
  3519. os2.usLastCharIndex = p.parseUShort();
  3520. os2.sTypoAscender = p.parseShort();
  3521. os2.sTypoDescender = p.parseShort();
  3522. os2.sTypoLineGap = p.parseShort();
  3523. os2.usWinAscent = p.parseUShort();
  3524. os2.usWinDescent = p.parseUShort();
  3525. if (os2.version >= 1) {
  3526. os2.ulCodePageRange1 = p.parseULong();
  3527. os2.ulCodePageRange2 = p.parseULong();
  3528. }
  3529. if (os2.version >= 2) {
  3530. os2.sxHeight = p.parseShort();
  3531. os2.sCapHeight = p.parseShort();
  3532. os2.usDefaultChar = p.parseUShort();
  3533. os2.usBreakChar = p.parseUShort();
  3534. os2.usMaxContent = p.parseUShort();
  3535. }
  3536. return os2;
  3537. }
  3538. function makeOS2Table(options) {
  3539. return new table.Table('OS/2', [
  3540. {name: 'version', type: 'USHORT', value: 0x0003},
  3541. {name: 'xAvgCharWidth', type: 'SHORT', value: 0},
  3542. {name: 'usWeightClass', type: 'USHORT', value: 0},
  3543. {name: 'usWidthClass', type: 'USHORT', value: 0},
  3544. {name: 'fsType', type: 'USHORT', value: 0},
  3545. {name: 'ySubscriptXSize', type: 'SHORT', value: 650},
  3546. {name: 'ySubscriptYSize', type: 'SHORT', value: 699},
  3547. {name: 'ySubscriptXOffset', type: 'SHORT', value: 0},
  3548. {name: 'ySubscriptYOffset', type: 'SHORT', value: 140},
  3549. {name: 'ySuperscriptXSize', type: 'SHORT', value: 650},
  3550. {name: 'ySuperscriptYSize', type: 'SHORT', value: 699},
  3551. {name: 'ySuperscriptXOffset', type: 'SHORT', value: 0},
  3552. {name: 'ySuperscriptYOffset', type: 'SHORT', value: 479},
  3553. {name: 'yStrikeoutSize', type: 'SHORT', value: 49},
  3554. {name: 'yStrikeoutPosition', type: 'SHORT', value: 258},
  3555. {name: 'sFamilyClass', type: 'SHORT', value: 0},
  3556. {name: 'bFamilyType', type: 'BYTE', value: 0},
  3557. {name: 'bSerifStyle', type: 'BYTE', value: 0},
  3558. {name: 'bWeight', type: 'BYTE', value: 0},
  3559. {name: 'bProportion', type: 'BYTE', value: 0},
  3560. {name: 'bContrast', type: 'BYTE', value: 0},
  3561. {name: 'bStrokeVariation', type: 'BYTE', value: 0},
  3562. {name: 'bArmStyle', type: 'BYTE', value: 0},
  3563. {name: 'bLetterform', type: 'BYTE', value: 0},
  3564. {name: 'bMidline', type: 'BYTE', value: 0},
  3565. {name: 'bXHeight', type: 'BYTE', value: 0},
  3566. {name: 'ulUnicodeRange1', type: 'ULONG', value: 0},
  3567. {name: 'ulUnicodeRange2', type: 'ULONG', value: 0},
  3568. {name: 'ulUnicodeRange3', type: 'ULONG', value: 0},
  3569. {name: 'ulUnicodeRange4', type: 'ULONG', value: 0},
  3570. {name: 'achVendID', type: 'CHARARRAY', value: 'XXXX'},
  3571. {name: 'fsSelection', type: 'USHORT', value: 0},
  3572. {name: 'usFirstCharIndex', type: 'USHORT', value: 0},
  3573. {name: 'usLastCharIndex', type: 'USHORT', value: 0},
  3574. {name: 'sTypoAscender', type: 'SHORT', value: 0},
  3575. {name: 'sTypoDescender', type: 'SHORT', value: 0},
  3576. {name: 'sTypoLineGap', type: 'SHORT', value: 0},
  3577. {name: 'usWinAscent', type: 'USHORT', value: 0},
  3578. {name: 'usWinDescent', type: 'USHORT', value: 0},
  3579. {name: 'ulCodePageRange1', type: 'ULONG', value: 0},
  3580. {name: 'ulCodePageRange2', type: 'ULONG', value: 0},
  3581. {name: 'sxHeight', type: 'SHORT', value: 0},
  3582. {name: 'sCapHeight', type: 'SHORT', value: 0},
  3583. {name: 'usDefaultChar', type: 'USHORT', value: 0},
  3584. {name: 'usBreakChar', type: 'USHORT', value: 0},
  3585. {name: 'usMaxContext', type: 'USHORT', value: 0}
  3586. ], options);
  3587. }
  3588. exports.unicodeRanges = unicodeRanges;
  3589. exports.getUnicodeRange = getUnicodeRange;
  3590. exports.parse = parseOS2Table;
  3591. exports.make = makeOS2Table;
  3592. },{"../parse":9,"../table":11}],24:[function(_dereq_,module,exports){
  3593. // The `post` table stores additional PostScript information, such as glyph names.
  3594. // https://www.microsoft.com/typography/OTSPEC/post.htm
  3595. 'use strict';
  3596. var encoding = _dereq_('../encoding');
  3597. var parse = _dereq_('../parse');
  3598. var table = _dereq_('../table');
  3599. // Parse the PostScript `post` table
  3600. function parsePostTable(data, start) {
  3601. var post = {};
  3602. var p = new parse.Parser(data, start);
  3603. var i;
  3604. post.version = p.parseVersion();
  3605. post.italicAngle = p.parseFixed();
  3606. post.underlinePosition = p.parseShort();
  3607. post.underlineThickness = p.parseShort();
  3608. post.isFixedPitch = p.parseULong();
  3609. post.minMemType42 = p.parseULong();
  3610. post.maxMemType42 = p.parseULong();
  3611. post.minMemType1 = p.parseULong();
  3612. post.maxMemType1 = p.parseULong();
  3613. switch (post.version) {
  3614. case 1:
  3615. post.names = encoding.standardNames.slice();
  3616. break;
  3617. case 2:
  3618. post.numberOfGlyphs = p.parseUShort();
  3619. post.glyphNameIndex = new Array(post.numberOfGlyphs);
  3620. for (i = 0; i < post.numberOfGlyphs; i++) {
  3621. post.glyphNameIndex[i] = p.parseUShort();
  3622. }
  3623. post.names = [];
  3624. for (i = 0; i < post.numberOfGlyphs; i++) {
  3625. if (post.glyphNameIndex[i] >= encoding.standardNames.length) {
  3626. var nameLength = p.parseChar();
  3627. post.names.push(p.parseString(nameLength));
  3628. }
  3629. }
  3630. break;
  3631. case 2.5:
  3632. post.numberOfGlyphs = p.parseUShort();
  3633. post.offset = new Array(post.numberOfGlyphs);
  3634. for (i = 0; i < post.numberOfGlyphs; i++) {
  3635. post.offset[i] = p.parseChar();
  3636. }
  3637. break;
  3638. }
  3639. return post;
  3640. }
  3641. function makePostTable() {
  3642. return new table.Table('post', [
  3643. {name: 'version', type: 'FIXED', value: 0x00030000},
  3644. {name: 'italicAngle', type: 'FIXED', value: 0},
  3645. {name: 'underlinePosition', type: 'FWORD', value: 0},
  3646. {name: 'underlineThickness', type: 'FWORD', value: 0},
  3647. {name: 'isFixedPitch', type: 'ULONG', value: 0},
  3648. {name: 'minMemType42', type: 'ULONG', value: 0},
  3649. {name: 'maxMemType42', type: 'ULONG', value: 0},
  3650. {name: 'minMemType1', type: 'ULONG', value: 0},
  3651. {name: 'maxMemType1', type: 'ULONG', value: 0}
  3652. ]);
  3653. }
  3654. exports.parse = parsePostTable;
  3655. exports.make = makePostTable;
  3656. },{"../encoding":4,"../parse":9,"../table":11}],25:[function(_dereq_,module,exports){
  3657. // The `sfnt` wrapper provides organization for the tables in the font.
  3658. // It is the top-level data structure in a font.
  3659. // https://www.microsoft.com/typography/OTSPEC/otff.htm
  3660. // Recommendations for creating OpenType Fonts:
  3661. // http://www.microsoft.com/typography/otspec140/recom.htm
  3662. 'use strict';
  3663. var check = _dereq_('../check');
  3664. var table = _dereq_('../table');
  3665. var cmap = _dereq_('./cmap');
  3666. var cff = _dereq_('./cff');
  3667. var head = _dereq_('./head');
  3668. var hhea = _dereq_('./hhea');
  3669. var hmtx = _dereq_('./hmtx');
  3670. var maxp = _dereq_('./maxp');
  3671. var _name = _dereq_('./name');
  3672. var os2 = _dereq_('./os2');
  3673. var post = _dereq_('./post');
  3674. function log2(v) {
  3675. return Math.log(v) / Math.log(2) | 0;
  3676. }
  3677. function computeCheckSum(bytes) {
  3678. while (bytes.length % 4 !== 0) {
  3679. bytes.push(0);
  3680. }
  3681. var sum = 0;
  3682. for (var i = 0; i < bytes.length; i += 4) {
  3683. sum += (bytes[i] << 24) +
  3684. (bytes[i + 1] << 16) +
  3685. (bytes[i + 2] << 8) +
  3686. (bytes[i + 3]);
  3687. }
  3688. sum %= Math.pow(2, 32);
  3689. return sum;
  3690. }
  3691. function makeTableRecord(tag, checkSum, offset, length) {
  3692. return new table.Table('Table Record', [
  3693. {name: 'tag', type: 'TAG', value: tag !== undefined ? tag : ''},
  3694. {name: 'checkSum', type: 'ULONG', value: checkSum !== undefined ? checkSum : 0},
  3695. {name: 'offset', type: 'ULONG', value: offset !== undefined ? offset : 0},
  3696. {name: 'length', type: 'ULONG', value: length !== undefined ? length : 0}
  3697. ]);
  3698. }
  3699. function makeSfntTable(tables) {
  3700. var sfnt = new table.Table('sfnt', [
  3701. {name: 'version', type: 'TAG', value: 'OTTO'},
  3702. {name: 'numTables', type: 'USHORT', value: 0},
  3703. {name: 'searchRange', type: 'USHORT', value: 0},
  3704. {name: 'entrySelector', type: 'USHORT', value: 0},
  3705. {name: 'rangeShift', type: 'USHORT', value: 0}
  3706. ]);
  3707. sfnt.tables = tables;
  3708. sfnt.numTables = tables.length;
  3709. var highestPowerOf2 = Math.pow(2, log2(sfnt.numTables));
  3710. sfnt.searchRange = 16 * highestPowerOf2;
  3711. sfnt.entrySelector = log2(highestPowerOf2);
  3712. sfnt.rangeShift = sfnt.numTables * 16 - sfnt.searchRange;
  3713. var recordFields = [];
  3714. var tableFields = [];
  3715. var offset = sfnt.sizeOf() + (makeTableRecord().sizeOf() * sfnt.numTables);
  3716. while (offset % 4 !== 0) {
  3717. offset += 1;
  3718. tableFields.push({name: 'padding', type: 'BYTE', value: 0});
  3719. }
  3720. for (var i = 0; i < tables.length; i += 1) {
  3721. var t = tables[i];
  3722. check.argument(t.tableName.length === 4, 'Table name' + t.tableName + ' is invalid.');
  3723. var tableLength = t.sizeOf();
  3724. var tableRecord = makeTableRecord(t.tableName, computeCheckSum(t.encode()), offset, tableLength);
  3725. recordFields.push({name: tableRecord.tag + ' Table Record', type: 'TABLE', value: tableRecord});
  3726. tableFields.push({name: t.tableName + ' table', type: 'TABLE', value: t});
  3727. offset += tableLength;
  3728. check.argument(!isNaN(offset), 'Something went wrong calculating the offset.');
  3729. while (offset % 4 !== 0) {
  3730. offset += 1;
  3731. tableFields.push({name: 'padding', type: 'BYTE', value: 0});
  3732. }
  3733. }
  3734. // Table records need to be sorted alphabetically.
  3735. recordFields.sort(function(r1, r2) {
  3736. if (r1.value.tag > r2.value.tag) {
  3737. return 1;
  3738. } else {
  3739. return -1;
  3740. }
  3741. });
  3742. sfnt.fields = sfnt.fields.concat(recordFields);
  3743. sfnt.fields = sfnt.fields.concat(tableFields);
  3744. return sfnt;
  3745. }
  3746. // Get the metrics for a character. If the string has more than one character
  3747. // this function returns metrics for the first available character.
  3748. // You can provide optional fallback metrics if no characters are available.
  3749. function metricsForChar(font, chars, notFoundMetrics) {
  3750. for (var i = 0; i < chars.length; i += 1) {
  3751. var glyphIndex = font.charToGlyphIndex(chars[i]);
  3752. if (glyphIndex > 0) {
  3753. var glyph = font.glyphs.get(glyphIndex);
  3754. return glyph.getMetrics();
  3755. }
  3756. }
  3757. return notFoundMetrics;
  3758. }
  3759. function average(vs) {
  3760. var sum = 0;
  3761. for (var i = 0; i < vs.length; i += 1) {
  3762. sum += vs[i];
  3763. }
  3764. return sum / vs.length;
  3765. }
  3766. // Convert the font object to a SFNT data structure.
  3767. // This structure contains all the necessary tables and metadata to create a binary OTF file.
  3768. function fontToSfntTable(font) {
  3769. var xMins = [];
  3770. var yMins = [];
  3771. var xMaxs = [];
  3772. var yMaxs = [];
  3773. var advanceWidths = [];
  3774. var leftSideBearings = [];
  3775. var rightSideBearings = [];
  3776. var firstCharIndex;
  3777. var lastCharIndex = 0;
  3778. var ulUnicodeRange1 = 0;
  3779. var ulUnicodeRange2 = 0;
  3780. var ulUnicodeRange3 = 0;
  3781. var ulUnicodeRange4 = 0;
  3782. for (var i = 0; i < font.glyphs.length; i += 1) {
  3783. var glyph = font.glyphs.get(i);
  3784. var unicode = glyph.unicode | 0;
  3785. if (firstCharIndex > unicode || firstCharIndex === null) {
  3786. firstCharIndex = unicode;
  3787. }
  3788. if (lastCharIndex < unicode) {
  3789. lastCharIndex = unicode;
  3790. }
  3791. var position = os2.getUnicodeRange(unicode);
  3792. if (position < 32) {
  3793. ulUnicodeRange1 |= 1 << position;
  3794. } else if (position < 64) {
  3795. ulUnicodeRange2 |= 1 << position - 32;
  3796. } else if (position < 96) {
  3797. ulUnicodeRange3 |= 1 << position - 64;
  3798. } else if (position < 123) {
  3799. ulUnicodeRange4 |= 1 << position - 96;
  3800. } else {
  3801. throw new Error('Unicode ranges bits > 123 are reserved for internal usage');
  3802. }
  3803. // Skip non-important characters.
  3804. if (glyph.name === '.notdef') continue;
  3805. var metrics = glyph.getMetrics();
  3806. xMins.push(metrics.xMin);
  3807. yMins.push(metrics.yMin);
  3808. xMaxs.push(metrics.xMax);
  3809. yMaxs.push(metrics.yMax);
  3810. leftSideBearings.push(metrics.leftSideBearing);
  3811. rightSideBearings.push(metrics.rightSideBearing);
  3812. advanceWidths.push(glyph.advanceWidth);
  3813. }
  3814. var globals = {
  3815. xMin: Math.min.apply(null, xMins),
  3816. yMin: Math.min.apply(null, yMins),
  3817. xMax: Math.max.apply(null, xMaxs),
  3818. yMax: Math.max.apply(null, yMaxs),
  3819. advanceWidthMax: Math.max.apply(null, advanceWidths),
  3820. advanceWidthAvg: average(advanceWidths),
  3821. minLeftSideBearing: Math.min.apply(null, leftSideBearings),
  3822. maxLeftSideBearing: Math.max.apply(null, leftSideBearings),
  3823. minRightSideBearing: Math.min.apply(null, rightSideBearings)
  3824. };
  3825. globals.ascender = font.ascender !== undefined ? font.ascender : globals.yMax;
  3826. globals.descender = font.descender !== undefined ? font.descender : globals.yMin;
  3827. var headTable = head.make({
  3828. unitsPerEm: font.unitsPerEm,
  3829. xMin: globals.xMin,
  3830. yMin: globals.yMin,
  3831. xMax: globals.xMax,
  3832. yMax: globals.yMax
  3833. });
  3834. var hheaTable = hhea.make({
  3835. ascender: globals.ascender,
  3836. descender: globals.descender,
  3837. advanceWidthMax: globals.advanceWidthMax,
  3838. minLeftSideBearing: globals.minLeftSideBearing,
  3839. minRightSideBearing: globals.minRightSideBearing,
  3840. xMaxExtent: globals.maxLeftSideBearing + (globals.xMax - globals.xMin),
  3841. numberOfHMetrics: font.glyphs.length
  3842. });
  3843. var maxpTable = maxp.make(font.glyphs.length);
  3844. var os2Table = os2.make({
  3845. xAvgCharWidth: Math.round(globals.advanceWidthAvg),
  3846. usWeightClass: 500, // Medium FIXME Make this configurable
  3847. usWidthClass: 5, // Medium (normal) FIXME Make this configurable
  3848. usFirstCharIndex: firstCharIndex,
  3849. usLastCharIndex: lastCharIndex,
  3850. ulUnicodeRange1: ulUnicodeRange1,
  3851. ulUnicodeRange2: ulUnicodeRange2,
  3852. ulUnicodeRange3: ulUnicodeRange3,
  3853. ulUnicodeRange4: ulUnicodeRange4,
  3854. // See http://typophile.com/node/13081 for more info on vertical metrics.
  3855. // We get metrics for typical characters (such as "x" for xHeight).
  3856. // We provide some fallback characters if characters are unavailable: their
  3857. // ordering was chosen experimentally.
  3858. sTypoAscender: globals.ascender,
  3859. sTypoDescender: globals.descender,
  3860. sTypoLineGap: 0,
  3861. usWinAscent: globals.ascender,
  3862. usWinDescent: -globals.descender,
  3863. sxHeight: metricsForChar(font, 'xyvw', {yMax: 0}).yMax,
  3864. sCapHeight: metricsForChar(font, 'HIKLEFJMNTZBDPRAGOQSUVWXY', globals).yMax,
  3865. usBreakChar: font.hasChar(' ') ? 32 : 0 // Use space as the break character, if available.
  3866. });
  3867. var hmtxTable = hmtx.make(font.glyphs);
  3868. var cmapTable = cmap.make(font.glyphs);
  3869. var fullName = font.familyName + ' ' + font.styleName;
  3870. var postScriptName = font.familyName.replace(/\s/g, '') + '-' + font.styleName;
  3871. var nameTable = _name.make({
  3872. copyright: font.copyright,
  3873. fontFamily: font.familyName,
  3874. fontSubfamily: font.styleName,
  3875. uniqueID: font.manufacturer + ':' + fullName,
  3876. fullName: fullName,
  3877. version: font.version,
  3878. postScriptName: postScriptName,
  3879. trademark: font.trademark,
  3880. manufacturer: font.manufacturer,
  3881. designer: font.designer,
  3882. description: font.description,
  3883. manufacturerURL: font.manufacturerURL,
  3884. designerURL: font.designerURL,
  3885. license: font.license,
  3886. licenseURL: font.licenseURL,
  3887. preferredFamily: font.familyName,
  3888. preferredSubfamily: font.styleName
  3889. });
  3890. var postTable = post.make();
  3891. var cffTable = cff.make(font.glyphs, {
  3892. version: font.version,
  3893. fullName: fullName,
  3894. familyName: font.familyName,
  3895. weightName: font.styleName,
  3896. postScriptName: postScriptName,
  3897. unitsPerEm: font.unitsPerEm
  3898. });
  3899. // Order the tables according to the the OpenType specification 1.4.
  3900. var tables = [headTable, hheaTable, maxpTable, os2Table, nameTable, cmapTable, postTable, cffTable, hmtxTable];
  3901. var sfntTable = makeSfntTable(tables);
  3902. // Compute the font's checkSum and store it in head.checkSumAdjustment.
  3903. var bytes = sfntTable.encode();
  3904. var checkSum = computeCheckSum(bytes);
  3905. var tableFields = sfntTable.fields;
  3906. var checkSumAdjusted = false;
  3907. for (i = 0; i < tableFields.length; i += 1) {
  3908. if (tableFields[i].name === 'head table') {
  3909. tableFields[i].value.checkSumAdjustment = 0xB1B0AFBA - checkSum;
  3910. checkSumAdjusted = true;
  3911. break;
  3912. }
  3913. }
  3914. if (!checkSumAdjusted) {
  3915. throw new Error('Could not find head table with checkSum to adjust.');
  3916. }
  3917. return sfntTable;
  3918. }
  3919. exports.computeCheckSum = computeCheckSum;
  3920. exports.make = makeSfntTable;
  3921. exports.fontToTable = fontToSfntTable;
  3922. },{"../check":2,"../table":11,"./cff":12,"./cmap":13,"./head":16,"./hhea":17,"./hmtx":18,"./maxp":21,"./name":22,"./os2":23,"./post":24}],26:[function(_dereq_,module,exports){
  3923. // Data types used in the OpenType font file.
  3924. // All OpenType fonts use Motorola-style byte ordering (Big Endian)
  3925. /* global WeakMap */
  3926. 'use strict';
  3927. var check = _dereq_('./check');
  3928. var LIMIT16 = 32768; // The limit at which a 16-bit number switches signs == 2^15
  3929. var LIMIT32 = 2147483648; // The limit at which a 32-bit number switches signs == 2 ^ 31
  3930. var decode = {};
  3931. var encode = {};
  3932. var sizeOf = {};
  3933. // Return a function that always returns the same value.
  3934. function constant(v) {
  3935. return function() {
  3936. return v;
  3937. };
  3938. }
  3939. // OpenType data types //////////////////////////////////////////////////////
  3940. // Convert an 8-bit unsigned integer to a list of 1 byte.
  3941. encode.BYTE = function(v) {
  3942. check.argument(v >= 0 && v <= 255, 'Byte value should be between 0 and 255.');
  3943. return [v];
  3944. };
  3945. sizeOf.BYTE = constant(1);
  3946. // Convert a 8-bit signed integer to a list of 1 byte.
  3947. encode.CHAR = function(v) {
  3948. return [v.charCodeAt(0)];
  3949. };
  3950. sizeOf.BYTE = constant(1);
  3951. // Convert an ASCII string to a list of bytes.
  3952. encode.CHARARRAY = function(v) {
  3953. var b = [];
  3954. for (var i = 0; i < v.length; i += 1) {
  3955. b.push(v.charCodeAt(i));
  3956. }
  3957. return b;
  3958. };
  3959. sizeOf.CHARARRAY = function(v) {
  3960. return v.length;
  3961. };
  3962. // Convert a 16-bit unsigned integer to a list of 2 bytes.
  3963. encode.USHORT = function(v) {
  3964. return [(v >> 8) & 0xFF, v & 0xFF];
  3965. };
  3966. sizeOf.USHORT = constant(2);
  3967. // Convert a 16-bit signed integer to a list of 2 bytes.
  3968. encode.SHORT = function(v) {
  3969. // Two's complement
  3970. if (v >= LIMIT16) {
  3971. v = -(2 * LIMIT16 - v);
  3972. }
  3973. return [(v >> 8) & 0xFF, v & 0xFF];
  3974. };
  3975. sizeOf.SHORT = constant(2);
  3976. // Convert a 24-bit unsigned integer to a list of 3 bytes.
  3977. encode.UINT24 = function(v) {
  3978. return [(v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF];
  3979. };
  3980. sizeOf.UINT24 = constant(3);
  3981. // Convert a 32-bit unsigned integer to a list of 4 bytes.
  3982. encode.ULONG = function(v) {
  3983. return [(v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF];
  3984. };
  3985. sizeOf.ULONG = constant(4);
  3986. // Convert a 32-bit unsigned integer to a list of 4 bytes.
  3987. encode.LONG = function(v) {
  3988. // Two's complement
  3989. if (v >= LIMIT32) {
  3990. v = -(2 * LIMIT32 - v);
  3991. }
  3992. return [(v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF];
  3993. };
  3994. sizeOf.LONG = constant(4);
  3995. encode.FIXED = encode.ULONG;
  3996. sizeOf.FIXED = sizeOf.ULONG;
  3997. encode.FWORD = encode.SHORT;
  3998. sizeOf.FWORD = sizeOf.SHORT;
  3999. encode.UFWORD = encode.USHORT;
  4000. sizeOf.UFWORD = sizeOf.USHORT;
  4001. // FIXME Implement LONGDATETIME
  4002. encode.LONGDATETIME = function() {
  4003. return [0, 0, 0, 0, 0, 0, 0, 0];
  4004. };
  4005. sizeOf.LONGDATETIME = constant(8);
  4006. // Convert a 4-char tag to a list of 4 bytes.
  4007. encode.TAG = function(v) {
  4008. check.argument(v.length === 4, 'Tag should be exactly 4 ASCII characters.');
  4009. return [v.charCodeAt(0),
  4010. v.charCodeAt(1),
  4011. v.charCodeAt(2),
  4012. v.charCodeAt(3)];
  4013. };
  4014. sizeOf.TAG = constant(4);
  4015. // CFF data types ///////////////////////////////////////////////////////////
  4016. encode.Card8 = encode.BYTE;
  4017. sizeOf.Card8 = sizeOf.BYTE;
  4018. encode.Card16 = encode.USHORT;
  4019. sizeOf.Card16 = sizeOf.USHORT;
  4020. encode.OffSize = encode.BYTE;
  4021. sizeOf.OffSize = sizeOf.BYTE;
  4022. encode.SID = encode.USHORT;
  4023. sizeOf.SID = sizeOf.USHORT;
  4024. // Convert a numeric operand or charstring number to a variable-size list of bytes.
  4025. encode.NUMBER = function(v) {
  4026. if (v >= -107 && v <= 107) {
  4027. return [v + 139];
  4028. } else if (v >= 108 && v <= 1131) {
  4029. v = v - 108;
  4030. return [(v >> 8) + 247, v & 0xFF];
  4031. } else if (v >= -1131 && v <= -108) {
  4032. v = -v - 108;
  4033. return [(v >> 8) + 251, v & 0xFF];
  4034. } else if (v >= -32768 && v <= 32767) {
  4035. return encode.NUMBER16(v);
  4036. } else {
  4037. return encode.NUMBER32(v);
  4038. }
  4039. };
  4040. sizeOf.NUMBER = function(v) {
  4041. return encode.NUMBER(v).length;
  4042. };
  4043. // Convert a signed number between -32768 and +32767 to a three-byte value.
  4044. // This ensures we always use three bytes, but is not the most compact format.
  4045. encode.NUMBER16 = function(v) {
  4046. return [28, (v >> 8) & 0xFF, v & 0xFF];
  4047. };
  4048. sizeOf.NUMBER16 = constant(2);
  4049. // Convert a signed number between -(2^31) and +(2^31-1) to a four-byte value.
  4050. // This is useful if you want to be sure you always use four bytes,
  4051. // at the expense of wasting a few bytes for smaller numbers.
  4052. encode.NUMBER32 = function(v) {
  4053. return [29, (v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF];
  4054. };
  4055. sizeOf.NUMBER32 = constant(4);
  4056. encode.REAL = function(v) {
  4057. var value = v.toString();
  4058. // Some numbers use an epsilon to encode the value. (e.g. JavaScript will store 0.0000001 as 1e-7)
  4059. // This code converts it back to a number without the epsilon.
  4060. var m = /\.(\d*?)(?:9{5,20}|0{5,20})\d{0,2}(?:e(.+)|$)/.exec(value);
  4061. if (m) {
  4062. var epsilon = parseFloat('1e' + ((m[2] ? +m[2] : 0) + m[1].length));
  4063. value = (Math.round(v * epsilon) / epsilon).toString();
  4064. }
  4065. var nibbles = '';
  4066. var i;
  4067. var ii;
  4068. for (i = 0, ii = value.length; i < ii; i += 1) {
  4069. var c = value[i];
  4070. if (c === 'e') {
  4071. nibbles += value[++i] === '-' ? 'c' : 'b';
  4072. } else if (c === '.') {
  4073. nibbles += 'a';
  4074. } else if (c === '-') {
  4075. nibbles += 'e';
  4076. } else {
  4077. nibbles += c;
  4078. }
  4079. }
  4080. nibbles += (nibbles.length & 1) ? 'f' : 'ff';
  4081. var out = [30];
  4082. for (i = 0, ii = nibbles.length; i < ii; i += 2) {
  4083. out.push(parseInt(nibbles.substr(i, 2), 16));
  4084. }
  4085. return out;
  4086. };
  4087. sizeOf.REAL = function(v) {
  4088. return encode.REAL(v).length;
  4089. };
  4090. encode.NAME = encode.CHARARRAY;
  4091. sizeOf.NAME = sizeOf.CHARARRAY;
  4092. encode.STRING = encode.CHARARRAY;
  4093. sizeOf.STRING = sizeOf.CHARARRAY;
  4094. // Convert a ASCII string to a list of UTF16 bytes.
  4095. encode.UTF16 = function(v) {
  4096. var b = [];
  4097. for (var i = 0; i < v.length; i += 1) {
  4098. b.push(0);
  4099. b.push(v.charCodeAt(i));
  4100. }
  4101. return b;
  4102. };
  4103. sizeOf.UTF16 = function(v) {
  4104. return v.length * 2;
  4105. };
  4106. // Convert a list of values to a CFF INDEX structure.
  4107. // The values should be objects containing name / type / value.
  4108. encode.INDEX = function(l) {
  4109. var i;
  4110. //var offset, offsets, offsetEncoder, encodedOffsets, encodedOffset, data,
  4111. // dataSize, i, v;
  4112. // Because we have to know which data type to use to encode the offsets,
  4113. // we have to go through the values twice: once to encode the data and
  4114. // calculate the offets, then again to encode the offsets using the fitting data type.
  4115. var offset = 1; // First offset is always 1.
  4116. var offsets = [offset];
  4117. var data = [];
  4118. var dataSize = 0;
  4119. for (i = 0; i < l.length; i += 1) {
  4120. var v = encode.OBJECT(l[i]);
  4121. Array.prototype.push.apply(data, v);
  4122. dataSize += v.length;
  4123. offset += v.length;
  4124. offsets.push(offset);
  4125. }
  4126. if (data.length === 0) {
  4127. return [0, 0];
  4128. }
  4129. var encodedOffsets = [];
  4130. var offSize = (1 + Math.floor(Math.log(dataSize) / Math.log(2)) / 8) | 0;
  4131. var offsetEncoder = [undefined, encode.BYTE, encode.USHORT, encode.UINT24, encode.ULONG][offSize];
  4132. for (i = 0; i < offsets.length; i += 1) {
  4133. var encodedOffset = offsetEncoder(offsets[i]);
  4134. Array.prototype.push.apply(encodedOffsets, encodedOffset);
  4135. }
  4136. return Array.prototype.concat(encode.Card16(l.length),
  4137. encode.OffSize(offSize),
  4138. encodedOffsets,
  4139. data);
  4140. };
  4141. sizeOf.INDEX = function(v) {
  4142. return encode.INDEX(v).length;
  4143. };
  4144. // Convert an object to a CFF DICT structure.
  4145. // The keys should be numeric.
  4146. // The values should be objects containing name / type / value.
  4147. encode.DICT = function(m) {
  4148. var d = [];
  4149. var keys = Object.keys(m);
  4150. var length = keys.length;
  4151. for (var i = 0; i < length; i += 1) {
  4152. // Object.keys() return string keys, but our keys are always numeric.
  4153. var k = parseInt(keys[i], 0);
  4154. var v = m[k];
  4155. // Value comes before the key.
  4156. d = d.concat(encode.OPERAND(v.value, v.type));
  4157. d = d.concat(encode.OPERATOR(k));
  4158. }
  4159. return d;
  4160. };
  4161. sizeOf.DICT = function(m) {
  4162. return encode.DICT(m).length;
  4163. };
  4164. encode.OPERATOR = function(v) {
  4165. if (v < 1200) {
  4166. return [v];
  4167. } else {
  4168. return [12, v - 1200];
  4169. }
  4170. };
  4171. encode.OPERAND = function(v, type) {
  4172. var d = [];
  4173. if (Array.isArray(type)) {
  4174. for (var i = 0; i < type.length; i += 1) {
  4175. check.argument(v.length === type.length, 'Not enough arguments given for type' + type);
  4176. d = d.concat(encode.OPERAND(v[i], type[i]));
  4177. }
  4178. } else {
  4179. if (type === 'SID') {
  4180. d = d.concat(encode.NUMBER(v));
  4181. } else if (type === 'offset') {
  4182. // We make it easy for ourselves and always encode offsets as
  4183. // 4 bytes. This makes offset calculation for the top dict easier.
  4184. d = d.concat(encode.NUMBER32(v));
  4185. } else if (type === 'number') {
  4186. d = d.concat(encode.NUMBER(v));
  4187. } else if (type === 'real') {
  4188. d = d.concat(encode.REAL(v));
  4189. } else {
  4190. throw new Error('Unknown operand type ' + type);
  4191. // FIXME Add support for booleans
  4192. }
  4193. }
  4194. return d;
  4195. };
  4196. encode.OP = encode.BYTE;
  4197. sizeOf.OP = sizeOf.BYTE;
  4198. // memoize charstring encoding using WeakMap if available
  4199. var wmm = typeof WeakMap === 'function' && new WeakMap();
  4200. // Convert a list of CharString operations to bytes.
  4201. encode.CHARSTRING = function(ops) {
  4202. if (wmm && wmm.has(ops)) {
  4203. return wmm.get(ops);
  4204. }
  4205. var d = [];
  4206. var length = ops.length;
  4207. for (var i = 0; i < length; i += 1) {
  4208. var op = ops[i];
  4209. d = d.concat(encode[op.type](op.value));
  4210. }
  4211. if (wmm) {
  4212. wmm.set(ops, d);
  4213. }
  4214. return d;
  4215. };
  4216. sizeOf.CHARSTRING = function(ops) {
  4217. return encode.CHARSTRING(ops).length;
  4218. };
  4219. // Utility functions ////////////////////////////////////////////////////////
  4220. // Convert an object containing name / type / value to bytes.
  4221. encode.OBJECT = function(v) {
  4222. var encodingFunction = encode[v.type];
  4223. check.argument(encodingFunction !== undefined, 'No encoding function for type ' + v.type);
  4224. return encodingFunction(v.value);
  4225. };
  4226. // Convert a table object to bytes.
  4227. // A table contains a list of fields containing the metadata (name, type and default value).
  4228. // The table itself has the field values set as attributes.
  4229. encode.TABLE = function(table) {
  4230. var d = [];
  4231. var length = table.fields.length;
  4232. for (var i = 0; i < length; i += 1) {
  4233. var field = table.fields[i];
  4234. var encodingFunction = encode[field.type];
  4235. check.argument(encodingFunction !== undefined, 'No encoding function for field type ' + field.type);
  4236. var value = table[field.name];
  4237. if (value === undefined) {
  4238. value = field.value;
  4239. }
  4240. var bytes = encodingFunction(value);
  4241. d = d.concat(bytes);
  4242. }
  4243. return d;
  4244. };
  4245. // Merge in a list of bytes.
  4246. encode.LITERAL = function(v) {
  4247. return v;
  4248. };
  4249. sizeOf.LITERAL = function(v) {
  4250. return v.length;
  4251. };
  4252. exports.decode = decode;
  4253. exports.encode = encode;
  4254. exports.sizeOf = sizeOf;
  4255. },{"./check":2}],27:[function(_dereq_,module,exports){
  4256. /*!
  4257. * Reqwest! A general purpose XHR connection manager
  4258. * license MIT (c) Dustin Diaz 2014
  4259. * https://github.com/ded/reqwest
  4260. */
  4261. !function (name, context, definition) {
  4262. if (typeof module != 'undefined' && module.exports) module.exports = definition()
  4263. else if (typeof define == 'function' && define.amd) define(definition)
  4264. else context[name] = definition()
  4265. }('reqwest', this, function () {
  4266. var win = window
  4267. , doc = document
  4268. , httpsRe = /^http/
  4269. , protocolRe = /(^\w+):\/\//
  4270. , twoHundo = /^(20\d|1223)$/ //http://stackoverflow.com/questions/10046972/msie-returns-status-code-of-1223-for-ajax-request
  4271. , byTag = 'getElementsByTagName'
  4272. , readyState = 'readyState'
  4273. , contentType = 'Content-Type'
  4274. , requestedWith = 'X-Requested-With'
  4275. , head = doc[byTag]('head')[0]
  4276. , uniqid = 0
  4277. , callbackPrefix = 'reqwest_' + (+new Date())
  4278. , lastValue // data stored by the most recent JSONP callback
  4279. , xmlHttpRequest = 'XMLHttpRequest'
  4280. , xDomainRequest = 'XDomainRequest'
  4281. , noop = function () {}
  4282. , isArray = typeof Array.isArray == 'function'
  4283. ? Array.isArray
  4284. : function (a) {
  4285. return a instanceof Array
  4286. }
  4287. , defaultHeaders = {
  4288. 'contentType': 'application/x-www-form-urlencoded'
  4289. , 'requestedWith': xmlHttpRequest
  4290. , 'accept': {
  4291. '*': 'text/javascript, text/html, application/xml, text/xml, */*'
  4292. , 'xml': 'application/xml, text/xml'
  4293. , 'html': 'text/html'
  4294. , 'text': 'text/plain'
  4295. , 'json': 'application/json, text/javascript'
  4296. , 'js': 'application/javascript, text/javascript'
  4297. }
  4298. }
  4299. , xhr = function(o) {
  4300. // is it x-domain
  4301. if (o['crossOrigin'] === true) {
  4302. var xhr = win[xmlHttpRequest] ? new XMLHttpRequest() : null
  4303. if (xhr && 'withCredentials' in xhr) {
  4304. return xhr
  4305. } else if (win[xDomainRequest]) {
  4306. return new XDomainRequest()
  4307. } else {
  4308. throw new Error('Browser does not support cross-origin requests')
  4309. }
  4310. } else if (win[xmlHttpRequest]) {
  4311. return new XMLHttpRequest()
  4312. } else {
  4313. return new ActiveXObject('Microsoft.XMLHTTP')
  4314. }
  4315. }
  4316. , globalSetupOptions = {
  4317. dataFilter: function (data) {
  4318. return data
  4319. }
  4320. }
  4321. function succeed(r) {
  4322. var protocol = protocolRe.exec(r.url);
  4323. protocol = (protocol && protocol[1]) || window.location.protocol;
  4324. return httpsRe.test(protocol) ? twoHundo.test(r.request.status) : !!r.request.response;
  4325. }
  4326. function handleReadyState(r, success, error) {
  4327. return function () {
  4328. // use _aborted to mitigate against IE err c00c023f
  4329. // (can't read props on aborted request objects)
  4330. if (r._aborted) return error(r.request)
  4331. if (r._timedOut) return error(r.request, 'Request is aborted: timeout')
  4332. if (r.request && r.request[readyState] == 4) {
  4333. r.request.onreadystatechange = noop
  4334. if (succeed(r)) success(r.request)
  4335. else
  4336. error(r.request)
  4337. }
  4338. }
  4339. }
  4340. function setHeaders(http, o) {
  4341. var headers = o['headers'] || {}
  4342. , h
  4343. headers['Accept'] = headers['Accept']
  4344. || defaultHeaders['accept'][o['type']]
  4345. || defaultHeaders['accept']['*']
  4346. var isAFormData = typeof FormData === 'function' && (o['data'] instanceof FormData);
  4347. // breaks cross-origin requests with legacy browsers
  4348. if (!o['crossOrigin'] && !headers[requestedWith]) headers[requestedWith] = defaultHeaders['requestedWith']
  4349. if (!headers[contentType] && !isAFormData) headers[contentType] = o['contentType'] || defaultHeaders['contentType']
  4350. for (h in headers)
  4351. headers.hasOwnProperty(h) && 'setRequestHeader' in http && http.setRequestHeader(h, headers[h])
  4352. }
  4353. function setCredentials(http, o) {
  4354. if (typeof o['withCredentials'] !== 'undefined' && typeof http.withCredentials !== 'undefined') {
  4355. http.withCredentials = !!o['withCredentials']
  4356. }
  4357. }
  4358. function generalCallback(data) {
  4359. lastValue = data
  4360. }
  4361. function urlappend (url, s) {
  4362. return url + (/\?/.test(url) ? '&' : '?') + s
  4363. }
  4364. function handleJsonp(o, fn, err, url) {
  4365. var reqId = uniqid++
  4366. , cbkey = o['jsonpCallback'] || 'callback' // the 'callback' key
  4367. , cbval = o['jsonpCallbackName'] || reqwest.getcallbackPrefix(reqId)
  4368. , cbreg = new RegExp('((^|\\?|&)' + cbkey + ')=([^&]+)')
  4369. , match = url.match(cbreg)
  4370. , script = doc.createElement('script')
  4371. , loaded = 0
  4372. , isIE10 = navigator.userAgent.indexOf('MSIE 10.0') !== -1
  4373. if (match) {
  4374. if (match[3] === '?') {
  4375. url = url.replace(cbreg, '$1=' + cbval) // wildcard callback func name
  4376. } else {
  4377. cbval = match[3] // provided callback func name
  4378. }
  4379. } else {
  4380. url = urlappend(url, cbkey + '=' + cbval) // no callback details, add 'em
  4381. }
  4382. win[cbval] = generalCallback
  4383. script.type = 'text/javascript'
  4384. script.src = url
  4385. script.async = true
  4386. if (typeof script.onreadystatechange !== 'undefined' && !isIE10) {
  4387. // need this for IE due to out-of-order onreadystatechange(), binding script
  4388. // execution to an event listener gives us control over when the script
  4389. // is executed. See http://jaubourg.net/2010/07/loading-script-as-onclick-handler-of.html
  4390. script.htmlFor = script.id = '_reqwest_' + reqId
  4391. }
  4392. script.onload = script.onreadystatechange = function () {
  4393. if ((script[readyState] && script[readyState] !== 'complete' && script[readyState] !== 'loaded') || loaded) {
  4394. return false
  4395. }
  4396. script.onload = script.onreadystatechange = null
  4397. script.onclick && script.onclick()
  4398. // Call the user callback with the last value stored and clean up values and scripts.
  4399. fn(lastValue)
  4400. lastValue = undefined
  4401. head.removeChild(script)
  4402. loaded = 1
  4403. }
  4404. // Add the script to the DOM head
  4405. head.appendChild(script)
  4406. // Enable JSONP timeout
  4407. return {
  4408. abort: function () {
  4409. script.onload = script.onreadystatechange = null
  4410. err({}, 'Request is aborted: timeout', {})
  4411. lastValue = undefined
  4412. head.removeChild(script)
  4413. loaded = 1
  4414. }
  4415. }
  4416. }
  4417. function getRequest(fn, err) {
  4418. var o = this.o
  4419. , method = (o['method'] || 'GET').toUpperCase()
  4420. , url = typeof o === 'string' ? o : o['url']
  4421. // convert non-string objects to query-string form unless o['processData'] is false
  4422. , data = (o['processData'] !== false && o['data'] && typeof o['data'] !== 'string')
  4423. ? reqwest.toQueryString(o['data'])
  4424. : (o['data'] || null)
  4425. , http
  4426. , sendWait = false
  4427. // if we're working on a GET request and we have data then we should append
  4428. // query string to end of URL and not post data
  4429. if ((o['type'] == 'jsonp' || method == 'GET') && data) {
  4430. url = urlappend(url, data)
  4431. data = null
  4432. }
  4433. if (o['type'] == 'jsonp') return handleJsonp(o, fn, err, url)
  4434. // get the xhr from the factory if passed
  4435. // if the factory returns null, fall-back to ours
  4436. http = (o.xhr && o.xhr(o)) || xhr(o)
  4437. http.open(method, url, o['async'] === false ? false : true)
  4438. setHeaders(http, o)
  4439. setCredentials(http, o)
  4440. if (win[xDomainRequest] && http instanceof win[xDomainRequest]) {
  4441. http.onload = fn
  4442. http.onerror = err
  4443. // NOTE: see
  4444. // http://social.msdn.microsoft.com/Forums/en-US/iewebdevelopment/thread/30ef3add-767c-4436-b8a9-f1ca19b4812e
  4445. http.onprogress = function() {}
  4446. sendWait = true
  4447. } else {
  4448. http.onreadystatechange = handleReadyState(this, fn, err)
  4449. }
  4450. o['before'] && o['before'](http)
  4451. if (sendWait) {
  4452. setTimeout(function () {
  4453. http.send(data)
  4454. }, 200)
  4455. } else {
  4456. http.send(data)
  4457. }
  4458. return http
  4459. }
  4460. function Reqwest(o, fn) {
  4461. this.o = o
  4462. this.fn = fn
  4463. init.apply(this, arguments)
  4464. }
  4465. function setType(header) {
  4466. // json, javascript, text/plain, text/html, xml
  4467. if (header.match('json')) return 'json'
  4468. if (header.match('javascript')) return 'js'
  4469. if (header.match('text')) return 'html'
  4470. if (header.match('xml')) return 'xml'
  4471. }
  4472. function init(o, fn) {
  4473. this.url = typeof o == 'string' ? o : o['url']
  4474. this.timeout = null
  4475. // whether request has been fulfilled for purpose
  4476. // of tracking the Promises
  4477. this._fulfilled = false
  4478. // success handlers
  4479. this._successHandler = function(){}
  4480. this._fulfillmentHandlers = []
  4481. // error handlers
  4482. this._errorHandlers = []
  4483. // complete (both success and fail) handlers
  4484. this._completeHandlers = []
  4485. this._erred = false
  4486. this._responseArgs = {}
  4487. var self = this
  4488. fn = fn || function () {}
  4489. if (o['timeout']) {
  4490. this.timeout = setTimeout(function () {
  4491. timedOut()
  4492. }, o['timeout'])
  4493. }
  4494. if (o['success']) {
  4495. this._successHandler = function () {
  4496. o['success'].apply(o, arguments)
  4497. }
  4498. }
  4499. if (o['error']) {
  4500. this._errorHandlers.push(function () {
  4501. o['error'].apply(o, arguments)
  4502. })
  4503. }
  4504. if (o['complete']) {
  4505. this._completeHandlers.push(function () {
  4506. o['complete'].apply(o, arguments)
  4507. })
  4508. }
  4509. function complete (resp) {
  4510. o['timeout'] && clearTimeout(self.timeout)
  4511. self.timeout = null
  4512. while (self._completeHandlers.length > 0) {
  4513. self._completeHandlers.shift()(resp)
  4514. }
  4515. }
  4516. function success (resp) {
  4517. var type = o['type'] || resp && setType(resp.getResponseHeader('Content-Type')) // resp can be undefined in IE
  4518. resp = (type !== 'jsonp') ? self.request : resp
  4519. // use global data filter on response text
  4520. var filteredResponse = globalSetupOptions.dataFilter(resp.responseText, type)
  4521. , r = filteredResponse
  4522. try {
  4523. resp.responseText = r
  4524. } catch (e) {
  4525. // can't assign this in IE<=8, just ignore
  4526. }
  4527. if (r) {
  4528. switch (type) {
  4529. case 'json':
  4530. try {
  4531. resp = win.JSON ? win.JSON.parse(r) : eval('(' + r + ')')
  4532. } catch (err) {
  4533. return error(resp, 'Could not parse JSON in response', err)
  4534. }
  4535. break
  4536. case 'js':
  4537. resp = eval(r)
  4538. break
  4539. case 'html':
  4540. resp = r
  4541. break
  4542. case 'xml':
  4543. resp = resp.responseXML
  4544. && resp.responseXML.parseError // IE trololo
  4545. && resp.responseXML.parseError.errorCode
  4546. && resp.responseXML.parseError.reason
  4547. ? null
  4548. : resp.responseXML
  4549. break
  4550. }
  4551. }
  4552. self._responseArgs.resp = resp
  4553. self._fulfilled = true
  4554. fn(resp)
  4555. self._successHandler(resp)
  4556. while (self._fulfillmentHandlers.length > 0) {
  4557. resp = self._fulfillmentHandlers.shift()(resp)
  4558. }
  4559. complete(resp)
  4560. }
  4561. function timedOut() {
  4562. self._timedOut = true
  4563. self.request.abort()
  4564. }
  4565. function error(resp, msg, t) {
  4566. resp = self.request
  4567. self._responseArgs.resp = resp
  4568. self._responseArgs.msg = msg
  4569. self._responseArgs.t = t
  4570. self._erred = true
  4571. while (self._errorHandlers.length > 0) {
  4572. self._errorHandlers.shift()(resp, msg, t)
  4573. }
  4574. complete(resp)
  4575. }
  4576. this.request = getRequest.call(this, success, error)
  4577. }
  4578. Reqwest.prototype = {
  4579. abort: function () {
  4580. this._aborted = true
  4581. this.request.abort()
  4582. }
  4583. , retry: function () {
  4584. init.call(this, this.o, this.fn)
  4585. }
  4586. /**
  4587. * Small deviation from the Promises A CommonJs specification
  4588. * http://wiki.commonjs.org/wiki/Promises/A
  4589. */
  4590. /**
  4591. * `then` will execute upon successful requests
  4592. */
  4593. , then: function (success, fail) {
  4594. success = success || function () {}
  4595. fail = fail || function () {}
  4596. if (this._fulfilled) {
  4597. this._responseArgs.resp = success(this._responseArgs.resp)
  4598. } else if (this._erred) {
  4599. fail(this._responseArgs.resp, this._responseArgs.msg, this._responseArgs.t)
  4600. } else {
  4601. this._fulfillmentHandlers.push(success)
  4602. this._errorHandlers.push(fail)
  4603. }
  4604. return this
  4605. }
  4606. /**
  4607. * `always` will execute whether the request succeeds or fails
  4608. */
  4609. , always: function (fn) {
  4610. if (this._fulfilled || this._erred) {
  4611. fn(this._responseArgs.resp)
  4612. } else {
  4613. this._completeHandlers.push(fn)
  4614. }
  4615. return this
  4616. }
  4617. /**
  4618. * `fail` will execute when the request fails
  4619. */
  4620. , fail: function (fn) {
  4621. if (this._erred) {
  4622. fn(this._responseArgs.resp, this._responseArgs.msg, this._responseArgs.t)
  4623. } else {
  4624. this._errorHandlers.push(fn)
  4625. }
  4626. return this
  4627. }
  4628. , 'catch': function (fn) {
  4629. return this.fail(fn)
  4630. }
  4631. }
  4632. function reqwest(o, fn) {
  4633. return new Reqwest(o, fn)
  4634. }
  4635. // normalize newline variants according to spec -> CRLF
  4636. function normalize(s) {
  4637. return s ? s.replace(/\r?\n/g, '\r\n') : ''
  4638. }
  4639. function serial(el, cb) {
  4640. var n = el.name
  4641. , t = el.tagName.toLowerCase()
  4642. , optCb = function (o) {
  4643. // IE gives value="" even where there is no value attribute
  4644. // 'specified' ref: http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-862529273
  4645. if (o && !o['disabled'])
  4646. cb(n, normalize(o['attributes']['value'] && o['attributes']['value']['specified'] ? o['value'] : o['text']))
  4647. }
  4648. , ch, ra, val, i
  4649. // don't serialize elements that are disabled or without a name
  4650. if (el.disabled || !n) return
  4651. switch (t) {
  4652. case 'input':
  4653. if (!/reset|button|image|file/i.test(el.type)) {
  4654. ch = /checkbox/i.test(el.type)
  4655. ra = /radio/i.test(el.type)
  4656. val = el.value
  4657. // WebKit gives us "" instead of "on" if a checkbox has no value, so correct it here
  4658. ;(!(ch || ra) || el.checked) && cb(n, normalize(ch && val === '' ? 'on' : val))
  4659. }
  4660. break
  4661. case 'textarea':
  4662. cb(n, normalize(el.value))
  4663. break
  4664. case 'select':
  4665. if (el.type.toLowerCase() === 'select-one') {
  4666. optCb(el.selectedIndex >= 0 ? el.options[el.selectedIndex] : null)
  4667. } else {
  4668. for (i = 0; el.length && i < el.length; i++) {
  4669. el.options[i].selected && optCb(el.options[i])
  4670. }
  4671. }
  4672. break
  4673. }
  4674. }
  4675. // collect up all form elements found from the passed argument elements all
  4676. // the way down to child elements; pass a '<form>' or form fields.
  4677. // called with 'this'=callback to use for serial() on each element
  4678. function eachFormElement() {
  4679. var cb = this
  4680. , e, i
  4681. , serializeSubtags = function (e, tags) {
  4682. var i, j, fa
  4683. for (i = 0; i < tags.length; i++) {
  4684. fa = e[byTag](tags[i])
  4685. for (j = 0; j < fa.length; j++) serial(fa[j], cb)
  4686. }
  4687. }
  4688. for (i = 0; i < arguments.length; i++) {
  4689. e = arguments[i]
  4690. if (/input|select|textarea/i.test(e.tagName)) serial(e, cb)
  4691. serializeSubtags(e, [ 'input', 'select', 'textarea' ])
  4692. }
  4693. }
  4694. // standard query string style serialization
  4695. function serializeQueryString() {
  4696. return reqwest.toQueryString(reqwest.serializeArray.apply(null, arguments))
  4697. }
  4698. // { 'name': 'value', ... } style serialization
  4699. function serializeHash() {
  4700. var hash = {}
  4701. eachFormElement.apply(function (name, value) {
  4702. if (name in hash) {
  4703. hash[name] && !isArray(hash[name]) && (hash[name] = [hash[name]])
  4704. hash[name].push(value)
  4705. } else hash[name] = value
  4706. }, arguments)
  4707. return hash
  4708. }
  4709. // [ { name: 'name', value: 'value' }, ... ] style serialization
  4710. reqwest.serializeArray = function () {
  4711. var arr = []
  4712. eachFormElement.apply(function (name, value) {
  4713. arr.push({name: name, value: value})
  4714. }, arguments)
  4715. return arr
  4716. }
  4717. reqwest.serialize = function () {
  4718. if (arguments.length === 0) return ''
  4719. var opt, fn
  4720. , args = Array.prototype.slice.call(arguments, 0)
  4721. opt = args.pop()
  4722. opt && opt.nodeType && args.push(opt) && (opt = null)
  4723. opt && (opt = opt.type)
  4724. if (opt == 'map') fn = serializeHash
  4725. else if (opt == 'array') fn = reqwest.serializeArray
  4726. else fn = serializeQueryString
  4727. return fn.apply(null, args)
  4728. }
  4729. reqwest.toQueryString = function (o, trad) {
  4730. var prefix, i
  4731. , traditional = trad || false
  4732. , s = []
  4733. , enc = encodeURIComponent
  4734. , add = function (key, value) {
  4735. // If value is a function, invoke it and return its value
  4736. value = ('function' === typeof value) ? value() : (value == null ? '' : value)
  4737. s[s.length] = enc(key) + '=' + enc(value)
  4738. }
  4739. // If an array was passed in, assume that it is an array of form elements.
  4740. if (isArray(o)) {
  4741. for (i = 0; o && i < o.length; i++) add(o[i]['name'], o[i]['value'])
  4742. } else {
  4743. // If traditional, encode the "old" way (the way 1.3.2 or older
  4744. // did it), otherwise encode params recursively.
  4745. for (prefix in o) {
  4746. if (o.hasOwnProperty(prefix)) buildParams(prefix, o[prefix], traditional, add)
  4747. }
  4748. }
  4749. // spaces should be + according to spec
  4750. return s.join('&').replace(/%20/g, '+')
  4751. }
  4752. function buildParams(prefix, obj, traditional, add) {
  4753. var name, i, v
  4754. , rbracket = /\[\]$/
  4755. if (isArray(obj)) {
  4756. // Serialize array item.
  4757. for (i = 0; obj && i < obj.length; i++) {
  4758. v = obj[i]
  4759. if (traditional || rbracket.test(prefix)) {
  4760. // Treat each array item as a scalar.
  4761. add(prefix, v)
  4762. } else {
  4763. buildParams(prefix + '[' + (typeof v === 'object' ? i : '') + ']', v, traditional, add)
  4764. }
  4765. }
  4766. } else if (obj && obj.toString() === '[object Object]') {
  4767. // Serialize object item.
  4768. for (name in obj) {
  4769. buildParams(prefix + '[' + name + ']', obj[name], traditional, add)
  4770. }
  4771. } else {
  4772. // Serialize scalar item.
  4773. add(prefix, obj)
  4774. }
  4775. }
  4776. reqwest.getcallbackPrefix = function () {
  4777. return callbackPrefix
  4778. }
  4779. // jQuery and Zepto compatibility, differences can be remapped here so you can call
  4780. // .ajax.compat(options, callback)
  4781. reqwest.compat = function (o, fn) {
  4782. if (o) {
  4783. o['type'] && (o['method'] = o['type']) && delete o['type']
  4784. o['dataType'] && (o['type'] = o['dataType'])
  4785. o['jsonpCallback'] && (o['jsonpCallbackName'] = o['jsonpCallback']) && delete o['jsonpCallback']
  4786. o['jsonp'] && (o['jsonpCallback'] = o['jsonp'])
  4787. }
  4788. return new Reqwest(o, fn)
  4789. }
  4790. reqwest.ajaxSetup = function (options) {
  4791. options = options || {}
  4792. for (var k in options) {
  4793. globalSetupOptions[k] = options[k]
  4794. }
  4795. }
  4796. return reqwest
  4797. });
  4798. },{}],28:[function(_dereq_,module,exports){
  4799. 'use strict';
  4800. var p5 = _dereq_('./core/core');
  4801. _dereq_('./color/p5.Color');
  4802. _dereq_('./core/p5.Element');
  4803. _dereq_('./typography/p5.Font');
  4804. _dereq_('./core/p5.Graphics');
  4805. _dereq_('./core/p5.Renderer2D');
  4806. _dereq_('./image/p5.Image');
  4807. _dereq_('./math/p5.Vector');
  4808. _dereq_('./io/p5.TableRow');
  4809. _dereq_('./io/p5.Table');
  4810. _dereq_('./io/p5.XML');
  4811. _dereq_('./color/creating_reading');
  4812. _dereq_('./color/setting');
  4813. _dereq_('./core/constants');
  4814. _dereq_('./utilities/conversion');
  4815. _dereq_('./utilities/array_functions');
  4816. _dereq_('./utilities/string_functions');
  4817. _dereq_('./core/environment');
  4818. _dereq_('./image/image');
  4819. _dereq_('./image/loading_displaying');
  4820. _dereq_('./image/pixels');
  4821. _dereq_('./io/files');
  4822. _dereq_('./events/keyboard');
  4823. _dereq_('./events/acceleration'); //john
  4824. _dereq_('./events/mouse');
  4825. _dereq_('./utilities/time_date');
  4826. _dereq_('./events/touch');
  4827. _dereq_('./math/math');
  4828. _dereq_('./math/calculation');
  4829. _dereq_('./math/random');
  4830. _dereq_('./math/noise');
  4831. _dereq_('./math/trigonometry');
  4832. _dereq_('./core/rendering');
  4833. _dereq_('./core/2d_primitives');
  4834. _dereq_('./core/attributes');
  4835. _dereq_('./core/curves');
  4836. _dereq_('./core/vertex');
  4837. _dereq_('./core/structure');
  4838. _dereq_('./core/transform');
  4839. _dereq_('./typography/attributes');
  4840. _dereq_('./typography/loading_displaying');
  4841. _dereq_('./webgl/p5.RendererGL');
  4842. _dereq_('./webgl/p5.Geometry');
  4843. _dereq_('./webgl/p5.RendererGL.Retained');
  4844. _dereq_('./webgl/p5.RendererGL.Immediate');
  4845. _dereq_('./webgl/primitives');
  4846. _dereq_('./webgl/loading');
  4847. _dereq_('./webgl/p5.Matrix');
  4848. _dereq_('./webgl/material');
  4849. _dereq_('./webgl/light');
  4850. _dereq_('./webgl/shader');
  4851. _dereq_('./webgl/camera');
  4852. _dereq_('./webgl/interaction');
  4853. /**
  4854. * _globalInit
  4855. *
  4856. * TODO: ???
  4857. * if sketch is on window
  4858. * assume "global" mode
  4859. * and instantiate p5 automatically
  4860. * otherwise do nothing
  4861. *
  4862. * @return {Undefined}
  4863. */
  4864. var _globalInit = function() {
  4865. if (!window.PHANTOMJS && !window.mocha) {
  4866. // If there is a setup or draw function on the window
  4867. // then instantiate p5 in "global" mode
  4868. if(((window.setup && typeof window.setup === 'function') ||
  4869. (window.draw && typeof window.draw === 'function')) &&
  4870. !p5.instance) {
  4871. new p5();
  4872. }
  4873. }
  4874. };
  4875. // TODO: ???
  4876. if (document.readyState === 'complete') {
  4877. _globalInit();
  4878. } else {
  4879. window.addEventListener('load', _globalInit , false);
  4880. }
  4881. module.exports = p5;
  4882. },{"./color/creating_reading":30,"./color/p5.Color":31,"./color/setting":32,"./core/2d_primitives":33,"./core/attributes":34,"./core/constants":36,"./core/core":37,"./core/curves":38,"./core/environment":39,"./core/p5.Element":41,"./core/p5.Graphics":42,"./core/p5.Renderer2D":44,"./core/rendering":45,"./core/structure":47,"./core/transform":48,"./core/vertex":49,"./events/acceleration":50,"./events/keyboard":51,"./events/mouse":52,"./events/touch":53,"./image/image":55,"./image/loading_displaying":56,"./image/p5.Image":57,"./image/pixels":58,"./io/files":59,"./io/p5.Table":60,"./io/p5.TableRow":61,"./io/p5.XML":62,"./math/calculation":63,"./math/math":64,"./math/noise":65,"./math/p5.Vector":66,"./math/random":68,"./math/trigonometry":69,"./typography/attributes":70,"./typography/loading_displaying":71,"./typography/p5.Font":72,"./utilities/array_functions":73,"./utilities/conversion":74,"./utilities/string_functions":75,"./utilities/time_date":76,"./webgl/camera":77,"./webgl/interaction":78,"./webgl/light":79,"./webgl/loading":80,"./webgl/material":81,"./webgl/p5.Geometry":82,"./webgl/p5.Matrix":83,"./webgl/p5.RendererGL":86,"./webgl/p5.RendererGL.Immediate":84,"./webgl/p5.RendererGL.Retained":85,"./webgl/primitives":87,"./webgl/shader":88}],29:[function(_dereq_,module,exports){
  4883. /**
  4884. * module Conversion
  4885. * submodule Color Conversion
  4886. * @for p5
  4887. * @requires core
  4888. */
  4889. 'use strict';
  4890. /**
  4891. * Conversions adapted from <http://www.easyrgb.com/math.html>.
  4892. *
  4893. * In these functions, hue is always in the range [0,1); all other components
  4894. * are in the range [0,1]. 'Brightness' and 'value' are used interchangeably.
  4895. */
  4896. var p5 = _dereq_('../core/core');
  4897. p5.ColorConversion = {};
  4898. /**
  4899. * Convert an HSBA array to HSLA.
  4900. */
  4901. p5.ColorConversion._hsbaToHSLA = function(hsba) {
  4902. var hue = hsba[0];
  4903. var sat = hsba[1];
  4904. var val = hsba[2];
  4905. // Calculate lightness.
  4906. var li = (2 - sat) * val / 2;
  4907. // Convert saturation.
  4908. if (li !== 0) {
  4909. if (li === 1) {
  4910. sat = 0;
  4911. } else if (li < 0.5) {
  4912. sat = sat / (2 - sat);
  4913. } else {
  4914. sat = sat * val / (2 - li * 2);
  4915. }
  4916. }
  4917. // Hue and alpha stay the same.
  4918. return [hue, sat, li, hsba[3]];
  4919. };
  4920. /**
  4921. * Convert an HSBA array to RGBA.
  4922. */
  4923. p5.ColorConversion._hsbaToRGBA = function(hsba) {
  4924. var hue = hsba[0] * 6; // We will split hue into 6 sectors.
  4925. var sat = hsba[1];
  4926. var val = hsba[2];
  4927. var RGBA = [];
  4928. if (sat === 0) {
  4929. RGBA = [val, val, val, hsba[3]]; // Return early if grayscale.
  4930. } else {
  4931. var sector = Math.floor(hue);
  4932. var tint1 = val * (1 - sat);
  4933. var tint2 = val * (1 - sat * (hue - sector));
  4934. var tint3 = val * (1 - sat * (1 + sector - hue));
  4935. var red, green, blue;
  4936. if (sector === 1) { // Yellow to green.
  4937. red = tint2;
  4938. green = val;
  4939. blue = tint1;
  4940. } else if (sector === 2) { // Green to cyan.
  4941. red = tint1;
  4942. green = val;
  4943. blue = tint3;
  4944. } else if (sector === 3) { // Cyan to blue.
  4945. red = tint1;
  4946. green = tint2;
  4947. blue = val;
  4948. } else if (sector === 4) { // Blue to magenta.
  4949. red = tint3;
  4950. green = tint1;
  4951. blue = val;
  4952. } else if (sector === 5) { // Magenta to red.
  4953. red = val;
  4954. green = tint1;
  4955. blue = tint2;
  4956. } else { // Red to yellow (sector could be 0 or 6).
  4957. red = val;
  4958. green = tint3;
  4959. blue = tint1;
  4960. }
  4961. RGBA = [red, green, blue, hsba[3]];
  4962. }
  4963. return RGBA;
  4964. };
  4965. /**
  4966. * Convert an HSLA array to HSBA.
  4967. */
  4968. p5.ColorConversion._hslaToHSBA = function(hsla) {
  4969. var hue = hsla[0];
  4970. var sat = hsla[1];
  4971. var li = hsla[2];
  4972. // Calculate brightness.
  4973. var val;
  4974. if (li < 0.5) {
  4975. val = (1 + sat) * li;
  4976. } else {
  4977. val = li + sat - li * sat;
  4978. }
  4979. // Convert saturation.
  4980. sat = 2 * (val - li) / val;
  4981. // Hue and alpha stay the same.
  4982. return [hue, sat, val, hsla[3]];
  4983. };
  4984. /**
  4985. * Convert an HSLA array to RGBA.
  4986. *
  4987. * We need to change basis from HSLA to something that can be more easily be
  4988. * projected onto RGBA. We will choose hue and brightness as our first two
  4989. * components, and pick a convenient third one ('zest') so that we don't need
  4990. * to calculate formal HSBA saturation.
  4991. */
  4992. p5.ColorConversion._hslaToRGBA = function(hsla){
  4993. var hue = hsla[0] * 6; // We will split hue into 6 sectors.
  4994. var sat = hsla[1];
  4995. var li = hsla[2];
  4996. var RGBA = [];
  4997. if (sat === 0) {
  4998. RGBA = [li, li, li, hsla[3]]; // Return early if grayscale.
  4999. } else {
  5000. // Calculate brightness.
  5001. var val;
  5002. if (li < 0.5) {
  5003. val = (1 + sat) * li;
  5004. } else {
  5005. val = li + sat - li * sat;
  5006. }
  5007. // Define zest.
  5008. var zest = 2 * li - val;
  5009. // Implement projection (project onto green by default).
  5010. var hzvToRGB = function(hue, zest, val) {
  5011. if (hue < 0) { // Hue must wrap to allow projection onto red and blue.
  5012. hue += 6;
  5013. } else if (hue >= 6) {
  5014. hue -= 6;
  5015. }
  5016. if (hue < 1) { // Red to yellow (increasing green).
  5017. return (zest + (val - zest) * hue);
  5018. } else if (hue < 3) { // Yellow to cyan (greatest green).
  5019. return val;
  5020. } else if (hue < 4) { // Cyan to blue (decreasing green).
  5021. return (zest + (val - zest) * (4 - hue));
  5022. } else { // Blue to red (least green).
  5023. return zest;
  5024. }
  5025. };
  5026. // Perform projections, offsetting hue as necessary.
  5027. RGBA = [hzvToRGB(hue + 2, zest, val),
  5028. hzvToRGB(hue , zest, val),
  5029. hzvToRGB(hue - 2, zest, val),
  5030. hsla[3]];
  5031. }
  5032. return RGBA;
  5033. };
  5034. /**
  5035. * Convert an RGBA array to HSBA.
  5036. */
  5037. p5.ColorConversion._rgbaToHSBA = function(rgba) {
  5038. var red = rgba[0];
  5039. var green = rgba[1];
  5040. var blue = rgba[2];
  5041. var val = Math.max(red, green, blue);
  5042. var chroma = val - Math.min(red, green, blue);
  5043. var hue, sat;
  5044. if (chroma === 0) { // Return early if grayscale.
  5045. hue = 0;
  5046. sat = 0;
  5047. }
  5048. else {
  5049. sat = chroma / val;
  5050. if (red === val) { // Magenta to yellow.
  5051. hue = (green - blue) / chroma;
  5052. } else if (green === val) { // Yellow to cyan.
  5053. hue = 2 + (blue - red) / chroma;
  5054. } else if (blue === val) { // Cyan to magenta.
  5055. hue = 4 + (red - green) / chroma;
  5056. }
  5057. if (hue < 0) { // Confine hue to the interval [0, 1).
  5058. hue += 6;
  5059. } else if (hue >= 6) {
  5060. hue -= 6;
  5061. }
  5062. }
  5063. return [hue / 6, sat, val, rgba[3]];
  5064. };
  5065. /**
  5066. * Convert an RGBA array to HSLA.
  5067. */
  5068. p5.ColorConversion._rgbaToHSLA = function(rgba) {
  5069. var red = rgba[0];
  5070. var green = rgba[1];
  5071. var blue = rgba[2];
  5072. var val = Math.max(red, green, blue);
  5073. var min = Math.min(red, green, blue);
  5074. var li = val + min; // We will halve this later.
  5075. var chroma = val - min;
  5076. var hue, sat;
  5077. if (chroma === 0) { // Return early if grayscale.
  5078. hue = 0;
  5079. sat = 0;
  5080. } else {
  5081. if (li < 1) {
  5082. sat = chroma / li;
  5083. } else {
  5084. sat = chroma / (2 - li);
  5085. }
  5086. if (red === val) { // Magenta to yellow.
  5087. hue = (green - blue) / chroma;
  5088. } else if (green === val) { // Yellow to cyan.
  5089. hue = 2 + (blue - red) / chroma;
  5090. } else if (blue === val) { // Cyan to magenta.
  5091. hue = 4 + (red - green) / chroma;
  5092. }
  5093. if (hue < 0) { // Confine hue to the interval [0, 1).
  5094. hue += 6;
  5095. } else if (hue >= 6) {
  5096. hue -= 6;
  5097. }
  5098. }
  5099. return [hue / 6, sat, li / 2, rgba[3]];
  5100. };
  5101. module.exports = p5.ColorConversion;
  5102. },{"../core/core":37}],30:[function(_dereq_,module,exports){
  5103. /**
  5104. * @module Color
  5105. * @submodule Creating & Reading
  5106. * @for p5
  5107. * @requires core
  5108. * @requires constants
  5109. */
  5110. 'use strict';
  5111. var p5 = _dereq_('../core/core');
  5112. var constants = _dereq_('../core/constants');
  5113. _dereq_('./p5.Color');
  5114. /**
  5115. * Extracts the alpha value from a color or pixel array.
  5116. *
  5117. * @method alpha
  5118. * @param {Object} obj p5.Color object or pixel array
  5119. * @example
  5120. * <div>
  5121. * <code>
  5122. * noStroke();
  5123. * c = color(0, 126, 255, 102);
  5124. * fill(c);
  5125. * rect(15, 15, 35, 70);
  5126. * value = alpha(c); // Sets 'value' to 102
  5127. * fill(value);
  5128. * rect(50, 15, 35, 70);
  5129. * </code>
  5130. * </div>
  5131. *
  5132. * @alt
  5133. * Left half of canvas light blue and right half light charcoal grey.
  5134. * Left half of canvas light purple and right half a royal blue.
  5135. * Left half of canvas salmon pink and the right half white.
  5136. * Yellow rect in middle right of canvas, with 55 pixel width and height.
  5137. * Yellow ellipse in top left canvas, black ellipse in bottom right,both 80x80.
  5138. * Bright fuschia rect in middle of canvas, 60 pixel width and height.
  5139. * Two bright green rects on opposite sides of the canvas, both 45x80.
  5140. * Four blue rects in each corner of the canvas, each are 35x35.
  5141. * Bright sea green rect on left and darker rect on right of canvas, both 45x80.
  5142. * Dark green rect on left and light green rect on right of canvas, both 45x80.
  5143. * Dark blue rect on left and light teal rect on right of canvas, both 45x80.
  5144. * blue rect on left and green on right, both with black outlines & 35x60.
  5145. * salmon pink rect on left and black on right, both 35x60.
  5146. * 4 rects, tan, brown, brownish purple and purple, with white outlines & 20x60.
  5147. * light pastel green rect on left and dark grey rect on right, both 35x60.
  5148. * yellow rect on left and red rect on right, both with black outlines & 35x60.
  5149. * grey canvas
  5150. * deep pink rect on left and grey rect on right, both 35x60.
  5151. */
  5152. p5.prototype.alpha = function(c) {
  5153. if (c instanceof p5.Color || c instanceof Array) {
  5154. return this.color(c)._getAlpha();
  5155. } else {
  5156. throw new Error('Needs p5.Color or pixel array as argument.');
  5157. }
  5158. };
  5159. /**
  5160. * Extracts the blue value from a color or pixel array.
  5161. *
  5162. * @method blue
  5163. * @param {Object} obj p5.Color object or pixel array
  5164. * @example
  5165. * <div>
  5166. * <code>
  5167. * c = color(175, 100, 220); // Define color 'c'
  5168. * fill(c); // Use color variable 'c' as fill color
  5169. * rect(15, 20, 35, 60); // Draw left rectangle
  5170. *
  5171. * blueValue = blue(c); // Get blue in 'c'
  5172. * print(blueValue); // Prints "220.0"
  5173. * fill(0, 0, blueValue); // Use 'blueValue' in new fill
  5174. * rect(50, 20, 35, 60); // Draw right rectangle
  5175. * </code>
  5176. * </div>
  5177. *
  5178. * @alt
  5179. * Left half of canvas light purple and right half a royal blue.
  5180. *
  5181. */
  5182. p5.prototype.blue = function(c) {
  5183. if (c instanceof p5.Color || c instanceof Array) {
  5184. return this.color(c)._getBlue();
  5185. } else {
  5186. throw new Error('Needs p5.Color or pixel array as argument.');
  5187. }
  5188. };
  5189. /**
  5190. * Extracts the HSB brightness value from a color or pixel array.
  5191. *
  5192. * @method brightness
  5193. * @param {Object} color p5.Color object or pixel array
  5194. * @example
  5195. * <div>
  5196. * <code>
  5197. * noStroke();
  5198. * colorMode(HSB, 255);
  5199. * c = color(0, 126, 255);
  5200. * fill(c);
  5201. * rect(15, 20, 35, 60);
  5202. * value = brightness(c); // Sets 'value' to 255
  5203. * fill(value);
  5204. * rect(50, 20, 35, 60);
  5205. * </code>
  5206. * </div>
  5207. *
  5208. * @alt
  5209. * Left half of canvas salmon pink and the right half white.
  5210. *
  5211. */
  5212. p5.prototype.brightness = function(c) {
  5213. if (c instanceof p5.Color || c instanceof Array) {
  5214. return this.color(c)._getBrightness();
  5215. } else {
  5216. throw new Error('Needs p5.Color or pixel array as argument.');
  5217. }
  5218. };
  5219. /**
  5220. * Creates colors for storing in variables of the color datatype. The
  5221. * parameters are interpreted as RGB or HSB values depending on the
  5222. * current colorMode(). The default mode is RGB values from 0 to 255
  5223. * and, therefore, the function call color(255, 204, 0) will return a
  5224. * bright yellow color.
  5225. * <br><br>
  5226. * Note that if only one value is provided to color(), it will be interpreted
  5227. * as a grayscale value. Add a second value, and it will be used for alpha
  5228. * transparency. When three values are specified, they are interpreted as
  5229. * either RGB or HSB values. Adding a fourth value applies alpha
  5230. * transparency. If a single string parameter is provided it will be
  5231. * interpreted as a CSS-compatible color string.
  5232. *
  5233. * Colors are stored as Numbers or Arrays.
  5234. *
  5235. * @method color
  5236. * @param {Number|String} gray number specifying value between white
  5237. * and black.
  5238. * @param {Number} [alpha] alpha value relative to current color range
  5239. * (default is 0-255)
  5240. * @return {Array} resulting color
  5241. *
  5242. * @example
  5243. * <div>
  5244. * <code>
  5245. * var c = color(255, 204, 0); // Define color 'c'
  5246. * fill(c); // Use color variable 'c' as fill color
  5247. * noStroke(); // Don't draw a stroke around shapes
  5248. * rect(30, 20, 55, 55); // Draw rectangle
  5249. * </code>
  5250. * </div>
  5251. *
  5252. * <div>
  5253. * <code>
  5254. * var c = color(255, 204, 0); // Define color 'c'
  5255. * fill(c); // Use color variable 'c' as fill color
  5256. * noStroke(); // Don't draw a stroke around shapes
  5257. * ellipse(25, 25, 80, 80); // Draw left circle
  5258. *
  5259. * // Using only one value with color()
  5260. * // generates a grayscale value.
  5261. * var c = color(65); // Update 'c' with grayscale value
  5262. * fill(c); // Use updated 'c' as fill color
  5263. * ellipse(75, 75, 80, 80); // Draw right circle
  5264. * </code>
  5265. * </div>
  5266. *
  5267. * <div>
  5268. * <code>
  5269. * // Named SVG & CSS colors may be used,
  5270. * var c = color('magenta');
  5271. * fill(c); // Use 'c' as fill color
  5272. * noStroke(); // Don't draw a stroke around shapes
  5273. * rect(20, 20, 60, 60); // Draw rectangle
  5274. * </code>
  5275. * </div>
  5276. *
  5277. * <div>
  5278. * <code>
  5279. * // as can hex color codes:
  5280. * noStroke(); // Don't draw a stroke around shapes
  5281. * var c = color('#0f0');
  5282. * fill(c); // Use 'c' as fill color
  5283. * rect(0, 10, 45, 80); // Draw rectangle
  5284. *
  5285. * c = color('#00ff00');
  5286. * fill(c); // Use updated 'c' as fill color
  5287. * rect(55, 10, 45, 80); // Draw rectangle
  5288. * </code>
  5289. * </div>
  5290. *
  5291. * <div>
  5292. * <code>
  5293. * // RGB and RGBA color strings are also supported:
  5294. * // these all set to the same color (solid blue)
  5295. * var c;
  5296. * noStroke(); // Don't draw a stroke around shapes
  5297. * c = color('rgb(0,0,255)');
  5298. * fill(c); // Use 'c' as fill color
  5299. * rect(10, 10, 35, 35); // Draw rectangle
  5300. *
  5301. * c = color('rgb(0%, 0%, 100%)');
  5302. * fill(c); // Use updated 'c' as fill color
  5303. * rect(55, 10, 35, 35); // Draw rectangle
  5304. *
  5305. * c = color('rgba(0, 0, 255, 1)');
  5306. * fill(c); // Use updated 'c' as fill color
  5307. * rect(10, 55, 35, 35); // Draw rectangle
  5308. *
  5309. * c = color('rgba(0%, 0%, 100%, 1)');
  5310. * fill(c); // Use updated 'c' as fill color
  5311. * rect(55, 55, 35, 35); // Draw rectangle
  5312. * </code>
  5313. * </div>
  5314. *
  5315. * <div>
  5316. * <code>
  5317. * // HSL color is also supported and can be specified
  5318. * // by value
  5319. * var c;
  5320. * noStroke(); // Don't draw a stroke around shapes
  5321. * c = color('hsl(160, 100%, 50%)');
  5322. * fill(c); // Use 'c' as fill color
  5323. * rect(0, 10, 45, 80); // Draw rectangle
  5324. *
  5325. * c = color('hsla(160, 100%, 50%, 0.5)');
  5326. * fill(c); // Use updated 'c' as fill color
  5327. * rect(55, 10, 45, 80); // Draw rectangle
  5328. * </code>
  5329. * </div>
  5330. *
  5331. * <div>
  5332. * <code>
  5333. * // HSB color is also supported and can be specified
  5334. * // by value
  5335. * var c;
  5336. * noStroke(); // Don't draw a stroke around shapes
  5337. * c = color('hsb(160, 100%, 50%)');
  5338. * fill(c); // Use 'c' as fill color
  5339. * rect(0, 10, 45, 80); // Draw rectangle
  5340. *
  5341. * c = color('hsba(160, 100%, 50%, 0.5)');
  5342. * fill(c); // Use updated 'c' as fill color
  5343. * rect(55, 10, 45, 80); // Draw rectangle
  5344. * </code>
  5345. * </div>
  5346. *
  5347. * <div>
  5348. * <code>
  5349. * var c; // Declare color 'c'
  5350. * noStroke(); // Don't draw a stroke around shapes
  5351. *
  5352. * // If no colorMode is specified, then the
  5353. * // default of RGB with scale of 0-255 is used.
  5354. * c = color(50, 55, 100); // Create a color for 'c'
  5355. * fill(c); // Use color variable 'c' as fill color
  5356. * rect(0, 10, 45, 80); // Draw left rect
  5357. *
  5358. * colorMode(HSB, 100); // Use HSB with scale of 0-100
  5359. * c = color(50, 55, 100); // Update 'c' with new color
  5360. * fill(c); // Use updated 'c' as fill color
  5361. * rect(55, 10, 45, 80); // Draw right rect
  5362. * </code>
  5363. * </div>
  5364. *
  5365. * @alt
  5366. * Yellow rect in middle right of canvas, with 55 pixel width and height.
  5367. * Yellow ellipse in top left of canvas, black ellipse in bottom right,both 80x80.
  5368. * Bright fuschia rect in middle of canvas, 60 pixel width and height.
  5369. * Two bright green rects on opposite sides of the canvas, both 45x80.
  5370. * Four blue rects in each corner of the canvas, each are 35x35.
  5371. * Bright sea green rect on left and darker rect on right of canvas, both 45x80.
  5372. * Dark green rect on left and lighter green rect on right of canvas, both 45x80.
  5373. * Dark blue rect on left and light teal rect on right of canvas, both 45x80.
  5374. *
  5375. */
  5376. /**
  5377. * @method color
  5378. * @param {Number|String} v1 red or hue value relative to
  5379. * the current color range, or a color string
  5380. * @param {Number} v2 green or saturation value
  5381. * relative to the current color range
  5382. * @param {Number} v3 blue or brightness value
  5383. * relative to the current color range
  5384. * @param {Number} [alpha]
  5385. */
  5386. p5.prototype.color = function() {
  5387. if (arguments[0] instanceof p5.Color) {
  5388. return arguments[0]; // Do nothing if argument is already a color object.
  5389. } else if (arguments[0] instanceof Array) {
  5390. if (this instanceof p5.Renderer) {
  5391. return new p5.Color(this, arguments[0]);
  5392. } else {
  5393. return new p5.Color(this._renderer, arguments[0]);
  5394. }
  5395. } else {
  5396. if (this instanceof p5.Renderer) {
  5397. return new p5.Color(this, arguments);
  5398. } else {
  5399. return new p5.Color(this._renderer, arguments);
  5400. }
  5401. }
  5402. };
  5403. /**
  5404. * Extracts the green value from a color or pixel array.
  5405. *
  5406. * @method green
  5407. * @param {Object} color p5.Color object or pixel array
  5408. * @example
  5409. * <div>
  5410. * <code>
  5411. * c = color(20, 75, 200); // Define color 'c'
  5412. * fill(c); // Use color variable 'c' as fill color
  5413. * rect(15, 20, 35, 60); // Draw left rectangle
  5414. *
  5415. * greenValue = green(c); // Get green in 'c'
  5416. * print(greenValue); // Print "75.0"
  5417. * fill(0, greenValue, 0); // Use 'greenValue' in new fill
  5418. * rect(50, 20, 35, 60); // Draw right rectangle
  5419. * </code>
  5420. * </div>
  5421. *
  5422. * @alt
  5423. * blue rect on left and green on right, both with black outlines & 35x60.
  5424. *
  5425. */
  5426. p5.prototype.green = function(c) {
  5427. if (c instanceof p5.Color || c instanceof Array) {
  5428. return this.color(c)._getGreen();
  5429. } else {
  5430. throw new Error('Needs p5.Color or pixel array as argument.');
  5431. }
  5432. };
  5433. /**
  5434. * Extracts the hue value from a color or pixel array.
  5435. *
  5436. * Hue exists in both HSB and HSL. This function will return the
  5437. * HSB-normalized hue when supplied with an HSB color object (or when supplied
  5438. * with a pixel array while the color mode is HSB), but will default to the
  5439. * HSL-normalized hue otherwise. (The values will only be different if the
  5440. * maximum hue setting for each system is different.)
  5441. *
  5442. * @method hue
  5443. * @param {Object} color p5.Color object or pixel array
  5444. * @example
  5445. * <div>
  5446. * <code>
  5447. * noStroke();
  5448. * colorMode(HSB, 255);
  5449. * c = color(0, 126, 255);
  5450. * fill(c);
  5451. * rect(15, 20, 35, 60);
  5452. * value = hue(c); // Sets 'value' to "0"
  5453. * fill(value);
  5454. * rect(50, 20, 35, 60);
  5455. * </code>
  5456. * </div>
  5457. *
  5458. * @alt
  5459. * salmon pink rect on left and black on right, both 35x60.
  5460. *
  5461. */
  5462. p5.prototype.hue = function(c) {
  5463. if (c instanceof p5.Color || c instanceof Array) {
  5464. return this.color(c)._getHue();
  5465. } else {
  5466. throw new Error('Needs p5.Color or pixel array as argument.');
  5467. }
  5468. };
  5469. /**
  5470. * Blends two colors to find a third color somewhere between them. The amt
  5471. * parameter is the amount to interpolate between the two values where 0.0
  5472. * equal to the first color, 0.1 is very near the first color, 0.5 is halfway
  5473. * in between, etc. An amount below 0 will be treated as 0. Likewise, amounts
  5474. * above 1 will be capped at 1. This is different from the behavior of lerp(),
  5475. * but necessary because otherwise numbers outside the range will produce
  5476. * strange and unexpected colors.
  5477. * <br><br>
  5478. * The way that colours are interpolated depends on the current color mode.
  5479. *
  5480. * @method lerpColor
  5481. * @param {Array/Number} c1 interpolate from this color
  5482. * @param {Array/Number} c2 interpolate to this color
  5483. * @param {Number} amt number between 0 and 1
  5484. * @return {Array/Number} interpolated color
  5485. * @example
  5486. * <div>
  5487. * <code>
  5488. * colorMode(RGB);
  5489. * stroke(255);
  5490. * background(51);
  5491. * from = color(218, 165, 32);
  5492. * to = color(72, 61, 139);
  5493. * colorMode(RGB); // Try changing to HSB.
  5494. * interA = lerpColor(from, to, .33);
  5495. * interB = lerpColor(from, to, .66);
  5496. * fill(from);
  5497. * rect(10, 20, 20, 60);
  5498. * fill(interA);
  5499. * rect(30, 20, 20, 60);
  5500. * fill(interB);
  5501. * rect(50, 20, 20, 60);
  5502. * fill(to);
  5503. * rect(70, 20, 20, 60);
  5504. * </code>
  5505. * </div>
  5506. *
  5507. * @alt
  5508. * 4 rects one tan, brown, brownish purple, purple, with white outlines & 20x60
  5509. *
  5510. */
  5511. p5.prototype.lerpColor = function(c1, c2, amt) {
  5512. var mode = this._renderer._colorMode;
  5513. var maxes = this._renderer._colorMaxes;
  5514. var l0, l1, l2, l3;
  5515. var fromArray, toArray;
  5516. if (mode === constants.RGB) {
  5517. fromArray = c1.levels.map(function(level) {
  5518. return level / 255;
  5519. });
  5520. toArray = c2.levels.map(function(level) {
  5521. return level / 255;
  5522. });
  5523. } else if (mode === constants.HSB) {
  5524. c1._getBrightness(); // Cache hsba so it definitely exists.
  5525. c2._getBrightness();
  5526. fromArray = c1.hsba;
  5527. toArray = c2.hsba;
  5528. } else if (mode === constants.HSL) {
  5529. c1._getLightness(); // Cache hsla so it definitely exists.
  5530. c2._getLightness();
  5531. fromArray = c1.hsla;
  5532. toArray = c2.hsla;
  5533. } else {
  5534. throw new Error (mode + 'cannot be used for interpolation.');
  5535. }
  5536. // Prevent extrapolation.
  5537. amt = Math.max(Math.min(amt, 1), 0);
  5538. // Perform interpolation.
  5539. l0 = this.lerp(fromArray[0], toArray[0], amt);
  5540. l1 = this.lerp(fromArray[1], toArray[1], amt);
  5541. l2 = this.lerp(fromArray[2], toArray[2], amt);
  5542. l3 = this.lerp(fromArray[3], toArray[3], amt);
  5543. // Scale components.
  5544. l0 *= maxes[mode][0];
  5545. l1 *= maxes[mode][1];
  5546. l2 *= maxes[mode][2];
  5547. l3 *= maxes[mode][3];
  5548. return this.color(l0, l1, l2, l3);
  5549. };
  5550. /**
  5551. * Extracts the HSL lightness value from a color or pixel array.
  5552. *
  5553. * @method lightness
  5554. * @param {Object} color p5.Color object or pixel array
  5555. * @example
  5556. * <div>
  5557. * <code>
  5558. * noStroke();
  5559. * colorMode(HSL);
  5560. * c = color(156, 100, 50, 1);
  5561. * fill(c);
  5562. * rect(15, 20, 35, 60);
  5563. * value = lightness(c); // Sets 'value' to 50
  5564. * fill(value);
  5565. * rect(50, 20, 35, 60);
  5566. * </code>
  5567. * </div>
  5568. *
  5569. * @alt
  5570. * light pastel green rect on left and dark grey rect on right, both 35x60.
  5571. *
  5572. */
  5573. p5.prototype.lightness = function(c) {
  5574. if (c instanceof p5.Color || c instanceof Array) {
  5575. return this.color(c)._getLightness();
  5576. } else {
  5577. throw new Error('Needs p5.Color or pixel array as argument.');
  5578. }
  5579. };
  5580. /**
  5581. * Extracts the red value from a color or pixel array.
  5582. *
  5583. * @method red
  5584. * @param {Object} obj p5.Color object or pixel array
  5585. * @example
  5586. * <div>
  5587. * <code>
  5588. * c = color(255, 204, 0); // Define color 'c'
  5589. * fill(c); // Use color variable 'c' as fill color
  5590. * rect(15, 20, 35, 60); // Draw left rectangle
  5591. *
  5592. * redValue = red(c); // Get red in 'c'
  5593. * print(redValue); // Print "255.0"
  5594. * fill(redValue, 0, 0); // Use 'redValue' in new fill
  5595. * rect(50, 20, 35, 60); // Draw right rectangle
  5596. * </code>
  5597. * </div>
  5598. *
  5599. * <div>
  5600. * <code>
  5601. * colorMode(RGB, 255);
  5602. * var c = color(127, 255, 0);
  5603. * colorMode(RGB, 1);
  5604. * var myColor = red(c);
  5605. * print(myColor);
  5606. * </code>
  5607. * </div>
  5608. *
  5609. * @alt
  5610. * yellow rect on left and red rect on right, both with black outlines and 35x60.
  5611. * grey canvas
  5612. */
  5613. p5.prototype.red = function(c) {
  5614. if (c instanceof p5.Color || c instanceof Array) {
  5615. return this.color(c)._getRed();
  5616. } else {
  5617. throw new Error('Needs p5.Color or pixel array as argument.');
  5618. }
  5619. };
  5620. /**
  5621. * Extracts the saturation value from a color or pixel array.
  5622. *
  5623. * Saturation is scaled differently in HSB and HSL. This function will return
  5624. * the HSB saturation when supplied with an HSB color object (or when supplied
  5625. * with a pixel array while the color mode is HSB), but will default to the
  5626. * HSL saturation otherwise.
  5627. *
  5628. * @method saturation
  5629. * @param {Object} color p5.Color object or pixel array
  5630. * @example
  5631. * <div>
  5632. * <code>
  5633. * noStroke();
  5634. * colorMode(HSB, 255);
  5635. * c = color(0, 126, 255);
  5636. * fill(c);
  5637. * rect(15, 20, 35, 60);
  5638. * value = saturation(c); // Sets 'value' to 126
  5639. * fill(value);
  5640. * rect(50, 20, 35, 60);
  5641. * </code>
  5642. * </div>
  5643. *
  5644. * @alt
  5645. *deep pink rect on left and grey rect on right, both 35x60.
  5646. *
  5647. */
  5648. p5.prototype.saturation = function(c) {
  5649. if (c instanceof p5.Color || c instanceof Array) {
  5650. return this.color(c)._getSaturation();
  5651. } else {
  5652. throw new Error('Needs p5.Color or pixel array as argument.');
  5653. }
  5654. };
  5655. module.exports = p5;
  5656. },{"../core/constants":36,"../core/core":37,"./p5.Color":31}],31:[function(_dereq_,module,exports){
  5657. /**
  5658. * @module Color
  5659. * @submodule Creating & Reading
  5660. * @for p5
  5661. * @requires core
  5662. * @requires constants
  5663. * @requires color_conversion
  5664. */
  5665. var p5 = _dereq_('../core/core');
  5666. var constants = _dereq_('../core/constants');
  5667. var color_conversion = _dereq_('./color_conversion');
  5668. /**
  5669. * We define colors to be immutable objects. Each color stores the color mode
  5670. * and level maxes that applied at the time of its construction. These are
  5671. * used to interpret the input arguments and to format the output e.g. when
  5672. * saturation() is requested.
  5673. *
  5674. * Internally we store an array representing the ideal RGBA values in floating
  5675. * point form, normalized from 0 to 1. From this we calculate the closest
  5676. * screen color (RGBA levels from 0 to 255) and expose this to the renderer.
  5677. *
  5678. * We also cache normalized, floating point components of the color in various
  5679. * representations as they are calculated. This is done to prevent repeating a
  5680. * conversion that has already been performed.
  5681. *
  5682. * @class p5.Color
  5683. * @constructor
  5684. */
  5685. p5.Color = function(renderer, vals) {
  5686. // Record color mode and maxes at time of construction.
  5687. this.mode = renderer._colorMode;
  5688. this.maxes = renderer._colorMaxes;
  5689. // Calculate normalized RGBA values.
  5690. if (this.mode !== constants.RGB &&
  5691. this.mode !== constants.HSL &&
  5692. this.mode !== constants.HSB) {
  5693. throw new Error(this.mode + ' is an invalid colorMode.');
  5694. } else {
  5695. this._array = p5.Color._parseInputs.apply(renderer, vals);
  5696. }
  5697. // Expose closest screen color.
  5698. this.levels = this._array.map(function(level) {
  5699. return Math.round(level * 255);
  5700. });
  5701. return this;
  5702. };
  5703. p5.Color.prototype.toString = function() {
  5704. var a = this.levels;
  5705. var alpha = this._array[3]; // String representation uses normalized alpha.
  5706. return 'rgba('+a[0]+','+a[1]+','+a[2]+','+ alpha +')';
  5707. };
  5708. p5.Color.prototype._getAlpha = function() {
  5709. return this._array[3] * this.maxes[this.mode][3];
  5710. };
  5711. p5.Color.prototype._getBlue = function() {
  5712. return this._array[2] * this.maxes[constants.RGB][2];
  5713. };
  5714. p5.Color.prototype._getBrightness = function() {
  5715. if (!this.hsba) {
  5716. this.hsba = color_conversion._rgbaToHSBA(this._array);
  5717. }
  5718. return this.hsba[2] * this.maxes[constants.HSB][2];
  5719. };
  5720. p5.Color.prototype._getGreen = function() {
  5721. return this._array[1] * this.maxes[constants.RGB][1];
  5722. };
  5723. /**
  5724. * Hue is the same in HSB and HSL, but the maximum value may be different.
  5725. * This function will return the HSB-normalized saturation when supplied with
  5726. * an HSB color object, but will default to the HSL-normalized saturation
  5727. * otherwise.
  5728. */
  5729. p5.Color.prototype._getHue = function() {
  5730. if (this.mode === constants.HSB) {
  5731. if (!this.hsba) {
  5732. this.hsba = color_conversion._rgbaToHSBA(this._array);
  5733. }
  5734. return this.hsba[0] * this.maxes[constants.HSB][0];
  5735. } else {
  5736. if (!this.hsla) {
  5737. this.hsla = color_conversion._rgbaToHSLA(this._array);
  5738. }
  5739. return this.hsla[0] * this.maxes[constants.HSL][0];
  5740. }
  5741. };
  5742. p5.Color.prototype._getLightness = function() {
  5743. if (!this.hsla) {
  5744. this.hsla = color_conversion._rgbaToHSLA(this._array);
  5745. }
  5746. return this.hsla[2] * this.maxes[constants.HSL][2];
  5747. };
  5748. p5.Color.prototype._getRed = function() {
  5749. return this._array[0] * this.maxes[constants.RGB][0];
  5750. };
  5751. /**
  5752. * Saturation is scaled differently in HSB and HSL. This function will return
  5753. * the HSB saturation when supplied with an HSB color object, but will default
  5754. * to the HSL saturation otherwise.
  5755. */
  5756. p5.Color.prototype._getSaturation = function() {
  5757. if (this.mode === constants.HSB) {
  5758. if (!this.hsba) {
  5759. this.hsba = color_conversion._rgbaToHSBA(this._array);
  5760. }
  5761. return this.hsba[1] * this.maxes[constants.HSB][1];
  5762. } else {
  5763. if (!this.hsla) {
  5764. this.hsla = color_conversion._rgbaToHSLA(this._array);
  5765. }
  5766. return this.hsla[1] * this.maxes[constants.HSL][1];
  5767. }
  5768. };
  5769. /**
  5770. * CSS named colors.
  5771. */
  5772. var namedColors = {
  5773. aliceblue: '#f0f8ff',
  5774. antiquewhite: '#faebd7',
  5775. aqua: '#00ffff',
  5776. aquamarine: '#7fffd4',
  5777. azure: '#f0ffff',
  5778. beige: '#f5f5dc',
  5779. bisque: '#ffe4c4',
  5780. black: '#000000',
  5781. blanchedalmond: '#ffebcd',
  5782. blue: '#0000ff',
  5783. blueviolet: '#8a2be2',
  5784. brown: '#a52a2a',
  5785. burlywood: '#deb887',
  5786. cadetblue: '#5f9ea0',
  5787. chartreuse: '#7fff00',
  5788. chocolate: '#d2691e',
  5789. coral: '#ff7f50',
  5790. cornflowerblue: '#6495ed',
  5791. cornsilk: '#fff8dc',
  5792. crimson: '#dc143c',
  5793. cyan: '#00ffff',
  5794. darkblue: '#00008b',
  5795. darkcyan: '#008b8b',
  5796. darkgoldenrod: '#b8860b',
  5797. darkgray: '#a9a9a9',
  5798. darkgreen: '#006400',
  5799. darkgrey: '#a9a9a9',
  5800. darkkhaki: '#bdb76b',
  5801. darkmagenta: '#8b008b',
  5802. darkolivegreen: '#556b2f',
  5803. darkorange: '#ff8c00',
  5804. darkorchid: '#9932cc',
  5805. darkred: '#8b0000',
  5806. darksalmon: '#e9967a',
  5807. darkseagreen: '#8fbc8f',
  5808. darkslateblue: '#483d8b',
  5809. darkslategray: '#2f4f4f',
  5810. darkslategrey: '#2f4f4f',
  5811. darkturquoise: '#00ced1',
  5812. darkviolet: '#9400d3',
  5813. deeppink: '#ff1493',
  5814. deepskyblue: '#00bfff',
  5815. dimgray: '#696969',
  5816. dimgrey: '#696969',
  5817. dodgerblue: '#1e90ff',
  5818. firebrick: '#b22222',
  5819. floralwhite: '#fffaf0',
  5820. forestgreen: '#228b22',
  5821. fuchsia: '#ff00ff',
  5822. gainsboro: '#dcdcdc',
  5823. ghostwhite: '#f8f8ff',
  5824. gold: '#ffd700',
  5825. goldenrod: '#daa520',
  5826. gray: '#808080',
  5827. green: '#008000',
  5828. greenyellow: '#adff2f',
  5829. grey: '#808080',
  5830. honeydew: '#f0fff0',
  5831. hotpink: '#ff69b4',
  5832. indianred: '#cd5c5c',
  5833. indigo: '#4b0082',
  5834. ivory: '#fffff0',
  5835. khaki: '#f0e68c',
  5836. lavender: '#e6e6fa',
  5837. lavenderblush: '#fff0f5',
  5838. lawngreen: '#7cfc00',
  5839. lemonchiffon: '#fffacd',
  5840. lightblue: '#add8e6',
  5841. lightcoral: '#f08080',
  5842. lightcyan: '#e0ffff',
  5843. lightgoldenrodyellow: '#fafad2',
  5844. lightgray: '#d3d3d3',
  5845. lightgreen: '#90ee90',
  5846. lightgrey: '#d3d3d3',
  5847. lightpink: '#ffb6c1',
  5848. lightsalmon: '#ffa07a',
  5849. lightseagreen: '#20b2aa',
  5850. lightskyblue: '#87cefa',
  5851. lightslategray: '#778899',
  5852. lightslategrey: '#778899',
  5853. lightsteelblue: '#b0c4de',
  5854. lightyellow: '#ffffe0',
  5855. lime: '#00ff00',
  5856. limegreen: '#32cd32',
  5857. linen: '#faf0e6',
  5858. magenta: '#ff00ff',
  5859. maroon: '#800000',
  5860. mediumaquamarine: '#66cdaa',
  5861. mediumblue: '#0000cd',
  5862. mediumorchid: '#ba55d3',
  5863. mediumpurple: '#9370db',
  5864. mediumseagreen: '#3cb371',
  5865. mediumslateblue: '#7b68ee',
  5866. mediumspringgreen: '#00fa9a',
  5867. mediumturquoise: '#48d1cc',
  5868. mediumvioletred: '#c71585',
  5869. midnightblue: '#191970',
  5870. mintcream: '#f5fffa',
  5871. mistyrose: '#ffe4e1',
  5872. moccasin: '#ffe4b5',
  5873. navajowhite: '#ffdead',
  5874. navy: '#000080',
  5875. oldlace: '#fdf5e6',
  5876. olive: '#808000',
  5877. olivedrab: '#6b8e23',
  5878. orange: '#ffa500',
  5879. orangered: '#ff4500',
  5880. orchid: '#da70d6',
  5881. palegoldenrod: '#eee8aa',
  5882. palegreen: '#98fb98',
  5883. paleturquoise: '#afeeee',
  5884. palevioletred: '#db7093',
  5885. papayawhip: '#ffefd5',
  5886. peachpuff: '#ffdab9',
  5887. peru: '#cd853f',
  5888. pink: '#ffc0cb',
  5889. plum: '#dda0dd',
  5890. powderblue: '#b0e0e6',
  5891. purple: '#800080',
  5892. red: '#ff0000',
  5893. rosybrown: '#bc8f8f',
  5894. royalblue: '#4169e1',
  5895. saddlebrown: '#8b4513',
  5896. salmon: '#fa8072',
  5897. sandybrown: '#f4a460',
  5898. seagreen: '#2e8b57',
  5899. seashell: '#fff5ee',
  5900. sienna: '#a0522d',
  5901. silver: '#c0c0c0',
  5902. skyblue: '#87ceeb',
  5903. slateblue: '#6a5acd',
  5904. slategray: '#708090',
  5905. slategrey: '#708090',
  5906. snow: '#fffafa',
  5907. springgreen: '#00ff7f',
  5908. steelblue: '#4682b4',
  5909. tan: '#d2b48c',
  5910. teal: '#008080',
  5911. thistle: '#d8bfd8',
  5912. tomato: '#ff6347',
  5913. turquoise: '#40e0d0',
  5914. violet: '#ee82ee',
  5915. wheat: '#f5deb3',
  5916. white: '#ffffff',
  5917. whitesmoke: '#f5f5f5',
  5918. yellow: '#ffff00',
  5919. yellowgreen: '#9acd32'
  5920. };
  5921. /**
  5922. * These regular expressions are used to build up the patterns for matching
  5923. * viable CSS color strings: fragmenting the regexes in this way increases the
  5924. * legibility and comprehensibility of the code.
  5925. *
  5926. * Note that RGB values of .9 are not parsed by IE, but are supported here for
  5927. * color string consistency.
  5928. */
  5929. var WHITESPACE = /\s*/; // Match zero or more whitespace characters.
  5930. var INTEGER = /(\d{1,3})/; // Match integers: 79, 255, etc.
  5931. var DECIMAL = /((?:\d+(?:\.\d+)?)|(?:\.\d+))/; // Match 129.6, 79, .9, etc.
  5932. var PERCENT = new RegExp(DECIMAL.source + '%'); // Match 12.9%, 79%, .9%, etc.
  5933. /**
  5934. * Full color string patterns. The capture groups are necessary.
  5935. */
  5936. var colorPatterns = {
  5937. // Match colors in format #XXX, e.g. #416.
  5938. HEX3: /^#([a-f0-9])([a-f0-9])([a-f0-9])$/i,
  5939. // Match colors in format #XXXXXX, e.g. #b4d455.
  5940. HEX6: /^#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})$/i,
  5941. // Match colors in format rgb(R, G, B), e.g. rgb(255, 0, 128).
  5942. RGB: new RegExp([
  5943. '^rgb\\(',
  5944. INTEGER.source,
  5945. ',',
  5946. INTEGER.source,
  5947. ',',
  5948. INTEGER.source,
  5949. '\\)$'
  5950. ].join(WHITESPACE.source), 'i'),
  5951. // Match colors in format rgb(R%, G%, B%), e.g. rgb(100%, 0%, 28.9%).
  5952. RGB_PERCENT: new RegExp([
  5953. '^rgb\\(',
  5954. PERCENT.source,
  5955. ',',
  5956. PERCENT.source,
  5957. ',',
  5958. PERCENT.source,
  5959. '\\)$'
  5960. ].join(WHITESPACE.source), 'i'),
  5961. // Match colors in format rgb(R, G, B, A), e.g. rgb(255, 0, 128, 0.25).
  5962. RGBA: new RegExp([
  5963. '^rgba\\(',
  5964. INTEGER.source,
  5965. ',',
  5966. INTEGER.source,
  5967. ',',
  5968. INTEGER.source,
  5969. ',',
  5970. DECIMAL.source,
  5971. '\\)$'
  5972. ].join(WHITESPACE.source), 'i'),
  5973. // Match colors in format rgb(R%, G%, B%, A), e.g. rgb(100%, 0%, 28.9%, 0.5).
  5974. RGBA_PERCENT: new RegExp([
  5975. '^rgba\\(',
  5976. PERCENT.source,
  5977. ',',
  5978. PERCENT.source,
  5979. ',',
  5980. PERCENT.source,
  5981. ',',
  5982. DECIMAL.source,
  5983. '\\)$'
  5984. ].join(WHITESPACE.source), 'i'),
  5985. // Match colors in format hsla(H, S%, L%), e.g. hsl(100, 40%, 28.9%).
  5986. HSL: new RegExp([
  5987. '^hsl\\(',
  5988. INTEGER.source,
  5989. ',',
  5990. PERCENT.source,
  5991. ',',
  5992. PERCENT.source,
  5993. '\\)$'
  5994. ].join(WHITESPACE.source), 'i'),
  5995. // Match colors in format hsla(H, S%, L%, A), e.g. hsla(100, 40%, 28.9%, 0.5).
  5996. HSLA: new RegExp([
  5997. '^hsla\\(',
  5998. INTEGER.source,
  5999. ',',
  6000. PERCENT.source,
  6001. ',',
  6002. PERCENT.source,
  6003. ',',
  6004. DECIMAL.source,
  6005. '\\)$'
  6006. ].join(WHITESPACE.source), 'i'),
  6007. // Match colors in format hsb(H, S%, B%), e.g. hsb(100, 40%, 28.9%).
  6008. HSB: new RegExp([
  6009. '^hsb\\(',
  6010. INTEGER.source,
  6011. ',',
  6012. PERCENT.source,
  6013. ',',
  6014. PERCENT.source,
  6015. '\\)$'
  6016. ].join(WHITESPACE.source), 'i'),
  6017. // Match colors in format hsba(H, S%, B%, A), e.g. hsba(100, 40%, 28.9%, 0.5).
  6018. HSBA: new RegExp([
  6019. '^hsba\\(',
  6020. INTEGER.source,
  6021. ',',
  6022. PERCENT.source,
  6023. ',',
  6024. PERCENT.source,
  6025. ',',
  6026. DECIMAL.source,
  6027. '\\)$'
  6028. ].join(WHITESPACE.source), 'i')
  6029. };
  6030. /**
  6031. * For a number of different inputs, returns a color formatted as [r, g, b, a]
  6032. * arrays, with each component normalized between 0 and 1.
  6033. *
  6034. * @param {Array-like} args An 'array-like' object that represents a list of
  6035. * arguments
  6036. * @return {Array} a color formatted as [r, g, b, a]
  6037. * Example:
  6038. * input ==> output
  6039. * g ==> [g, g, g, 255]
  6040. * g,a ==> [g, g, g, a]
  6041. * r, g, b ==> [r, g, b, 255]
  6042. * r, g, b, a ==> [r, g, b, a]
  6043. * [g] ==> [g, g, g, 255]
  6044. * [g, a] ==> [g, g, g, a]
  6045. * [r, g, b] ==> [r, g, b, 255]
  6046. * [r, g, b, a] ==> [r, g, b, a]
  6047. * @example
  6048. * <div>
  6049. * <code>
  6050. * // todo
  6051. * </code>
  6052. * </div>
  6053. *
  6054. * @alt
  6055. * //todo
  6056. *
  6057. */
  6058. p5.Color._parseInputs = function() {
  6059. var numArgs = arguments.length;
  6060. var mode = this._colorMode;
  6061. var maxes = this._colorMaxes;
  6062. var results = [];
  6063. if (numArgs >= 3) { // Argument is a list of component values.
  6064. results[0] = arguments[0] / maxes[mode][0];
  6065. results[1] = arguments[1] / maxes[mode][1];
  6066. results[2] = arguments[2] / maxes[mode][2];
  6067. // Alpha may be undefined, so default it to 100%.
  6068. if (typeof arguments[3] === 'number') {
  6069. results[3] = arguments[3] / maxes[mode][3];
  6070. } else {
  6071. results[3] = 1;
  6072. }
  6073. // Constrain components to the range [0,1].
  6074. results = results.map(function(value) {
  6075. return Math.max(Math.min(value, 1), 0);
  6076. });
  6077. // Convert to RGBA and return.
  6078. if (mode === constants.HSL) {
  6079. return color_conversion._hslaToRGBA(results);
  6080. } else if (mode === constants.HSB) {
  6081. return color_conversion._hsbaToRGBA(results);
  6082. } else {
  6083. return results;
  6084. }
  6085. } else if (numArgs === 1 && typeof arguments[0] === 'string') {
  6086. var str = arguments[0].trim().toLowerCase();
  6087. // Return if string is a named colour.
  6088. if (namedColors[str]) {
  6089. return p5.Color._parseInputs.apply(this, [namedColors[str]]);
  6090. }
  6091. // Try RGBA pattern matching.
  6092. if (colorPatterns.HEX3.test(str)) { // #rgb
  6093. results = colorPatterns.HEX3.exec(str).slice(1).map(function(color) {
  6094. return parseInt(color + color, 16) / 255;
  6095. });
  6096. results[3] = 1;
  6097. return results;
  6098. } else if (colorPatterns.HEX6.test(str)) { // #rrggbb
  6099. results = colorPatterns.HEX6.exec(str).slice(1).map(function(color) {
  6100. return parseInt(color, 16) / 255;
  6101. });
  6102. results[3] = 1;
  6103. return results;
  6104. } else if (colorPatterns.RGB.test(str)) { // rgb(R,G,B)
  6105. results = colorPatterns.RGB.exec(str).slice(1).map(function(color) {
  6106. return color / 255;
  6107. });
  6108. results[3] = 1;
  6109. return results;
  6110. } else if (colorPatterns.RGB_PERCENT.test(str)) { // rgb(R%,G%,B%)
  6111. results = colorPatterns.RGB_PERCENT.exec(str).slice(1)
  6112. .map(function(color) {
  6113. return parseFloat(color) / 100;
  6114. });
  6115. results[3] = 1;
  6116. return results;
  6117. } else if (colorPatterns.RGBA.test(str)) { // rgba(R,G,B,A)
  6118. results = colorPatterns.RGBA.exec(str).slice(1)
  6119. .map(function(color, idx) {
  6120. if (idx === 3) {
  6121. return parseFloat(color);
  6122. }
  6123. return color / 255;
  6124. });
  6125. return results;
  6126. } else if (colorPatterns.RGBA_PERCENT.test(str)) { // rgba(R%,G%,B%,A%)
  6127. results = colorPatterns.RGBA_PERCENT.exec(str).slice(1)
  6128. .map(function(color, idx) {
  6129. if (idx === 3) {
  6130. return parseFloat(color);
  6131. }
  6132. return parseFloat(color) / 100;
  6133. });
  6134. return results;
  6135. }
  6136. // Try HSLA pattern matching.
  6137. if (colorPatterns.HSL.test(str)) { // hsl(H,S,L)
  6138. results = colorPatterns.HSL.exec(str).slice(1)
  6139. .map(function(color, idx) {
  6140. if (idx === 0) {
  6141. return parseInt(color, 10) / 360;
  6142. }
  6143. return parseInt(color, 10) / 100;
  6144. });
  6145. results[3] = 1;
  6146. } else if (colorPatterns.HSLA.test(str)) { // hsla(H,S,L,A)
  6147. results = colorPatterns.HSLA.exec(str).slice(1)
  6148. .map(function(color, idx) {
  6149. if (idx === 0) {
  6150. return parseInt(color, 10) / 360;
  6151. }
  6152. else if (idx === 3) {
  6153. return parseFloat(color);
  6154. }
  6155. return parseInt(color, 10) / 100;
  6156. });
  6157. }
  6158. if (results.length) {
  6159. return color_conversion._hslaToRGBA(results);
  6160. }
  6161. // Try HSBA pattern matching.
  6162. if (colorPatterns.HSB.test(str)) { // hsb(H,S,B)
  6163. results = colorPatterns.HSB.exec(str).slice(1)
  6164. .map(function(color, idx) {
  6165. if (idx === 0) {
  6166. return parseInt(color, 10) / 360;
  6167. }
  6168. return parseInt(color, 10) / 100;
  6169. });
  6170. results[3] = 1;
  6171. } else if (colorPatterns.HSBA.test(str)) { // hsba(H,S,B,A)
  6172. results = colorPatterns.HSBA.exec(str).slice(1)
  6173. .map(function(color, idx) {
  6174. if (idx === 0) {
  6175. return parseInt(color, 10) / 360;
  6176. }
  6177. else if (idx === 3) {
  6178. return parseFloat(color);
  6179. }
  6180. return parseInt(color, 10) / 100;
  6181. });
  6182. }
  6183. if (results.length) {
  6184. return color_conversion._hsbaToRGBA(results);
  6185. }
  6186. // Input did not match any CSS color pattern: default to white.
  6187. results = [1, 1, 1, 1];
  6188. } else if ((numArgs === 1 || numArgs === 2) &&
  6189. typeof arguments[0] === 'number') { // 'Grayscale' mode.
  6190. /**
  6191. * For HSB and HSL, interpret the gray level as a brightness/lightness
  6192. * value (they are equivalent when chroma is zero). For RGB, normalize the
  6193. * gray level according to the blue maximum.
  6194. */
  6195. results[0] = arguments[0] / maxes[mode][2];
  6196. results[1] = arguments[0] / maxes[mode][2];
  6197. results[2] = arguments[0] / maxes[mode][2];
  6198. // Alpha may be undefined, so default it to 100%.
  6199. if (typeof arguments[1] === 'number') {
  6200. results[3] = arguments[1] / maxes[mode][3];
  6201. } else {
  6202. results[3] = 1;
  6203. }
  6204. // Constrain components to the range [0,1].
  6205. results = results.map(function(value) {
  6206. return Math.max(Math.min(value, 1), 0);
  6207. });
  6208. } else {
  6209. throw new Error (arguments + 'is not a valid color representation.');
  6210. }
  6211. return results;
  6212. };
  6213. module.exports = p5.Color;
  6214. },{"../core/constants":36,"../core/core":37,"./color_conversion":29}],32:[function(_dereq_,module,exports){
  6215. /**
  6216. * @module Color
  6217. * @submodule Setting
  6218. * @for p5
  6219. * @requires core
  6220. * @requires constants
  6221. */
  6222. 'use strict';
  6223. var p5 = _dereq_('../core/core');
  6224. var constants = _dereq_('../core/constants');
  6225. _dereq_('./p5.Color');
  6226. /**
  6227. * The background() function sets the color used for the background of the
  6228. * p5.js canvas. The default background is light gray. This function is
  6229. * typically used within draw() to clear the display window at the beginning
  6230. * of each frame, but it can be used inside setup() to set the background on
  6231. * the first frame of animation or if the background need only be set once.
  6232. *
  6233. * @method background
  6234. * @param {p5.Color} color any value created by the color() function
  6235. * @param {Number} [a] opacity of the background relative to current
  6236. * color range (default is 0-100)
  6237. *
  6238. * @example
  6239. * <div>
  6240. * <code>
  6241. * // Grayscale integer value
  6242. * background(51);
  6243. * </code>
  6244. * </div>
  6245. *
  6246. * <div>
  6247. * <code>
  6248. * // R, G & B integer values
  6249. * background(255, 204, 0);
  6250. * </code>
  6251. * </div>
  6252. *
  6253. * <div>
  6254. * <code>
  6255. * // H, S & B integer values
  6256. * colorMode(HSB);
  6257. * background(255, 204, 100);
  6258. * </code>
  6259. * </div>
  6260. *
  6261. * <div>
  6262. * <code>
  6263. * // Named SVG/CSS color string
  6264. * background('red');
  6265. * </code>
  6266. * </div>
  6267. *
  6268. * <div>
  6269. * <code>
  6270. * // three-digit hexadecimal RGB notation
  6271. * background('#fae');
  6272. * </code>
  6273. * </div>
  6274. *
  6275. * <div>
  6276. * <code>
  6277. * // six-digit hexadecimal RGB notation
  6278. * background('#222222');
  6279. * </code>
  6280. * </div>
  6281. *
  6282. * <div>
  6283. * <code>
  6284. * // integer RGB notation
  6285. * background('rgb(0,255,0)');
  6286. * </code>
  6287. * </div>
  6288. *
  6289. * <div>
  6290. * <code>
  6291. * // integer RGBA notation
  6292. * background('rgba(0,255,0, 0.25)');
  6293. * </code>
  6294. * </div>
  6295. *
  6296. * <div>
  6297. * <code>
  6298. * // percentage RGB notation
  6299. * background('rgb(100%,0%,10%)');
  6300. * </code>
  6301. * </div>
  6302. *
  6303. * <div>
  6304. * <code>
  6305. * // percentage RGBA notation
  6306. * background('rgba(100%,0%,100%,0.5)');
  6307. * </code>
  6308. * </div>
  6309. *
  6310. * <div>
  6311. * <code>
  6312. * // p5 Color object
  6313. * background(color(0, 0, 255));
  6314. * </code>
  6315. * </div>
  6316. *
  6317. * @alt
  6318. * canvas with darkest charcoal grey background.
  6319. * canvas with yellow background.
  6320. * canvas with royal blue background.
  6321. * canvas with red background.
  6322. * canvas with pink background.
  6323. * canvas with black background.
  6324. * canvas with bright green background.
  6325. * canvas with soft green background.
  6326. * canvas with red background.
  6327. * canvas with light purple background.
  6328. * canvas with blue background.
  6329. */
  6330. /**
  6331. * @method background
  6332. * @param {String} colorstring color string, possible formats include: integer
  6333. * rgb() or rgba(), percentage rgb() or rgba(),
  6334. * 3-digit hex, 6-digit hex
  6335. * @param {Number} [a]
  6336. */
  6337. /**
  6338. * @method background
  6339. * @param {Number} gray specifies a value between white and black
  6340. * @param {Number} [a]
  6341. */
  6342. /**
  6343. * @method background
  6344. * @param {Number} v1 red or hue value (depending on the current color
  6345. * mode)
  6346. * @param {Number} v2 green or saturation value (depending on the current
  6347. * color mode)
  6348. * @param {Number} v3 blue or brightness value (depending on the current
  6349. * color mode)
  6350. * @param {Number} [a]
  6351. */
  6352. /**
  6353. * @method background
  6354. * @param {p5.Image} image image created with loadImage() or createImage(),
  6355. * to set as background
  6356. * (must be same size as the sketch window)
  6357. * @param {Number} [a]
  6358. */
  6359. p5.prototype.background = function() {
  6360. if (arguments[0] instanceof p5.Image) {
  6361. this.image(arguments[0], 0, 0, this.width, this.height);
  6362. } else {
  6363. this._renderer.background.apply(this._renderer, arguments);
  6364. }
  6365. return this;
  6366. };
  6367. /**
  6368. * Clears the pixels within a buffer. This function only works on p5.Canvas
  6369. * objects created with the createCanvas() function; it won't work with the
  6370. * main display window. Unlike the main graphics context, pixels in
  6371. * additional graphics areas created with createGraphics() can be entirely
  6372. * or partially transparent. This function clears everything to make all of
  6373. * the pixels 100% transparent.
  6374. *
  6375. * @method clear
  6376. * @example
  6377. * <div>
  6378. * <code>
  6379. * // Clear the screen on mouse press.
  6380. * function setup() {
  6381. * createCanvas(100, 100);
  6382. * }
  6383. *
  6384. * function draw() {
  6385. * ellipse(mouseX, mouseY, 20, 20);
  6386. * }
  6387. *
  6388. * function mousePressed() {
  6389. * clear();
  6390. * }
  6391. * </code>
  6392. * </div>
  6393. *
  6394. * @alt
  6395. * 20x20 white ellipses are continually drawn at mouse x and y coordinates.
  6396. *
  6397. */
  6398. p5.prototype.clear = function() {
  6399. this._renderer.clear();
  6400. return this;
  6401. };
  6402. /**
  6403. * colorMode() changes the way p5.js interprets color data. By default, the
  6404. * parameters for fill(), stroke(), background(), and color() are defined by
  6405. * values between 0 and 255 using the RGB color model. This is equivalent to
  6406. * setting colorMode(RGB, 255). Setting colorMode(HSB) lets you use the HSB
  6407. * system instead. By default, this is colorMode(HSB, 360, 100, 100, 1). You
  6408. * can also use HSL.
  6409. * <br><br>
  6410. * Note: existing color objects remember the mode that they were created in,
  6411. * so you can change modes as you like without affecting their appearance.
  6412. *
  6413. * @method colorMode
  6414. * @param {Constant} mode either RGB or HSB, corresponding to
  6415. * Red/Green/Blue and Hue/Saturation/Brightness
  6416. * (or Lightness)
  6417. * @param {Number} [max1] range for the red or hue depending on the
  6418. * current color mode, or range for all values
  6419. * @param {Number} [max2] range for the green or saturation depending
  6420. * on the current color mode
  6421. * @param {Number} [max3] range for the blue or brightness/lighntess
  6422. * depending on the current color mode
  6423. * @param {Number} [maxA] range for the alpha
  6424. * @example
  6425. * <div>
  6426. * <code>
  6427. * noStroke();
  6428. * colorMode(RGB, 100);
  6429. * for (i = 0; i < 100; i++) {
  6430. * for (j = 0; j < 100; j++) {
  6431. * stroke(i, j, 0);
  6432. * point(i, j);
  6433. * }
  6434. * }
  6435. * </code>
  6436. * </div>
  6437. *
  6438. * <div>
  6439. * <code>
  6440. * noStroke();
  6441. * colorMode(HSB, 100);
  6442. * for (i = 0; i < 100; i++) {
  6443. * for (j = 0; j < 100; j++) {
  6444. * stroke(i, j, 100);
  6445. * point(i, j);
  6446. * }
  6447. * }
  6448. * </code>
  6449. * </div>
  6450. *
  6451. * <div>
  6452. * <code>
  6453. * colorMode(RGB, 255);
  6454. * var c = color(127, 255, 0);
  6455. *
  6456. * colorMode(RGB, 1);
  6457. * var myColor = c._getRed();
  6458. * text(myColor, 10, 10, 80, 80);
  6459. * </code>
  6460. * </div>
  6461. *
  6462. * <div>
  6463. * <code>
  6464. * noFill();
  6465. * colorMode(RGB, 255, 255, 255, 1);
  6466. * background(255);
  6467. *
  6468. * strokeWeight(4);
  6469. * stroke(255, 0 , 10, 0.3);
  6470. * ellipse(40, 40, 50, 50);
  6471. * ellipse(50, 50, 40, 40);
  6472. * </code>
  6473. * </div>
  6474. *
  6475. * @alt
  6476. *Green to red gradient from bottom L to top R. shading originates from top left.
  6477. *Rainbow gradient from left to right. Brightness increasing to white at top.
  6478. *unknown image.
  6479. *50x50 ellipse at middle L & 40x40 ellipse at center. Transluscent pink outlines.
  6480. *
  6481. */
  6482. p5.prototype.colorMode = function() {
  6483. if (arguments[0] === constants.RGB ||
  6484. arguments[0] === constants.HSB ||
  6485. arguments[0] === constants.HSL) {
  6486. // Set color mode.
  6487. this._renderer._colorMode = arguments[0];
  6488. // Set color maxes.
  6489. var maxes = this._renderer._colorMaxes[this._renderer._colorMode];
  6490. if (arguments.length === 2) {
  6491. maxes[0] = arguments[1]; // Red
  6492. maxes[1] = arguments[1]; // Green
  6493. maxes[2] = arguments[1]; // Blue
  6494. maxes[3] = arguments[1]; // Alpha
  6495. } else if (arguments.length === 4) {
  6496. maxes[0] = arguments[1]; // Red
  6497. maxes[1] = arguments[2]; // Green
  6498. maxes[2] = arguments[3]; // Blue
  6499. } else if (arguments.length === 5) {
  6500. maxes[0] = arguments[1]; // Red
  6501. maxes[1] = arguments[2]; // Green
  6502. maxes[2] = arguments[3]; // Blue
  6503. maxes[3] = arguments[4]; // Alpha
  6504. }
  6505. }
  6506. return this;
  6507. };
  6508. /**
  6509. * Sets the color used to fill shapes. For example, if you run
  6510. * fill(204, 102, 0), all subsequent shapes will be filled with orange. This
  6511. * color is either specified in terms of the RGB or HSB color depending on
  6512. * the current colorMode(). (The default color space is RGB, with each value
  6513. * in the range from 0 to 255).
  6514. * <br><br>
  6515. * If a single string argument is provided, RGB, RGBA and Hex CSS color strings
  6516. * and all named color strings are supported. A p5 Color object can also be
  6517. * provided to set the fill color.
  6518. *
  6519. * @method fill
  6520. * @param {Number|Array|String|p5.Color} v1 gray value, red or hue value
  6521. * (depending on the current color
  6522. * mode), or color Array, or CSS
  6523. * color string
  6524. * @param {Number} [v2] green or saturation value
  6525. * (depending on the current
  6526. * color mode)
  6527. * @param {Number} [v3] blue or brightness value
  6528. * (depending on the current
  6529. * color mode)
  6530. * @param {Number} [a] opacity of the background
  6531. *
  6532. * @example
  6533. * <div>
  6534. * <code>
  6535. * // Grayscale integer value
  6536. * fill(51);
  6537. * rect(20, 20, 60, 60);
  6538. * </code>
  6539. * </div>
  6540. *
  6541. * <div>
  6542. * <code>
  6543. * // R, G & B integer values
  6544. * fill(255, 204, 0);
  6545. * rect(20, 20, 60, 60);
  6546. * </code>
  6547. * </div>
  6548. *
  6549. * <div>
  6550. * <code>
  6551. * // H, S & B integer values
  6552. * colorMode(HSB);
  6553. * fill(255, 204, 100);
  6554. * rect(20, 20, 60, 60);
  6555. * </code>
  6556. * </div>
  6557. *
  6558. * <div>
  6559. * <code>
  6560. * // Named SVG/CSS color string
  6561. * fill('red');
  6562. * rect(20, 20, 60, 60);
  6563. * </code>
  6564. * </div>
  6565. *
  6566. * <div>
  6567. * <code>
  6568. * // three-digit hexadecimal RGB notation
  6569. * fill('#fae');
  6570. * rect(20, 20, 60, 60);
  6571. * </code>
  6572. * </div>
  6573. *
  6574. * <div>
  6575. * <code>
  6576. * // six-digit hexadecimal RGB notation
  6577. * fill('#222222');
  6578. * rect(20, 20, 60, 60);
  6579. * </code>
  6580. * </div>
  6581. *
  6582. * <div>
  6583. * <code>
  6584. * // integer RGB notation
  6585. * fill('rgb(0,255,0)');
  6586. * rect(20, 20, 60, 60);
  6587. * </code>
  6588. * </div>
  6589. *
  6590. * <div>
  6591. * <code>
  6592. * // integer RGBA notation
  6593. * fill('rgba(0,255,0, 0.25)');
  6594. * rect(20, 20, 60, 60);
  6595. * </code>
  6596. * </div>
  6597. *
  6598. * <div>
  6599. * <code>
  6600. * // percentage RGB notation
  6601. * fill('rgb(100%,0%,10%)');
  6602. * rect(20, 20, 60, 60);
  6603. * </code>
  6604. * </div>
  6605. *
  6606. * <div>
  6607. * <code>
  6608. * // percentage RGBA notation
  6609. * fill('rgba(100%,0%,100%,0.5)');
  6610. * rect(20, 20, 60, 60);
  6611. * </code>
  6612. * </div>
  6613. *
  6614. * <div>
  6615. * <code>
  6616. * // p5 Color object
  6617. * fill(color(0, 0, 255));
  6618. * rect(20, 20, 60, 60);
  6619. * </code>
  6620. * </div>
  6621. * @alt
  6622. * 60x60 dark charcoal grey rect with black outline in center of canvas.
  6623. * 60x60 yellow rect with black outline in center of canvas.
  6624. * 60x60 royal blue rect with black outline in center of canvas.
  6625. * 60x60 red rect with black outline in center of canvas.
  6626. * 60x60 pink rect with black outline in center of canvas.
  6627. * 60x60 black rect with black outline in center of canvas.
  6628. * 60x60 light green rect with black outline in center of canvas.
  6629. * 60x60 soft green rect with black outline in center of canvas.
  6630. * 60x60 red rect with black outline in center of canvas.
  6631. * 60x60 dark fushcia rect with black outline in center of canvas.
  6632. * 60x60 blue rect with black outline in center of canvas.
  6633. */
  6634. p5.prototype.fill = function() {
  6635. this._renderer._setProperty('_fillSet', true);
  6636. this._renderer._setProperty('_doFill', true);
  6637. this._renderer.fill.apply(this._renderer, arguments);
  6638. return this;
  6639. };
  6640. /**
  6641. * Disables filling geometry. If both noStroke() and noFill() are called,
  6642. * nothing will be drawn to the screen.
  6643. *
  6644. * @method noFill
  6645. * @example
  6646. * <div>
  6647. * <code>
  6648. * rect(15, 10, 55, 55);
  6649. * noFill();
  6650. * rect(20, 20, 60, 60);
  6651. * </code>
  6652. * </div>
  6653. * @alt
  6654. * white rect top middle and noFill rect center. Both 60x60 with black outlines.
  6655. */
  6656. p5.prototype.noFill = function() {
  6657. this._renderer._setProperty('_doFill', false);
  6658. return this;
  6659. };
  6660. /**
  6661. * Disables drawing the stroke (outline). If both noStroke() and noFill()
  6662. * are called, nothing will be drawn to the screen.
  6663. *
  6664. * @method noStroke
  6665. * @example
  6666. * <div>
  6667. * <code>
  6668. * noStroke();
  6669. * rect(20, 20, 60, 60);
  6670. * </code>
  6671. * </div>
  6672. *
  6673. *
  6674. * @alt
  6675. *60x60 white rect at center. no outline.
  6676. *
  6677. */
  6678. p5.prototype.noStroke = function() {
  6679. this._renderer._setProperty('_doStroke', false);
  6680. return this;
  6681. };
  6682. /**
  6683. * Sets the color used to draw lines and borders around shapes. This color
  6684. * is either specified in terms of the RGB or HSB color depending on the
  6685. * current colorMode() (the default color space is RGB, with each value in
  6686. * the range from 0 to 255).
  6687. * <br><br>
  6688. * If a single string argument is provided, RGB, RGBA and Hex CSS color
  6689. * strings and all named color strings are supported. A p5 Color object
  6690. * can also be provided to set the stroke color.
  6691. *
  6692. * @method stroke
  6693. * @param {Number|Array|String|p5.Color} v1 gray value, red or hue value
  6694. * (depending on the current color
  6695. * mode), or color Array, or CSS
  6696. * color string
  6697. * @param {Number} [v2] green or saturation value
  6698. * (depending on the current
  6699. * color mode)
  6700. * @param {Number} [v3] blue or brightness value
  6701. * (depending on the current
  6702. * color mode)
  6703. * @param {Number} [a] opacity of the background
  6704. *
  6705. * @example
  6706. * <div>
  6707. * <code>
  6708. * // Grayscale integer value
  6709. * strokeWeight(4);
  6710. * stroke(51);
  6711. * rect(20, 20, 60, 60);
  6712. * </code>
  6713. * </div>
  6714. *
  6715. * <div>
  6716. * <code>
  6717. * // R, G & B integer values
  6718. * stroke(255, 204, 0);
  6719. * strokeWeight(4);
  6720. * rect(20, 20, 60, 60);
  6721. * </code>
  6722. * </div>
  6723. *
  6724. * <div>
  6725. * <code>
  6726. * // H, S & B integer values
  6727. * colorMode(HSB);
  6728. * strokeWeight(4);
  6729. * stroke(255, 204, 100);
  6730. * rect(20, 20, 60, 60);
  6731. * </code>
  6732. * </div>
  6733. *
  6734. * <div>
  6735. * <code>
  6736. * // Named SVG/CSS color string
  6737. * stroke('red');
  6738. * strokeWeight(4);
  6739. * rect(20, 20, 60, 60);
  6740. * </code>
  6741. * </div>
  6742. *
  6743. * <div>
  6744. * <code>
  6745. * // three-digit hexadecimal RGB notation
  6746. * stroke('#fae');
  6747. * strokeWeight(4);
  6748. * rect(20, 20, 60, 60);
  6749. * </code>
  6750. * </div>
  6751. *
  6752. * <div>
  6753. * <code>
  6754. * // six-digit hexadecimal RGB notation
  6755. * stroke('#222222');
  6756. * strokeWeight(4);
  6757. * rect(20, 20, 60, 60);
  6758. * </code>
  6759. * </div>
  6760. *
  6761. * <div>
  6762. * <code>
  6763. * // integer RGB notation
  6764. * stroke('rgb(0,255,0)');
  6765. * strokeWeight(4);
  6766. * rect(20, 20, 60, 60);
  6767. * </code>
  6768. * </div>
  6769. *
  6770. * <div>
  6771. * <code>
  6772. * // integer RGBA notation
  6773. * stroke('rgba(0,255,0,0.25)');
  6774. * strokeWeight(4);
  6775. * rect(20, 20, 60, 60);
  6776. * </code>
  6777. * </div>
  6778. *
  6779. * <div>
  6780. * <code>
  6781. * // percentage RGB notation
  6782. * stroke('rgb(100%,0%,10%)');
  6783. * strokeWeight(4);
  6784. * rect(20, 20, 60, 60);
  6785. * </code>
  6786. * </div>
  6787. *
  6788. * <div>
  6789. * <code>
  6790. * // percentage RGBA notation
  6791. * stroke('rgba(100%,0%,100%,0.5)');
  6792. * strokeWeight(4);
  6793. * rect(20, 20, 60, 60);
  6794. * </code>
  6795. * </div>
  6796. *
  6797. * <div>
  6798. * <code>
  6799. * // p5 Color object
  6800. * stroke(color(0, 0, 255));
  6801. * strokeWeight(4);
  6802. * rect(20, 20, 60, 60);
  6803. * </code>
  6804. * </div>
  6805. *
  6806. * @alt
  6807. * 60x60 white rect at center. Dark charcoal grey outline.
  6808. * 60x60 white rect at center. Yellow outline.
  6809. * 60x60 white rect at center. Royal blue outline.
  6810. * 60x60 white rect at center. Red outline.
  6811. * 60x60 white rect at center. Pink outline.
  6812. * 60x60 white rect at center. Black outline.
  6813. * 60x60 white rect at center. Bright green outline.
  6814. * 60x60 white rect at center. Soft green outline.
  6815. * 60x60 white rect at center. Red outline.
  6816. * 60x60 white rect at center. Dark fushcia outline.
  6817. * 60x60 white rect at center. Blue outline.
  6818. */
  6819. p5.prototype.stroke = function() {
  6820. this._renderer._setProperty('_strokeSet', true);
  6821. this._renderer._setProperty('_doStroke', true);
  6822. this._renderer.stroke.apply(this._renderer, arguments);
  6823. return this;
  6824. };
  6825. module.exports = p5;
  6826. },{"../core/constants":36,"../core/core":37,"./p5.Color":31}],33:[function(_dereq_,module,exports){
  6827. /**
  6828. * @module Shape
  6829. * @submodule 2D Primitives
  6830. * @for p5
  6831. * @requires core
  6832. * @requires constants
  6833. */
  6834. 'use strict';
  6835. var p5 = _dereq_('./core');
  6836. var constants = _dereq_('./constants');
  6837. var canvas = _dereq_('./canvas');
  6838. _dereq_('./error_helpers');
  6839. /**
  6840. * Draw an arc to the screen. If called with only a, b, c, d, start, and
  6841. * stop, the arc will be drawn as an open pie. If mode is provided, the arc
  6842. * will be drawn either open, as a chord, or as a pie as specified. The
  6843. * origin may be changed with the ellipseMode() function.<br><br>
  6844. * Note that drawing a full circle (ex: 0 to TWO_PI) will appear blank
  6845. * because 0 and TWO_PI are the same position on the unit circle. The
  6846. * best way to handle this is by using the ellipse() function instead
  6847. * to create a closed ellipse, and to use the arc() function
  6848. * only to draw parts of an ellipse.
  6849. *
  6850. * @method arc
  6851. * @param {Number} a x-coordinate of the arc's ellipse
  6852. * @param {Number} b y-coordinate of the arc's ellipse
  6853. * @param {Number} c width of the arc's ellipse by default
  6854. * @param {Number} d height of the arc's ellipse by default
  6855. * @param {Number} start angle to start the arc, specified in radians
  6856. * @param {Number} stop angle to stop the arc, specified in radians
  6857. * @param {Constant} [mode] optional parameter to determine the way of drawing
  6858. * the arc
  6859. * @return {Object} the p5 object
  6860. * @example
  6861. * <div>
  6862. * <code>
  6863. * arc(50, 55, 50, 50, 0, HALF_PI);
  6864. * noFill();
  6865. * arc(50, 55, 60, 60, HALF_PI, PI);
  6866. * arc(50, 55, 70, 70, PI, PI+QUARTER_PI);
  6867. * arc(50, 55, 80, 80, PI+QUARTER_PI, TWO_PI);
  6868. * </code>
  6869. * </div>
  6870. *
  6871. * <div>
  6872. * <code>
  6873. * arc(50, 50, 80, 80, 0, PI+QUARTER_PI, OPEN);
  6874. * </code>
  6875. * </div>
  6876. *
  6877. * <div>
  6878. * <code>
  6879. * arc(50, 50, 80, 80, 0, PI+QUARTER_PI, CHORD);
  6880. * </code>
  6881. * </div>
  6882. *
  6883. * <div>
  6884. * <code>
  6885. * arc(50, 50, 80, 80, 0, PI+QUARTER_PI, PIE);
  6886. * </code>
  6887. * </div>
  6888. *
  6889. * @alt
  6890. *shattered outline of an ellipse with a quarter of a white circle bottom-right.
  6891. *white ellipse with black outline with top right missing.
  6892. *white ellipse with top right missing with black outline around shape.
  6893. *white ellipse with top right quarter missing with black outline around the shape.
  6894. *
  6895. */
  6896. p5.prototype.arc = function(x, y, w, h, start, stop, mode) {
  6897. var args = new Array(arguments.length);
  6898. for (var i = 0; i < args.length; ++i) {
  6899. args[i] = arguments[i];
  6900. }
  6901. if (!this._renderer._doStroke && !this._renderer._doFill) {
  6902. return this;
  6903. }
  6904. if (this._angleMode === constants.DEGREES) {
  6905. start = this.radians(start);
  6906. stop = this.radians(stop);
  6907. }
  6908. // Make all angles positive...
  6909. while (start < 0) {
  6910. start += constants.TWO_PI;
  6911. }
  6912. while (stop < 0) {
  6913. stop += constants.TWO_PI;
  6914. }
  6915. // ...and confine them to the interval [0,TWO_PI).
  6916. start %= constants.TWO_PI;
  6917. stop %= constants.TWO_PI;
  6918. // account for full circle
  6919. if (stop === start) {
  6920. stop += constants.TWO_PI;
  6921. }
  6922. // Adjust angles to counter linear scaling.
  6923. if (start <= constants.HALF_PI) {
  6924. start = Math.atan(w / h * Math.tan(start));
  6925. } else if (start > constants.HALF_PI && start <= 3 * constants.HALF_PI) {
  6926. start = Math.atan(w / h * Math.tan(start)) + constants.PI;
  6927. } else {
  6928. start = Math.atan(w / h * Math.tan(start)) + constants.TWO_PI;
  6929. }
  6930. if (stop <= constants.HALF_PI) {
  6931. stop = Math.atan(w / h * Math.tan(stop));
  6932. } else if (stop > constants.HALF_PI && stop <= 3 * constants.HALF_PI) {
  6933. stop = Math.atan(w / h * Math.tan(stop)) + constants.PI;
  6934. } else {
  6935. stop = Math.atan(w / h * Math.tan(stop)) + constants.TWO_PI;
  6936. }
  6937. // Exceed the interval if necessary in order to preserve the size and
  6938. // orientation of the arc.
  6939. if (start > stop) {
  6940. stop += constants.TWO_PI;
  6941. }
  6942. // p5 supports negative width and heights for ellipses
  6943. w = Math.abs(w);
  6944. h = Math.abs(h);
  6945. this._renderer.arc(x, y, w, h, start, stop, mode);
  6946. return this;
  6947. };
  6948. /**
  6949. * Draws an ellipse (oval) to the screen. An ellipse with equal width and
  6950. * height is a circle. By default, the first two parameters set the location,
  6951. * and the third and fourth parameters set the shape's width and height. If
  6952. * no height is specified, the value of width is used for both the width and
  6953. * height. If a negative height or width is specified, the absolute value is taken.
  6954. * The origin may be changed with the ellipseMode() function.
  6955. *
  6956. * @method ellipse
  6957. * @param {Number} x x-coordinate of the ellipse.
  6958. * @param {Number} y y-coordinate of the ellipse.
  6959. * @param {Number} w width of the ellipse.
  6960. * @param {Number} [h] height of the ellipse.
  6961. * @return {p5} the p5 object
  6962. * @example
  6963. * <div>
  6964. * <code>
  6965. * ellipse(56, 46, 55, 55);
  6966. * </code>
  6967. * </div>
  6968. *
  6969. * @alt
  6970. *white ellipse with black outline in middle-right of canvas that is 55x55.
  6971. *
  6972. */
  6973. /**
  6974. * @method ellipse
  6975. * @param {Number} x
  6976. * @param {Number} y
  6977. * @param {Number} w
  6978. * @param {Number} [h]
  6979. * @return {p5}
  6980. */
  6981. p5.prototype.ellipse = function() {
  6982. var args = new Array(arguments.length);
  6983. for (var i = 0; i < args.length; ++i) {
  6984. args[i] = arguments[i];
  6985. }
  6986. // Duplicate 3rd argument if only 3 given.
  6987. if (args.length === 3) {
  6988. args.push(args[2]);
  6989. }
  6990. // p5 supports negative width and heights for rects
  6991. if (args[2] < 0){args[2] = Math.abs(args[2]);}
  6992. if (args[3] < 0){args[3] = Math.abs(args[3]);}
  6993. if (!this._renderer._doStroke && !this._renderer._doFill) {
  6994. return this;
  6995. }
  6996. var vals = canvas.modeAdjust(
  6997. args[0],
  6998. args[1],
  6999. args[2],
  7000. args[3],
  7001. this._renderer._ellipseMode);
  7002. args[0] = vals.x;
  7003. args[1] = vals.y;
  7004. args[2] = vals.w;
  7005. args[3] = vals.h;
  7006. this._renderer.ellipse(args);
  7007. return this;
  7008. };
  7009. /**
  7010. * Draws a line (a direct path between two points) to the screen. The version
  7011. * of line() with four parameters draws the line in 2D. To color a line, use
  7012. * the stroke() function. A line cannot be filled, therefore the fill()
  7013. * function will not affect the color of a line. 2D lines are drawn with a
  7014. * width of one pixel by default, but this can be changed with the
  7015. * strokeWeight() function.
  7016. *
  7017. * @method line
  7018. * @param {Number} x1 the x-coordinate of the first point
  7019. * @param {Number} y1 the y-coordinate of the first point
  7020. * @param {Number} x2 the x-coordinate of the second point
  7021. * @param {Number} y2 the y-coordinate of the second point
  7022. * @return {p5} the p5 object
  7023. * @example
  7024. * <div>
  7025. * <code>
  7026. * line(30, 20, 85, 75);
  7027. * </code>
  7028. * </div>
  7029. *
  7030. * <div>
  7031. * <code>
  7032. * line(30, 20, 85, 20);
  7033. * stroke(126);
  7034. * line(85, 20, 85, 75);
  7035. * stroke(255);
  7036. * line(85, 75, 30, 75);
  7037. * </code>
  7038. * </div>
  7039. *
  7040. * @alt
  7041. *line 78 pixels long running from mid-top to bottom-right of canvas.
  7042. *3 lines of various stroke sizes. Form top, bottom and right sides of a square.
  7043. *
  7044. */
  7045. ////commented out original
  7046. // p5.prototype.line = function(x1, y1, x2, y2) {
  7047. // if (!this._renderer._doStroke) {
  7048. // return this;
  7049. // }
  7050. // if(this._renderer.isP3D){
  7051. // } else {
  7052. // this._renderer.line(x1, y1, x2, y2);
  7053. // }
  7054. // };
  7055. p5.prototype.line = function() {
  7056. if (!this._renderer._doStroke) {
  7057. return this;
  7058. }
  7059. var args = new Array(arguments.length);
  7060. for (var i = 0; i < args.length; ++i) {
  7061. args[i] = arguments[i];
  7062. }
  7063. //check whether we should draw a 3d line or 2d
  7064. if(this._renderer.isP3D){
  7065. this._renderer.line(
  7066. args[0],
  7067. args[1],
  7068. args[2],
  7069. args[3],
  7070. args[4],
  7071. args[5]);
  7072. } else {
  7073. this._renderer.line(
  7074. args[0],
  7075. args[1],
  7076. args[2],
  7077. args[3]);
  7078. }
  7079. return this;
  7080. };
  7081. /**
  7082. * Draws a point, a coordinate in space at the dimension of one pixel.
  7083. * The first parameter is the horizontal value for the point, the second
  7084. * value is the vertical value for the point. The color of the point is
  7085. * determined by the current stroke.
  7086. *
  7087. * @method point
  7088. * @param {Number} x the x-coordinate
  7089. * @param {Number} y the y-coordinate
  7090. * @return {p5} the p5 object
  7091. * @example
  7092. * <div>
  7093. * <code>
  7094. * point(30, 20);
  7095. * point(85, 20);
  7096. * point(85, 75);
  7097. * point(30, 75);
  7098. * </code>
  7099. * </div>
  7100. *
  7101. * @alt
  7102. *4 points centered in the middle-right of the canvas.
  7103. *
  7104. */
  7105. p5.prototype.point = function() {
  7106. if (!this._renderer._doStroke) {
  7107. return this;
  7108. }
  7109. var args = new Array(arguments.length);
  7110. for (var i = 0; i < args.length; ++i) {
  7111. args[i] = arguments[i];
  7112. }
  7113. //check whether we should draw a 3d line or 2d
  7114. if(this._renderer.isP3D){
  7115. this._renderer.point(
  7116. args[0],
  7117. args[1],
  7118. args[2]
  7119. );
  7120. } else {
  7121. this._renderer.point(
  7122. args[0],
  7123. args[1]
  7124. );
  7125. }
  7126. return this;
  7127. };
  7128. /**
  7129. * Draw a quad. A quad is a quadrilateral, a four sided polygon. It is
  7130. * similar to a rectangle, but the angles between its edges are not
  7131. * constrained to ninety degrees. The first pair of parameters (x1,y1)
  7132. * sets the first vertex and the subsequent pairs should proceed
  7133. * clockwise or counter-clockwise around the defined shape.
  7134. *
  7135. * @method quad
  7136. * @param {Number} x1 the x-coordinate of the first point
  7137. * @param {Number} y1 the y-coordinate of the first point
  7138. * @param {Number} x2 the x-coordinate of the second point
  7139. * @param {Number} y2 the y-coordinate of the second point
  7140. * @param {Number} x3 the x-coordinate of the third point
  7141. * @param {Number} y3 the y-coordinate of the third point
  7142. * @param {Number} x4 the x-coordinate of the fourth point
  7143. * @param {Number} y4 the y-coordinate of the fourth point
  7144. * @return {p5} the p5 object
  7145. * @example
  7146. * <div>
  7147. * <code>
  7148. * quad(38, 31, 86, 20, 69, 63, 30, 76);
  7149. * </code>
  7150. * </div>
  7151. *
  7152. * @alt
  7153. *irregular white quadrilateral shape with black outline mid-right of canvas.
  7154. *
  7155. */
  7156. /**
  7157. * @method quad
  7158. * @param {Number} x1
  7159. * @param {Number} y1
  7160. * @param {Number} x2
  7161. * @param {Number} y2
  7162. * @param {Number} x3
  7163. * @param {Number} y3
  7164. * @param {Number} x4
  7165. * @param {Number} y4
  7166. * @return {p5} the p5 object
  7167. */
  7168. p5.prototype.quad = function() {
  7169. if (!this._renderer._doStroke && !this._renderer._doFill) {
  7170. return this;
  7171. }
  7172. var args = new Array(arguments.length);
  7173. for (var i = 0; i < args.length; ++i) {
  7174. args[i] = arguments[i];
  7175. }
  7176. if(this._renderer.isP3D){
  7177. this._renderer.quad(
  7178. args[0],
  7179. args[1],
  7180. args[2],
  7181. args[3],
  7182. args[4],
  7183. args[5],
  7184. args[6],
  7185. args[7],
  7186. args[8],
  7187. args[9],
  7188. args[10],
  7189. args[11]
  7190. );
  7191. } else {
  7192. this._renderer.quad(
  7193. args[0],
  7194. args[1],
  7195. args[2],
  7196. args[3],
  7197. args[4],
  7198. args[5],
  7199. args[6],
  7200. args[7]
  7201. );
  7202. }
  7203. return this;
  7204. };
  7205. /**
  7206. * Draws a rectangle to the screen. A rectangle is a four-sided shape with
  7207. * every angle at ninety degrees. By default, the first two parameters set
  7208. * the location of the upper-left corner, the third sets the width, and the
  7209. * fourth sets the height. The way these parameters are interpreted, however,
  7210. * may be changed with the rectMode() function.
  7211. * <br><br>
  7212. * The fifth, sixth, seventh and eighth parameters, if specified,
  7213. * determine corner radius for the top-right, top-left, lower-right and
  7214. * lower-left corners, respectively. An omitted corner radius parameter is set
  7215. * to the value of the previously specified radius value in the parameter list.
  7216. *
  7217. * @method rect
  7218. * @param {Number} x x-coordinate of the rectangle.
  7219. * @param {Number} y y-coordinate of the rectangle.
  7220. * @param {Number} w width of the rectangle.
  7221. * @param {Number} h height of the rectangle.
  7222. * @param {Number} [tl] optional radius of top-left corner.
  7223. * @param {Number} [tr] optional radius of top-right corner.
  7224. * @param {Number} [br] optional radius of bottom-right corner.
  7225. * @param {Number} [bl] optional radius of bottom-left corner.
  7226. * @return {p5} the p5 object.
  7227. * @example
  7228. * <div>
  7229. * <code>
  7230. * // Draw a rectangle at location (30, 20) with a width and height of 55.
  7231. * rect(30, 20, 55, 55);
  7232. * </code>
  7233. * </div>
  7234. *
  7235. * <div>
  7236. * <code>
  7237. * // Draw a rectangle with rounded corners, each having a radius of 20.
  7238. * rect(30, 20, 55, 55, 20);
  7239. * </code>
  7240. * </div>
  7241. *
  7242. * <div>
  7243. * <code>
  7244. * // Draw a rectangle with rounded corners having the following radii:
  7245. * // top-left = 20, top-right = 15, bottom-right = 10, bottom-left = 5.
  7246. * rect(30, 20, 55, 55, 20, 15, 10, 5);
  7247. * </code>
  7248. * </div>
  7249. *
  7250. * @alt
  7251. * 55x55 white rect with black outline in mid-right of canvas.
  7252. * 55x55 white rect with black outline and rounded edges in mid-right of canvas.
  7253. * 55x55 white rect with black outline and rounded edges of different radii.
  7254. */
  7255. /**
  7256. * @method rect
  7257. * @param {Number} x
  7258. * @param {Number} y
  7259. * @param {Number} w
  7260. * @param {Number} h
  7261. * @param {Number} [detailX]
  7262. * @param {Number} [detailY]
  7263. * @return {p5} the p5 object.
  7264. */
  7265. p5.prototype.rect = function () {
  7266. var args = new Array(arguments.length);
  7267. for (var i = 0; i < args.length; ++i) {
  7268. args[i] = arguments[i];
  7269. }
  7270. if (!this._renderer._doStroke && !this._renderer._doFill) {
  7271. return;
  7272. }
  7273. var vals = canvas.modeAdjust(
  7274. args[0],
  7275. args[1],
  7276. args[2],
  7277. args[3],
  7278. this._renderer._rectMode);
  7279. args[0] = vals.x;
  7280. args[1] = vals.y;
  7281. args[2] = vals.w;
  7282. args[3] = vals.h;
  7283. this._renderer.rect(args);
  7284. return this;
  7285. };
  7286. /**
  7287. * A triangle is a plane created by connecting three points. The first two
  7288. * arguments specify the first point, the middle two arguments specify the
  7289. * second point, and the last two arguments specify the third point.
  7290. *
  7291. * @method triangle
  7292. * @param {Number} x1 x-coordinate of the first point
  7293. * @param {Number} y1 y-coordinate of the first point
  7294. * @param {Number} x2 x-coordinate of the second point
  7295. * @param {Number} y2 y-coordinate of the second point
  7296. * @param {Number} x3 x-coordinate of the third point
  7297. * @param {Number} y3 y-coordinate of the third point
  7298. * @return {p5} the p5 object
  7299. * @example
  7300. * <div>
  7301. * <code>
  7302. * triangle(30, 75, 58, 20, 86, 75);
  7303. * </code>
  7304. * </div>
  7305. *
  7306. *@alt
  7307. * white triangle with black outline in mid-right of canvas.
  7308. *
  7309. */
  7310. p5.prototype.triangle = function() {
  7311. if (!this._renderer._doStroke && !this._renderer._doFill) {
  7312. return this;
  7313. }
  7314. var args = new Array(arguments.length);
  7315. for (var i = 0; i < args.length; ++i) {
  7316. args[i] = arguments[i];
  7317. }
  7318. this._renderer.triangle(args);
  7319. return this;
  7320. };
  7321. module.exports = p5;
  7322. },{"./canvas":35,"./constants":36,"./core":37,"./error_helpers":40}],34:[function(_dereq_,module,exports){
  7323. /**
  7324. * @module Shape
  7325. * @submodule Attributes
  7326. * @for p5
  7327. * @requires core
  7328. * @requires constants
  7329. */
  7330. 'use strict';
  7331. var p5 = _dereq_('./core');
  7332. var constants = _dereq_('./constants');
  7333. /**
  7334. * Modifies the location from which ellipses are drawn by changing the way
  7335. * in which parameters given to ellipse() are interpreted.
  7336. * <br><br>
  7337. * The default mode is ellipseMode(CENTER), which interprets the first two
  7338. * parameters of ellipse() as the shape's center point, while the third and
  7339. * fourth parameters are its width and height.
  7340. * <br><br>
  7341. * ellipseMode(RADIUS) also uses the first two parameters of ellipse() as
  7342. * the shape's center point, but uses the third and fourth parameters to
  7343. * specify half of the shapes's width and height.
  7344. * <br><br>
  7345. * ellipseMode(CORNER) interprets the first two parameters of ellipse() as
  7346. * the upper-left corner of the shape, while the third and fourth parameters
  7347. * are its width and height.
  7348. * <br><br>
  7349. * ellipseMode(CORNERS) interprets the first two parameters of ellipse() as
  7350. * the location of one corner of the ellipse's bounding box, and the third
  7351. * and fourth parameters as the location of the opposite corner.
  7352. * <br><br>
  7353. * The parameter must be written in ALL CAPS because Javascript is a
  7354. * case-sensitive language.
  7355. *
  7356. * @method ellipseMode
  7357. * @param {Constant} mode either CENTER, RADIUS, CORNER, or CORNERS
  7358. * @return {p5} the p5 object
  7359. * @example
  7360. * <div>
  7361. * <code>
  7362. * ellipseMode(RADIUS); // Set ellipseMode to RADIUS
  7363. * fill(255); // Set fill to white
  7364. * ellipse(50, 50, 30, 30); // Draw white ellipse using RADIUS mode
  7365. *
  7366. * ellipseMode(CENTER); // Set ellipseMode to CENTER
  7367. * fill(100); // Set fill to gray
  7368. * ellipse(50, 50, 30, 30); // Draw gray ellipse using CENTER mode
  7369. * </code>
  7370. * </div>
  7371. *
  7372. * <div>
  7373. * <code>
  7374. * ellipseMode(CORNER); // Set ellipseMode is CORNER
  7375. * fill(255); // Set fill to white
  7376. * ellipse(25, 25, 50, 50); // Draw white ellipse using CORNER mode
  7377. *
  7378. * ellipseMode(CORNERS); // Set ellipseMode to CORNERS
  7379. * fill(100); // Set fill to gray
  7380. * ellipse(25, 25, 50, 50); // Draw gray ellipse using CORNERS mode
  7381. * </code>
  7382. * </div>
  7383. *
  7384. * @alt
  7385. * 60x60 white ellipse and 30x30 grey ellipse with black outlines at center.
  7386. * 60x60 white ellipse @center and 30x30 grey ellipse top-right, black outlines.
  7387. *
  7388. */
  7389. p5.prototype.ellipseMode = function(m) {
  7390. if (m === constants.CORNER ||
  7391. m === constants.CORNERS ||
  7392. m === constants.RADIUS ||
  7393. m === constants.CENTER) {
  7394. this._renderer._ellipseMode = m;
  7395. }
  7396. return this;
  7397. };
  7398. /**
  7399. * Draws all geometry with jagged (aliased) edges. Note that smooth() is
  7400. * active by default, so it is necessary to call noSmooth() to disable
  7401. * smoothing of geometry, images, and fonts.
  7402. *
  7403. * @method noSmooth
  7404. * @return {p5} the p5 object
  7405. * @example
  7406. * <div>
  7407. * <code>
  7408. * background(0);
  7409. * noStroke();
  7410. * smooth();
  7411. * ellipse(30, 48, 36, 36);
  7412. * noSmooth();
  7413. * ellipse(70, 48, 36, 36);
  7414. * </code>
  7415. * </div>
  7416. *
  7417. * @alt
  7418. * 2 pixelated 36x36 white ellipses to left & right of center, black background
  7419. *
  7420. */
  7421. p5.prototype.noSmooth = function() {
  7422. this._renderer.noSmooth();
  7423. return this;
  7424. };
  7425. /**
  7426. * Modifies the location from which rectangles are drawn by changing the way
  7427. * in which parameters given to rect() are interpreted.
  7428. * <br><br>
  7429. * The default mode is rectMode(CORNER), which interprets the first two
  7430. * parameters of rect() as the upper-left corner of the shape, while the
  7431. * third and fourth parameters are its width and height.
  7432. * <br><br>
  7433. * rectMode(CORNERS) interprets the first two parameters of rect() as the
  7434. * location of one corner, and the third and fourth parameters as the
  7435. * location of the opposite corner.
  7436. * <br><br>
  7437. * rectMode(CENTER) interprets the first two parameters of rect() as the
  7438. * shape's center point, while the third and fourth parameters are its
  7439. * width and height.
  7440. * <br><br>
  7441. * rectMode(RADIUS) also uses the first two parameters of rect() as the
  7442. * shape's center point, but uses the third and fourth parameters to specify
  7443. * half of the shapes's width and height.
  7444. * <br><br>
  7445. * The parameter must be written in ALL CAPS because Javascript is a
  7446. * case-sensitive language.
  7447. *
  7448. * @method rectMode
  7449. * @param {Constant} mode either CORNER, CORNERS, CENTER, or RADIUS
  7450. * @return {p5} the p5 object
  7451. * @example
  7452. * <div>
  7453. * <code>
  7454. * rectMode(CORNER); // Default rectMode is CORNER
  7455. * fill(255); // Set fill to white
  7456. * rect(25, 25, 50, 50); // Draw white rect using CORNER mode
  7457. *
  7458. * rectMode(CORNERS); // Set rectMode to CORNERS
  7459. * fill(100); // Set fill to gray
  7460. * rect(25, 25, 50, 50); // Draw gray rect using CORNERS mode
  7461. * </code>
  7462. * </div>
  7463. *
  7464. * <div>
  7465. * <code>
  7466. * rectMode(RADIUS); // Set rectMode to RADIUS
  7467. * fill(255); // Set fill to white
  7468. * rect(50, 50, 30, 30); // Draw white rect using RADIUS mode
  7469. *
  7470. * rectMode(CENTER); // Set rectMode to CENTER
  7471. * fill(100); // Set fill to gray
  7472. * rect(50, 50, 30, 30); // Draw gray rect using CENTER mode
  7473. * </code>
  7474. * </div>
  7475. *
  7476. * @alt
  7477. * 50x50 white rect at center and 25x25 grey rect in the top left of the other.
  7478. * 50x50 white rect at center and 25x25 grey rect in the center of the other.
  7479. *
  7480. */
  7481. p5.prototype.rectMode = function(m) {
  7482. if (m === constants.CORNER ||
  7483. m === constants.CORNERS ||
  7484. m === constants.RADIUS ||
  7485. m === constants.CENTER) {
  7486. this._renderer._rectMode = m;
  7487. }
  7488. return this;
  7489. };
  7490. /**
  7491. * Draws all geometry with smooth (anti-aliased) edges. smooth() will also
  7492. * improve image quality of resized images. Note that smooth() is active by
  7493. * default; noSmooth() can be used to disable smoothing of geometry,
  7494. * images, and fonts.
  7495. *
  7496. * @method smooth
  7497. * @return {p5} the p5 object
  7498. * @example
  7499. * <div>
  7500. * <code>
  7501. * background(0);
  7502. * noStroke();
  7503. * smooth();
  7504. * ellipse(30, 48, 36, 36);
  7505. * noSmooth();
  7506. * ellipse(70, 48, 36, 36);
  7507. * </code>
  7508. * </div>
  7509. *
  7510. * @alt
  7511. * 2 pixelated 36x36 white ellipses one left one right of center. On black.
  7512. *
  7513. */
  7514. p5.prototype.smooth = function() {
  7515. this._renderer.smooth();
  7516. return this;
  7517. };
  7518. /**
  7519. * Sets the style for rendering line endings. These ends are either squared,
  7520. * extended, or rounded, each of which specified with the corresponding
  7521. * parameters: SQUARE, PROJECT, and ROUND. The default cap is ROUND.
  7522. *
  7523. * @method strokeCap
  7524. * @param {Number/Constant} cap either SQUARE, PROJECT, or ROUND
  7525. * @return {p5} the p5 object
  7526. * @example
  7527. * <div>
  7528. * <code>
  7529. * strokeWeight(12.0);
  7530. * strokeCap(ROUND);
  7531. * line(20, 30, 80, 30);
  7532. * strokeCap(SQUARE);
  7533. * line(20, 50, 80, 50);
  7534. * strokeCap(PROJECT);
  7535. * line(20, 70, 80, 70);
  7536. * </code>
  7537. * </div>
  7538. *
  7539. * @alt
  7540. * 3 lines. Top line: rounded ends, mid: squared, bottom:longer squared ends.
  7541. *
  7542. */
  7543. p5.prototype.strokeCap = function(cap) {
  7544. if (cap === constants.ROUND ||
  7545. cap === constants.SQUARE ||
  7546. cap === constants.PROJECT) {
  7547. this._renderer.strokeCap(cap);
  7548. }
  7549. return this;
  7550. };
  7551. /**
  7552. * Sets the style of the joints which connect line segments. These joints
  7553. * are either mitered, beveled, or rounded and specified with the
  7554. * corresponding parameters MITER, BEVEL, and ROUND. The default joint is
  7555. * MITER.
  7556. *
  7557. * @method strokeJoin
  7558. * @param {Number/Constant} join either MITER, BEVEL, ROUND
  7559. * @return {p5} the p5 object
  7560. * @example
  7561. * <div>
  7562. * <code>
  7563. * noFill();
  7564. * strokeWeight(10.0);
  7565. * strokeJoin(MITER);
  7566. * beginShape();
  7567. * vertex(35, 20);
  7568. * vertex(65, 50);
  7569. * vertex(35, 80);
  7570. * endShape();
  7571. * </code>
  7572. * </div>
  7573. *
  7574. * <div>
  7575. * <code>
  7576. * noFill();
  7577. * strokeWeight(10.0);
  7578. * strokeJoin(BEVEL);
  7579. * beginShape();
  7580. * vertex(35, 20);
  7581. * vertex(65, 50);
  7582. * vertex(35, 80);
  7583. * endShape();
  7584. * </code>
  7585. * </div>
  7586. *
  7587. * <div>
  7588. * <code>
  7589. * noFill();
  7590. * strokeWeight(10.0);
  7591. * strokeJoin(ROUND);
  7592. * beginShape();
  7593. * vertex(35, 20);
  7594. * vertex(65, 50);
  7595. * vertex(35, 80);
  7596. * endShape();
  7597. * </code>
  7598. * </div>
  7599. *
  7600. * @alt
  7601. * Right-facing arrowhead shape with pointed tip in center of canvas.
  7602. * Right-facing arrowhead shape with flat tip in center of canvas.
  7603. * Right-facing arrowhead shape with rounded tip in center of canvas.
  7604. *
  7605. */
  7606. p5.prototype.strokeJoin = function(join) {
  7607. if (join === constants.ROUND ||
  7608. join === constants.BEVEL ||
  7609. join === constants.MITER) {
  7610. this._renderer.strokeJoin(join);
  7611. }
  7612. return this;
  7613. };
  7614. /**
  7615. * Sets the width of the stroke used for lines, points, and the border
  7616. * around shapes. All widths are set in units of pixels.
  7617. *
  7618. * @method strokeWeight
  7619. * @param {Number} weight the weight (in pixels) of the stroke
  7620. * @return {p5} the p5 object
  7621. * @example
  7622. * <div>
  7623. * <code>
  7624. * strokeWeight(1); // Default
  7625. * line(20, 20, 80, 20);
  7626. * strokeWeight(4); // Thicker
  7627. * line(20, 40, 80, 40);
  7628. * strokeWeight(10); // Beastly
  7629. * line(20, 70, 80, 70);
  7630. * </code>
  7631. * </div>
  7632. *
  7633. * @alt
  7634. * 3 horizontal black lines. Top line: thin, mid: medium, bottom:thick.
  7635. *
  7636. */
  7637. p5.prototype.strokeWeight = function(w) {
  7638. this._renderer.strokeWeight(w);
  7639. return this;
  7640. };
  7641. module.exports = p5;
  7642. },{"./constants":36,"./core":37}],35:[function(_dereq_,module,exports){
  7643. /**
  7644. * @requires constants
  7645. */
  7646. var constants = _dereq_('./constants');
  7647. module.exports = {
  7648. modeAdjust: function(a, b, c, d, mode) {
  7649. if (mode === constants.CORNER) {
  7650. return { x: a, y: b, w: c, h: d };
  7651. } else if (mode === constants.CORNERS) {
  7652. return { x: a, y: b, w: c-a, h: d-b };
  7653. } else if (mode === constants.RADIUS) {
  7654. return { x: a-c, y: b-d, w: 2*c, h: 2*d };
  7655. } else if (mode === constants.CENTER) {
  7656. return { x: a-c*0.5, y: b-d*0.5, w: c, h: d };
  7657. }
  7658. },
  7659. arcModeAdjust: function(a, b, c, d, mode) {
  7660. if (mode === constants.CORNER) {
  7661. return { x: a+c*0.5, y: b+d*0.5, w: c, h: d };
  7662. } else if (mode === constants.CORNERS) {
  7663. return { x: a, y: b, w: c+a, h: d+b };
  7664. } else if (mode === constants.RADIUS) {
  7665. return { x: a, y: b, w: 2*c, h: 2*d };
  7666. } else if (mode === constants.CENTER) {
  7667. return { x: a, y: b, w: c, h: d };
  7668. }
  7669. }
  7670. };
  7671. },{"./constants":36}],36:[function(_dereq_,module,exports){
  7672. /**
  7673. * @module Constants
  7674. * @submodule Constants
  7675. * @for p5
  7676. */
  7677. var PI = Math.PI;
  7678. module.exports = {
  7679. // GRAPHICS RENDERER
  7680. P2D: 'p2d',
  7681. WEBGL: 'webgl',
  7682. // ENVIRONMENT
  7683. ARROW: 'default',
  7684. CROSS: 'crosshair',
  7685. HAND: 'pointer',
  7686. MOVE: 'move',
  7687. TEXT: 'text',
  7688. WAIT: 'wait',
  7689. // TRIGONOMETRY
  7690. /**
  7691. * HALF_PI is a mathematical constant with the value
  7692. * 1.57079632679489661923. It is half the ratio of the
  7693. * circumference of a circle to its diameter. It is useful in
  7694. * combination with the trigonometric functions sin() and cos().
  7695. *
  7696. * @property HALF_PI
  7697. *
  7698. * @example
  7699. * <div><code>
  7700. * arc(50, 50, 80, 80, 0, HALF_PI);
  7701. * </code></div>
  7702. *
  7703. * @alt
  7704. * 80x80 white quarter-circle with curve toward bottom right of canvas.
  7705. *
  7706. */
  7707. HALF_PI: PI / 2,
  7708. /**
  7709. * PI is a mathematical constant with the value
  7710. * 3.14159265358979323846. It is the ratio of the circumference
  7711. * of a circle to its diameter. It is useful in combination with
  7712. * the trigonometric functions sin() and cos().
  7713. *
  7714. * @property PI
  7715. *
  7716. * @example
  7717. * <div><code>
  7718. * arc(50, 50, 80, 80, 0, PI);
  7719. * </code></div>
  7720. *
  7721. * @alt
  7722. * white half-circle with curve toward bottom of canvas.
  7723. *
  7724. */
  7725. PI: PI,
  7726. /**
  7727. * QUARTER_PI is a mathematical constant with the value 0.7853982.
  7728. * It is one quarter the ratio of the circumference of a circle to
  7729. * its diameter. It is useful in combination with the trigonometric
  7730. * functions sin() and cos().
  7731. *
  7732. * @property QUARTER_PI
  7733. *
  7734. * @example
  7735. * <div><code>
  7736. * arc(50, 50, 80, 80, 0, QUARTER_PI);
  7737. * </code></div>
  7738. *
  7739. * @alt
  7740. * white eighth-circle rotated about 40 degrees with curve bottom right canvas.
  7741. *
  7742. */
  7743. QUARTER_PI: PI / 4,
  7744. /**
  7745. * TAU is an alias for TWO_PI, a mathematical constant with the
  7746. * value 6.28318530717958647693. It is twice the ratio of the
  7747. * circumference of a circle to its diameter. It is useful in
  7748. * combination with the trigonometric functions sin() and cos().
  7749. *
  7750. * @property TAU
  7751. *
  7752. * @example
  7753. * <div><code>
  7754. * arc(50, 50, 80, 80, 0, TAU);
  7755. * </code></div>
  7756. *
  7757. * @alt
  7758. * 80x80 white ellipse shape in center of canvas.
  7759. *
  7760. */
  7761. TAU: PI * 2,
  7762. /**
  7763. * TWO_PI is a mathematical constant with the value
  7764. * 6.28318530717958647693. It is twice the ratio of the
  7765. * circumference of a circle to its diameter. It is useful in
  7766. * combination with the trigonometric functions sin() and cos().
  7767. *
  7768. * @property TWO_PI
  7769. *
  7770. * @example
  7771. * <div><code>
  7772. * arc(50, 50, 80, 80, 0, TWO_PI);
  7773. * </code></div>
  7774. *
  7775. * @alt
  7776. * 80x80 white ellipse shape in center of canvas.
  7777. *
  7778. */
  7779. TWO_PI: PI * 2,
  7780. DEGREES: 'degrees',
  7781. RADIANS: 'radians',
  7782. // SHAPE
  7783. CORNER: 'corner',
  7784. CORNERS: 'corners',
  7785. RADIUS: 'radius',
  7786. RIGHT: 'right',
  7787. LEFT: 'left',
  7788. CENTER: 'center',
  7789. TOP: 'top',
  7790. BOTTOM: 'bottom',
  7791. BASELINE: 'alphabetic',
  7792. POINTS: 0x0000,
  7793. LINES: 0x0001,
  7794. LINE_STRIP: 0x0003,
  7795. LINE_LOOP: 0x0002,
  7796. TRIANGLES: 0x0004,
  7797. TRIANGLE_FAN: 0x0006,
  7798. TRIANGLE_STRIP: 0x0005,
  7799. QUADS: 'quads',
  7800. QUAD_STRIP: 'quad_strip',
  7801. CLOSE: 'close',
  7802. OPEN: 'open',
  7803. CHORD: 'chord',
  7804. PIE: 'pie',
  7805. PROJECT: 'square', // PEND: careful this is counterintuitive
  7806. SQUARE: 'butt',
  7807. ROUND: 'round',
  7808. BEVEL: 'bevel',
  7809. MITER: 'miter',
  7810. // COLOR
  7811. RGB: 'rgb',
  7812. HSB: 'hsb',
  7813. HSL: 'hsl',
  7814. // DOM EXTENSION
  7815. AUTO: 'auto',
  7816. // INPUT
  7817. ALT: 18,
  7818. BACKSPACE: 8,
  7819. CONTROL: 17,
  7820. DELETE: 46,
  7821. DOWN_ARROW: 40,
  7822. ENTER: 13,
  7823. ESCAPE: 27,
  7824. LEFT_ARROW: 37,
  7825. OPTION: 18,
  7826. RETURN: 13,
  7827. RIGHT_ARROW: 39,
  7828. SHIFT: 16,
  7829. TAB: 9,
  7830. UP_ARROW: 38,
  7831. // RENDERING
  7832. BLEND: 'normal',
  7833. ADD: 'lighter',
  7834. //ADD: 'add', //
  7835. //SUBTRACT: 'subtract', //
  7836. DARKEST: 'darken',
  7837. LIGHTEST: 'lighten',
  7838. DIFFERENCE: 'difference',
  7839. EXCLUSION: 'exclusion',
  7840. MULTIPLY: 'multiply',
  7841. SCREEN: 'screen',
  7842. REPLACE: 'source-over',
  7843. OVERLAY: 'overlay',
  7844. HARD_LIGHT: 'hard-light',
  7845. SOFT_LIGHT: 'soft-light',
  7846. DODGE: 'color-dodge',
  7847. BURN: 'color-burn',
  7848. // FILTERS
  7849. THRESHOLD: 'threshold',
  7850. GRAY: 'gray',
  7851. OPAQUE: 'opaque',
  7852. INVERT: 'invert',
  7853. POSTERIZE: 'posterize',
  7854. DILATE: 'dilate',
  7855. ERODE: 'erode',
  7856. BLUR: 'blur',
  7857. // TYPOGRAPHY
  7858. NORMAL: 'normal',
  7859. ITALIC: 'italic',
  7860. BOLD: 'bold',
  7861. // TYPOGRAPHY-INTERNAL
  7862. _DEFAULT_TEXT_FILL: '#000000',
  7863. _DEFAULT_LEADMULT: 1.25,
  7864. _CTX_MIDDLE: 'middle',
  7865. // VERTICES
  7866. LINEAR: 'linear',
  7867. QUADRATIC: 'quadratic',
  7868. BEZIER: 'bezier',
  7869. CURVE: 'curve',
  7870. // DEFAULTS
  7871. _DEFAULT_STROKE: '#000000',
  7872. _DEFAULT_FILL: '#FFFFFF'
  7873. };
  7874. },{}],37:[function(_dereq_,module,exports){
  7875. /**
  7876. * @module Structure
  7877. * @submodule Structure
  7878. * @for p5
  7879. * @requires constants
  7880. */
  7881. 'use strict';
  7882. _dereq_('./shim');
  7883. // Core needs the PVariables object
  7884. var constants = _dereq_('./constants');
  7885. /**
  7886. * This is the p5 instance constructor.
  7887. *
  7888. * A p5 instance holds all the properties and methods related to
  7889. * a p5 sketch. It expects an incoming sketch closure and it can also
  7890. * take an optional node parameter for attaching the generated p5 canvas
  7891. * to a node. The sketch closure takes the newly created p5 instance as
  7892. * its sole argument and may optionally set preload(), setup(), and/or
  7893. * draw() properties on it for running a sketch.
  7894. *
  7895. * A p5 sketch can run in "global" or "instance" mode:
  7896. * "global" - all properties and methods are attached to the window
  7897. * "instance" - all properties and methods are bound to this p5 object
  7898. *
  7899. * @param {Function} sketch a closure that can set optional preload(),
  7900. * setup(), and/or draw() properties on the
  7901. * given p5 instance
  7902. * @param {HTMLElement|boolean} [node] element to attach canvas to, if a
  7903. * boolean is passed in use it as sync
  7904. * @param {boolean} [sync] start synchronously (optional)
  7905. * @return {p5} a p5 instance
  7906. */
  7907. var p5 = function(sketch, node, sync) {
  7908. if (arguments.length === 2 && typeof node === 'boolean') {
  7909. sync = node;
  7910. node = undefined;
  7911. }
  7912. //////////////////////////////////////////////
  7913. // PUBLIC p5 PROPERTIES AND METHODS
  7914. //////////////////////////////////////////////
  7915. /**
  7916. * Called directly before setup(), the preload() function is used to handle
  7917. * asynchronous loading of external files. If a preload function is
  7918. * defined, setup() will wait until any load calls within have finished.
  7919. * Nothing besides load calls should be inside preload (loadImage,
  7920. * loadJSON, loadFont, loadStrings, etc).<br><br>
  7921. * By default the text "loading..." will be displayed. To make your own
  7922. * loading page, include an HTML element with id "p5_loading" in your
  7923. * page. More information <a href="http://bit.ly/2kQ6Nio">here</a>.
  7924. *
  7925. * @method preload
  7926. * @example
  7927. * <div><code>
  7928. * var img;
  7929. * var c;
  7930. * function preload() { // preload() runs once
  7931. * img = loadImage('assets/laDefense.jpg');
  7932. * }
  7933. *
  7934. * function setup() { // setup() waits until preload() is done
  7935. * img.loadPixels();
  7936. * // get color of middle pixel
  7937. * c = img.get(img.width/2, img.height/2);
  7938. * }
  7939. *
  7940. * function draw() {
  7941. * background(c);
  7942. * image(img, 25, 25, 50, 50);
  7943. * }
  7944. * </code></div>
  7945. *
  7946. * @alt
  7947. * nothing displayed
  7948. *
  7949. */
  7950. /**
  7951. * The setup() function is called once when the program starts. It's used to
  7952. * define initial environment properties such as screen size and background
  7953. * color and to load media such as images and fonts as the program starts.
  7954. * There can only be one setup() function for each program and it shouldn't
  7955. * be called again after its initial execution.
  7956. * <br><br>
  7957. * Note: Variables declared within setup() are not accessible within other
  7958. * functions, including draw().
  7959. *
  7960. * @method setup
  7961. * @example
  7962. * <div><code>
  7963. * var a = 0;
  7964. *
  7965. * function setup() {
  7966. * background(0);
  7967. * noStroke();
  7968. * fill(102);
  7969. * }
  7970. *
  7971. * function draw() {
  7972. * rect(a++%width, 10, 2, 80);
  7973. * }
  7974. * </code></div>
  7975. *
  7976. * @alt
  7977. * nothing displayed
  7978. *
  7979. */
  7980. /**
  7981. * Called directly after setup(), the draw() function continuously executes
  7982. * the lines of code contained inside its block until the program is stopped
  7983. * or noLoop() is called. Note if noLoop() is called in setup(), draw() will
  7984. * still be executed once before stopping. draw() is called automatically and
  7985. * should never be called explicitly.
  7986. * <br><br>
  7987. * It should always be controlled with noLoop(), redraw() and loop(). After
  7988. * noLoop() stops the code in draw() from executing, redraw() causes the
  7989. * code inside draw() to execute once, and loop() will cause the code
  7990. * inside draw() to resume executing continuously.
  7991. * <br><br>
  7992. * The number of times draw() executes in each second may be controlled with
  7993. * the frameRate() function.
  7994. * <br><br>
  7995. * There can only be one draw() function for each sketch, and draw() must
  7996. * exist if you want the code to run continuously, or to process events such
  7997. * as mousePressed(). Sometimes, you might have an empty call to draw() in
  7998. * your program, as shown in the above example.
  7999. * <br><br>
  8000. * It is important to note that the drawing coordinate system will be reset
  8001. * at the beginning of each draw() call. If any transformations are performed
  8002. * within draw() (ex: scale, rotate, translate, their effects will be
  8003. * undone at the beginning of draw(), so transformations will not accumulate
  8004. * over time. On the other hand, styling applied (ex: fill, stroke, etc) will
  8005. * remain in effect.
  8006. *
  8007. * @method draw
  8008. * @example
  8009. * <div><code>
  8010. * var yPos = 0;
  8011. * function setup() { // setup() runs once
  8012. * frameRate(30);
  8013. * }
  8014. * function draw() { // draw() loops forever, until stopped
  8015. * background(204);
  8016. * yPos = yPos - 1;
  8017. * if (yPos < 0) {
  8018. * yPos = height;
  8019. * }
  8020. * line(0, yPos, width, yPos);
  8021. * }
  8022. * </code></div>
  8023. *
  8024. * @alt
  8025. * nothing displayed
  8026. *
  8027. */
  8028. //////////////////////////////////////////////
  8029. // PRIVATE p5 PROPERTIES AND METHODS
  8030. //////////////////////////////////////////////
  8031. this._setupDone = false;
  8032. // for handling hidpi
  8033. this._pixelDensity = Math.ceil(window.devicePixelRatio) || 1;
  8034. this._userNode = node;
  8035. this._curElement = null;
  8036. this._elements = [];
  8037. this._requestAnimId = 0;
  8038. this._preloadCount = 0;
  8039. this._isGlobal = false;
  8040. this._loop = true;
  8041. this._styles = [];
  8042. this._defaultCanvasSize = {
  8043. width: 100,
  8044. height: 100
  8045. };
  8046. this._events = { // keep track of user-events for unregistering later
  8047. 'mousemove': null,
  8048. 'mousedown': null,
  8049. 'mouseup': null,
  8050. 'dragend': null,
  8051. 'dragover': null,
  8052. 'click': null,
  8053. 'mouseover': null,
  8054. 'mouseout': null,
  8055. 'keydown': null,
  8056. 'keyup': null,
  8057. 'keypress': null,
  8058. 'touchstart': null,
  8059. 'touchmove': null,
  8060. 'touchend': null,
  8061. 'resize': null,
  8062. 'blur': null
  8063. };
  8064. this._events.wheel = null;
  8065. this._loadingScreenId = 'p5_loading';
  8066. if (window.DeviceOrientationEvent) {
  8067. this._events.deviceorientation = null;
  8068. }
  8069. if (window.DeviceMotionEvent && !window._isNodeWebkit) {
  8070. this._events.devicemotion = null;
  8071. }
  8072. this._start = function () {
  8073. // Find node if id given
  8074. if (this._userNode) {
  8075. if (typeof this._userNode === 'string') {
  8076. this._userNode = document.getElementById(this._userNode);
  8077. }
  8078. }
  8079. var userPreload = this.preload || window.preload; // look for "preload"
  8080. if (userPreload) {
  8081. // Setup loading screen
  8082. // Set loading scfeen into dom if not present
  8083. // Otherwise displays and removes user provided loading screen
  8084. var loadingScreen = document.getElementById(this._loadingScreenId);
  8085. if(!loadingScreen){
  8086. loadingScreen = document.createElement('div');
  8087. loadingScreen.innerHTML = 'Loading...';
  8088. loadingScreen.style.position = 'absolute';
  8089. loadingScreen.id = this._loadingScreenId;
  8090. var node = this._userNode || document.body;
  8091. node.appendChild(loadingScreen);
  8092. }
  8093. // var methods = this._preloadMethods;
  8094. for (var method in this._preloadMethods){
  8095. // default to p5 if no object defined
  8096. this._preloadMethods[method] = this._preloadMethods[method] || p5;
  8097. var obj = this._preloadMethods[method];
  8098. //it's p5, check if it's global or instance
  8099. if (obj === p5.prototype || obj === p5){
  8100. obj = this._isGlobal ? window : this;
  8101. }
  8102. this._registeredPreloadMethods[method] = obj[method];
  8103. obj[method] = this._wrapPreload(obj, method);
  8104. }
  8105. userPreload();
  8106. this._runIfPreloadsAreDone();
  8107. } else {
  8108. this._setup();
  8109. this._runFrames();
  8110. this._draw();
  8111. }
  8112. }.bind(this);
  8113. this._runIfPreloadsAreDone = function(){
  8114. var context = this._isGlobal ? window : this;
  8115. if (context._preloadCount === 0) {
  8116. var loadingScreen = document.getElementById(context._loadingScreenId);
  8117. if (loadingScreen) {
  8118. loadingScreen.parentNode.removeChild(loadingScreen);
  8119. }
  8120. context._setup();
  8121. context._runFrames();
  8122. context._draw();
  8123. }
  8124. };
  8125. this._decrementPreload = function(){
  8126. var context = this._isGlobal ? window : this;
  8127. context._setProperty('_preloadCount', context._preloadCount - 1);
  8128. context._runIfPreloadsAreDone();
  8129. };
  8130. this._wrapPreload = function(obj, fnName){
  8131. return function(){
  8132. //increment counter
  8133. this._incrementPreload();
  8134. //call original function
  8135. var args = new Array(arguments.length);
  8136. for (var i = 0; i < args.length; ++i) {
  8137. args[i] = arguments[i];
  8138. }
  8139. args.push(this._decrementPreload.bind(this));
  8140. return this._registeredPreloadMethods[fnName].apply(obj, args);
  8141. }.bind(this);
  8142. };
  8143. this._incrementPreload = function(){
  8144. var context = this._isGlobal ? window : this;
  8145. context._setProperty('_preloadCount', context._preloadCount + 1);
  8146. };
  8147. this._setup = function() {
  8148. // Always create a default canvas.
  8149. // Later on if the user calls createCanvas, this default one
  8150. // will be replaced
  8151. this.createCanvas(
  8152. this._defaultCanvasSize.width,
  8153. this._defaultCanvasSize.height,
  8154. 'p2d',
  8155. true
  8156. );
  8157. // return preload functions to their normal vals if switched by preload
  8158. var context = this._isGlobal ? window : this;
  8159. if (typeof context.preload === 'function') {
  8160. for (var f in this._preloadMethods) {
  8161. context[f] = this._preloadMethods[f][f];
  8162. if (context[f] && this) {
  8163. context[f] = context[f].bind(this);
  8164. }
  8165. }
  8166. }
  8167. // Short-circuit on this, in case someone used the library in "global"
  8168. // mode earlier
  8169. if (typeof context.setup === 'function') {
  8170. context.setup();
  8171. }
  8172. // unhide any hidden canvases that were created
  8173. var canvases = document.getElementsByTagName('canvas');
  8174. for (var i = 0; i < canvases.length; i++) {
  8175. var k = canvases[i];
  8176. if (k.dataset.hidden === 'true') {
  8177. k.style.visibility = '';
  8178. delete(k.dataset.hidden);
  8179. }
  8180. }
  8181. this._setupDone = true;
  8182. }.bind(this);
  8183. this._draw = function () {
  8184. var now = window.performance.now();
  8185. var time_since_last = now - this._lastFrameTime;
  8186. var target_time_between_frames = 1000 / this._targetFrameRate;
  8187. // only draw if we really need to; don't overextend the browser.
  8188. // draw if we're within 5ms of when our next frame should paint
  8189. // (this will prevent us from giving up opportunities to draw
  8190. // again when it's really about time for us to do so). fixes an
  8191. // issue where the frameRate is too low if our refresh loop isn't
  8192. // in sync with the browser. note that we have to draw once even
  8193. // if looping is off, so we bypass the time delay if that
  8194. // is the case.
  8195. var epsilon = 5;
  8196. if (!this._loop ||
  8197. time_since_last >= target_time_between_frames - epsilon) {
  8198. //mandatory update values(matrixs and stack)
  8199. this._setProperty('frameCount', this.frameCount + 1);
  8200. this.redraw();
  8201. this._updateMouseCoords();
  8202. this._frameRate = 1000.0/(now - this._lastFrameTime);
  8203. this._lastFrameTime = now;
  8204. }
  8205. // get notified the next time the browser gives us
  8206. // an opportunity to draw.
  8207. if (this._loop) {
  8208. this._requestAnimId = window.requestAnimationFrame(this._draw);
  8209. }
  8210. }.bind(this);
  8211. this._runFrames = function() {
  8212. if (this._updateInterval) {
  8213. clearInterval(this._updateInterval);
  8214. }
  8215. }.bind(this);
  8216. this._setProperty = function(prop, value) {
  8217. this[prop] = value;
  8218. if (this._isGlobal) {
  8219. window[prop] = value;
  8220. }
  8221. }.bind(this);
  8222. /**
  8223. * Removes the entire p5 sketch. This will remove the canvas and any
  8224. * elements created by p5.js. It will also stop the draw loop and unbind
  8225. * any properties or methods from the window global scope. It will
  8226. * leave a variable p5 in case you wanted to create a new p5 sketch.
  8227. * If you like, you can set p5 = null to erase it.
  8228. * @method remove
  8229. * @example
  8230. * <div class='norender'><code>
  8231. * function draw() {
  8232. * ellipse(50, 50, 10, 10);
  8233. * }
  8234. *
  8235. * function mousePressed() {
  8236. * remove(); // remove whole sketch on mouse press
  8237. * }
  8238. * </code></div>
  8239. *
  8240. * @alt
  8241. * nothing displayed
  8242. *
  8243. */
  8244. this.remove = function() {
  8245. if (this._curElement) {
  8246. // stop draw
  8247. this._loop = false;
  8248. if (this._requestAnimId) {
  8249. window.cancelAnimationFrame(this._requestAnimId);
  8250. }
  8251. // unregister events sketch-wide
  8252. for (var ev in this._events) {
  8253. window.removeEventListener(ev, this._events[ev]);
  8254. }
  8255. // remove DOM elements created by p5, and listeners
  8256. for (var i=0; i<this._elements.length; i++) {
  8257. var e = this._elements[i];
  8258. if (e.elt.parentNode) {
  8259. e.elt.parentNode.removeChild(e.elt);
  8260. }
  8261. for (var elt_ev in e._events) {
  8262. e.elt.removeEventListener(elt_ev, e._events[elt_ev]);
  8263. }
  8264. }
  8265. // call any registered remove functions
  8266. var self = this;
  8267. this._registeredMethods.remove.forEach(function (f) {
  8268. if (typeof(f) !== 'undefined') {
  8269. f.call(self);
  8270. }
  8271. });
  8272. // remove window bound properties and methods
  8273. if (this._isGlobal) {
  8274. for (var p in p5.prototype) {
  8275. try {
  8276. delete window[p];
  8277. } catch (x) {
  8278. window[p] = undefined;
  8279. }
  8280. }
  8281. for (var p2 in this) {
  8282. if (this.hasOwnProperty(p2)) {
  8283. try {
  8284. delete window[p2];
  8285. } catch (x) {
  8286. window[p2] = undefined;
  8287. }
  8288. }
  8289. }
  8290. }
  8291. }
  8292. // window.p5 = undefined;
  8293. }.bind(this);
  8294. // call any registered init functions
  8295. this._registeredMethods.init.forEach(function (f) {
  8296. if (typeof(f) !== 'undefined') {
  8297. f.call(this);
  8298. }
  8299. }, this);
  8300. var friendlyBindGlobal = this._createFriendlyGlobalFunctionBinder();
  8301. // If the user has created a global setup or draw function,
  8302. // assume "global" mode and make everything global (i.e. on the window)
  8303. if (!sketch) {
  8304. this._isGlobal = true;
  8305. p5.instance = this;
  8306. // Loop through methods on the prototype and attach them to the window
  8307. for (var p in p5.prototype) {
  8308. if(typeof p5.prototype[p] === 'function') {
  8309. var ev = p.substring(2);
  8310. if (!this._events.hasOwnProperty(ev)) {
  8311. if (Math.hasOwnProperty(p) && (Math[p] === p5.prototype[p])) {
  8312. // Multiple p5 methods are just native Math functions. These can be
  8313. // called without any binding.
  8314. friendlyBindGlobal(p, p5.prototype[p]);
  8315. } else {
  8316. friendlyBindGlobal(p, p5.prototype[p].bind(this));
  8317. }
  8318. }
  8319. } else {
  8320. friendlyBindGlobal(p, p5.prototype[p]);
  8321. }
  8322. }
  8323. // Attach its properties to the window
  8324. for (var p2 in this) {
  8325. if (this.hasOwnProperty(p2)) {
  8326. friendlyBindGlobal(p2, this[p2]);
  8327. }
  8328. }
  8329. } else {
  8330. // Else, the user has passed in a sketch closure that may set
  8331. // user-provided 'setup', 'draw', etc. properties on this instance of p5
  8332. sketch(this);
  8333. }
  8334. // Bind events to window (not using container div bc key events don't work)
  8335. for (var e in this._events) {
  8336. var f = this['_on'+e];
  8337. if (f) {
  8338. var m = f.bind(this);
  8339. window.addEventListener(e, m);
  8340. this._events[e] = m;
  8341. }
  8342. }
  8343. var focusHandler = function() {
  8344. this._setProperty('focused', true);
  8345. }.bind(this);
  8346. var blurHandler = function() {
  8347. this._setProperty('focused', false);
  8348. }.bind(this);
  8349. window.addEventListener('focus', focusHandler);
  8350. window.addEventListener('blur', blurHandler);
  8351. this.registerMethod('remove', function() {
  8352. window.removeEventListener('focus', focusHandler);
  8353. window.removeEventListener('blur', blurHandler);
  8354. });
  8355. if (sync) {
  8356. this._start();
  8357. } else {
  8358. if (document.readyState === 'complete') {
  8359. this._start();
  8360. } else {
  8361. window.addEventListener('load', this._start.bind(this), false);
  8362. }
  8363. }
  8364. };
  8365. // This is a pointer to our global mode p5 instance, if we're in
  8366. // global mode.
  8367. p5.instance = null;
  8368. // Allows for the friendly error system to be turned off when creating a sketch,
  8369. // which can give a significant boost to performance when needed.
  8370. p5.disableFriendlyErrors = false;
  8371. // attach constants to p5 prototype
  8372. for (var k in constants) {
  8373. p5.prototype[k] = constants[k];
  8374. }
  8375. // functions that cause preload to wait
  8376. // more can be added by using registerPreloadMethod(func)
  8377. p5.prototype._preloadMethods = {
  8378. loadJSON: p5.prototype,
  8379. loadImage: p5.prototype,
  8380. loadStrings: p5.prototype,
  8381. loadXML: p5.prototype,
  8382. loadShape: p5.prototype,
  8383. loadTable: p5.prototype,
  8384. loadFont: p5.prototype,
  8385. loadModel: p5.prototype
  8386. };
  8387. p5.prototype._registeredMethods = { init: [], pre: [], post: [], remove: [] };
  8388. p5.prototype._registeredPreloadMethods = {};
  8389. p5.prototype.registerPreloadMethod = function(fnString, obj) {
  8390. // obj = obj || p5.prototype;
  8391. if (!p5.prototype._preloadMethods.hasOwnProperty(fnString)) {
  8392. p5.prototype._preloadMethods[fnString] = obj;
  8393. }
  8394. };
  8395. p5.prototype.registerMethod = function(name, m) {
  8396. if (!p5.prototype._registeredMethods.hasOwnProperty(name)) {
  8397. p5.prototype._registeredMethods[name] = [];
  8398. }
  8399. p5.prototype._registeredMethods[name].push(m);
  8400. };
  8401. p5.prototype._createFriendlyGlobalFunctionBinder = function(options) {
  8402. options = options || {};
  8403. var globalObject = options.globalObject || window;
  8404. var log = options.log || console.log.bind(console);
  8405. var propsToForciblyOverwrite = {
  8406. // p5.print actually always overwrites an existing global function,
  8407. // albeit one that is very unlikely to be used:
  8408. //
  8409. // https://developer.mozilla.org/en-US/docs/Web/API/Window/print
  8410. 'print': true
  8411. };
  8412. return function(prop, value) {
  8413. if (!p5.disableFriendlyErrors &&
  8414. typeof(IS_MINIFIED) === 'undefined' &&
  8415. typeof(value) === 'function' &&
  8416. !(prop in p5.prototype._preloadMethods)) {
  8417. try {
  8418. // Because p5 has so many common function names, it's likely
  8419. // that users may accidentally overwrite global p5 functions with
  8420. // their own variables. Let's allow this but log a warning to
  8421. // help users who may be doing this unintentionally.
  8422. //
  8423. // For more information, see:
  8424. //
  8425. // https://github.com/processing/p5.js/issues/1317
  8426. if (prop in globalObject && !(prop in propsToForciblyOverwrite)) {
  8427. throw new Error('global "' + prop + '" already exists');
  8428. }
  8429. // It's possible that this might throw an error because there
  8430. // are a lot of edge-cases in which `Object.defineProperty` might
  8431. // not succeed; since this functionality is only intended to
  8432. // help beginners anyways, we'll just catch such an exception
  8433. // if it occurs, and fall back to legacy behavior.
  8434. Object.defineProperty(globalObject, prop, {
  8435. configurable: true,
  8436. enumerable: true,
  8437. get: function() {
  8438. return value;
  8439. },
  8440. set: function(newValue) {
  8441. Object.defineProperty(globalObject, prop, {
  8442. configurable: true,
  8443. enumerable: true,
  8444. value: newValue,
  8445. writable: true
  8446. });
  8447. log(
  8448. 'You just changed the value of "' + prop + '", which was ' +
  8449. 'a p5 function. This could cause problems later if you\'re ' +
  8450. 'not careful.'
  8451. );
  8452. }
  8453. });
  8454. } catch (e) {
  8455. log(
  8456. 'p5 had problems creating the global function "' + prop + '", ' +
  8457. 'possibly because your code is already using that name as ' +
  8458. 'a variable. You may want to rename your variable to something ' +
  8459. 'else.'
  8460. );
  8461. globalObject[prop] = value;
  8462. }
  8463. } else {
  8464. globalObject[prop] = value;
  8465. }
  8466. };
  8467. };
  8468. module.exports = p5;
  8469. },{"./constants":36,"./shim":46}],38:[function(_dereq_,module,exports){
  8470. /**
  8471. * @module Shape
  8472. * @submodule Curves
  8473. * @for p5
  8474. * @requires core
  8475. */
  8476. 'use strict';
  8477. var p5 = _dereq_('./core');
  8478. _dereq_('./error_helpers');
  8479. var bezierDetail = 20;
  8480. var curveDetail = 20;
  8481. /**
  8482. * Draws a cubic Bezier curve on the screen. These curves are defined by a
  8483. * series of anchor and control points. The first two parameters specify
  8484. * the first anchor point and the last two parameters specify the other
  8485. * anchor point, which become the first and last points on the curve. The
  8486. * middle parameters specify the two control points which define the shape
  8487. * of the curve. Approximately speaking, control points "pull" the curve
  8488. * towards them.<br /><br />Bezier curves were developed by French
  8489. * automotive engineer Pierre Bezier, and are commonly used in computer
  8490. * graphics to define gently sloping curves. See also curve().
  8491. *
  8492. * @method bezier
  8493. * @param {Number} x1 x-coordinate for the first anchor point
  8494. * @param {Number} y1 y-coordinate for the first anchor point
  8495. * @param {Number} x2 x-coordinate for the first control point
  8496. * @param {Number} y2 y-coordinate for the first control point
  8497. * @param {Number} x3 x-coordinate for the second control point
  8498. * @param {Number} y3 y-coordinate for the second control point
  8499. * @param {Number} x4 x-coordinate for the second anchor point
  8500. * @param {Number} y4 y-coordinate for the second anchor point
  8501. * @return {Object} the p5 object
  8502. * @example
  8503. * <div>
  8504. * <code>
  8505. * noFill();
  8506. * stroke(255, 102, 0);
  8507. * line(85, 20, 10, 10);
  8508. * line(90, 90, 15, 80);
  8509. * stroke(0, 0, 0);
  8510. * bezier(85, 20, 10, 10, 90, 90, 15, 80);
  8511. * </code>
  8512. * </div>
  8513. * @alt
  8514. * stretched black s-shape in center with orange lines extending from end points.
  8515. * stretched black s-shape with 10 5x5 white ellipses along the shape.
  8516. * stretched black s-shape with 7 5x5 ellipses and orange lines along the shape.
  8517. * stretched black s-shape with 17 small orange lines extending from under shape.
  8518. * horseshoe shape with orange ends facing left and black curved center.
  8519. * horseshoe shape with orange ends facing left and black curved center.
  8520. * Line shaped like right-facing arrow,points move with mouse-x and warp shape.
  8521. * horizontal line that hooks downward on the right and 13 5x5 ellipses along it.
  8522. * right curving line mid-right of canvas with 7 short lines radiating from it.
  8523. */
  8524. /**
  8525. * @method bezier
  8526. * @param {Number} z1 z-coordinate for the first anchor point
  8527. * @param {Number} z2 z-coordinate for the first control point
  8528. * @param {Number} z3 z-coordinate for the first anchor point
  8529. * @param {Number} z4 z-coordinate for the first control point
  8530. * @return {p5.Renderer3D} [description]
  8531. * @example
  8532. * <div>
  8533. * <code>
  8534. *background(0, 0, 0);
  8535. *noFill();
  8536. *stroke(255);
  8537. *bezier(250,250,0, 100,100,0, 100,0,0, 0,100,0);
  8538. * </code>
  8539. * </div>
  8540. */
  8541. p5.prototype.bezier = function() {
  8542. var args = new Array(arguments.length);
  8543. for (var i = 0; i < args.length; ++i) {
  8544. args[i] = arguments[i];
  8545. }
  8546. if (!this._renderer._doStroke && !this._renderer._doFill) {
  8547. return this;
  8548. }
  8549. if (this._renderer.isP3D){
  8550. args.push(bezierDetail);//adding value of bezier detail to the args array
  8551. this._renderer.bezier(args);
  8552. } else{
  8553. this._renderer.bezier(args[0],args[1],
  8554. args[2],args[3],
  8555. args[4],args[5],
  8556. args[6],args[7]);
  8557. }
  8558. return this;
  8559. };
  8560. /**
  8561. * Sets the resolution at which Beziers display.
  8562. *
  8563. * The default value is 20.
  8564. *
  8565. * @param {Number} detail resolution of the curves
  8566. * @return {Object} the p5 object
  8567. * @example
  8568. * <div>
  8569. * <code>
  8570. * background(204);
  8571. * bezierDetail(50);
  8572. * bezier(85, 20, 10, 10, 90, 90, 15, 80);
  8573. * </code>
  8574. * </div>
  8575. *
  8576. * @alt
  8577. * stretched black s-shape with 7 5x5 ellipses and orange lines along the shape.
  8578. *
  8579. */
  8580. p5.prototype.bezierDetail = function(d) {
  8581. bezierDetail = d;
  8582. return this;
  8583. };
  8584. /**
  8585. * Evaluates the Bezier at position t for points a, b, c, d.
  8586. * The parameters a and d are the first and last points
  8587. * on the curve, and b and c are the control points.
  8588. * The final parameter t varies between 0 and 1.
  8589. * This can be done once with the x coordinates and a second time
  8590. * with the y coordinates to get the location of a bezier curve at t.
  8591. *
  8592. * @method bezierPoint
  8593. * @param {Number} a coordinate of first point on the curve
  8594. * @param {Number} b coordinate of first control point
  8595. * @param {Number} c coordinate of second control point
  8596. * @param {Number} d coordinate of second point on the curve
  8597. * @param {Number} t value between 0 and 1
  8598. * @return {Number} the value of the Bezier at position t
  8599. * @example
  8600. * <div>
  8601. * <code>
  8602. * noFill();
  8603. * x1 = 85, x2 = 10, x3 = 90, x4 = 15;
  8604. * y1 = 20, y2 = 10, y3 = 90, y4 = 80;
  8605. * bezier(x1, y1, x2, y2, x3, y3, x4, y4);
  8606. * fill(255);
  8607. * steps = 10;
  8608. * for (i = 0; i <= steps; i++) {
  8609. * t = i / steps;
  8610. * x = bezierPoint(x1, x2, x3, x4, t);
  8611. * y = bezierPoint(y1, y2, y3, y4, t);
  8612. * ellipse(x, y, 5, 5);
  8613. * }
  8614. * </code>
  8615. * </div>
  8616. *
  8617. * @alt
  8618. * stretched black s-shape with 17 small orange lines extending from under shape.
  8619. *
  8620. */
  8621. p5.prototype.bezierPoint = function(a, b, c, d, t) {
  8622. var adjustedT = 1-t;
  8623. return Math.pow(adjustedT,3)*a +
  8624. 3*(Math.pow(adjustedT,2))*t*b +
  8625. 3*adjustedT*Math.pow(t,2)*c +
  8626. Math.pow(t,3)*d;
  8627. };
  8628. /**
  8629. * Evaluates the tangent to the Bezier at position t for points a, b, c, d.
  8630. * The parameters a and d are the first and last points
  8631. * on the curve, and b and c are the control points.
  8632. * The final parameter t varies between 0 and 1.
  8633. *
  8634. * @method bezierTangent
  8635. * @param {Number} a coordinate of first point on the curve
  8636. * @param {Number} b coordinate of first control point
  8637. * @param {Number} c coordinate of second control point
  8638. * @param {Number} d coordinate of second point on the curve
  8639. * @param {Number} t value between 0 and 1
  8640. * @return {Number} the tangent at position t
  8641. * @example
  8642. * <div>
  8643. * <code>
  8644. * noFill();
  8645. * bezier(85, 20, 10, 10, 90, 90, 15, 80);
  8646. * steps = 6;
  8647. * fill(255);
  8648. * for (i = 0; i <= steps; i++) {
  8649. * t = i / steps;
  8650. * // Get the location of the point
  8651. * x = bezierPoint(85, 10, 90, 15, t);
  8652. * y = bezierPoint(20, 10, 90, 80, t);
  8653. * // Get the tangent points
  8654. * tx = bezierTangent(85, 10, 90, 15, t);
  8655. * ty = bezierTangent(20, 10, 90, 80, t);
  8656. * // Calculate an angle from the tangent points
  8657. * a = atan2(ty, tx);
  8658. * a += PI;
  8659. * stroke(255, 102, 0);
  8660. * line(x, y, cos(a)*30 + x, sin(a)*30 + y);
  8661. * // The following line of code makes a line
  8662. * // inverse of the above line
  8663. * //line(x, y, cos(a)*-30 + x, sin(a)*-30 + y);
  8664. * stroke(0);
  8665. * ellipse(x, y, 5, 5);
  8666. * }
  8667. * </code>
  8668. * </div>
  8669. *
  8670. * <div>
  8671. * <code>
  8672. * noFill();
  8673. * bezier(85, 20, 10, 10, 90, 90, 15, 80);
  8674. * stroke(255, 102, 0);
  8675. * steps = 16;
  8676. * for (i = 0; i <= steps; i++) {
  8677. * t = i / steps;
  8678. * x = bezierPoint(85, 10, 90, 15, t);
  8679. * y = bezierPoint(20, 10, 90, 80, t);
  8680. * tx = bezierTangent(85, 10, 90, 15, t);
  8681. * ty = bezierTangent(20, 10, 90, 80, t);
  8682. * a = atan2(ty, tx);
  8683. * a -= HALF_PI;
  8684. * line(x, y, cos(a)*8 + x, sin(a)*8 + y);
  8685. * }
  8686. * </code>
  8687. * </div>
  8688. *
  8689. * @alt
  8690. * s-shaped line with 17 short orange lines extending from underside of shape
  8691. *
  8692. */
  8693. p5.prototype.bezierTangent = function(a, b, c, d, t) {
  8694. var adjustedT = 1-t;
  8695. return 3*d*Math.pow(t,2) -
  8696. 3*c*Math.pow(t,2) +
  8697. 6*c*adjustedT*t -
  8698. 6*b*adjustedT*t +
  8699. 3*b*Math.pow(adjustedT,2) -
  8700. 3*a*Math.pow(adjustedT,2);
  8701. };
  8702. /**
  8703. * Draws a curved line on the screen between two points, given as the
  8704. * middle four parameters. The first two parameters are a control point, as
  8705. * if the curve came from this point even though it's not drawn. The last
  8706. * two parameters similarly describe the other control point. <br /><br />
  8707. * Longer curves can be created by putting a series of curve() functions
  8708. * together or using curveVertex(). An additional function called
  8709. * curveTightness() provides control for the visual quality of the curve.
  8710. * The curve() function is an implementation of Catmull-Rom splines.
  8711. *
  8712. * @method curve
  8713. * @param {Number} x1 x-coordinate for the beginning control point
  8714. * @param {Number} y1 y-coordinate for the beginning control point
  8715. * @param {Number} x2 x-coordinate for the first point
  8716. * @param {Number} y2 y-coordinate for the first point
  8717. * @param {Number} x3 x-coordinate for the second point
  8718. * @param {Number} y3 y-coordinate for the second point
  8719. * @param {Number} x4 x-coordinate for the ending control point
  8720. * @param {Number} y4 y-coordinate for the ending control point
  8721. * @return {Object} the p5 object
  8722. * @example
  8723. * <div>
  8724. * <code>
  8725. * noFill();
  8726. * stroke(255, 102, 0);
  8727. * curve(5, 26, 5, 26, 73, 24, 73, 61);
  8728. * stroke(0);
  8729. * curve(5, 26, 73, 24, 73, 61, 15, 65);
  8730. * stroke(255, 102, 0);
  8731. * curve(73, 24, 73, 61, 15, 65, 15, 65);
  8732. * </code>
  8733. * </div>
  8734. * <div>
  8735. * <code>
  8736. * // Define the curve points as JavaScript objects
  8737. * p1 = {x: 5, y: 26}, p2 = {x: 73, y: 24}
  8738. * p3 = {x: 73, y: 61}, p4 = {x: 15, y: 65}
  8739. * noFill();
  8740. * stroke(255, 102, 0);
  8741. * curve(p1.x, p1.y, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y)
  8742. * stroke(0);
  8743. * curve(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y)
  8744. * stroke(255, 102, 0);
  8745. * curve(p2.x, p2.y, p3.x, p3.y, p4.x, p4.y, p4.x, p4.y)
  8746. * </code>
  8747. * </div>
  8748. *
  8749. * @alt
  8750. * horseshoe shape with orange ends facing left and black curved center.
  8751. * horseshoe shape with orange ends facing left and black curved center.
  8752. *
  8753. */
  8754. /**
  8755. * @method curve
  8756. * @param {Number} z1 z-coordinate for the beginning control point
  8757. * @param {Number} z2 z-coordinate for the first point
  8758. * @param {Number} z3 z-coordinate for the second point
  8759. * @param {Number} z4 z-coordinate for the ending control point
  8760. * @return {Object} the p5 object
  8761. * @example
  8762. * <div>
  8763. * <code>
  8764. * noFill();
  8765. * stroke(255, 102, 0);
  8766. * curve(5,26,0, 5,26,0, 73,24,0, 73,61,0);
  8767. * stroke(0);
  8768. * curve(5,26,0, 73,24,0, 73,61,0, 15,65,0);
  8769. * stroke(255, 102, 0);
  8770. * curve(73,24,0, 73,61,0, 15,65,0, 15,65,0);
  8771. * </code>
  8772. * </div>
  8773. *
  8774. * @alt
  8775. * curving black and orange lines.
  8776. */
  8777. p5.prototype.curve = function() {
  8778. var args = new Array(arguments.length);
  8779. for (var i = 0; i < args.length; ++i) {
  8780. args[i] = arguments[i];
  8781. }
  8782. if (!this._renderer._doStroke) {
  8783. return this;
  8784. }
  8785. if (this._renderer.isP3D){
  8786. args.push(curveDetail);
  8787. this._renderer.curve(args);
  8788. } else{
  8789. this._renderer.curve(args[0],args[1],
  8790. args[2],args[3],
  8791. args[4],args[5],
  8792. args[6],args[7]);
  8793. }
  8794. return this;
  8795. };
  8796. /**
  8797. * Sets the resolution at which curves display.
  8798. *
  8799. * The default value is 20.
  8800. *
  8801. * @param {Number} resolution of the curves
  8802. * @return {Object} the p5 object
  8803. * @example
  8804. * <div>
  8805. * <code>
  8806. * background(204);
  8807. * curveDetail(20);
  8808. * curve(5, 26, 5, 26, 73, 24, 73, 61);
  8809. * </code>
  8810. * </div>
  8811. *
  8812. * @alt
  8813. * white arch shape in top-mid canvas.
  8814. *
  8815. */
  8816. p5.prototype.curveDetail = function(d) {
  8817. curveDetail = d;
  8818. return this;
  8819. };
  8820. /**
  8821. * Modifies the quality of forms created with curve() and curveVertex().
  8822. * The parameter tightness determines how the curve fits to the vertex
  8823. * points. The value 0.0 is the default value for tightness (this value
  8824. * defines the curves to be Catmull-Rom splines) and the value 1.0 connects
  8825. * all the points with straight lines. Values within the range -5.0 and 5.0
  8826. * will deform the curves but will leave them recognizable and as values
  8827. * increase in magnitude, they will continue to deform.
  8828. *
  8829. * @method curveTightness
  8830. * @param {Number} amount of deformation from the original vertices
  8831. * @return {Object} the p5 object
  8832. * @example
  8833. * <div>
  8834. * <code>
  8835. * // Move the mouse left and right to see the curve change
  8836. *
  8837. * function setup() {
  8838. * createCanvas(100, 100);
  8839. * noFill();
  8840. * }
  8841. *
  8842. * function draw() {
  8843. * background(204);
  8844. * var t = map(mouseX, 0, width, -5, 5);
  8845. * curveTightness(t);
  8846. * beginShape();
  8847. * curveVertex(10, 26);
  8848. * curveVertex(10, 26);
  8849. * curveVertex(83, 24);
  8850. * curveVertex(83, 61);
  8851. * curveVertex(25, 65);
  8852. * curveVertex(25, 65);
  8853. * endShape();
  8854. * }
  8855. * </code>
  8856. * </div>
  8857. *
  8858. * @alt
  8859. * Line shaped like right-facing arrow,points move with mouse-x and warp shape.
  8860. */
  8861. p5.prototype.curveTightness = function (t) {
  8862. this._renderer._curveTightness = t;
  8863. };
  8864. /**
  8865. * Evaluates the curve at position t for points a, b, c, d.
  8866. * The parameter t varies between 0 and 1, a and d are points
  8867. * on the curve, and b and c are the control points.
  8868. * This can be done once with the x coordinates and a second time
  8869. * with the y coordinates to get the location of a curve at t.
  8870. *
  8871. * @method curvePoint
  8872. * @param {Number} a coordinate of first point on the curve
  8873. * @param {Number} b coordinate of first control point
  8874. * @param {Number} c coordinate of second control point
  8875. * @param {Number} d coordinate of second point on the curve
  8876. * @param {Number} t value between 0 and 1
  8877. * @return {Number} bezier value at position t
  8878. * @example
  8879. * <div>
  8880. * <code>
  8881. * noFill();
  8882. * curve(5, 26, 5, 26, 73, 24, 73, 61);
  8883. * curve(5, 26, 73, 24, 73, 61, 15, 65);
  8884. * fill(255);
  8885. * ellipseMode(CENTER);
  8886. * steps = 6;
  8887. * for (i = 0; i <= steps; i++) {
  8888. * t = i / steps;
  8889. * x = curvePoint(5, 5, 73, 73, t);
  8890. * y = curvePoint(26, 26, 24, 61, t);
  8891. * ellipse(x, y, 5, 5);
  8892. * x = curvePoint(5, 73, 73, 15, t);
  8893. * y = curvePoint(26, 24, 61, 65, t);
  8894. * ellipse(x, y, 5, 5);
  8895. * }
  8896. * </code>
  8897. * </div>
  8898. *
  8899. *line hooking down to right-bottom with 13 5x5 white ellipse points
  8900. */
  8901. p5.prototype.curvePoint = function(a, b, c, d, t) {
  8902. var t3 = t*t*t,
  8903. t2 = t*t,
  8904. f1 = -0.5 * t3 + t2 - 0.5 * t,
  8905. f2 = 1.5 * t3 - 2.5 * t2 + 1.0,
  8906. f3 = -1.5 * t3 + 2.0 * t2 + 0.5 * t,
  8907. f4 = 0.5 * t3 - 0.5 * t2;
  8908. return a*f1 + b*f2 + c*f3 + d*f4;
  8909. };
  8910. /**
  8911. * Evaluates the tangent to the curve at position t for points a, b, c, d.
  8912. * The parameter t varies between 0 and 1, a and d are points on the curve,
  8913. * and b and c are the control points.
  8914. *
  8915. * @method curveTangent
  8916. * @param {Number} a coordinate of first point on the curve
  8917. * @param {Number} b coordinate of first control point
  8918. * @param {Number} c coordinate of second control point
  8919. * @param {Number} d coordinate of second point on the curve
  8920. * @param {Number} t value between 0 and 1
  8921. * @return {Number} the tangent at position t
  8922. * @example
  8923. * <div>
  8924. * <code>
  8925. * noFill();
  8926. * curve(5, 26, 73, 24, 73, 61, 15, 65);
  8927. * steps = 6;
  8928. * for (i = 0; i <= steps; i++) {
  8929. * t = i / steps;
  8930. * x = curvePoint(5, 73, 73, 15, t);
  8931. * y = curvePoint(26, 24, 61, 65, t);
  8932. * //ellipse(x, y, 5, 5);
  8933. * tx = curveTangent(5, 73, 73, 15, t);
  8934. * ty = curveTangent(26, 24, 61, 65, t);
  8935. * a = atan2(ty, tx);
  8936. * a -= PI/2.0;
  8937. * line(x, y, cos(a)*8 + x, sin(a)*8 + y);
  8938. * }
  8939. * </code>
  8940. * </div>
  8941. *
  8942. * @alt
  8943. *right curving line mid-right of canvas with 7 short lines radiating from it.
  8944. */
  8945. p5.prototype.curveTangent = function(a, b,c, d, t) {
  8946. var t2 = t*t,
  8947. f1 = (-3*t2)/2 + 2*t - 0.5,
  8948. f2 = (9*t2)/2 - 5*t,
  8949. f3 = (-9*t2)/2 + 4*t + 0.5,
  8950. f4 = (3*t2)/2 - t;
  8951. return a*f1 + b*f2 + c*f3 + d*f4;
  8952. };
  8953. module.exports = p5;
  8954. },{"./core":37,"./error_helpers":40}],39:[function(_dereq_,module,exports){
  8955. /**
  8956. * @module Environment
  8957. * @submodule Environment
  8958. * @for p5
  8959. * @requires core
  8960. * @requires constants
  8961. */
  8962. 'use strict';
  8963. var p5 = _dereq_('./core');
  8964. var C = _dereq_('./constants');
  8965. var standardCursors = [C.ARROW, C.CROSS, C.HAND, C.MOVE, C.TEXT, C.WAIT];
  8966. p5.prototype._frameRate = 0;
  8967. p5.prototype._lastFrameTime = window.performance.now();
  8968. p5.prototype._targetFrameRate = 60;
  8969. var _windowPrint = window.print;
  8970. if (window.console && console.log) {
  8971. /**
  8972. * The print() function writes to the console area of your browser.
  8973. * This function is often helpful for looking at the data a program is
  8974. * producing. This function creates a new line of text for each call to
  8975. * the function. Individual elements can be
  8976. * separated with quotes ("") and joined with the addition operator (+).
  8977. * <br><br>
  8978. * While print() is similar to console.log(), it does not directly map to
  8979. * it in order to simulate easier to understand behavior than
  8980. * console.log(). Due to this, it is slower. For fastest results, use
  8981. * console.log().
  8982. *
  8983. * @method print
  8984. * @param {Any} contents any combination of Number, String, Object, Boolean,
  8985. * Array to print
  8986. * @example
  8987. * <div><code class='norender'>
  8988. * var x = 10;
  8989. * print("The value of x is " + x);
  8990. * // prints "The value of x is 10"
  8991. * </code></div>
  8992. * @alt
  8993. * default grey canvas
  8994. */
  8995. // Converts passed args into a string and then parses that string to
  8996. // simulate synchronous behavior. This is a hack and is gross.
  8997. // Since this will not work on all objects, particularly circular
  8998. // structures, simply console.log() on error.
  8999. p5.prototype.print = function(args) {
  9000. try {
  9001. if (arguments.length === 0) {
  9002. _windowPrint();
  9003. }
  9004. else if (arguments.length > 1) {
  9005. console.log.apply(console, arguments);
  9006. } else {
  9007. var newArgs = JSON.parse(JSON.stringify(args));
  9008. console.log(newArgs);
  9009. }
  9010. } catch(err) {
  9011. console.log(args);
  9012. }
  9013. };
  9014. } else {
  9015. p5.prototype.print = function() {};
  9016. }
  9017. /**
  9018. * The system variable frameCount contains the number of frames that have
  9019. * been displayed since the program started. Inside setup() the value is 0,
  9020. * after the first iteration of draw it is 1, etc.
  9021. *
  9022. * @property frameCount
  9023. * @example
  9024. * <div><code>
  9025. * function setup() {
  9026. * frameRate(30);
  9027. * textSize(20);
  9028. * textSize(30);
  9029. * textAlign(CENTER);
  9030. * }
  9031. *
  9032. * function draw() {
  9033. * background(200);
  9034. * text(frameCount, width/2, height/2);
  9035. * }
  9036. * </code></div>
  9037. *
  9038. * @alt
  9039. * numbers rapidly counting upward with frame count set to 30.
  9040. *
  9041. */
  9042. p5.prototype.frameCount = 0;
  9043. /**
  9044. * Confirms if the window a p5.js program is in is "focused," meaning that
  9045. * the sketch will accept mouse or keyboard input. This variable is
  9046. * "true" if the window is focused and "false" if not.
  9047. *
  9048. * @property focused
  9049. * @example
  9050. * <div><code>
  9051. * // To demonstrate, put two windows side by side.
  9052. * // Click on the window that the p5 sketch isn't in!
  9053. * function draw() {
  9054. * background(200);
  9055. * noStroke();
  9056. * fill(0, 200, 0);
  9057. * ellipse(25, 25, 50, 50);
  9058. *
  9059. * if (!focused) { // or "if (focused === false)"
  9060. * stroke(200,0,0);
  9061. * line(0, 0, 100, 100);
  9062. * line(100, 0, 0, 100);
  9063. * }
  9064. * }
  9065. * </code></div>
  9066. *
  9067. * @alt
  9068. * green 50x50 ellipse at top left. Red X covers canvas when page focus changes
  9069. *
  9070. */
  9071. p5.prototype.focused = (document.hasFocus());
  9072. /**
  9073. * Sets the cursor to a predefined symbol or an image, or makes it visible
  9074. * if already hidden. If you are trying to set an image as the cursor, the
  9075. * recommended size is 16x16 or 32x32 pixels. It is not possible to load an
  9076. * image as the cursor if you are exporting your program for the Web, and not
  9077. * all MODES work with all browsers. The values for parameters x and y must
  9078. * be less than the dimensions of the image.
  9079. *
  9080. * @method cursor
  9081. * @param {Number/Constant} type either ARROW, CROSS, HAND, MOVE, TEXT, or
  9082. * WAIT, or path for image
  9083. * @param {Number} [x] the horizontal active spot of the cursor
  9084. * @param {Number} [y] the vertical active spot of the cursor
  9085. * @example
  9086. * <div><code>
  9087. * // Move the mouse left and right across the image
  9088. * // to see the cursor change from a cross to a hand
  9089. * function draw() {
  9090. * line(width/2, 0, width/2, height);
  9091. * if (mouseX < 50) {
  9092. * cursor(CROSS);
  9093. * } else {
  9094. * cursor(HAND);
  9095. * }
  9096. * }
  9097. * </code></div>
  9098. *
  9099. * @alt
  9100. * horizontal line divides canvas. cursor on left is a cross, right is hand.
  9101. *
  9102. */
  9103. p5.prototype.cursor = function(type, x, y) {
  9104. var cursor = 'auto';
  9105. var canvas = this._curElement.elt;
  9106. if (standardCursors.indexOf(type) > -1) {
  9107. // Standard css cursor
  9108. cursor = type;
  9109. } else if (typeof type === 'string') {
  9110. var coords = '';
  9111. if (x && y && (typeof x === 'number' && typeof y === 'number')) {
  9112. // Note that x and y values must be unit-less positive integers < 32
  9113. // https://developer.mozilla.org/en-US/docs/Web/CSS/cursor
  9114. coords = x + ' ' + y;
  9115. }
  9116. if ((type.substring(0, 7) === 'http://') ||
  9117. (type.substring(0, 8) === 'https://')) {
  9118. // Image (absolute url)
  9119. cursor = 'url(' + type + ') ' + coords + ', auto';
  9120. } else if (/\.(cur|jpg|jpeg|gif|png|CUR|JPG|JPEG|GIF|PNG)$/.test(type)) {
  9121. // Image file (relative path) - Separated for performance reasons
  9122. cursor = 'url(' + type + ') ' + coords + ', auto';
  9123. } else {
  9124. // Any valid string for the css cursor property
  9125. cursor = type;
  9126. }
  9127. }
  9128. canvas.style.cursor = cursor;
  9129. };
  9130. /**
  9131. * Specifies the number of frames to be displayed every second. For example,
  9132. * the function call frameRate(30) will attempt to refresh 30 times a second.
  9133. * If the processor is not fast enough to maintain the specified rate, the
  9134. * frame rate will not be achieved. Setting the frame rate within setup() is
  9135. * recommended. The default rate is 60 frames per second. This is the same as
  9136. * setFrameRate(val).
  9137. * <br><br>
  9138. * Calling frameRate() with no arguments returns the current framerate. This
  9139. * is the same as getFrameRate().
  9140. * <br><br>
  9141. * Calling frameRate() with arguments that are not of the type numbers
  9142. * or are non positive also returns current framerate.
  9143. *
  9144. * @method frameRate
  9145. * @param {Number} [fps] number of frames to be displayed every second
  9146. * @return {Number} current frameRate
  9147. * @example
  9148. *
  9149. * <div><code>
  9150. * var rectX = 0;
  9151. * var fr = 30; //starting FPS
  9152. * var clr;
  9153. *
  9154. * function setup() {
  9155. * background(200);
  9156. * frameRate(fr); // Attempt to refresh at starting FPS
  9157. * clr = color(255,0,0);
  9158. * }
  9159. *
  9160. * function draw() {
  9161. * background(200);
  9162. * rectX = rectX += 1; // Move Rectangle
  9163. *
  9164. * if (rectX >= width) { // If you go off screen.
  9165. * if (fr == 30) {
  9166. * clr = color(0,0,255);
  9167. * fr = 10;
  9168. * frameRate(fr); // make frameRate 10 FPS
  9169. * } else {
  9170. * clr = color(255,0,0);
  9171. * fr = 30;
  9172. * frameRate(fr); // make frameRate 30 FPS
  9173. * }
  9174. * rectX = 0;
  9175. * }
  9176. * fill(clr);
  9177. * rect(rectX, 40, 20,20);
  9178. * }
  9179. * </div></code>
  9180. *
  9181. * @alt
  9182. * blue rect moves left to right, followed by red rect moving faster. Loops.
  9183. *
  9184. */
  9185. p5.prototype.frameRate = function(fps) {
  9186. if (typeof fps !== 'number' || fps <= 0) {
  9187. return this._frameRate;
  9188. } else {
  9189. this._setProperty('_targetFrameRate', fps);
  9190. this._runFrames();
  9191. return this;
  9192. }
  9193. };
  9194. /**
  9195. * Returns the current framerate.
  9196. *
  9197. * @return {Number} current frameRate
  9198. */
  9199. p5.prototype.getFrameRate = function() {
  9200. return this.frameRate();
  9201. };
  9202. /**
  9203. * Specifies the number of frames to be displayed every second. For example,
  9204. * the function call frameRate(30) will attempt to refresh 30 times a second.
  9205. * If the processor is not fast enough to maintain the specified rate, the
  9206. * frame rate will not be achieved. Setting the frame rate within setup() is
  9207. * recommended. The default rate is 60 frames per second.
  9208. *
  9209. * Calling frameRate() with no arguments returns the current framerate.
  9210. *
  9211. * @param {Number} [fps] number of frames to be displayed every second
  9212. */
  9213. p5.prototype.setFrameRate = function(fps) {
  9214. return this.frameRate(fps);
  9215. };
  9216. /**
  9217. * Hides the cursor from view.
  9218. *
  9219. * @method noCursor
  9220. * @example
  9221. * <div><code>
  9222. * function setup() {
  9223. * noCursor();
  9224. * }
  9225. *
  9226. * function draw() {
  9227. * background(200);
  9228. * ellipse(mouseX, mouseY, 10, 10);
  9229. * }
  9230. * </code></div>
  9231. *
  9232. *
  9233. * @alt
  9234. * cursor becomes 10x 10 white ellipse the moves with mouse x and y.
  9235. *
  9236. */
  9237. p5.prototype.noCursor = function() {
  9238. this._curElement.elt.style.cursor = 'none';
  9239. };
  9240. /**
  9241. * System variable that stores the width of the entire screen display. This
  9242. * is used to run a full-screen program on any display size.
  9243. *
  9244. * @property displayWidth
  9245. * @example
  9246. * <div class="norender"><code>
  9247. * createCanvas(displayWidth, displayHeight);
  9248. * </code></div>
  9249. *
  9250. * @alt
  9251. * cursor becomes 10x 10 white ellipse the moves with mouse x and y.
  9252. *
  9253. */
  9254. p5.prototype.displayWidth = screen.width;
  9255. /**
  9256. * System variable that stores the height of the entire screen display. This
  9257. * is used to run a full-screen program on any display size.
  9258. *
  9259. * @property displayHeight
  9260. * @example
  9261. * <div class="norender"><code>
  9262. * createCanvas(displayWidth, displayHeight);
  9263. * </code></div>
  9264. *
  9265. * @alt
  9266. * no display.
  9267. *
  9268. */
  9269. p5.prototype.displayHeight = screen.height;
  9270. /**
  9271. * System variable that stores the width of the inner window, it maps to
  9272. * window.innerWidth.
  9273. *
  9274. * @property windowWidth
  9275. * @example
  9276. * <div class="norender"><code>
  9277. * createCanvas(windowWidth, windowHeight);
  9278. * </code></div>
  9279. *
  9280. * @alt
  9281. * no display.
  9282. *
  9283. */
  9284. p5.prototype.windowWidth = getWindowWidth();
  9285. /**
  9286. * System variable that stores the height of the inner window, it maps to
  9287. * window.innerHeight.
  9288. *
  9289. * @property windowHeight
  9290. * @example
  9291. * <div class="norender"><code>
  9292. * createCanvas(windowWidth, windowHeight);
  9293. * </code></div>
  9294. *@alt
  9295. * no display.
  9296. *
  9297. */
  9298. p5.prototype.windowHeight = getWindowHeight();
  9299. /**
  9300. * The windowResized() function is called once every time the browser window
  9301. * is resized. This is a good place to resize the canvas or do any other
  9302. * adjustments to accommodate the new window size.
  9303. *
  9304. * @method windowResized
  9305. * @example
  9306. * <div class="norender"><code>
  9307. * function setup() {
  9308. * createCanvas(windowWidth, windowHeight);
  9309. * }
  9310. *
  9311. * function draw() {
  9312. * background(0, 100, 200);
  9313. * }
  9314. *
  9315. * function windowResized() {
  9316. * resizeCanvas(windowWidth, windowHeight);
  9317. * }
  9318. * </code></div>
  9319. * @alt
  9320. * no display.
  9321. */
  9322. p5.prototype._onresize = function(e){
  9323. this._setProperty('windowWidth', getWindowWidth());
  9324. this._setProperty('windowHeight', getWindowHeight());
  9325. var context = this._isGlobal ? window : this;
  9326. var executeDefault;
  9327. if (typeof context.windowResized === 'function') {
  9328. executeDefault = context.windowResized(e);
  9329. if (executeDefault !== undefined && !executeDefault) {
  9330. e.preventDefault();
  9331. }
  9332. }
  9333. };
  9334. function getWindowWidth() {
  9335. return window.innerWidth ||
  9336. document.documentElement && document.documentElement.clientWidth ||
  9337. document.body && document.body.clientWidth ||
  9338. 0;
  9339. }
  9340. function getWindowHeight() {
  9341. return window.innerHeight ||
  9342. document.documentElement && document.documentElement.clientHeight ||
  9343. document.body && document.body.clientHeight ||
  9344. 0;
  9345. }
  9346. /**
  9347. * System variable that stores the width of the drawing canvas. This value
  9348. * is set by the first parameter of the createCanvas() function.
  9349. * For example, the function call createCanvas(320, 240) sets the width
  9350. * variable to the value 320. The value of width defaults to 100 if
  9351. * createCanvas() is not used in a program.
  9352. *
  9353. * @property width
  9354. */
  9355. p5.prototype.width = 0;
  9356. /**
  9357. * System variable that stores the height of the drawing canvas. This value
  9358. * is set by the second parameter of the createCanvas() function. For
  9359. * example, the function call createCanvas(320, 240) sets the height
  9360. * variable to the value 240. The value of height defaults to 100 if
  9361. * createCanvas() is not used in a program.
  9362. *
  9363. * @property height
  9364. */
  9365. p5.prototype.height = 0;
  9366. /**
  9367. * If argument is given, sets the sketch to fullscreen or not based on the
  9368. * value of the argument. If no argument is given, returns the current
  9369. * fullscreen state. Note that due to browser restrictions this can only
  9370. * be called on user input, for example, on mouse press like the example
  9371. * below.
  9372. *
  9373. * @method fullscreen
  9374. * @param {Boolean} [val] whether the sketch should be in fullscreen mode
  9375. * or not
  9376. * @return {Boolean} current fullscreen state
  9377. * @example
  9378. * <div>
  9379. * <code>
  9380. * // Clicking in the box toggles fullscreen on and off.
  9381. * function setup() {
  9382. * background(200);
  9383. * }
  9384. * function mousePressed() {
  9385. * if (mouseX > 0 && mouseX < 100 && mouseY > 0 && mouseY < 100) {
  9386. * var fs = fullscreen();
  9387. * fullscreen(!fs);
  9388. * }
  9389. * }
  9390. * </code>
  9391. * </div>
  9392. *
  9393. * @alt
  9394. * no display.
  9395. *
  9396. */
  9397. p5.prototype.fullscreen = function(val) {
  9398. // no arguments, return fullscreen or not
  9399. if (typeof val === 'undefined') {
  9400. return document.fullscreenElement ||
  9401. document.webkitFullscreenElement ||
  9402. document.mozFullScreenElement ||
  9403. document.msFullscreenElement;
  9404. } else { // otherwise set to fullscreen or not
  9405. if (val) {
  9406. launchFullscreen(document.documentElement);
  9407. } else {
  9408. exitFullscreen();
  9409. }
  9410. }
  9411. };
  9412. /**
  9413. * Sets the pixel scaling for high pixel density displays. By default
  9414. * pixel density is set to match display density, call pixelDensity(1)
  9415. * to turn this off. Calling pixelDensity() with no arguments returns
  9416. * the current pixel density of the sketch.
  9417. *
  9418. *
  9419. * @method pixelDensity
  9420. * @param {Number} [val] whether or how much the sketch should scale
  9421. * @returns {Number} current pixel density of the sketch
  9422. * @example
  9423. * <div>
  9424. * <code>
  9425. * function setup() {
  9426. * pixelDensity(1);
  9427. * createCanvas(100, 100);
  9428. * background(200);
  9429. * ellipse(width/2, height/2, 50, 50);
  9430. * }
  9431. * </code>
  9432. * </div>
  9433. * <div>
  9434. * <code>
  9435. * function setup() {
  9436. * pixelDensity(3.0);
  9437. * createCanvas(100, 100);
  9438. * background(200);
  9439. * ellipse(width/2, height/2, 50, 50);
  9440. * }
  9441. * </code>
  9442. * </div>
  9443. *
  9444. * @alt
  9445. * fuzzy 50x50 white ellipse with black outline in center of canvas.
  9446. * sharp 50x50 white ellipse with black outline in center of canvas.
  9447. */
  9448. p5.prototype.pixelDensity = function(val) {
  9449. if (typeof val === 'number') {
  9450. this._pixelDensity = val;
  9451. } else {
  9452. return this._pixelDensity;
  9453. }
  9454. this.resizeCanvas(this.width, this.height, true);
  9455. };
  9456. /**
  9457. * Returns the pixel density of the current display the sketch is running on.
  9458. *
  9459. * @method displayDensity
  9460. * @returns {Number} current pixel density of the display
  9461. * @example
  9462. * <div>
  9463. * <code>
  9464. * function setup() {
  9465. * var density = displayDensity();
  9466. * pixelDensity(density);
  9467. * createCanvas(100, 100);
  9468. * background(200);
  9469. * ellipse(width/2, height/2, 50, 50);
  9470. * }
  9471. * </code>
  9472. * </div>
  9473. *
  9474. * @alt
  9475. * 50x50 white ellipse with black outline in center of canvas.
  9476. */
  9477. p5.prototype.displayDensity = function() {
  9478. return window.devicePixelRatio;
  9479. };
  9480. function launchFullscreen(element) {
  9481. var enabled = document.fullscreenEnabled ||
  9482. document.webkitFullscreenEnabled ||
  9483. document.mozFullScreenEnabled ||
  9484. document.msFullscreenEnabled;
  9485. if (!enabled) {
  9486. throw new Error('Fullscreen not enabled in this browser.');
  9487. }
  9488. if(element.requestFullscreen) {
  9489. element.requestFullscreen();
  9490. } else if(element.mozRequestFullScreen) {
  9491. element.mozRequestFullScreen();
  9492. } else if(element.webkitRequestFullscreen) {
  9493. element.webkitRequestFullscreen();
  9494. } else if(element.msRequestFullscreen) {
  9495. element.msRequestFullscreen();
  9496. }
  9497. }
  9498. function exitFullscreen() {
  9499. if(document.exitFullscreen) {
  9500. document.exitFullscreen();
  9501. } else if(document.mozCancelFullScreen) {
  9502. document.mozCancelFullScreen();
  9503. } else if(document.webkitExitFullscreen) {
  9504. document.webkitExitFullscreen();
  9505. } else if (document.msExitFullscreen) {
  9506. document.msExitFullscreen();
  9507. }
  9508. }
  9509. /**
  9510. * Gets the current URL.
  9511. * @method getURL
  9512. * @return {String} url
  9513. * @example
  9514. * <div>
  9515. * <code>
  9516. * var url;
  9517. * var x = 100;
  9518. *
  9519. * function setup() {
  9520. * fill(0);
  9521. * noStroke();
  9522. * url = getURL();
  9523. * }
  9524. *
  9525. * function draw() {
  9526. * background(200);
  9527. * text(url, x, height/2);
  9528. * x--;
  9529. * }
  9530. * </code>
  9531. * </div>
  9532. *
  9533. * @alt
  9534. * current url (http://p5js.org/reference/#/p5/getURL) moves right to left.
  9535. *
  9536. */
  9537. p5.prototype.getURL = function() {
  9538. return location.href;
  9539. };
  9540. /**
  9541. * Gets the current URL path as an array.
  9542. * @method getURLPath
  9543. * @return {Array} path components
  9544. * @example
  9545. * <div class='norender'><code>
  9546. * function setup() {
  9547. * var urlPath = getURLPath();
  9548. * for (var i=0; i&lt;urlPath.length; i++) {
  9549. * text(urlPath[i], 10, i*20+20);
  9550. * }
  9551. * }
  9552. * </code></div>
  9553. *
  9554. * @alt
  9555. *no display
  9556. *
  9557. */
  9558. p5.prototype.getURLPath = function() {
  9559. return location.pathname.split('/').filter(function(v){return v!=='';});
  9560. };
  9561. /**
  9562. * Gets the current URL params as an Object.
  9563. * @method getURLParams
  9564. * @return {Object} URL params
  9565. * @example
  9566. * <div class='norender'>
  9567. * <code>
  9568. * // Example: http://p5js.org?year=2014&month=May&day=15
  9569. *
  9570. * function setup() {
  9571. * var params = getURLParams();
  9572. * text(params.day, 10, 20);
  9573. * text(params.month, 10, 40);
  9574. * text(params.year, 10, 60);
  9575. * }
  9576. * </code>
  9577. * </div>
  9578. * @alt
  9579. * no display.
  9580. *
  9581. */
  9582. p5.prototype.getURLParams = function() {
  9583. var re = /[?&]([^&=]+)(?:[&=])([^&=]+)/gim;
  9584. var m;
  9585. var v={};
  9586. while ((m = re.exec(location.search)) != null) {
  9587. if (m.index === re.lastIndex) {
  9588. re.lastIndex++;
  9589. }
  9590. v[m[1]]=m[2];
  9591. }
  9592. return v;
  9593. };
  9594. module.exports = p5;
  9595. },{"./constants":36,"./core":37}],40:[function(_dereq_,module,exports){
  9596. /**
  9597. * @for p5
  9598. * @requires core
  9599. */
  9600. 'use strict';
  9601. var p5 = _dereq_('./core');
  9602. var doFriendlyWelcome = false; // TEMP until we get it all working LM
  9603. // -- Borrowed from jQuery 1.11.3 --
  9604. var class2type = {};
  9605. var toString = class2type.toString;
  9606. var names = ['Boolean', 'Number', 'String', 'Function',
  9607. 'Array', 'Date', 'RegExp', 'Object', 'Error'];
  9608. for (var n=0; n<names.length; n++) {
  9609. class2type[ '[object ' + names[n] + ']' ] = names[n].toLowerCase();
  9610. }
  9611. var getType = function( obj ) {
  9612. if ( obj == null ) {
  9613. return obj + '';
  9614. }
  9615. return typeof obj === 'object' || typeof obj === 'function' ?
  9616. class2type[ toString.call(obj) ] || 'object' :
  9617. typeof obj;
  9618. };
  9619. // -- End borrow --
  9620. /**
  9621. * Prints out a fancy, colorful message to the console log
  9622. *
  9623. * @param {String} message the words to be said
  9624. * @param {String} func the name of the function to link
  9625. * @param {Integer/Color String} color CSS color string or error type
  9626. *
  9627. * @return console logs
  9628. */
  9629. // Wrong number of params, undefined param, wrong type
  9630. var FILE_LOAD = 3;
  9631. // p5.js blue, p5.js orange, auto dark green; fallback p5.js darkened magenta
  9632. // See testColors below for all the color codes and names
  9633. var typeColors = ['#2D7BB6', '#EE9900', '#4DB200', '#C83C00'];
  9634. function report(message, func, color) {
  9635. if(doFriendlyWelcome){
  9636. friendlyWelcome();
  9637. doFriendlyWelcome =false;
  9638. }
  9639. if ('undefined' === getType(color)) {
  9640. color = '#B40033'; // dark magenta
  9641. } else if (getType(color) === 'number') { // Type to color
  9642. color = typeColors[color];
  9643. }
  9644. // LM TEMP commenting this out until we get the whole system working
  9645. // if (func.substring(0,4) === 'load'){
  9646. // console.log(
  9647. // '%c> p5.js says: '+message+'%c'+
  9648. // '[https://github.com/processing/p5.js/wiki/Local-server]',
  9649. // 'background-color:' + color + ';color:#FFF;',
  9650. // 'background-color:transparent;color:' + color +';',
  9651. // 'background-color:' + color + ';color:#FFF;',
  9652. // 'background-color:transparent;color:' + color +';'
  9653. // );
  9654. // }
  9655. // else{
  9656. // console.log(
  9657. // '%c> p5.js says: '+message+'%c [http://p5js.org/reference/#p5/'+func+
  9658. // ']', 'background-color:' + color + ';color:#FFF;',
  9659. // 'background-color:transparent;color:' + color +';'
  9660. // );
  9661. // }
  9662. }
  9663. var errorCases = {
  9664. '0': {
  9665. fileType: 'image',
  9666. method: 'loadImage',
  9667. message: ' hosting the image online,'
  9668. },
  9669. '1': {
  9670. fileType: 'XML file',
  9671. method: 'loadXML'
  9672. },
  9673. '2': {
  9674. fileType: 'table file',
  9675. method: 'loadTable'
  9676. },
  9677. '3': {
  9678. fileType: 'text file',
  9679. method: 'loadStrings'
  9680. },
  9681. '4': {
  9682. fileType: 'font',
  9683. method: 'loadFont',
  9684. message: ' hosting the font online,'
  9685. },
  9686. };
  9687. p5._friendlyFileLoadError = function (errorType, filePath) {
  9688. var errorInfo = errorCases[ errorType ];
  9689. var message = 'It looks like there was a problem' +
  9690. ' loading your ' + errorInfo.fileType + '.' +
  9691. ' Try checking if the file path%c [' + filePath + '] %cis correct,' +
  9692. (errorInfo.message || '') + ' or running a local server.';
  9693. report(message, errorInfo.method, FILE_LOAD);
  9694. };
  9695. function friendlyWelcome() {
  9696. // p5.js brand - magenta: #ED225D
  9697. var astrixBgColor = 'transparent';
  9698. var astrixTxtColor = '#ED225D';
  9699. var welcomeBgColor = '#ED225D';
  9700. var welcomeTextColor = 'white';
  9701. console.log(
  9702. '%c _ \n'+
  9703. ' /\\| |/\\ \n'+
  9704. ' \\ ` \' / \n'+
  9705. ' / , . \\ \n'+
  9706. ' \\/|_|\\/ '+
  9707. '\n\n%c> p5.js says: Welcome! '+
  9708. 'This is your friendly debugger. ' +
  9709. 'To turn me off switch to using “p5.min.js”.',
  9710. 'background-color:'+astrixBgColor+';color:' + astrixTxtColor +';',
  9711. 'background-color:'+welcomeBgColor+';color:' + welcomeTextColor +';'
  9712. );
  9713. }
  9714. /**
  9715. * Prints out all the colors in the color pallete with white text.
  9716. * For color blindness testing.
  9717. */
  9718. /* function testColors() {
  9719. var str = 'A box of biscuits, a box of mixed biscuits and a biscuit mixer';
  9720. report(str, 'print', '#ED225D'); // p5.js magenta
  9721. report(str, 'print', '#2D7BB6'); // p5.js blue
  9722. report(str, 'print', '#EE9900'); // p5.js orange
  9723. report(str, 'print', '#A67F59'); // p5.js light brown
  9724. report(str, 'print', '#704F21'); // p5.js gold
  9725. report(str, 'print', '#1CC581'); // auto cyan
  9726. report(str, 'print', '#FF6625'); // auto orange
  9727. report(str, 'print', '#79EB22'); // auto green
  9728. report(str, 'print', '#B40033'); // p5.js darkened magenta
  9729. report(str, 'print', '#084B7F'); // p5.js darkened blue
  9730. report(str, 'print', '#945F00'); // p5.js darkened orange
  9731. report(str, 'print', '#6B441D'); // p5.js darkened brown
  9732. report(str, 'print', '#2E1B00'); // p5.js darkened gold
  9733. report(str, 'print', '#008851'); // auto dark cyan
  9734. report(str, 'print', '#C83C00'); // auto dark orange
  9735. report(str, 'print', '#4DB200'); // auto dark green
  9736. } */
  9737. // This is a lazily-defined list of p5 symbols that may be
  9738. // misused by beginners at top-level code, outside of setup/draw. We'd like
  9739. // to detect these errors and help the user by suggesting they move them
  9740. // into setup/draw.
  9741. //
  9742. // For more details, see https://github.com/processing/p5.js/issues/1121.
  9743. var misusedAtTopLevelCode = null;
  9744. var FAQ_URL = 'https://github.com/processing/p5.js/wiki/' +
  9745. 'Frequently-Asked-Questions' +
  9746. '#why-cant-i-assign-variables-using-p5-functions-and-' +
  9747. 'variables-before-setup';
  9748. function defineMisusedAtTopLevelCode() {
  9749. var uniqueNamesFound = {};
  9750. var getSymbols = function(obj) {
  9751. return Object.getOwnPropertyNames(obj).filter(function(name) {
  9752. if (name[0] === '_') {
  9753. return false;
  9754. }
  9755. if (name in uniqueNamesFound) {
  9756. return false;
  9757. }
  9758. uniqueNamesFound[name] = true;
  9759. return true;
  9760. }).map(function(name) {
  9761. var type;
  9762. if (typeof(obj[name]) === 'function') {
  9763. type = 'function';
  9764. } else if (name === name.toUpperCase()) {
  9765. type = 'constant';
  9766. } else {
  9767. type = 'variable';
  9768. }
  9769. return {name: name, type: type};
  9770. });
  9771. };
  9772. misusedAtTopLevelCode = [].concat(
  9773. getSymbols(p5.prototype),
  9774. // At present, p5 only adds its constants to p5.prototype during
  9775. // construction, which may not have happened at the time a
  9776. // ReferenceError is thrown, so we'll manually add them to our list.
  9777. getSymbols(_dereq_('./constants'))
  9778. );
  9779. // This will ultimately ensure that we report the most specific error
  9780. // possible to the user, e.g. advising them about HALF_PI instead of PI
  9781. // when their code misuses the former.
  9782. misusedAtTopLevelCode.sort(function(a, b) {
  9783. return b.name.length - a.name.length;
  9784. });
  9785. }
  9786. function helpForMisusedAtTopLevelCode(e, log) {
  9787. if (!log) {
  9788. log = console.log.bind(console);
  9789. }
  9790. if (!misusedAtTopLevelCode) {
  9791. defineMisusedAtTopLevelCode();
  9792. }
  9793. // If we find that we're logging lots of false positives, we can
  9794. // uncomment the following code to avoid displaying anything if the
  9795. // user's code isn't likely to be using p5's global mode. (Note that
  9796. // setup/draw are more likely to be defined due to JS function hoisting.)
  9797. //
  9798. //if (!('setup' in window || 'draw' in window)) {
  9799. // return;
  9800. //}
  9801. misusedAtTopLevelCode.some(function(symbol) {
  9802. // Note that while just checking for the occurrence of the
  9803. // symbol name in the error message could result in false positives,
  9804. // a more rigorous test is difficult because different browsers
  9805. // log different messages, and the format of those messages may
  9806. // change over time.
  9807. //
  9808. // For example, if the user uses 'PI' in their code, it may result
  9809. // in any one of the following messages:
  9810. //
  9811. // * 'PI' is undefined (Microsoft Edge)
  9812. // * ReferenceError: PI is undefined (Firefox)
  9813. // * Uncaught ReferenceError: PI is not defined (Chrome)
  9814. if (e.message && e.message.match('\\W?'+symbol.name+'\\W') !== null) {
  9815. log('%cDid you just try to use p5.js\'s ' + symbol.name +
  9816. (symbol.type === 'function' ? '() ' : ' ') + symbol.type +
  9817. '? If so, you may want to ' +
  9818. 'move it into your sketch\'s setup() function.\n\n' +
  9819. 'For more details, see: ' + FAQ_URL,
  9820. 'color: #B40033' /* Dark magenta */);
  9821. return true;
  9822. }
  9823. });
  9824. }
  9825. // Exposing this primarily for unit testing.
  9826. p5.prototype._helpForMisusedAtTopLevelCode = helpForMisusedAtTopLevelCode;
  9827. if (document.readyState !== 'complete') {
  9828. window.addEventListener('error', helpForMisusedAtTopLevelCode, false);
  9829. // Our job is only to catch ReferenceErrors that are thrown when
  9830. // global (non-instance mode) p5 APIs are used at the top-level
  9831. // scope of a file, so we'll unbind our error listener now to make
  9832. // sure we don't log false positives later.
  9833. window.addEventListener('load', function() {
  9834. window.removeEventListener('error', helpForMisusedAtTopLevelCode, false);
  9835. });
  9836. }
  9837. module.exports = p5;
  9838. },{"./constants":36,"./core":37}],41:[function(_dereq_,module,exports){
  9839. /**
  9840. * @module DOM
  9841. * @submodule DOM
  9842. * @for p5.Element
  9843. */
  9844. var p5 = _dereq_('./core');
  9845. /**
  9846. * Base class for all elements added to a sketch, including canvas,
  9847. * graphics buffers, and other HTML elements. Methods in blue are
  9848. * included in the core functionality, methods in brown are added
  9849. * with the <a href="http://p5js.org/reference/#/libraries/p5.dom">p5.dom
  9850. * library</a>.
  9851. * It is not called directly, but p5.Element
  9852. * objects are created by calling createCanvas, createGraphics,
  9853. * or in the p5.dom library, createDiv, createImg, createInput, etc.
  9854. *
  9855. * @class p5.Element
  9856. * @constructor
  9857. * @param {String} elt DOM node that is wrapped
  9858. * @param {Object} [pInst] pointer to p5 instance
  9859. */
  9860. p5.Element = function(elt, pInst) {
  9861. /**
  9862. * Underlying HTML element. All normal HTML methods can be called on this.
  9863. *
  9864. * @property elt
  9865. */
  9866. this.elt = elt;
  9867. this._pInst = pInst;
  9868. this._events = {};
  9869. this.width = this.elt.offsetWidth;
  9870. this.height = this.elt.offsetHeight;
  9871. };
  9872. /**
  9873. *
  9874. * Attaches the element to the parent specified. A way of setting
  9875. * the container for the element. Accepts either a string ID, DOM
  9876. * node, or p5.Element. If no arguments given, parent node is returned.
  9877. * For more ways to position the canvas, see the
  9878. * <a href='https://github.com/processing/p5.js/wiki/Positioning-your-canvas'>
  9879. * positioning the canvas</a> wiki page.
  9880. *
  9881. * @method parent
  9882. * @param {String|Object} parent the ID, DOM node, or p5.Element
  9883. * of desired parent element
  9884. * @return {p5.Element}
  9885. * @example
  9886. * <div class="norender"><code>
  9887. * // in the html file:
  9888. * &lt;div id="myContainer">&lt;/div>
  9889. * // in the js file:
  9890. * var cnv = createCanvas(100, 100);
  9891. * cnv.parent("myContainer");
  9892. * </code></div>
  9893. * <div class='norender'><code>
  9894. * var div0 = createDiv('this is the parent');
  9895. * var div1 = createDiv('this is the child');
  9896. * div1.parent(div0); // use p5.Element
  9897. * </code></div>
  9898. * <div class='norender'><code>
  9899. * var div0 = createDiv('this is the parent');
  9900. * div0.id('apples');
  9901. * var div1 = createDiv('this is the child');
  9902. * div1.parent('apples'); // use id
  9903. * </code></div>
  9904. * <div class='norender'><code>
  9905. * var elt = document.getElementById('myParentDiv');
  9906. * var div1 = createDiv('this is the child');
  9907. * div1.parent(elt); // use element from page
  9908. * </code></div>
  9909. *
  9910. * @alt
  9911. * no display.
  9912. *
  9913. */
  9914. p5.Element.prototype.parent = function(p) {
  9915. if (arguments.length === 0){
  9916. return this.elt.parentNode;
  9917. } else {
  9918. if (typeof p === 'string') {
  9919. if (p[0] === '#') {
  9920. p = p.substring(1);
  9921. }
  9922. p = document.getElementById(p);
  9923. } else if (p instanceof p5.Element) {
  9924. p = p.elt;
  9925. }
  9926. p.appendChild(this.elt);
  9927. return this;
  9928. }
  9929. };
  9930. /**
  9931. *
  9932. * Sets the ID of the element. If no ID argument is passed in, it instead
  9933. * returns the current ID of the element.
  9934. *
  9935. * @method id
  9936. * @param {String} [id] ID of the element
  9937. * @return {p5.Element|String}
  9938. * @example
  9939. * <div><code class='norender'>
  9940. * function setup() {
  9941. * var cnv = createCanvas(100, 100);
  9942. * // Assigns a CSS selector ID to
  9943. * // the canvas element.
  9944. * cnv.id("mycanvas");
  9945. * }
  9946. * </code></div>
  9947. *
  9948. * @alt
  9949. * no display.
  9950. *
  9951. */
  9952. p5.Element.prototype.id = function(id) {
  9953. if (arguments.length === 0) {
  9954. return this.elt.id;
  9955. } else {
  9956. this.elt.id = id;
  9957. this.width = this.elt.offsetWidth;
  9958. this.height = this.elt.offsetHeight;
  9959. return this;
  9960. }
  9961. };
  9962. /**
  9963. *
  9964. * Adds given class to the element. If no class argument is passed in, it
  9965. * instead returns a string containing the current class(es) of the element.
  9966. *
  9967. * @method class
  9968. * @param {String} [class] class to add
  9969. * @return {p5.Element|String}
  9970. */
  9971. p5.Element.prototype.class = function(c) {
  9972. if (arguments.length === 0) {
  9973. return this.elt.className;
  9974. } else {
  9975. this.elt.className = c;
  9976. return this;
  9977. }
  9978. };
  9979. /**
  9980. * The .mousePressed() function is called once after every time a
  9981. * mouse button is pressed over the element. This can be used to
  9982. * attach element specific event listeners.
  9983. *
  9984. * @method mousePressed
  9985. * @param {Function} fxn function to be fired when mouse is
  9986. * pressed over the element.
  9987. * @return {p5.Element}
  9988. * @example
  9989. * <div class='norender'><code>
  9990. * var cnv;
  9991. * var d;
  9992. * var g;
  9993. * function setup() {
  9994. * cnv = createCanvas(100, 100);
  9995. * cnv.mousePressed(changeGray); // attach listener for
  9996. * // canvas click only
  9997. * d = 10;
  9998. * g = 100;
  9999. * }
  10000. *
  10001. * function draw() {
  10002. * background(g);
  10003. * ellipse(width/2, height/2, d, d);
  10004. * }
  10005. *
  10006. * // this function fires with any click anywhere
  10007. * function mousePressed() {
  10008. * d = d + 10;
  10009. * }
  10010. *
  10011. * // this function fires only when cnv is clicked
  10012. * function changeGray() {
  10013. * g = random(0, 255);
  10014. * }
  10015. * </code></div>
  10016. *
  10017. * @alt
  10018. * no display.
  10019. *
  10020. */
  10021. p5.Element.prototype.mousePressed = function (fxn) {
  10022. attachListener('mousedown', fxn, this);
  10023. attachListener('touchstart', fxn, this);
  10024. return this;
  10025. };
  10026. /**
  10027. * The .mouseWheel() function is called once after every time a
  10028. * mouse wheel is scrolled over the element. This can be used to
  10029. * attach element specific event listeners.
  10030. * <br><br>
  10031. * The function accepts a callback function as argument which will be executed
  10032. * when the `wheel` event is triggered on the element, the callabck function is
  10033. * passed one argument `event`. The `event.deltaY` property returns negative
  10034. * values if the mouse wheel is rotated up or away from the user and positive
  10035. * in the other direction. The `event.deltaX` does the same as `event.deltaY`
  10036. * except it reads the horizontal wheel scroll of the mouse wheel.
  10037. * <br><br>
  10038. * On OS X with "natural" scrolling enabled, the `event.deltaY` values are
  10039. * reversed.
  10040. *
  10041. * @method mouseWheel
  10042. * @param {Function} fxn function to be fired when mouse wheel is
  10043. * scrolled over the element.
  10044. * @return {p5.Element}
  10045. * @example
  10046. * <div class='norender'><code>
  10047. * var cnv;
  10048. * var d;
  10049. * var g;
  10050. * function setup() {
  10051. * cnv = createCanvas(100, 100);
  10052. * cnv.mouseWheel(changeSize); // attach listener for
  10053. * // activity on canvas only
  10054. * d = 10;
  10055. * g = 100;
  10056. * }
  10057. *
  10058. * function draw() {
  10059. * background(g);
  10060. * ellipse(width/2, height/2, d, d);
  10061. * }
  10062. *
  10063. * // this function fires with mousewheel movement
  10064. * // anywhere on screen
  10065. * function mouseWheel() {
  10066. * g = g + 10;
  10067. * }
  10068. *
  10069. * // this function fires with mousewheel movement
  10070. * // over canvas only
  10071. * function changeSize(event) {
  10072. * if (event.deltaY > 0) {
  10073. * d = d + 10;
  10074. * } else {
  10075. * d = d - 10;
  10076. * }
  10077. * }
  10078. * </code></div>
  10079. *
  10080. *
  10081. * @alt
  10082. * no display.
  10083. *
  10084. */
  10085. p5.Element.prototype.mouseWheel = function (fxn) {
  10086. attachListener('wheel', fxn, this);
  10087. return this;
  10088. };
  10089. /**
  10090. * The .mouseReleased() function is called once after every time a
  10091. * mouse button is released over the element. This can be used to
  10092. * attach element specific event listeners.
  10093. *
  10094. * @method mouseReleased
  10095. * @param {Function} fxn function to be fired when mouse is
  10096. * released over the element.
  10097. * @return {p5.Element}
  10098. * @example
  10099. * <div class='norender'><code>
  10100. * var cnv;
  10101. * var d;
  10102. * var g;
  10103. * function setup() {
  10104. * cnv = createCanvas(100, 100);
  10105. * cnv.mouseReleased(changeGray); // attach listener for
  10106. * // activity on canvas only
  10107. * d = 10;
  10108. * g = 100;
  10109. * }
  10110. *
  10111. * function draw() {
  10112. * background(g);
  10113. * ellipse(width/2, height/2, d, d);
  10114. * }
  10115. *
  10116. * // this function fires after the mouse has been
  10117. * // released
  10118. * function mouseReleased() {
  10119. * d = d + 10;
  10120. * }
  10121. *
  10122. * // this function fires after the mouse has been
  10123. * // released while on canvas
  10124. * function changeGray() {
  10125. * g = random(0, 255);
  10126. * }
  10127. * </code></div>
  10128. *
  10129. *
  10130. * @alt
  10131. * no display.
  10132. *
  10133. */
  10134. p5.Element.prototype.mouseReleased = function (fxn) {
  10135. attachListener('mouseup', fxn, this);
  10136. attachListener('touchend', fxn, this);
  10137. return this;
  10138. };
  10139. /**
  10140. * The .mouseClicked() function is called once after a mouse button is
  10141. * pressed and released over the element. This can be used to
  10142. * attach element specific event listeners.
  10143. *
  10144. * @method mouseClicked
  10145. * @param {Function} fxn function to be fired when mouse is
  10146. * clicked over the element.
  10147. * @return {p5.Element}
  10148. * @example
  10149. * var cnv;
  10150. * var d;
  10151. * var g;
  10152. * function setup() {
  10153. * cnv = createCanvas(100, 100);
  10154. * cnv.mouseClicked(changeGray); // attach listener for
  10155. * // activity on canvas only
  10156. * d = 10;
  10157. * g = 100;
  10158. * }
  10159. *
  10160. * function draw() {
  10161. * background(g);
  10162. * ellipse(width/2, height/2, d, d);
  10163. * }
  10164. *
  10165. * // this function fires after the mouse has been
  10166. * // clicked anywhere
  10167. * function mouseClicked() {
  10168. * d = d + 10;
  10169. * }
  10170. *
  10171. * // this function fires after the mouse has been
  10172. * // clicked on canvas
  10173. * function changeGray() {
  10174. * g = random(0, 255);
  10175. * }
  10176. * </code></div>
  10177. *
  10178. *
  10179. * @alt
  10180. * no display.
  10181. *
  10182. */
  10183. p5.Element.prototype.mouseClicked = function (fxn) {
  10184. attachListener('click', fxn, this);
  10185. return this;
  10186. };
  10187. /**
  10188. * The .mouseMoved() function is called once every time a
  10189. * mouse moves over the element. This can be used to attach an
  10190. * element specific event listener.
  10191. *
  10192. * @method mouseMoved
  10193. * @param {Function} fxn function to be fired when mouse is
  10194. * moved over the element.
  10195. * @return {p5.Element}
  10196. * @example
  10197. * <div class='norender'><code>
  10198. * var cnv;
  10199. * var d = 30;
  10200. * var g;
  10201. * function setup() {
  10202. * cnv = createCanvas(100, 100);
  10203. * cnv.mouseMoved(changeSize); // attach listener for
  10204. * // activity on canvas only
  10205. * d = 10;
  10206. * g = 100;
  10207. * }
  10208. *
  10209. * function draw() {
  10210. * background(g);
  10211. * fill(200);
  10212. * ellipse(width/2, height/2, d, d);
  10213. * }
  10214. *
  10215. * // this function fires when mouse moves anywhere on
  10216. * // page
  10217. * function mouseMoved() {
  10218. * g = g + 5;
  10219. * if (g > 255) {
  10220. * g = 0;
  10221. * }
  10222. * }
  10223. *
  10224. * // this function fires when mouse moves over canvas
  10225. * function changeSize() {
  10226. * d = d + 2;
  10227. * if (d > 100) {
  10228. * d = 0;
  10229. * }
  10230. * }
  10231. * </code></div>
  10232. *
  10233. *
  10234. * @alt
  10235. * no display.
  10236. *
  10237. */
  10238. p5.Element.prototype.mouseMoved = function (fxn) {
  10239. attachListener('mousemove', fxn, this);
  10240. attachListener('touchmove', fxn, this);
  10241. return this;
  10242. };
  10243. /**
  10244. * The .mouseOver() function is called once after every time a
  10245. * mouse moves onto the element. This can be used to attach an
  10246. * element specific event listener.
  10247. *
  10248. * @method mouseOver
  10249. * @param {Function} fxn function to be fired when mouse is
  10250. * moved over the element.
  10251. * @return {p5.Element}
  10252. * @example
  10253. * <div class='norender'><code>
  10254. * var cnv;
  10255. * var d;
  10256. * var g;
  10257. * function setup() {
  10258. * cnv = createCanvas(100, 100);
  10259. * cnv.mouseOver(changeGray);
  10260. * d = 10;
  10261. * }
  10262. *
  10263. * function draw() {
  10264. * ellipse(width/2, height/2, d, d);
  10265. * }
  10266. *
  10267. * function changeGray() {
  10268. * d = d + 10;
  10269. * if (d > 100) {
  10270. * d = 0;
  10271. * }
  10272. * }
  10273. * </code></div>
  10274. *
  10275. *
  10276. * @alt
  10277. * no display.
  10278. *
  10279. */
  10280. p5.Element.prototype.mouseOver = function (fxn) {
  10281. attachListener('mouseover', fxn, this);
  10282. return this;
  10283. };
  10284. /**
  10285. * The .changed() function is called when the value of an
  10286. * element is changed.
  10287. * This can be used to attach an element specific event listener.
  10288. *
  10289. * @method changed
  10290. * @param {Function} fxn function to be fired when the value of an
  10291. * element changes.
  10292. * @return {p5.Element}
  10293. * @example
  10294. * <div><code>
  10295. * var sel;
  10296. *
  10297. * function setup() {
  10298. * textAlign(CENTER);
  10299. * background(200);
  10300. * sel = createSelect();
  10301. * sel.position(10, 10);
  10302. * sel.option('pear');
  10303. * sel.option('kiwi');
  10304. * sel.option('grape');
  10305. * sel.changed(mySelectEvent);
  10306. * }
  10307. *
  10308. * function mySelectEvent() {
  10309. * var item = sel.value();
  10310. * background(200);
  10311. * text("it's a "+item+"!", 50, 50);
  10312. * }
  10313. * </code></div>
  10314. * <div><code>
  10315. * var checkbox;
  10316. * var cnv;
  10317. *
  10318. * function setup() {
  10319. * checkbox = createCheckbox(" fill");
  10320. * checkbox.changed(changeFill);
  10321. * cnv = createCanvas(100, 100);
  10322. * cnv.position(0, 30);
  10323. * noFill();
  10324. * }
  10325. *
  10326. * function draw() {
  10327. * background(200);
  10328. * ellipse(50, 50, 50, 50);
  10329. * }
  10330. *
  10331. * function changeFill() {
  10332. * if (checkbox.checked()) {
  10333. * fill(0);
  10334. * } else {
  10335. * noFill();
  10336. * }
  10337. * }
  10338. * </code></div>
  10339. *
  10340. * @alt
  10341. * dropdown: pear, kiwi, grape. When selected text "its a" + selection shown.
  10342. *
  10343. */
  10344. p5.Element.prototype.changed = function (fxn) {
  10345. attachListener('change', fxn, this);
  10346. return this;
  10347. };
  10348. /**
  10349. * The .input() function is called when any user input is
  10350. * detected with an element. The input event is often used
  10351. * to detect keystrokes in a input element, or changes on a
  10352. * slider element. This can be used to attach an element specific
  10353. * event listener.
  10354. *
  10355. * @method input
  10356. * @param {Function} fxn function to be fired on user input.
  10357. * @return {p5.Element}
  10358. * @example
  10359. * <div class='norender'><code>
  10360. * // Open your console to see the output
  10361. * function setup() {
  10362. * var inp = createInput('');
  10363. * inp.input(myInputEvent);
  10364. * }
  10365. *
  10366. * function myInputEvent() {
  10367. * console.log('you are typing: ', this.value());
  10368. * }
  10369. * </code></div>
  10370. *
  10371. * @alt
  10372. * no display.
  10373. *
  10374. */
  10375. p5.Element.prototype.input = function (fxn) {
  10376. attachListener('input', fxn, this);
  10377. return this;
  10378. };
  10379. /**
  10380. * The .mouseOut() function is called once after every time a
  10381. * mouse moves off the element. This can be used to attach an
  10382. * element specific event listener.
  10383. *
  10384. * @method mouseOut
  10385. * @param {Function} fxn function to be fired when mouse is
  10386. * moved off the element.
  10387. * @return {p5.Element}
  10388. * @example
  10389. * <div class='norender'><code>
  10390. * var cnv;
  10391. * var d;
  10392. * var g;
  10393. * function setup() {
  10394. * cnv = createCanvas(100, 100);
  10395. * cnv.mouseOut(changeGray);
  10396. * d = 10;
  10397. * }
  10398. *
  10399. * function draw() {
  10400. * ellipse(width/2, height/2, d, d);
  10401. * }
  10402. *
  10403. * function changeGray() {
  10404. * d = d + 10;
  10405. * if (d > 100) {
  10406. * d = 0;
  10407. * }
  10408. * }
  10409. * </code></div>
  10410. *
  10411. * @alt
  10412. * no display.
  10413. *
  10414. */
  10415. p5.Element.prototype.mouseOut = function (fxn) {
  10416. attachListener('mouseout', fxn, this);
  10417. return this;
  10418. };
  10419. /**
  10420. * The .touchStarted() function is called once after every time a touch is
  10421. * registered. This can be used to attach element specific event listeners.
  10422. *
  10423. * @method touchStarted
  10424. * @param {Function} fxn function to be fired when touch is
  10425. * started over the element.
  10426. * @return {p5.Element}
  10427. * @example
  10428. * <div class='norender'><code>
  10429. * var cnv;
  10430. * var d;
  10431. * var g;
  10432. * function setup() {
  10433. * cnv = createCanvas(100, 100);
  10434. * cnv.touchStarted(changeGray); // attach listener for
  10435. * // canvas click only
  10436. * d = 10;
  10437. * g = 100;
  10438. * }
  10439. *
  10440. * function draw() {
  10441. * background(g);
  10442. * ellipse(width/2, height/2, d, d);
  10443. * }
  10444. *
  10445. * // this function fires with any touch anywhere
  10446. * function touchStarted() {
  10447. * d = d + 10;
  10448. * }
  10449. *
  10450. * // this function fires only when cnv is clicked
  10451. * function changeGray() {
  10452. * g = random(0, 255);
  10453. * }
  10454. * </code></div>
  10455. *
  10456. * @alt
  10457. * no display.
  10458. *
  10459. */
  10460. p5.Element.prototype.touchStarted = function (fxn) {
  10461. attachListener('touchstart', fxn, this);
  10462. attachListener('mousedown', fxn, this);
  10463. return this;
  10464. };
  10465. /**
  10466. * The .touchMoved() function is called once after every time a touch move is
  10467. * registered. This can be used to attach element specific event listeners.
  10468. *
  10469. * @method touchMoved
  10470. * @param {Function} fxn function to be fired when touch is moved
  10471. * over the element.
  10472. * @return {p5.Element}
  10473. * @example
  10474. * <div class='norender'><code>
  10475. * var cnv;
  10476. * var g;
  10477. * function setup() {
  10478. * cnv = createCanvas(100, 100);
  10479. * cnv.touchMoved(changeGray); // attach listener for
  10480. * // canvas click only
  10481. * g = 100;
  10482. * }
  10483. *
  10484. * function draw() {
  10485. * background(g);
  10486. * }
  10487. *
  10488. * // this function fires only when cnv is clicked
  10489. * function changeGray() {
  10490. * g = random(0, 255);
  10491. * }
  10492. * </code></div>
  10493. *
  10494. * @alt
  10495. * no display.
  10496. *
  10497. */
  10498. p5.Element.prototype.touchMoved = function (fxn) {
  10499. attachListener('touchmove', fxn, this);
  10500. attachListener('mousemove', fxn, this);
  10501. return this;
  10502. };
  10503. /**
  10504. * The .touchEnded() function is called once after every time a touch is
  10505. * registered. This can be used to attach element specific event listeners.
  10506. *
  10507. * @method touchEnded
  10508. * @param {Function} fxn function to be fired when touch is
  10509. * ended over the element.
  10510. * @return {p5.Element}
  10511. * @example
  10512. * <div class='norender'><code>
  10513. * var cnv;
  10514. * var d;
  10515. * var g;
  10516. * function setup() {
  10517. * cnv = createCanvas(100, 100);
  10518. * cnv.touchEnded(changeGray); // attach listener for
  10519. * // canvas click only
  10520. * d = 10;
  10521. * g = 100;
  10522. * }
  10523. *
  10524. * function draw() {
  10525. * background(g);
  10526. * ellipse(width/2, height/2, d, d);
  10527. * }
  10528. *
  10529. * // this function fires with any touch anywhere
  10530. * function touchEnded() {
  10531. * d = d + 10;
  10532. * }
  10533. *
  10534. * // this function fires only when cnv is clicked
  10535. * function changeGray() {
  10536. * g = random(0, 255);
  10537. * }
  10538. * </code></div>
  10539. *
  10540. *
  10541. * @alt
  10542. * no display.
  10543. *
  10544. */
  10545. p5.Element.prototype.touchEnded = function (fxn) {
  10546. attachListener('touchend', fxn, this);
  10547. attachListener('mouseup', fxn, this);
  10548. return this;
  10549. };
  10550. /**
  10551. * The .dragOver() function is called once after every time a
  10552. * file is dragged over the element. This can be used to attach an
  10553. * element specific event listener.
  10554. *
  10555. * @method dragOver
  10556. * @param {Function} fxn function to be fired when mouse is
  10557. * dragged over the element.
  10558. * @return {p5.Element}
  10559. */
  10560. p5.Element.prototype.dragOver = function (fxn) {
  10561. attachListener('dragover', fxn, this);
  10562. return this;
  10563. };
  10564. /**
  10565. * The .dragLeave() function is called once after every time a
  10566. * dragged file leaves the element area. This can be used to attach an
  10567. * element specific event listener.
  10568. *
  10569. * @method dragLeave
  10570. * @param {Function} fxn function to be fired when mouse is
  10571. * dragged over the element.
  10572. * @return {p5.Element}
  10573. */
  10574. p5.Element.prototype.dragLeave = function (fxn) {
  10575. attachListener('dragleave', fxn, this);
  10576. return this;
  10577. };
  10578. /**
  10579. * The .drop() function is called for each file dropped on the element.
  10580. * It requires a callback that is passed a p5.File object. You can
  10581. * optionally pass two callbacks, the first one (required) is triggered
  10582. * for each file dropped when the file is loaded. The second (optional)
  10583. * is triggered just once when a file (or files) are dropped.
  10584. *
  10585. * @method drop
  10586. * @param {Function} callback triggered when files are dropped.
  10587. * @param {Function} callback to receive loaded file.
  10588. * @return {p5.Element}
  10589. * @example
  10590. * <div><code>
  10591. * function setup() {
  10592. * var c = createCanvas(100, 100);
  10593. * background(200);
  10594. * textAlign(CENTER);
  10595. * text('drop image', width/2, height/2);
  10596. * c.drop(gotFile);
  10597. * }
  10598. *
  10599. * function gotFile(file) {
  10600. * var img = createImg(file.data).hide();
  10601. * // Draw the image onto the canvas
  10602. * image(img, 0, 0, width, height);
  10603. * }
  10604. * </code></div>
  10605. *
  10606. * @alt
  10607. * Canvas turns into whatever image is dragged/dropped onto it.
  10608. *
  10609. */
  10610. p5.Element.prototype.drop = function (callback, fxn) {
  10611. // Make a file loader callback and trigger user's callback
  10612. function makeLoader(theFile) {
  10613. // Making a p5.File object
  10614. var p5file = new p5.File(theFile);
  10615. return function(e) {
  10616. p5file.data = e.target.result;
  10617. callback(p5file);
  10618. };
  10619. }
  10620. // Is the file stuff supported?
  10621. if (window.File && window.FileReader && window.FileList && window.Blob) {
  10622. // If you want to be able to drop you've got to turn off
  10623. // a lot of default behavior
  10624. attachListener('dragover',function(evt) {
  10625. evt.stopPropagation();
  10626. evt.preventDefault();
  10627. },this);
  10628. // If this is a drag area we need to turn off the default behavior
  10629. attachListener('dragleave',function(evt) {
  10630. evt.stopPropagation();
  10631. evt.preventDefault();
  10632. },this);
  10633. // If just one argument it's the callback for the files
  10634. if (arguments.length > 1) {
  10635. attachListener('drop', fxn, this);
  10636. }
  10637. // Deal with the files
  10638. attachListener('drop', function(evt) {
  10639. evt.stopPropagation();
  10640. evt.preventDefault();
  10641. // A FileList
  10642. var files = evt.dataTransfer.files;
  10643. // Load each one and trigger the callback
  10644. for (var i = 0; i < files.length; i++) {
  10645. var f = files[i];
  10646. var reader = new FileReader();
  10647. reader.onload = makeLoader(f);
  10648. // Text or data?
  10649. // This should likely be improved
  10650. if (f.type.indexOf('text') > -1) {
  10651. reader.readAsText(f);
  10652. } else {
  10653. reader.readAsDataURL(f);
  10654. }
  10655. }
  10656. }, this);
  10657. } else {
  10658. console.log('The File APIs are not fully supported in this browser.');
  10659. }
  10660. return this;
  10661. };
  10662. function attachListener(ev, fxn, ctx) {
  10663. // LM removing, not sure why we had this?
  10664. // var _this = ctx;
  10665. // var f = function (e) { fxn(e, _this); };
  10666. var f = fxn.bind(ctx);
  10667. ctx.elt.addEventListener(ev, f, false);
  10668. ctx._events[ev] = f;
  10669. }
  10670. /**
  10671. * Helper fxn for sharing pixel methods
  10672. *
  10673. */
  10674. p5.Element.prototype._setProperty = function (prop, value) {
  10675. this[prop] = value;
  10676. };
  10677. module.exports = p5.Element;
  10678. },{"./core":37}],42:[function(_dereq_,module,exports){
  10679. /**
  10680. * @module Rendering
  10681. * @submodule Rendering
  10682. * @for p5
  10683. */
  10684. var p5 = _dereq_('./core');
  10685. var constants = _dereq_('./constants');
  10686. /**
  10687. * Thin wrapper around a renderer, to be used for creating a
  10688. * graphics buffer object. Use this class if you need
  10689. * to draw into an off-screen graphics buffer. The two parameters define the
  10690. * width and height in pixels. The fields and methods for this class are
  10691. * extensive, but mirror the normal drawing API for p5.
  10692. *
  10693. * @class p5.Graphics
  10694. * @constructor
  10695. * @extends p5.Element
  10696. * @param {String} elt DOM node that is wrapped
  10697. * @param {Object} [pInst] pointer to p5 instance
  10698. * @param {Boolean} whether we're using it as main canvas
  10699. */
  10700. p5.Graphics = function(w, h, renderer, pInst) {
  10701. var r = renderer || constants.P2D;
  10702. var c = document.createElement('canvas');
  10703. var node = this._userNode || document.body;
  10704. node.appendChild(c);
  10705. p5.Element.call(this, c, pInst, false);
  10706. this._styles = [];
  10707. this.width = w;
  10708. this.height = h;
  10709. this._pixelDensity = pInst._pixelDensity;
  10710. if (r === constants.WEBGL) {
  10711. this._renderer = new p5.RendererGL(c, this, false);
  10712. } else {
  10713. this._renderer = new p5.Renderer2D(c, this, false);
  10714. }
  10715. this._renderer.resize(w, h);
  10716. this._renderer._applyDefaults();
  10717. pInst._elements.push(this);
  10718. // bind methods and props of p5 to the new object
  10719. for (var p in p5.prototype) {
  10720. if (!this[p]) {
  10721. if (typeof p5.prototype[p] === 'function') {
  10722. this[p] = p5.prototype[p].bind(this);
  10723. } else {
  10724. this[p] = p5.prototype[p];
  10725. }
  10726. }
  10727. }
  10728. return this;
  10729. };
  10730. p5.Graphics.prototype = Object.create(p5.Element.prototype);
  10731. p5.Graphics.prototype.remove = function() {
  10732. if (this.elt.parentNode) {
  10733. this.elt.parentNode.removeChild(this.elt);
  10734. }
  10735. for (var elt_ev in this._events) {
  10736. this.elt.removeEventListener(elt_ev, this._events[elt_ev]);
  10737. }
  10738. };
  10739. module.exports = p5.Graphics;
  10740. },{"./constants":36,"./core":37}],43:[function(_dereq_,module,exports){
  10741. /**
  10742. * @module Rendering
  10743. * @submodule Rendering
  10744. * @for p5
  10745. */
  10746. var p5 = _dereq_('./core');
  10747. var constants = _dereq_('../core/constants');
  10748. /**
  10749. * Main graphics and rendering context, as well as the base API
  10750. * implementation for p5.js "core". To be used as the superclass for
  10751. * Renderer2D and Renderer3D classes, respecitvely.
  10752. *
  10753. * @class p5.Renderer
  10754. * @constructor
  10755. * @extends p5.Element
  10756. * @param {String} elt DOM node that is wrapped
  10757. * @param {Object} [pInst] pointer to p5 instance
  10758. * @param {Boolean} whether we're using it as main canvas
  10759. */
  10760. p5.Renderer = function(elt, pInst, isMainCanvas) {
  10761. p5.Element.call(this, elt, pInst);
  10762. this.canvas = elt;
  10763. this._pInst = pInst;
  10764. if (isMainCanvas) {
  10765. this._isMainCanvas = true;
  10766. // for pixel method sharing with pimage
  10767. this._pInst._setProperty('_curElement', this);
  10768. this._pInst._setProperty('canvas', this.canvas);
  10769. this._pInst._setProperty('width', this.width);
  10770. this._pInst._setProperty('height', this.height);
  10771. } else { // hide if offscreen buffer by default
  10772. this.canvas.style.display = 'none';
  10773. this._styles = []; // non-main elt styles stored in p5.Renderer
  10774. }
  10775. this._textSize = 12;
  10776. this._textLeading = 15;
  10777. this._textFont = 'sans-serif';
  10778. this._textStyle = constants.NORMAL;
  10779. this._textAscent = null;
  10780. this._textDescent = null;
  10781. this._rectMode = constants.CORNER;
  10782. this._ellipseMode = constants.CENTER;
  10783. this._curveTightness = 0;
  10784. this._imageMode = constants.CORNER;
  10785. this._tint = null;
  10786. this._doStroke = true;
  10787. this._doFill = true;
  10788. this._strokeSet = false;
  10789. this._fillSet = false;
  10790. this._colorMode = constants.RGB;
  10791. this._colorMaxes = {
  10792. rgb: [255, 255, 255, 255],
  10793. hsb: [360, 100, 100, 1],
  10794. hsl: [360, 100, 100, 1]
  10795. };
  10796. };
  10797. p5.Renderer.prototype = Object.create(p5.Element.prototype);
  10798. /**
  10799. * Resize our canvas element.
  10800. */
  10801. p5.Renderer.prototype.resize = function(w, h) {
  10802. this.width = w;
  10803. this.height = h;
  10804. this.elt.width = w * this._pInst._pixelDensity;
  10805. this.elt.height = h * this._pInst._pixelDensity;
  10806. this.elt.style.width = w +'px';
  10807. this.elt.style.height = h + 'px';
  10808. if (this._isMainCanvas) {
  10809. this._pInst._setProperty('width', this.width);
  10810. this._pInst._setProperty('height', this.height);
  10811. }
  10812. };
  10813. p5.Renderer.prototype.textLeading = function(l) {
  10814. if (arguments.length && arguments[0]) {
  10815. this._setProperty('_textLeading', l);
  10816. return this;
  10817. }
  10818. return this._textLeading;
  10819. };
  10820. p5.Renderer.prototype.textSize = function(s) {
  10821. if (arguments.length && arguments[0]) {
  10822. this._setProperty('_textSize', s);
  10823. this._setProperty('_textLeading', s * constants._DEFAULT_LEADMULT);
  10824. return this._applyTextProperties();
  10825. }
  10826. return this._textSize;
  10827. };
  10828. p5.Renderer.prototype.textStyle = function(s) {
  10829. if (arguments.length && arguments[0]) {
  10830. if (s === constants.NORMAL ||
  10831. s === constants.ITALIC ||
  10832. s === constants.BOLD) {
  10833. this._setProperty('_textStyle', s);
  10834. }
  10835. return this._applyTextProperties();
  10836. }
  10837. return this._textStyle;
  10838. };
  10839. p5.Renderer.prototype.textAscent = function() {
  10840. if (this._textAscent === null) {
  10841. this._updateTextMetrics();
  10842. }
  10843. return this._textAscent;
  10844. };
  10845. p5.Renderer.prototype.textDescent = function() {
  10846. if (this._textDescent === null) {
  10847. this._updateTextMetrics();
  10848. }
  10849. return this._textDescent;
  10850. };
  10851. p5.Renderer.prototype._applyDefaults = function(){
  10852. return this;
  10853. };
  10854. /**
  10855. * Helper fxn to check font type (system or otf)
  10856. */
  10857. p5.Renderer.prototype._isOpenType = function(f) {
  10858. f = f || this._textFont;
  10859. return (typeof f === 'object' && f.font && f.font.supported);
  10860. };
  10861. p5.Renderer.prototype._updateTextMetrics = function() {
  10862. if (this._isOpenType()) {
  10863. this._setProperty('_textAscent', this._textFont._textAscent());
  10864. this._setProperty('_textDescent', this._textFont._textDescent());
  10865. return this;
  10866. }
  10867. // Adapted from http://stackoverflow.com/a/25355178
  10868. var text = document.createElement('span');
  10869. text.style.fontFamily = this._textFont;
  10870. text.style.fontSize = this._textSize + 'px';
  10871. text.innerHTML = 'ABCjgq|';
  10872. var block = document.createElement('div');
  10873. block.style.display = 'inline-block';
  10874. block.style.width = '1px';
  10875. block.style.height = '0px';
  10876. var container = document.createElement('div');
  10877. container.appendChild(text);
  10878. container.appendChild(block);
  10879. container.style.height = '0px';
  10880. container.style.overflow = 'hidden';
  10881. document.body.appendChild(container);
  10882. block.style.verticalAlign = 'baseline';
  10883. var blockOffset = calculateOffset(block);
  10884. var textOffset = calculateOffset(text);
  10885. var ascent = blockOffset[1] - textOffset[1];
  10886. block.style.verticalAlign = 'bottom';
  10887. blockOffset = calculateOffset(block);
  10888. textOffset = calculateOffset(text);
  10889. var height = blockOffset[1] - textOffset[1];
  10890. var descent = height - ascent;
  10891. document.body.removeChild(container);
  10892. this._setProperty('_textAscent', ascent);
  10893. this._setProperty('_textDescent', descent);
  10894. return this;
  10895. };
  10896. /**
  10897. * Helper fxn to measure ascent and descent.
  10898. * Adapted from http://stackoverflow.com/a/25355178
  10899. */
  10900. function calculateOffset(object) {
  10901. var currentLeft = 0,
  10902. currentTop = 0;
  10903. if (object.offsetParent) {
  10904. do {
  10905. currentLeft += object.offsetLeft;
  10906. currentTop += object.offsetTop;
  10907. } while (object = object.offsetParent);
  10908. } else {
  10909. currentLeft += object.offsetLeft;
  10910. currentTop += object.offsetTop;
  10911. }
  10912. return [currentLeft, currentTop];
  10913. }
  10914. module.exports = p5.Renderer;
  10915. },{"../core/constants":36,"./core":37}],44:[function(_dereq_,module,exports){
  10916. var p5 = _dereq_('./core');
  10917. var canvas = _dereq_('./canvas');
  10918. var constants = _dereq_('./constants');
  10919. var filters = _dereq_('../image/filters');
  10920. _dereq_('./p5.Renderer');
  10921. /**
  10922. * p5.Renderer2D
  10923. * The 2D graphics canvas renderer class.
  10924. * extends p5.Renderer
  10925. */
  10926. var styleEmpty = 'rgba(0,0,0,0)';
  10927. // var alphaThreshold = 0.00125; // minimum visible
  10928. p5.Renderer2D = function(elt, pInst, isMainCanvas){
  10929. p5.Renderer.call(this, elt, pInst, isMainCanvas);
  10930. this.drawingContext = this.canvas.getContext('2d');
  10931. this._pInst._setProperty('drawingContext', this.drawingContext);
  10932. return this;
  10933. };
  10934. p5.Renderer2D.prototype = Object.create(p5.Renderer.prototype);
  10935. p5.Renderer2D.prototype._applyDefaults = function() {
  10936. this.drawingContext.fillStyle = constants._DEFAULT_FILL;
  10937. this.drawingContext.strokeStyle = constants._DEFAULT_STROKE;
  10938. this.drawingContext.lineCap = constants.ROUND;
  10939. this.drawingContext.font = 'normal 12px sans-serif';
  10940. };
  10941. p5.Renderer2D.prototype.resize = function(w,h) {
  10942. p5.Renderer.prototype.resize.call(this, w,h);
  10943. this.drawingContext.scale(this._pInst._pixelDensity,
  10944. this._pInst._pixelDensity);
  10945. };
  10946. //////////////////////////////////////////////
  10947. // COLOR | Setting
  10948. //////////////////////////////////////////////
  10949. p5.Renderer2D.prototype.background = function() {
  10950. this.drawingContext.save();
  10951. this.drawingContext.setTransform(1, 0, 0, 1, 0, 0);
  10952. this.drawingContext.scale(this._pInst._pixelDensity,
  10953. this._pInst._pixelDensity);
  10954. if (arguments[0] instanceof p5.Image) {
  10955. this._pInst.image(arguments[0], 0, 0, this.width, this.height);
  10956. } else {
  10957. var curFill = this.drawingContext.fillStyle;
  10958. // create background rect
  10959. var color = this._pInst.color.apply(this, arguments);
  10960. var newFill = color.toString();
  10961. this.drawingContext.fillStyle = newFill;
  10962. this.drawingContext.fillRect(0, 0, this.width, this.height);
  10963. // reset fill
  10964. this.drawingContext.fillStyle = curFill;
  10965. }
  10966. this.drawingContext.restore();
  10967. };
  10968. p5.Renderer2D.prototype.clear = function() {
  10969. this.drawingContext.clearRect(0, 0, this.width, this.height);
  10970. };
  10971. p5.Renderer2D.prototype.fill = function() {
  10972. var ctx = this.drawingContext;
  10973. var color = this._pInst.color.apply(this, arguments);
  10974. ctx.fillStyle = color.toString();
  10975. };
  10976. p5.Renderer2D.prototype.stroke = function() {
  10977. var ctx = this.drawingContext;
  10978. var color = this._pInst.color.apply(this, arguments);
  10979. ctx.strokeStyle = color.toString();
  10980. };
  10981. //////////////////////////////////////////////
  10982. // IMAGE | Loading & Displaying
  10983. //////////////////////////////////////////////
  10984. p5.Renderer2D.prototype.image =
  10985. function (img, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight) {
  10986. var cnv;
  10987. try {
  10988. if (this._tint) {
  10989. if (p5.MediaElement && img instanceof p5.MediaElement) {
  10990. img.loadPixels();
  10991. }
  10992. if (img.canvas) {
  10993. cnv = this._getTintedImageCanvas(img);
  10994. }
  10995. }
  10996. if (!cnv) {
  10997. cnv = img.canvas || img.elt;
  10998. }
  10999. this.drawingContext.drawImage(cnv, sx, sy, sWidth, sHeight, dx, dy,
  11000. dWidth, dHeight);
  11001. } catch (e) {
  11002. if (e.name !== 'NS_ERROR_NOT_AVAILABLE') {
  11003. throw e;
  11004. }
  11005. }
  11006. };
  11007. p5.Renderer2D.prototype._getTintedImageCanvas = function (img) {
  11008. if (!img.canvas) {
  11009. return img;
  11010. }
  11011. var pixels = filters._toPixels(img.canvas);
  11012. var tmpCanvas = document.createElement('canvas');
  11013. tmpCanvas.width = img.canvas.width;
  11014. tmpCanvas.height = img.canvas.height;
  11015. var tmpCtx = tmpCanvas.getContext('2d');
  11016. var id = tmpCtx.createImageData(img.canvas.width, img.canvas.height);
  11017. var newPixels = id.data;
  11018. for (var i = 0; i < pixels.length; i += 4) {
  11019. var r = pixels[i];
  11020. var g = pixels[i + 1];
  11021. var b = pixels[i + 2];
  11022. var a = pixels[i + 3];
  11023. newPixels[i] = r * this._tint[0] / 255;
  11024. newPixels[i + 1] = g * this._tint[1] / 255;
  11025. newPixels[i + 2] = b * this._tint[2] / 255;
  11026. newPixels[i + 3] = a * this._tint[3] / 255;
  11027. }
  11028. tmpCtx.putImageData(id, 0, 0);
  11029. return tmpCanvas;
  11030. };
  11031. //////////////////////////////////////////////
  11032. // IMAGE | Pixels
  11033. //////////////////////////////////////////////
  11034. p5.Renderer2D.prototype.blendMode = function(mode) {
  11035. this.drawingContext.globalCompositeOperation = mode;
  11036. };
  11037. p5.Renderer2D.prototype.blend = function() {
  11038. var currBlend = this.drawingContext.globalCompositeOperation;
  11039. var blendMode = arguments[arguments.length - 1];
  11040. var copyArgs = Array.prototype.slice.call(
  11041. arguments,
  11042. 0,
  11043. arguments.length - 1
  11044. );
  11045. this.drawingContext.globalCompositeOperation = blendMode;
  11046. if (this._pInst) {
  11047. this._pInst.copy.apply(this._pInst, copyArgs);
  11048. } else {
  11049. this.copy.apply(this, copyArgs);
  11050. }
  11051. this.drawingContext.globalCompositeOperation = currBlend;
  11052. };
  11053. p5.Renderer2D.prototype.copy = function () {
  11054. var srcImage, sx, sy, sw, sh, dx, dy, dw, dh;
  11055. if (arguments.length === 9) {
  11056. srcImage = arguments[0];
  11057. sx = arguments[1];
  11058. sy = arguments[2];
  11059. sw = arguments[3];
  11060. sh = arguments[4];
  11061. dx = arguments[5];
  11062. dy = arguments[6];
  11063. dw = arguments[7];
  11064. dh = arguments[8];
  11065. } else if (arguments.length === 8) {
  11066. srcImage = this._pInst;
  11067. sx = arguments[0];
  11068. sy = arguments[1];
  11069. sw = arguments[2];
  11070. sh = arguments[3];
  11071. dx = arguments[4];
  11072. dy = arguments[5];
  11073. dw = arguments[6];
  11074. dh = arguments[7];
  11075. } else {
  11076. throw new Error('Signature not supported');
  11077. }
  11078. p5.Renderer2D._copyHelper(srcImage, sx, sy, sw, sh, dx, dy, dw, dh);
  11079. };
  11080. p5.Renderer2D._copyHelper =
  11081. function (srcImage, sx, sy, sw, sh, dx, dy, dw, dh) {
  11082. srcImage.loadPixels();
  11083. var s = srcImage.canvas.width / srcImage.width;
  11084. this.drawingContext.drawImage(srcImage.canvas,
  11085. s * sx, s * sy, s * sw, s * sh, dx, dy, dw, dh);
  11086. };
  11087. p5.Renderer2D.prototype.get = function(x, y, w, h) {
  11088. if (x === undefined && y === undefined &&
  11089. w === undefined && h === undefined){
  11090. x = 0;
  11091. y = 0;
  11092. w = this.width;
  11093. h = this.height;
  11094. } else if (w === undefined && h === undefined) {
  11095. w = 1;
  11096. h = 1;
  11097. }
  11098. // if the section does not overlap the canvas
  11099. if(x + w < 0 || y + h < 0 || x > this.width || y > this.height){
  11100. return [0, 0, 0, 255];
  11101. }
  11102. var ctx = this._pInst || this;
  11103. ctx.loadPixels();
  11104. var pd = ctx._pixelDensity;
  11105. // round down to get integer numbers
  11106. x = Math.floor(x);
  11107. y = Math.floor(y);
  11108. w = Math.floor(w);
  11109. h = Math.floor(h);
  11110. var sx = x * pd;
  11111. var sy = y * pd;
  11112. if (w === 1 && h === 1){
  11113. var imageData = this.drawingContext.getImageData(sx, sy, 1, 1).data;
  11114. //imageData = [0,0,0,0];
  11115. return [
  11116. imageData[0],
  11117. imageData[1],
  11118. imageData[2],
  11119. imageData[3]
  11120. ];
  11121. } else {
  11122. //auto constrain the width and height to
  11123. //dimensions of the source image
  11124. var dw = Math.min(w, ctx.width);
  11125. var dh = Math.min(h, ctx.height);
  11126. var sw = dw * pd;
  11127. var sh = dh * pd;
  11128. var region = new p5.Image(dw, dh);
  11129. region.canvas.getContext('2d').drawImage(this.canvas, sx, sy, sw, sh,
  11130. 0, 0, dw, dh);
  11131. return region;
  11132. }
  11133. };
  11134. p5.Renderer2D.prototype.loadPixels = function () {
  11135. var pd = this._pixelDensity || this._pInst._pixelDensity;
  11136. var w = this.width * pd;
  11137. var h = this.height * pd;
  11138. var imageData = this.drawingContext.getImageData(0, 0, w, h);
  11139. // @todo this should actually set pixels per object, so diff buffers can
  11140. // have diff pixel arrays.
  11141. if (this._pInst) {
  11142. this._pInst._setProperty('imageData', imageData);
  11143. this._pInst._setProperty('pixels', imageData.data);
  11144. } else { // if called by p5.Image
  11145. this._setProperty('imageData', imageData);
  11146. this._setProperty('pixels', imageData.data);
  11147. }
  11148. };
  11149. p5.Renderer2D.prototype.set = function (x, y, imgOrCol) {
  11150. // round down to get integer numbers
  11151. x = Math.floor(x);
  11152. y = Math.floor(y);
  11153. if (imgOrCol instanceof p5.Image) {
  11154. this.drawingContext.save();
  11155. this.drawingContext.setTransform(1, 0, 0, 1, 0, 0);
  11156. this.drawingContext.scale(this._pInst._pixelDensity,
  11157. this._pInst._pixelDensity);
  11158. this.drawingContext.drawImage(imgOrCol.canvas, x, y);
  11159. this.loadPixels.call(this._pInst);
  11160. this.drawingContext.restore();
  11161. } else {
  11162. var ctx = this._pInst || this;
  11163. var r = 0, g = 0, b = 0, a = 0;
  11164. var idx = 4*((y * ctx._pixelDensity) *
  11165. (this.width * ctx._pixelDensity) + (x * ctx._pixelDensity));
  11166. if (!ctx.imageData) {
  11167. ctx.loadPixels.call(ctx);
  11168. }
  11169. if (typeof imgOrCol === 'number') {
  11170. if (idx < ctx.pixels.length) {
  11171. r = imgOrCol;
  11172. g = imgOrCol;
  11173. b = imgOrCol;
  11174. a = 255;
  11175. //this.updatePixels.call(this);
  11176. }
  11177. }
  11178. else if (imgOrCol instanceof Array) {
  11179. if (imgOrCol.length < 4) {
  11180. throw new Error('pixel array must be of the form [R, G, B, A]');
  11181. }
  11182. if (idx < ctx.pixels.length) {
  11183. r = imgOrCol[0];
  11184. g = imgOrCol[1];
  11185. b = imgOrCol[2];
  11186. a = imgOrCol[3];
  11187. //this.updatePixels.call(this);
  11188. }
  11189. } else if (imgOrCol instanceof p5.Color) {
  11190. if (idx < ctx.pixels.length) {
  11191. r = imgOrCol.levels[0];
  11192. g = imgOrCol.levels[1];
  11193. b = imgOrCol.levels[2];
  11194. a = imgOrCol.levels[3];
  11195. //this.updatePixels.call(this);
  11196. }
  11197. }
  11198. // loop over pixelDensity * pixelDensity
  11199. for (var i = 0; i < ctx._pixelDensity; i++) {
  11200. for (var j = 0; j < ctx._pixelDensity; j++) {
  11201. // loop over
  11202. idx = 4*((y * ctx._pixelDensity + j) * this.width *
  11203. ctx._pixelDensity + (x * ctx._pixelDensity + i));
  11204. ctx.pixels[idx] = r;
  11205. ctx.pixels[idx+1] = g;
  11206. ctx.pixels[idx+2] = b;
  11207. ctx.pixels[idx+3] = a;
  11208. }
  11209. }
  11210. }
  11211. };
  11212. p5.Renderer2D.prototype.updatePixels = function (x, y, w, h) {
  11213. var pd = this._pixelDensity || this._pInst._pixelDensity;
  11214. if (x === undefined &&
  11215. y === undefined &&
  11216. w === undefined &&
  11217. h === undefined) {
  11218. x = 0;
  11219. y = 0;
  11220. w = this.width;
  11221. h = this.height;
  11222. }
  11223. w *= pd;
  11224. h *= pd;
  11225. if (this._pInst) {
  11226. this.drawingContext.putImageData(this._pInst.imageData, x, y, 0, 0, w, h);
  11227. } else {
  11228. this.drawingContext.putImageData(this.imageData, x, y, 0, 0, w, h);
  11229. }
  11230. };
  11231. //////////////////////////////////////////////
  11232. // SHAPE | 2D Primitives
  11233. //////////////////////////////////////////////
  11234. /**
  11235. * Generate a cubic Bezier representing an arc on the unit circle of total
  11236. * angle `size` radians, beginning `start` radians above the x-axis. Up to
  11237. * four of these curves are combined to make a full arc.
  11238. *
  11239. * See www.joecridge.me/bezier.pdf for an explanation of the method.
  11240. */
  11241. p5.Renderer2D.prototype._acuteArcToBezier =
  11242. function _acuteArcToBezier(start, size) {
  11243. // Evauate constants.
  11244. var alpha = size / 2.0,
  11245. cos_alpha = Math.cos(alpha),
  11246. sin_alpha = Math.sin(alpha),
  11247. cot_alpha = 1.0 / Math.tan(alpha),
  11248. phi = start + alpha, // This is how far the arc needs to be rotated.
  11249. cos_phi = Math.cos(phi),
  11250. sin_phi = Math.sin(phi),
  11251. lambda = (4.0 - cos_alpha) / 3.0,
  11252. mu = sin_alpha + (cos_alpha - lambda) * cot_alpha;
  11253. // Return rotated waypoints.
  11254. return {
  11255. ax: Math.cos(start),
  11256. ay: Math.sin(start),
  11257. bx: lambda * cos_phi + mu * sin_phi,
  11258. by: lambda * sin_phi - mu * cos_phi,
  11259. cx: lambda * cos_phi - mu * sin_phi,
  11260. cy: lambda * sin_phi + mu * cos_phi,
  11261. dx: Math.cos(start + size),
  11262. dy: Math.sin(start + size)
  11263. };
  11264. };
  11265. p5.Renderer2D.prototype.arc =
  11266. function(x, y, w, h, start, stop, mode) {
  11267. var ctx = this.drawingContext;
  11268. var vals = canvas.arcModeAdjust(x, y, w, h, this._ellipseMode);
  11269. var rx = vals.w / 2.0;
  11270. var ry = vals.h / 2.0;
  11271. var epsilon = 0.00001; // Smallest visible angle on displays up to 4K.
  11272. var arcToDraw = 0;
  11273. var curves = [];
  11274. // Create curves
  11275. while(stop - start > epsilon) {
  11276. arcToDraw = Math.min(stop - start, constants.HALF_PI);
  11277. curves.push(this._acuteArcToBezier(start, arcToDraw));
  11278. start += arcToDraw;
  11279. }
  11280. // Fill curves
  11281. if (this._doFill) {
  11282. ctx.beginPath();
  11283. curves.forEach(function (curve, index) {
  11284. if (index === 0) {
  11285. ctx.moveTo(vals.x + curve.ax * rx, vals.y + curve.ay * ry);
  11286. }
  11287. ctx.bezierCurveTo(vals.x + curve.bx * rx, vals.y + curve.by * ry,
  11288. vals.x + curve.cx * rx, vals.y + curve.cy * ry,
  11289. vals.x + curve.dx * rx, vals.y + curve.dy * ry);
  11290. });
  11291. if (mode === constants.PIE || mode == null) {
  11292. ctx.lineTo(vals.x, vals.y);
  11293. }
  11294. ctx.closePath();
  11295. ctx.fill();
  11296. }
  11297. // Stroke curves
  11298. if (this._doStroke) {
  11299. ctx.beginPath();
  11300. curves.forEach(function (curve, index) {
  11301. if (index === 0) {
  11302. ctx.moveTo(vals.x + curve.ax * rx, vals.y + curve.ay * ry);
  11303. }
  11304. ctx.bezierCurveTo(vals.x + curve.bx * rx, vals.y + curve.by * ry,
  11305. vals.x + curve.cx * rx, vals.y + curve.cy * ry,
  11306. vals.x + curve.dx * rx, vals.y + curve.dy * ry);
  11307. });
  11308. if (mode === constants.PIE) {
  11309. ctx.lineTo(vals.x, vals.y);
  11310. ctx.closePath();
  11311. } else if (mode === constants.CHORD) {
  11312. ctx.closePath();
  11313. }
  11314. ctx.stroke();
  11315. }
  11316. return this;
  11317. };
  11318. p5.Renderer2D.prototype.ellipse = function(args) {
  11319. var ctx = this.drawingContext;
  11320. var doFill = this._doFill, doStroke = this._doStroke;
  11321. var x = args[0],
  11322. y = args[1],
  11323. w = args[2],
  11324. h = args[3];
  11325. if (doFill && !doStroke) {
  11326. if(ctx.fillStyle === styleEmpty) {
  11327. return this;
  11328. }
  11329. } else if (!doFill && doStroke) {
  11330. if(ctx.strokeStyle === styleEmpty) {
  11331. return this;
  11332. }
  11333. }
  11334. var kappa = 0.5522847498,
  11335. ox = (w / 2) * kappa, // control point offset horizontal
  11336. oy = (h / 2) * kappa, // control point offset vertical
  11337. xe = x + w, // x-end
  11338. ye = y + h, // y-end
  11339. xm = x + w / 2, // x-middle
  11340. ym = y + h / 2; // y-middle
  11341. ctx.beginPath();
  11342. ctx.moveTo(x, ym);
  11343. ctx.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y);
  11344. ctx.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym);
  11345. ctx.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye);
  11346. ctx.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym);
  11347. ctx.closePath();
  11348. if (doFill) {
  11349. ctx.fill();
  11350. }
  11351. if (doStroke) {
  11352. ctx.stroke();
  11353. }
  11354. };
  11355. p5.Renderer2D.prototype.line = function(x1, y1, x2, y2) {
  11356. var ctx = this.drawingContext;
  11357. if (!this._doStroke) {
  11358. return this;
  11359. } else if(ctx.strokeStyle === styleEmpty){
  11360. return this;
  11361. }
  11362. // Translate the line by (0.5, 0.5) to draw it crisp
  11363. if (ctx.lineWidth % 2 === 1) {
  11364. ctx.translate(0.5, 0.5);
  11365. }
  11366. ctx.beginPath();
  11367. ctx.moveTo(x1, y1);
  11368. ctx.lineTo(x2, y2);
  11369. ctx.stroke();
  11370. if (ctx.lineWidth % 2 === 1) {
  11371. ctx.translate(-0.5, -0.5);
  11372. }
  11373. return this;
  11374. };
  11375. p5.Renderer2D.prototype.point = function(x, y) {
  11376. var ctx = this.drawingContext;
  11377. var s = ctx.strokeStyle;
  11378. var f = ctx.fillStyle;
  11379. if (!this._doStroke) {
  11380. return this;
  11381. } else if(ctx.strokeStyle === styleEmpty){
  11382. return this;
  11383. }
  11384. x = Math.round(x);
  11385. y = Math.round(y);
  11386. ctx.fillStyle = s;
  11387. if (ctx.lineWidth > 1) {
  11388. ctx.beginPath();
  11389. ctx.arc(
  11390. x,
  11391. y,
  11392. ctx.lineWidth / 2,
  11393. 0,
  11394. constants.TWO_PI,
  11395. false
  11396. );
  11397. ctx.fill();
  11398. } else {
  11399. ctx.fillRect(x, y, 1, 1);
  11400. }
  11401. ctx.fillStyle = f;
  11402. };
  11403. p5.Renderer2D.prototype.quad =
  11404. function(x1, y1, x2, y2, x3, y3, x4, y4) {
  11405. var ctx = this.drawingContext;
  11406. var doFill = this._doFill, doStroke = this._doStroke;
  11407. if (doFill && !doStroke) {
  11408. if(ctx.fillStyle === styleEmpty) {
  11409. return this;
  11410. }
  11411. } else if (!doFill && doStroke) {
  11412. if(ctx.strokeStyle === styleEmpty) {
  11413. return this;
  11414. }
  11415. }
  11416. ctx.beginPath();
  11417. ctx.moveTo(x1, y1);
  11418. ctx.lineTo(x2, y2);
  11419. ctx.lineTo(x3, y3);
  11420. ctx.lineTo(x4, y4);
  11421. ctx.closePath();
  11422. if (doFill) {
  11423. ctx.fill();
  11424. }
  11425. if (doStroke) {
  11426. ctx.stroke();
  11427. }
  11428. return this;
  11429. };
  11430. p5.Renderer2D.prototype.rect = function(args) {
  11431. var x = args[0],
  11432. y = args[1],
  11433. w = args[2],
  11434. h = args[3],
  11435. tl = args[4],
  11436. tr = args[5],
  11437. br = args[6],
  11438. bl = args[7];
  11439. var ctx = this.drawingContext;
  11440. var doFill = this._doFill, doStroke = this._doStroke;
  11441. if (doFill && !doStroke) {
  11442. if(ctx.fillStyle === styleEmpty) {
  11443. return this;
  11444. }
  11445. } else if (!doFill && doStroke) {
  11446. if(ctx.strokeStyle === styleEmpty) {
  11447. return this;
  11448. }
  11449. }
  11450. // Translate the line by (0.5, 0.5) to draw a crisp rectangle border
  11451. if (this._doStroke && ctx.lineWidth % 2 === 1) {
  11452. ctx.translate(0.5, 0.5);
  11453. }
  11454. ctx.beginPath();
  11455. if (typeof tl === 'undefined') {
  11456. // No rounded corners
  11457. ctx.rect(x, y, w, h);
  11458. } else {
  11459. // At least one rounded corner
  11460. // Set defaults when not specified
  11461. if (typeof tr === 'undefined') { tr = tl; }
  11462. if (typeof br === 'undefined') { br = tr; }
  11463. if (typeof bl === 'undefined') { bl = br; }
  11464. var hw = w / 2;
  11465. var hh = h / 2;
  11466. // Clip radii
  11467. if (w < 2 * tl) { tl = hw; }
  11468. if (h < 2 * tl) { tl = hh; }
  11469. if (w < 2 * tr) { tr = hw; }
  11470. if (h < 2 * tr) { tr = hh; }
  11471. if (w < 2 * br) { br = hw; }
  11472. if (h < 2 * br) { br = hh; }
  11473. if (w < 2 * bl) { bl = hw; }
  11474. if (h < 2 * bl) { bl = hh; }
  11475. // Draw shape
  11476. ctx.beginPath();
  11477. ctx.moveTo(x + tl, y);
  11478. ctx.arcTo(x + w, y, x + w, y + h, tr);
  11479. ctx.arcTo(x + w, y + h, x, y + h, br);
  11480. ctx.arcTo(x, y + h, x, y, bl);
  11481. ctx.arcTo(x, y, x + w, y, tl);
  11482. ctx.closePath();
  11483. }
  11484. if (this._doFill) {
  11485. ctx.fill();
  11486. }
  11487. if (this._doStroke) {
  11488. ctx.stroke();
  11489. }
  11490. if (this._doStroke && ctx.lineWidth % 2 === 1) {
  11491. ctx.translate(-0.5, -0.5);
  11492. }
  11493. return this;
  11494. };
  11495. p5.Renderer2D.prototype.triangle = function(args) {
  11496. var ctx = this.drawingContext;
  11497. var doFill = this._doFill, doStroke = this._doStroke;
  11498. var x1=args[0], y1=args[1];
  11499. var x2=args[2], y2=args[3];
  11500. var x3=args[4], y3=args[5];
  11501. if (doFill && !doStroke) {
  11502. if(ctx.fillStyle === styleEmpty) {
  11503. return this;
  11504. }
  11505. } else if (!doFill && doStroke) {
  11506. if(ctx.strokeStyle === styleEmpty) {
  11507. return this;
  11508. }
  11509. }
  11510. ctx.beginPath();
  11511. ctx.moveTo(x1, y1);
  11512. ctx.lineTo(x2, y2);
  11513. ctx.lineTo(x3, y3);
  11514. ctx.closePath();
  11515. if (doFill) {
  11516. ctx.fill();
  11517. }
  11518. if (doStroke) {
  11519. ctx.stroke();
  11520. }
  11521. };
  11522. p5.Renderer2D.prototype.endShape =
  11523. function (mode, vertices, isCurve, isBezier,
  11524. isQuadratic, isContour, shapeKind) {
  11525. if (vertices.length === 0) {
  11526. return this;
  11527. }
  11528. if (!this._doStroke && !this._doFill) {
  11529. return this;
  11530. }
  11531. var closeShape = mode === constants.CLOSE;
  11532. var v;
  11533. if (closeShape && !isContour) {
  11534. vertices.push(vertices[0]);
  11535. }
  11536. var i, j;
  11537. var numVerts = vertices.length;
  11538. if (isCurve && (shapeKind === constants.POLYGON || shapeKind === null)) {
  11539. if (numVerts > 3) {
  11540. var b = [], s = 1 - this._curveTightness;
  11541. this.drawingContext.beginPath();
  11542. this.drawingContext.moveTo(vertices[1][0], vertices[1][1]);
  11543. for (i = 1; i + 2 < numVerts; i++) {
  11544. v = vertices[i];
  11545. b[0] = [
  11546. v[0],
  11547. v[1]
  11548. ];
  11549. b[1] = [
  11550. v[0] + (s * vertices[i + 1][0] - s * vertices[i - 1][0]) / 6,
  11551. v[1] + (s * vertices[i + 1][1] - s * vertices[i - 1][1]) / 6
  11552. ];
  11553. b[2] = [
  11554. vertices[i + 1][0] +
  11555. (s * vertices[i][0]-s * vertices[i + 2][0]) / 6,
  11556. vertices[i + 1][1]+(s * vertices[i][1] - s*vertices[i + 2][1]) / 6
  11557. ];
  11558. b[3] = [
  11559. vertices[i + 1][0],
  11560. vertices[i + 1][1]
  11561. ];
  11562. this.drawingContext.bezierCurveTo(b[1][0],b[1][1],
  11563. b[2][0],b[2][1],b[3][0],b[3][1]);
  11564. }
  11565. if (closeShape) {
  11566. this.drawingContext.lineTo(vertices[i + 1][0], vertices[i + 1][1]);
  11567. }
  11568. this._doFillStrokeClose();
  11569. }
  11570. } else if (isBezier&&(shapeKind===constants.POLYGON ||shapeKind === null)) {
  11571. this.drawingContext.beginPath();
  11572. for (i = 0; i < numVerts; i++) {
  11573. if (vertices[i].isVert) {
  11574. if (vertices[i].moveTo) {
  11575. this.drawingContext.moveTo(vertices[i][0], vertices[i][1]);
  11576. } else {
  11577. this.drawingContext.lineTo(vertices[i][0], vertices[i][1]);
  11578. }
  11579. } else {
  11580. this.drawingContext.bezierCurveTo(vertices[i][0], vertices[i][1],
  11581. vertices[i][2], vertices[i][3], vertices[i][4], vertices[i][5]);
  11582. }
  11583. }
  11584. this._doFillStrokeClose();
  11585. } else if (isQuadratic &&
  11586. (shapeKind === constants.POLYGON || shapeKind === null)) {
  11587. this.drawingContext.beginPath();
  11588. for (i = 0; i < numVerts; i++) {
  11589. if (vertices[i].isVert) {
  11590. if (vertices[i].moveTo) {
  11591. this.drawingContext.moveTo([0], vertices[i][1]);
  11592. } else {
  11593. this.drawingContext.lineTo(vertices[i][0], vertices[i][1]);
  11594. }
  11595. } else {
  11596. this.drawingContext.quadraticCurveTo(vertices[i][0], vertices[i][1],
  11597. vertices[i][2], vertices[i][3]);
  11598. }
  11599. }
  11600. this._doFillStrokeClose();
  11601. } else {
  11602. if (shapeKind === constants.POINTS) {
  11603. for (i = 0; i < numVerts; i++) {
  11604. v = vertices[i];
  11605. if (this._doStroke) {
  11606. this._pInst.stroke(v[6]);
  11607. }
  11608. this._pInst.point(v[0], v[1]);
  11609. }
  11610. } else if (shapeKind === constants.LINES) {
  11611. for (i = 0; i + 1 < numVerts; i += 2) {
  11612. v = vertices[i];
  11613. if (this._doStroke) {
  11614. this._pInst.stroke(vertices[i + 1][6]);
  11615. }
  11616. this._pInst.line(v[0], v[1], vertices[i + 1][0], vertices[i + 1][1]);
  11617. }
  11618. } else if (shapeKind === constants.TRIANGLES) {
  11619. for (i = 0; i + 2 < numVerts; i += 3) {
  11620. v = vertices[i];
  11621. this.drawingContext.beginPath();
  11622. this.drawingContext.moveTo(v[0], v[1]);
  11623. this.drawingContext.lineTo(vertices[i + 1][0], vertices[i + 1][1]);
  11624. this.drawingContext.lineTo(vertices[i + 2][0], vertices[i + 2][1]);
  11625. this.drawingContext.lineTo(v[0], v[1]);
  11626. if (this._doFill) {
  11627. this._pInst.fill(vertices[i + 2][5]);
  11628. this.drawingContext.fill();
  11629. }
  11630. if (this._doStroke) {
  11631. this._pInst.stroke(vertices[i + 2][6]);
  11632. this.drawingContext.stroke();
  11633. }
  11634. this.drawingContext.closePath();
  11635. }
  11636. } else if (shapeKind === constants.TRIANGLE_STRIP) {
  11637. for (i = 0; i + 1 < numVerts; i++) {
  11638. v = vertices[i];
  11639. this.drawingContext.beginPath();
  11640. this.drawingContext.moveTo(vertices[i + 1][0], vertices[i + 1][1]);
  11641. this.drawingContext.lineTo(v[0], v[1]);
  11642. if (this._doStroke) {
  11643. this._pInst.stroke(vertices[i + 1][6]);
  11644. }
  11645. if (this._doFill) {
  11646. this._pInst.fill(vertices[i + 1][5]);
  11647. }
  11648. if (i + 2 < numVerts) {
  11649. this.drawingContext.lineTo(vertices[i + 2][0], vertices[i + 2][1]);
  11650. if (this._doStroke) {
  11651. this._pInst.stroke(vertices[i + 2][6]);
  11652. }
  11653. if (this._doFill) {
  11654. this._pInst.fill(vertices[i + 2][5]);
  11655. }
  11656. }
  11657. this._doFillStrokeClose();
  11658. }
  11659. } else if (shapeKind === constants.TRIANGLE_FAN) {
  11660. if (numVerts > 2) {
  11661. this.drawingContext.beginPath();
  11662. this.drawingContext.moveTo(vertices[0][0], vertices[0][1]);
  11663. this.drawingContext.lineTo(vertices[1][0], vertices[1][1]);
  11664. this.drawingContext.lineTo(vertices[2][0], vertices[2][1]);
  11665. if (this._doFill) {
  11666. this._pInst.fill(vertices[2][5]);
  11667. }
  11668. if (this._doStroke) {
  11669. this._pInst.stroke(vertices[2][6]);
  11670. }
  11671. this._doFillStrokeClose();
  11672. for (i = 3; i < numVerts; i++) {
  11673. v = vertices[i];
  11674. this.drawingContext.beginPath();
  11675. this.drawingContext.moveTo(vertices[0][0], vertices[0][1]);
  11676. this.drawingContext.lineTo(vertices[i - 1][0], vertices[i - 1][1]);
  11677. this.drawingContext.lineTo(v[0], v[1]);
  11678. if (this._doFill) {
  11679. this._pInst.fill(v[5]);
  11680. }
  11681. if (this._doStroke) {
  11682. this._pInst.stroke(v[6]);
  11683. }
  11684. this._doFillStrokeClose();
  11685. }
  11686. }
  11687. } else if (shapeKind === constants.QUADS) {
  11688. for (i = 0; i + 3 < numVerts; i += 4) {
  11689. v = vertices[i];
  11690. this.drawingContext.beginPath();
  11691. this.drawingContext.moveTo(v[0], v[1]);
  11692. for (j = 1; j < 4; j++) {
  11693. this.drawingContext.lineTo(vertices[i + j][0], vertices[i + j][1]);
  11694. }
  11695. this.drawingContext.lineTo(v[0], v[1]);
  11696. if (this._doFill) {
  11697. this._pInst.fill(vertices[i + 3][5]);
  11698. }
  11699. if (this._doStroke) {
  11700. this._pInst.stroke(vertices[i + 3][6]);
  11701. }
  11702. this._doFillStrokeClose();
  11703. }
  11704. } else if (shapeKind === constants.QUAD_STRIP) {
  11705. if (numVerts > 3) {
  11706. for (i = 0; i + 1 < numVerts; i += 2) {
  11707. v = vertices[i];
  11708. this.drawingContext.beginPath();
  11709. if (i + 3 < numVerts) {
  11710. this.drawingContext.moveTo(vertices[i + 2][0], vertices[i+2][1]);
  11711. this.drawingContext.lineTo(v[0], v[1]);
  11712. this.drawingContext.lineTo(vertices[i + 1][0], vertices[i+1][1]);
  11713. this.drawingContext.lineTo(vertices[i + 3][0], vertices[i+3][1]);
  11714. if (this._doFill) {
  11715. this._pInst.fill(vertices[i + 3][5]);
  11716. }
  11717. if (this._doStroke) {
  11718. this._pInst.stroke(vertices[i + 3][6]);
  11719. }
  11720. } else {
  11721. this.drawingContext.moveTo(v[0], v[1]);
  11722. this.drawingContext.lineTo(vertices[i + 1][0], vertices[i+1][1]);
  11723. }
  11724. this._doFillStrokeClose();
  11725. }
  11726. }
  11727. } else {
  11728. this.drawingContext.beginPath();
  11729. this.drawingContext.moveTo(vertices[0][0], vertices[0][1]);
  11730. for (i = 1; i < numVerts; i++) {
  11731. v = vertices[i];
  11732. if (v.isVert) {
  11733. if (v.moveTo) {
  11734. this.drawingContext.moveTo(v[0], v[1]);
  11735. } else {
  11736. this.drawingContext.lineTo(v[0], v[1]);
  11737. }
  11738. }
  11739. }
  11740. this._doFillStrokeClose();
  11741. }
  11742. }
  11743. isCurve = false;
  11744. isBezier = false;
  11745. isQuadratic = false;
  11746. isContour = false;
  11747. if (closeShape) {
  11748. vertices.pop();
  11749. }
  11750. return this;
  11751. };
  11752. //////////////////////////////////////////////
  11753. // SHAPE | Attributes
  11754. //////////////////////////////////////////////
  11755. p5.Renderer2D.prototype.noSmooth = function() {
  11756. if ('imageSmoothingEnabled' in this.drawingContext) {
  11757. this.drawingContext.imageSmoothingEnabled = false;
  11758. }
  11759. else if ('mozImageSmoothingEnabled' in this.drawingContext) {
  11760. this.drawingContext.mozImageSmoothingEnabled = false;
  11761. }
  11762. else if ('webkitImageSmoothingEnabled' in this.drawingContext) {
  11763. this.drawingContext.webkitImageSmoothingEnabled = false;
  11764. }
  11765. else if ('msImageSmoothingEnabled' in this.drawingContext) {
  11766. this.drawingContext.msImageSmoothingEnabled = false;
  11767. }
  11768. return this;
  11769. };
  11770. p5.Renderer2D.prototype.smooth = function() {
  11771. if ('imageSmoothingEnabled' in this.drawingContext) {
  11772. this.drawingContext.imageSmoothingEnabled = true;
  11773. }
  11774. else if ('mozImageSmoothingEnabled' in this.drawingContext) {
  11775. this.drawingContext.mozImageSmoothingEnabled = true;
  11776. }
  11777. else if ('webkitImageSmoothingEnabled' in this.drawingContext) {
  11778. this.drawingContext.webkitImageSmoothingEnabled = true;
  11779. }
  11780. else if ('msImageSmoothingEnabled' in this.drawingContext) {
  11781. this.drawingContext.msImageSmoothingEnabled = true;
  11782. }
  11783. return this;
  11784. };
  11785. p5.Renderer2D.prototype.strokeCap = function(cap) {
  11786. if (cap === constants.ROUND ||
  11787. cap === constants.SQUARE ||
  11788. cap === constants.PROJECT) {
  11789. this.drawingContext.lineCap = cap;
  11790. }
  11791. return this;
  11792. };
  11793. p5.Renderer2D.prototype.strokeJoin = function(join) {
  11794. if (join === constants.ROUND ||
  11795. join === constants.BEVEL ||
  11796. join === constants.MITER) {
  11797. this.drawingContext.lineJoin = join;
  11798. }
  11799. return this;
  11800. };
  11801. p5.Renderer2D.prototype.strokeWeight = function(w) {
  11802. if (typeof w === 'undefined' || w === 0) {
  11803. // hack because lineWidth 0 doesn't work
  11804. this.drawingContext.lineWidth = 0.0001;
  11805. } else {
  11806. this.drawingContext.lineWidth = w;
  11807. }
  11808. return this;
  11809. };
  11810. p5.Renderer2D.prototype._getFill = function(){
  11811. return this.drawingContext.fillStyle;
  11812. };
  11813. p5.Renderer2D.prototype._getStroke = function(){
  11814. return this.drawingContext.strokeStyle;
  11815. };
  11816. //////////////////////////////////////////////
  11817. // SHAPE | Curves
  11818. //////////////////////////////////////////////
  11819. p5.Renderer2D.prototype.bezier = function (x1, y1, x2, y2, x3, y3, x4, y4) {
  11820. this._pInst.beginShape();
  11821. this._pInst.vertex(x1, y1);
  11822. this._pInst.bezierVertex(x2, y2, x3, y3, x4, y4);
  11823. this._pInst.endShape();
  11824. return this;
  11825. };
  11826. p5.Renderer2D.prototype.curve = function (x1, y1, x2, y2, x3, y3, x4, y4) {
  11827. this._pInst.beginShape();
  11828. this._pInst.curveVertex(x1, y1);
  11829. this._pInst.curveVertex(x2, y2);
  11830. this._pInst.curveVertex(x3, y3);
  11831. this._pInst.curveVertex(x4, y4);
  11832. this._pInst.endShape();
  11833. return this;
  11834. };
  11835. //////////////////////////////////////////////
  11836. // SHAPE | Vertex
  11837. //////////////////////////////////////////////
  11838. p5.Renderer2D.prototype._doFillStrokeClose = function () {
  11839. if (this._doFill) {
  11840. this.drawingContext.fill();
  11841. }
  11842. if (this._doStroke) {
  11843. this.drawingContext.stroke();
  11844. }
  11845. this.drawingContext.closePath();
  11846. };
  11847. //////////////////////////////////////////////
  11848. // TRANSFORM
  11849. //////////////////////////////////////////////
  11850. p5.Renderer2D.prototype.applyMatrix =
  11851. function(n00, n01, n02, n10, n11, n12) {
  11852. this.drawingContext.transform(n00, n01, n02, n10, n11, n12);
  11853. };
  11854. p5.Renderer2D.prototype.resetMatrix = function() {
  11855. this.drawingContext.setTransform(1, 0, 0, 1, 0, 0);
  11856. this.drawingContext.scale(this._pInst._pixelDensity,
  11857. this._pInst._pixelDensity);
  11858. return this;
  11859. };
  11860. p5.Renderer2D.prototype.rotate = function(r) {
  11861. this.drawingContext.rotate(r);
  11862. };
  11863. p5.Renderer2D.prototype.scale = function(x,y) {
  11864. this.drawingContext.scale(x, y);
  11865. return this;
  11866. };
  11867. p5.Renderer2D.prototype.shearX = function(angle) {
  11868. if (this._pInst._angleMode === constants.DEGREES) {
  11869. // undoing here, because it gets redone in tan()
  11870. angle = this._pInst.degrees(angle);
  11871. }
  11872. this.drawingContext.transform(1, 0, this._pInst.tan(angle), 1, 0, 0);
  11873. return this;
  11874. };
  11875. p5.Renderer2D.prototype.shearY = function(angle) {
  11876. if (this._pInst._angleMode === constants.DEGREES) {
  11877. // undoing here, because it gets redone in tan()
  11878. angle = this._pInst.degrees(angle);
  11879. }
  11880. this.drawingContext.transform(1, this._pInst.tan(angle), 0, 1, 0, 0);
  11881. return this;
  11882. };
  11883. p5.Renderer2D.prototype.translate = function(x, y) {
  11884. this.drawingContext.translate(x, y);
  11885. return this;
  11886. };
  11887. //////////////////////////////////////////////
  11888. // TYPOGRAPHY
  11889. //
  11890. //////////////////////////////////////////////
  11891. p5.Renderer2D.prototype.text = function (str, x, y, maxWidth, maxHeight) {
  11892. var p = this._pInst, cars, n, ii, jj, line, testLine,
  11893. testWidth, words, totalHeight, baselineHacked,
  11894. finalMaxHeight = Number.MAX_VALUE;
  11895. // baselineHacked: (HACK)
  11896. // A temporary fix to conform to Processing's implementation
  11897. // of BASELINE vertical alignment in a bounding box
  11898. if (!(this._doFill || this._doStroke)) {
  11899. return;
  11900. }
  11901. if (typeof str !== 'string') {
  11902. str = str.toString();
  11903. }
  11904. str = str.replace(/(\t)/g, ' ');
  11905. cars = str.split('\n');
  11906. if (typeof maxWidth !== 'undefined') {
  11907. totalHeight = 0;
  11908. for (ii = 0; ii < cars.length; ii++) {
  11909. line = '';
  11910. words = cars[ii].split(' ');
  11911. for (n = 0; n < words.length; n++) {
  11912. testLine = line + words[n] + ' ';
  11913. testWidth = this.textWidth(testLine);
  11914. if (testWidth > maxWidth) {
  11915. line = words[n] + ' ';
  11916. totalHeight += p.textLeading();
  11917. } else {
  11918. line = testLine;
  11919. }
  11920. }
  11921. }
  11922. if (this._rectMode === constants.CENTER) {
  11923. x -= maxWidth / 2;
  11924. y -= maxHeight / 2;
  11925. }
  11926. switch (this.drawingContext.textAlign) {
  11927. case constants.CENTER:
  11928. x += maxWidth / 2;
  11929. break;
  11930. case constants.RIGHT:
  11931. x += maxWidth;
  11932. break;
  11933. }
  11934. if (typeof maxHeight !== 'undefined') {
  11935. switch (this.drawingContext.textBaseline) {
  11936. case constants.BOTTOM:
  11937. y += (maxHeight - totalHeight);
  11938. break;
  11939. case constants._CTX_MIDDLE: // CENTER?
  11940. y += (maxHeight - totalHeight) / 2;
  11941. break;
  11942. case constants.BASELINE:
  11943. baselineHacked = true;
  11944. this.drawingContext.textBaseline = constants.TOP;
  11945. break;
  11946. }
  11947. // remember the max-allowed y-position for any line (fix to #928)
  11948. finalMaxHeight = (y + maxHeight) - p.textAscent();
  11949. }
  11950. for (ii = 0; ii < cars.length; ii++) {
  11951. line = '';
  11952. words = cars[ii].split(' ');
  11953. for (n = 0; n < words.length; n++) {
  11954. testLine = line + words[n] + ' ';
  11955. testWidth = this.textWidth(testLine);
  11956. if (testWidth > maxWidth && line.length > 0) {
  11957. this._renderText(p, line, x, y, finalMaxHeight);
  11958. line = words[n] + ' ';
  11959. y += p.textLeading();
  11960. } else {
  11961. line = testLine;
  11962. }
  11963. }
  11964. this._renderText(p, line, x, y, finalMaxHeight);
  11965. y += p.textLeading();
  11966. }
  11967. }
  11968. else {
  11969. // Offset to account for vertically centering multiple lines of text - no
  11970. // need to adjust anything for vertical align top or baseline
  11971. var offset = 0,
  11972. vAlign = p.textAlign().vertical;
  11973. if (vAlign === constants.CENTER) {
  11974. offset = ((cars.length - 1) * p.textLeading()) / 2;
  11975. } else if (vAlign === constants.BOTTOM) {
  11976. offset = (cars.length - 1) * p.textLeading();
  11977. }
  11978. for (jj = 0; jj < cars.length; jj++) {
  11979. this._renderText(p, cars[jj], x, y-offset, finalMaxHeight);
  11980. y += p.textLeading();
  11981. }
  11982. }
  11983. if (baselineHacked) {
  11984. this.drawingContext.textBaseline = constants.BASELINE;
  11985. }
  11986. return p;
  11987. };
  11988. p5.Renderer2D.prototype._renderText = function(p, line, x, y, maxY) {
  11989. if (y >= maxY) {
  11990. return; // don't render lines beyond our maxY position
  11991. }
  11992. p.push(); // fix to #803
  11993. if (!this._isOpenType()) { // a system/browser font
  11994. // no stroke unless specified by user
  11995. if (this._doStroke && this._strokeSet) {
  11996. this.drawingContext.strokeText(line, x, y);
  11997. }
  11998. if (this._doFill) {
  11999. // if fill hasn't been set by user, use default text fill
  12000. this.drawingContext.fillStyle = this._fillSet ?
  12001. this.drawingContext.fillStyle : constants._DEFAULT_TEXT_FILL;
  12002. this.drawingContext.fillText(line, x, y);
  12003. }
  12004. }
  12005. else { // an opentype font, let it handle the rendering
  12006. this._textFont._renderPath(line, x, y, { renderer: this });
  12007. }
  12008. p.pop();
  12009. return p;
  12010. };
  12011. p5.Renderer2D.prototype.textWidth = function(s) {
  12012. if (this._isOpenType()) {
  12013. return this._textFont._textWidth(s, this._textSize);
  12014. }
  12015. return this.drawingContext.measureText(s).width;
  12016. };
  12017. p5.Renderer2D.prototype.textAlign = function(h, v) {
  12018. if (arguments.length) {
  12019. if (h === constants.LEFT ||
  12020. h === constants.RIGHT ||
  12021. h === constants.CENTER) {
  12022. this.drawingContext.textAlign = h;
  12023. }
  12024. if (v === constants.TOP ||
  12025. v === constants.BOTTOM ||
  12026. v === constants.CENTER ||
  12027. v === constants.BASELINE) {
  12028. if (v === constants.CENTER) {
  12029. this.drawingContext.textBaseline = constants._CTX_MIDDLE;
  12030. } else {
  12031. this.drawingContext.textBaseline = v;
  12032. }
  12033. }
  12034. return this._pInst;
  12035. } else {
  12036. var valign = this.drawingContext.textBaseline;
  12037. if (valign === constants._CTX_MIDDLE) {
  12038. valign = constants.CENTER;
  12039. }
  12040. return {
  12041. horizontal: this.drawingContext.textAlign,
  12042. vertical: valign
  12043. };
  12044. }
  12045. };
  12046. p5.Renderer2D.prototype._applyTextProperties = function() {
  12047. var font, p = this._pInst;
  12048. this._setProperty('_textAscent', null);
  12049. this._setProperty('_textDescent', null);
  12050. font = this._textFont;
  12051. if (this._isOpenType()) {
  12052. font = this._textFont.font.familyName;
  12053. this._setProperty('_textStyle', this._textFont.font.styleName);
  12054. }
  12055. this.drawingContext.font = this._textStyle + ' ' +
  12056. this._textSize + 'px ' + font;
  12057. return p;
  12058. };
  12059. //////////////////////////////////////////////
  12060. // STRUCTURE
  12061. //////////////////////////////////////////////
  12062. p5.Renderer2D.prototype.push = function() {
  12063. this.drawingContext.save();
  12064. };
  12065. p5.Renderer2D.prototype.pop = function() {
  12066. this.drawingContext.restore();
  12067. };
  12068. module.exports = p5.Renderer2D;
  12069. },{"../image/filters":54,"./canvas":35,"./constants":36,"./core":37,"./p5.Renderer":43}],45:[function(_dereq_,module,exports){
  12070. /**
  12071. * @module Rendering
  12072. * @submodule Rendering
  12073. * @for p5
  12074. */
  12075. var p5 = _dereq_('./core');
  12076. var constants = _dereq_('./constants');
  12077. _dereq_('./p5.Graphics');
  12078. _dereq_('./p5.Renderer2D');
  12079. _dereq_('../webgl/p5.RendererGL');
  12080. var defaultId = 'defaultCanvas0'; // this gets set again in createCanvas
  12081. /**
  12082. * Creates a canvas element in the document, and sets the dimensions of it
  12083. * in pixels. This method should be called only once at the start of setup.
  12084. * Calling createCanvas more than once in a sketch will result in very
  12085. * unpredicable behavior. If you want more than one drawing canvas
  12086. * you could use createGraphics (hidden by default but it can be shown).
  12087. * <br><br>
  12088. * The system variables width and height are set by the parameters passed
  12089. * to this function. If createCanvas() is not used, the window will be
  12090. * given a default size of 100x100 pixels.
  12091. * <br><br>
  12092. * For more ways to position the canvas, see the
  12093. * <a href='https://github.com/processing/p5.js/wiki/Positioning-your-canvas'>
  12094. * positioning the canvas</a> wiki page.
  12095. *
  12096. * @method createCanvas
  12097. * @param {Number} w width of the canvas
  12098. * @param {Number} h height of the canvas
  12099. * @param {Constant} [renderer] P2D or WEBGL
  12100. * @return {Object} canvas generated
  12101. * @example
  12102. * <div>
  12103. * <code>
  12104. * function setup() {
  12105. * createCanvas(100, 50);
  12106. * background(153);
  12107. * line(0, 0, width, height);
  12108. * }
  12109. * </code>
  12110. * </div>
  12111. *
  12112. * @alt
  12113. * Black line extending from top-left of canvas to bottom right.
  12114. *
  12115. */
  12116. p5.prototype.createCanvas = function(w, h, renderer) {
  12117. //optional: renderer, otherwise defaults to p2d
  12118. var r = renderer || constants.P2D;
  12119. var isDefault, c;
  12120. //4th arg (isDefault) used when called onLoad,
  12121. //otherwise hidden to the public api
  12122. if(arguments[3]){
  12123. isDefault =
  12124. (typeof arguments[3] === 'boolean') ? arguments[3] : false;
  12125. }
  12126. if(r === constants.WEBGL){
  12127. c = document.getElementById(defaultId);
  12128. if(c){ //if defaultCanvas already exists
  12129. c.parentNode.removeChild(c); //replace the existing defaultCanvas
  12130. }
  12131. c = document.createElement('canvas');
  12132. c.id = defaultId;
  12133. }
  12134. else {
  12135. if (isDefault) {
  12136. c = document.createElement('canvas');
  12137. var i = 0;
  12138. while (document.getElementById('defaultCanvas'+i)) {
  12139. i++;
  12140. }
  12141. defaultId = 'defaultCanvas'+i;
  12142. c.id = defaultId;
  12143. } else { // resize the default canvas if new one is created
  12144. c = this.canvas;
  12145. }
  12146. }
  12147. // set to invisible if still in setup (to prevent flashing with manipulate)
  12148. if (!this._setupDone) {
  12149. c.dataset.hidden = true; // tag to show later
  12150. c.style.visibility='hidden';
  12151. }
  12152. if (this._userNode) { // user input node case
  12153. this._userNode.appendChild(c);
  12154. } else {
  12155. document.body.appendChild(c);
  12156. }
  12157. // Init our graphics renderer
  12158. //webgl mode
  12159. if (r === constants.WEBGL) {
  12160. this._setProperty('_renderer', new p5.RendererGL(c, this, true));
  12161. this._isdefaultGraphics = true;
  12162. }
  12163. //P2D mode
  12164. else {
  12165. if (!this._isdefaultGraphics) {
  12166. this._setProperty('_renderer', new p5.Renderer2D(c, this, true));
  12167. this._isdefaultGraphics = true;
  12168. }
  12169. }
  12170. this._renderer.resize(w, h);
  12171. this._renderer._applyDefaults();
  12172. if (isDefault) { // only push once
  12173. this._elements.push(this._renderer);
  12174. }
  12175. return this._renderer;
  12176. };
  12177. /**
  12178. * Resizes the canvas to given width and height. The canvas will be cleared
  12179. * and draw will be called immediately, allowing the sketch to re-render itself
  12180. * in the resized canvas.
  12181. * @method resizeCanvas
  12182. * @example
  12183. * <div class="norender"><code>
  12184. * function setup() {
  12185. * createCanvas(windowWidth, windowHeight);
  12186. * }
  12187. *
  12188. * function draw() {
  12189. * background(0, 100, 200);
  12190. * }
  12191. *
  12192. * function windowResized() {
  12193. * resizeCanvas(windowWidth, windowHeight);
  12194. * }
  12195. * </code></div>
  12196. *
  12197. * @alt
  12198. * No image displayed.
  12199. *
  12200. */
  12201. p5.prototype.resizeCanvas = function (w, h, noRedraw) {
  12202. if (this._renderer) {
  12203. // save canvas properties
  12204. var props = {};
  12205. for (var key in this.drawingContext) {
  12206. var val = this.drawingContext[key];
  12207. if (typeof val !== 'object' && typeof val !== 'function') {
  12208. props[key] = val;
  12209. }
  12210. }
  12211. this._renderer.resize(w, h);
  12212. // reset canvas properties
  12213. for (var savedKey in props) {
  12214. this.drawingContext[savedKey] = props[savedKey];
  12215. }
  12216. if (!noRedraw) {
  12217. this.redraw();
  12218. }
  12219. }
  12220. };
  12221. /**
  12222. * Removes the default canvas for a p5 sketch that doesn't
  12223. * require a canvas
  12224. * @method noCanvas
  12225. * @example
  12226. * <div>
  12227. * <code>
  12228. * function setup() {
  12229. * noCanvas();
  12230. * }
  12231. * </code>
  12232. * </div>
  12233. *
  12234. * @alt
  12235. * no image displayed
  12236. *
  12237. */
  12238. p5.prototype.noCanvas = function() {
  12239. if (this.canvas) {
  12240. this.canvas.parentNode.removeChild(this.canvas);
  12241. }
  12242. };
  12243. /**
  12244. * Creates and returns a new p5.Renderer object. Use this class if you need
  12245. * to draw into an off-screen graphics buffer. The two parameters define the
  12246. * width and height in pixels.
  12247. *
  12248. * @method createGraphics
  12249. * @param {Number} w width of the offscreen graphics buffer
  12250. * @param {Number} h height of the offscreen graphics buffer
  12251. * @param {Constant} [renderer] P2D or WEBGL
  12252. * undefined defaults to p2d
  12253. * @return {Object} offscreen graphics buffer
  12254. * @example
  12255. * <div>
  12256. * <code>
  12257. * var pg;
  12258. * function setup() {
  12259. * createCanvas(100, 100);
  12260. * pg = createGraphics(100, 100);
  12261. * }
  12262. * function draw() {
  12263. * background(200);
  12264. * pg.background(100);
  12265. * pg.noStroke();
  12266. * pg.ellipse(pg.width/2, pg.height/2, 50, 50);
  12267. * image(pg, 50, 50);
  12268. * image(pg, 0, 0, 50, 50);
  12269. * }
  12270. * </code>
  12271. * </div>
  12272. *
  12273. * @alt
  12274. * 4 grey squares alternating light and dark grey. White quarter circle mid-left.
  12275. *
  12276. */
  12277. p5.prototype.createGraphics = function(w, h, renderer){
  12278. return new p5.Graphics(w, h, renderer, this);
  12279. };
  12280. /**
  12281. * Blends the pixels in the display window according to the defined mode.
  12282. * There is a choice of the following modes to blend the source pixels (A)
  12283. * with the ones of pixels already in the display window (B):
  12284. * <ul>
  12285. * <li><code>BLEND</code> - linear interpolation of colours: C =
  12286. * A*factor + B. This is the default blending mode.</li>
  12287. * <li><code>ADD</code> - sum of A and B</li>
  12288. * <li><code>DARKEST</code> - only the darkest colour succeeds: C =
  12289. * min(A*factor, B).</li>
  12290. * <li><code>LIGHTEST</code> - only the lightest colour succeeds: C =
  12291. * max(A*factor, B).</li>
  12292. * <li><code>DIFFERENCE</code> - subtract colors from underlying image.</li>
  12293. * <li><code>EXCLUSION</code> - similar to <code>DIFFERENCE</code>, but less
  12294. * extreme.</li>
  12295. * <li><code>MULTIPLY</code> - multiply the colors, result will always be
  12296. * darker.</li>
  12297. * <li><code>SCREEN</code> - opposite multiply, uses inverse values of the
  12298. * colors.</li>
  12299. * <li><code>REPLACE</code> - the pixels entirely replace the others and
  12300. * don't utilize alpha (transparency) values.</li>
  12301. * <li><code>OVERLAY</code> - mix of <code>MULTIPLY</code> and <code>SCREEN
  12302. * </code>. Multiplies dark values, and screens light values.</li>
  12303. * <li><code>HARD_LIGHT</code> - <code>SCREEN</code> when greater than 50%
  12304. * gray, <code>MULTIPLY</code> when lower.</li>
  12305. * <li><code>SOFT_LIGHT</code> - mix of <code>DARKEST</code> and
  12306. * <code>LIGHTEST</code>. Works like <code>OVERLAY</code>, but not as harsh.
  12307. * </li>
  12308. * <li><code>DODGE</code> - lightens light tones and increases contrast,
  12309. * ignores darks.</li>
  12310. * <li><code>BURN</code> - darker areas are applied, increasing contrast,
  12311. * ignores lights.</li>
  12312. * </ul>
  12313. *
  12314. * @method blendMode
  12315. * @param {Constant} mode blend mode to set for canvas
  12316. * @example
  12317. * <div>
  12318. * <code>
  12319. * blendMode(LIGHTEST);
  12320. * strokeWeight(30);
  12321. * stroke(80, 150, 255);
  12322. * line(25, 25, 75, 75);
  12323. * stroke(255, 50, 50);
  12324. * line(75, 25, 25, 75);
  12325. * </code>
  12326. * </div>
  12327. * <div>
  12328. * <code>
  12329. * blendMode(MULTIPLY);
  12330. * strokeWeight(30);
  12331. * stroke(80, 150, 255);
  12332. * line(25, 25, 75, 75);
  12333. * stroke(255, 50, 50);
  12334. * line(75, 25, 25, 75);
  12335. * </code>
  12336. * </div>
  12337. * @alt
  12338. * translucent image thick red & blue diagonal rounded lines intersecting center
  12339. * Thick red & blue diagonal rounded lines intersecting center. dark at overlap
  12340. *
  12341. */
  12342. p5.prototype.blendMode = function(mode) {
  12343. if (mode === constants.BLEND || mode === constants.DARKEST ||
  12344. mode === constants.LIGHTEST || mode === constants.DIFFERENCE ||
  12345. mode === constants.MULTIPLY || mode === constants.EXCLUSION ||
  12346. mode === constants.SCREEN || mode === constants.REPLACE ||
  12347. mode === constants.OVERLAY || mode === constants.HARD_LIGHT ||
  12348. mode === constants.SOFT_LIGHT || mode === constants.DODGE ||
  12349. mode === constants.BURN || mode === constants.ADD ||
  12350. mode === constants.NORMAL) {
  12351. this._renderer.blendMode(mode);
  12352. } else {
  12353. throw new Error('Mode '+mode+' not recognized.');
  12354. }
  12355. };
  12356. module.exports = p5;
  12357. },{"../webgl/p5.RendererGL":86,"./constants":36,"./core":37,"./p5.Graphics":42,"./p5.Renderer2D":44}],46:[function(_dereq_,module,exports){
  12358. // requestAnim shim layer by Paul Irish
  12359. window.requestAnimationFrame = (function(){
  12360. return window.requestAnimationFrame ||
  12361. window.webkitRequestAnimationFrame ||
  12362. window.mozRequestAnimationFrame ||
  12363. window.oRequestAnimationFrame ||
  12364. window.msRequestAnimationFrame ||
  12365. function(callback, element){
  12366. // should '60' here be framerate?
  12367. window.setTimeout(callback, 1000 / 60);
  12368. };
  12369. })();
  12370. // use window.performance() to get max fast and accurate time in milliseconds
  12371. window.performance = window.performance || {};
  12372. window.performance.now = (function(){
  12373. var load_date = Date.now();
  12374. return window.performance.now ||
  12375. window.performance.mozNow ||
  12376. window.performance.msNow ||
  12377. window.performance.oNow ||
  12378. window.performance.webkitNow ||
  12379. function () {
  12380. return Date.now() - load_date;
  12381. };
  12382. })();
  12383. /*
  12384. // http://paulirish.com/2011/requestanimationframe-for-smart-animating/
  12385. // http://my.opera.com/emoller/blog/2011/12/20/
  12386. // requestanimationframe-for-smart-er-animating
  12387. // requestAnimationFrame polyfill by Erik Möller
  12388. // fixes from Paul Irish and Tino Zijdel
  12389. (function() {
  12390. var lastTime = 0;
  12391. var vendors = ['ms', 'moz', 'webkit', 'o'];
  12392. for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
  12393. window.requestAnimationFrame =
  12394. window[vendors[x]+'RequestAnimationFrame'];
  12395. window.cancelAnimationFrame =
  12396. window[vendors[x]+'CancelAnimationFrame'] ||
  12397. window[vendors[x]+'CancelRequestAnimationFrame'];
  12398. }
  12399. if (!window.requestAnimationFrame) {
  12400. window.requestAnimationFrame = function(callback, element) {
  12401. var currTime = new Date().getTime();
  12402. var timeToCall = Math.max(0, 16 - (currTime - lastTime));
  12403. var id = window.setTimeout(function()
  12404. { callback(currTime + timeToCall); }, timeToCall);
  12405. lastTime = currTime + timeToCall;
  12406. return id;
  12407. };
  12408. }
  12409. if (!window.cancelAnimationFrame) {
  12410. window.cancelAnimationFrame = function(id) {
  12411. clearTimeout(id);
  12412. };
  12413. }
  12414. }());
  12415. */
  12416. /**
  12417. * shim for Uint8ClampedArray.slice
  12418. * (allows arrayCopy to work with pixels[])
  12419. * with thanks to http://halfpapstudios.com/blog/tag/html5-canvas/
  12420. * Enumerable set to false to protect for...in from
  12421. * Uint8ClampedArray.prototype pollution.
  12422. */
  12423. (function () {
  12424. 'use strict';
  12425. if (typeof Uint8ClampedArray !== 'undefined' &&
  12426. !Uint8ClampedArray.prototype.slice) {
  12427. Object.defineProperty(Uint8ClampedArray.prototype, 'slice', {
  12428. value: Array.prototype.slice,
  12429. writable: true, configurable: true, enumerable: false
  12430. });
  12431. }
  12432. }());
  12433. },{}],47:[function(_dereq_,module,exports){
  12434. /**
  12435. * @module Structure
  12436. * @submodule Structure
  12437. * @for p5
  12438. * @requires core
  12439. */
  12440. 'use strict';
  12441. var p5 = _dereq_('./core');
  12442. p5.prototype.exit = function() {
  12443. throw 'exit() not implemented, see remove()';
  12444. };
  12445. /**
  12446. * Stops p5.js from continuously executing the code within draw().
  12447. * If loop() is called, the code in draw() begins to run continuously again.
  12448. * If using noLoop() in setup(), it should be the last line inside the block.
  12449. * <br><br>
  12450. * When noLoop() is used, it's not possible to manipulate or access the
  12451. * screen inside event handling functions such as mousePressed() or
  12452. * keyPressed(). Instead, use those functions to call redraw() or loop(),
  12453. * which will run draw(), which can update the screen properly. This means
  12454. * that when noLoop() has been called, no drawing can happen, and functions
  12455. * like saveFrame() or loadPixels() may not be used.
  12456. * <br><br>
  12457. * Note that if the sketch is resized, redraw() will be called to update
  12458. * the sketch, even after noLoop() has been specified. Otherwise, the sketch
  12459. * would enter an odd state until loop() was called.
  12460. *
  12461. * @method noLoop
  12462. * @example
  12463. * <div><code>
  12464. * function setup() {
  12465. * createCanvas(100, 100);
  12466. * background(200);
  12467. * noLoop();
  12468. * }
  12469. * function draw() {
  12470. * line(10, 10, 90, 90);
  12471. * }
  12472. * </code></div>
  12473. *
  12474. * <div><code>
  12475. * var x = 0;
  12476. * function setup() {
  12477. * createCanvas(100, 100);
  12478. * }
  12479. *
  12480. * function draw() {
  12481. * background(204);
  12482. * x = x + 0.1;
  12483. * if (x > width) {
  12484. * x = 0;
  12485. * }
  12486. * line(x, 0, x, height);
  12487. * }
  12488. *
  12489. * function mousePressed() {
  12490. * noLoop();
  12491. * }
  12492. *
  12493. * function mouseReleased() {
  12494. * loop();
  12495. * }
  12496. * </code></div>
  12497. *
  12498. * @alt
  12499. * 113 pixel long line extending from top-left to bottom right of canvas.
  12500. * horizontal line moves slowly from left. Loops but stops on mouse press.
  12501. *
  12502. */
  12503. p5.prototype.noLoop = function() {
  12504. this._loop = false;
  12505. };
  12506. /**
  12507. * By default, p5.js loops through draw() continuously, executing the code
  12508. * within it. However, the draw() loop may be stopped by calling noLoop().
  12509. * In that case, the draw() loop can be resumed with loop().
  12510. *
  12511. * @method loop
  12512. * @example
  12513. * <div><code>
  12514. * var x = 0;
  12515. * function setup() {
  12516. * createCanvas(100, 100);
  12517. * noLoop();
  12518. * }
  12519. *
  12520. * function draw() {
  12521. * background(204);
  12522. * x = x + 0.1;
  12523. * if (x > width) {
  12524. * x = 0;
  12525. * }
  12526. * line(x, 0, x, height);
  12527. * }
  12528. *
  12529. * function mousePressed() {
  12530. * loop();
  12531. * }
  12532. *
  12533. * function mouseReleased() {
  12534. * noLoop();
  12535. * }
  12536. * </code></div>
  12537. *
  12538. * @alt
  12539. * horizontal line moves slowly from left. Loops but stops on mouse press.
  12540. *
  12541. */
  12542. p5.prototype.loop = function() {
  12543. this._loop = true;
  12544. this._draw();
  12545. };
  12546. /**
  12547. * The push() function saves the current drawing style settings and
  12548. * transformations, while pop() restores these settings. Note that these
  12549. * functions are always used together. They allow you to change the style
  12550. * and transformation settings and later return to what you had. When a new
  12551. * state is started with push(), it builds on the current style and transform
  12552. * information. The push() and pop() functions can be embedded to provide
  12553. * more control. (See the second example for a demonstration.)
  12554. * <br><br>
  12555. * push() stores information related to the current transformation state
  12556. * and style settings controlled by the following functions: fill(),
  12557. * stroke(), tint(), strokeWeight(), strokeCap(), strokeJoin(),
  12558. * imageMode(), rectMode(), ellipseMode(), colorMode(), textAlign(),
  12559. * textFont(), textMode(), textSize(), textLeading().
  12560. *
  12561. * @method push
  12562. * @example
  12563. * <div>
  12564. * <code>
  12565. * ellipse(0, 50, 33, 33); // Left circle
  12566. *
  12567. * push(); // Start a new drawing state
  12568. * strokeWeight(10);
  12569. * fill(204, 153, 0);
  12570. * translate(50, 0);
  12571. * ellipse(0, 50, 33, 33); // Middle circle
  12572. * pop(); // Restore original state
  12573. *
  12574. * ellipse(100, 50, 33, 33); // Right circle
  12575. * </code>
  12576. * </div>
  12577. * <div>
  12578. * <code>
  12579. * ellipse(0, 50, 33, 33); // Left circle
  12580. *
  12581. * push(); // Start a new drawing state
  12582. * strokeWeight(10);
  12583. * fill(204, 153, 0);
  12584. * ellipse(33, 50, 33, 33); // Left-middle circle
  12585. *
  12586. * push(); // Start another new drawing state
  12587. * stroke(0, 102, 153);
  12588. * ellipse(66, 50, 33, 33); // Right-middle circle
  12589. * pop(); // Restore previous state
  12590. *
  12591. * pop(); // Restore original state
  12592. *
  12593. * ellipse(100, 50, 33, 33); // Right circle
  12594. * </code>
  12595. * </div>
  12596. *
  12597. * @alt
  12598. * Gold ellipse + thick black outline @center 2 white ellipses on left and right.
  12599. * 2 Gold ellipses left black right blue stroke. 2 white ellipses on left+right.
  12600. *
  12601. */
  12602. p5.prototype.push = function () {
  12603. this._renderer.push();
  12604. this._styles.push({
  12605. _doStroke: this._renderer._doStroke,
  12606. _strokeSet: this._renderer._strokeSet,
  12607. _doFill: this._renderer._doFill,
  12608. _fillSet: this._renderer._fillSet,
  12609. _tint: this._renderer._tint,
  12610. _imageMode: this._renderer._imageMode,
  12611. _rectMode: this._renderer._rectMode,
  12612. _ellipseMode: this._renderer._ellipseMode,
  12613. _colorMode: this._renderer._colorMode,
  12614. _textFont: this._renderer._textFont,
  12615. _textLeading: this._renderer._textLeading,
  12616. _textSize: this._renderer._textSize,
  12617. _textStyle: this._renderer._textStyle
  12618. });
  12619. };
  12620. /**
  12621. * The push() function saves the current drawing style settings and
  12622. * transformations, while pop() restores these settings. Note that these
  12623. * functions are always used together. They allow you to change the style
  12624. * and transformation settings and later return to what you had. When a new
  12625. * state is started with push(), it builds on the current style and transform
  12626. * information. The push() and pop() functions can be embedded to provide
  12627. * more control. (See the second example for a demonstration.)
  12628. * <br><br>
  12629. * push() stores information related to the current transformation state
  12630. * and style settings controlled by the following functions: fill(),
  12631. * stroke(), tint(), strokeWeight(), strokeCap(), strokeJoin(),
  12632. * imageMode(), rectMode(), ellipseMode(), colorMode(), textAlign(),
  12633. * textFont(), textMode(), textSize(), textLeading().
  12634. *
  12635. * @method pop
  12636. * @example
  12637. * <div>
  12638. * <code>
  12639. * ellipse(0, 50, 33, 33); // Left circle
  12640. *
  12641. * push(); // Start a new drawing state
  12642. * translate(50, 0);
  12643. * strokeWeight(10);
  12644. * fill(204, 153, 0);
  12645. * ellipse(0, 50, 33, 33); // Middle circle
  12646. * pop(); // Restore original state
  12647. *
  12648. * ellipse(100, 50, 33, 33); // Right circle
  12649. * </code>
  12650. * </div>
  12651. * <div>
  12652. * <code>
  12653. * ellipse(0, 50, 33, 33); // Left circle
  12654. *
  12655. * push(); // Start a new drawing state
  12656. * strokeWeight(10);
  12657. * fill(204, 153, 0);
  12658. * ellipse(33, 50, 33, 33); // Left-middle circle
  12659. *
  12660. * push(); // Start another new drawing state
  12661. * stroke(0, 102, 153);
  12662. * ellipse(66, 50, 33, 33); // Right-middle circle
  12663. * pop(); // Restore previous state
  12664. *
  12665. * pop(); // Restore original state
  12666. *
  12667. * ellipse(100, 50, 33, 33); // Right circle
  12668. * </code>
  12669. * </div>
  12670. *
  12671. * @alt
  12672. * Gold ellipse + thick black outline @center 2 white ellipses on left and right.
  12673. * 2 Gold ellipses left black right blue stroke. 2 white ellipses on left+right.
  12674. *
  12675. */
  12676. p5.prototype.pop = function () {
  12677. this._renderer.pop();
  12678. var lastS = this._styles.pop();
  12679. for(var prop in lastS){
  12680. this._renderer[prop] = lastS[prop];
  12681. }
  12682. };
  12683. p5.prototype.pushStyle = function() {
  12684. throw new Error('pushStyle() not used, see push()');
  12685. };
  12686. p5.prototype.popStyle = function() {
  12687. throw new Error('popStyle() not used, see pop()');
  12688. };
  12689. /**
  12690. *
  12691. * Executes the code within draw() one time. This functions allows the
  12692. * program to update the display window only when necessary, for example
  12693. * when an event registered by mousePressed() or keyPressed() occurs.
  12694. * <br><br>
  12695. * In structuring a program, it only makes sense to call redraw() within
  12696. * events such as mousePressed(). This is because redraw() does not run
  12697. * draw() immediately (it only sets a flag that indicates an update is
  12698. * needed).
  12699. * <br><br>
  12700. * The redraw() function does not work properly when called inside draw().
  12701. * To enable/disable animations, use loop() and noLoop().
  12702. * <br><br>
  12703. * In addition you can set the number of redraws per method call. Just
  12704. * add an integer as single parameter for the number of redraws.
  12705. *
  12706. * @method redraw
  12707. * @param {Integer} [n] Redraw for n-times. The default value is 1.
  12708. * @example
  12709. * <div><code>
  12710. * var x = 0;
  12711. *
  12712. * function setup() {
  12713. * createCanvas(100, 100);
  12714. * noLoop();
  12715. * }
  12716. *
  12717. * function draw() {
  12718. * background(204);
  12719. * line(x, 0, x, height);
  12720. * }
  12721. *
  12722. * function mousePressed() {
  12723. * x += 1;
  12724. * redraw();
  12725. * }
  12726. * </code></div>
  12727. *
  12728. * <div class='norender'><code>
  12729. * var x = 0;
  12730. *
  12731. * function setup() {
  12732. * createCanvas(100, 100);
  12733. * noLoop();
  12734. * }
  12735. *
  12736. * function draw() {
  12737. * background(204);
  12738. * x += 1;
  12739. * line(x, 0, x, height);
  12740. * }
  12741. *
  12742. * function mousePressed() {
  12743. * redraw(5);
  12744. * }
  12745. * </code></div>
  12746. *
  12747. * @alt
  12748. * black line on far left of canvas
  12749. * black line on far left of canvas
  12750. *
  12751. */
  12752. p5.prototype.redraw = function () {
  12753. this.resetMatrix();
  12754. if(this._renderer.isP3D){
  12755. this._renderer._update();
  12756. }
  12757. var numberOfRedraws = 1;
  12758. if (arguments.length === 1) {
  12759. try {
  12760. if (parseInt(arguments[0]) > 1) {
  12761. numberOfRedraws = parseInt(arguments[0]);
  12762. }
  12763. } catch (error) {
  12764. // Do nothing, because the default value didn't be changed.
  12765. }
  12766. }
  12767. var userSetup = this.setup || window.setup;
  12768. var userDraw = this.draw || window.draw;
  12769. if (typeof userDraw === 'function') {
  12770. if (typeof userSetup === 'undefined') {
  12771. this.scale(this._pixelDensity, this._pixelDensity);
  12772. }
  12773. var self = this;
  12774. var callMethod = function (f) {
  12775. f.call(self);
  12776. };
  12777. for (var idxRedraw = 0; idxRedraw < numberOfRedraws; idxRedraw++) {
  12778. this._registeredMethods.pre.forEach(callMethod);
  12779. userDraw();
  12780. this._registeredMethods.post.forEach(callMethod);
  12781. }
  12782. }
  12783. };
  12784. p5.prototype.size = function() {
  12785. var s = 'size() is not a valid p5 function, to set the size of the ';
  12786. s += 'drawing canvas, please use createCanvas() instead';
  12787. throw s;
  12788. };
  12789. module.exports = p5;
  12790. },{"./core":37}],48:[function(_dereq_,module,exports){
  12791. /**
  12792. * @module Transform
  12793. * @submodule Transform
  12794. * @for p5
  12795. * @requires core
  12796. * @requires constants
  12797. */
  12798. 'use strict';
  12799. var p5 = _dereq_('./core');
  12800. var constants = _dereq_('./constants');
  12801. /**
  12802. * Multiplies the current matrix by the one specified through the parameters.
  12803. * This is very slow because it will try to calculate the inverse of the
  12804. * transform, so avoid it whenever possible.
  12805. *
  12806. * @method applyMatrix
  12807. * @param {Number} n00 numbers which define the 3x2 matrix to be multiplied
  12808. * @param {Number} n01 numbers which define the 3x2 matrix to be multiplied
  12809. * @param {Number} n02 numbers which define the 3x2 matrix to be multiplied
  12810. * @param {Number} n10 numbers which define the 3x2 matrix to be multiplied
  12811. * @param {Number} n11 numbers which define the 3x2 matrix to be multiplied
  12812. * @param {Number} n12 numbers which define the 3x2 matrix to be multiplied
  12813. * @return {p5} the p5 object
  12814. * @example
  12815. * <div>
  12816. * <code>
  12817. * // Example in the works.
  12818. * </code>
  12819. * </div>
  12820. *
  12821. * @alt
  12822. * no image diplayed
  12823. *
  12824. */
  12825. p5.prototype.applyMatrix = function(n00, n01, n02, n10, n11, n12) {
  12826. this._renderer.applyMatrix(n00, n01, n02, n10, n11, n12);
  12827. return this;
  12828. };
  12829. p5.prototype.popMatrix = function() {
  12830. throw new Error('popMatrix() not used, see pop()');
  12831. };
  12832. p5.prototype.printMatrix = function() {
  12833. throw new Error('printMatrix() not implemented');
  12834. };
  12835. p5.prototype.pushMatrix = function() {
  12836. throw new Error('pushMatrix() not used, see push()');
  12837. };
  12838. /**
  12839. * Replaces the current matrix with the identity matrix.
  12840. *
  12841. * @method resetMatrix
  12842. * @return {p5} the p5 object
  12843. * @example
  12844. * <div>
  12845. * <code>
  12846. * // Example in the works.
  12847. * </code>
  12848. * </div>
  12849. *
  12850. * @alt
  12851. * no image diplayed
  12852. *
  12853. */
  12854. p5.prototype.resetMatrix = function() {
  12855. this._renderer.resetMatrix();
  12856. return this;
  12857. };
  12858. /**
  12859. * Rotates a shape the amount specified by the angle parameter. This
  12860. * function accounts for angleMode, so angles can be entered in either
  12861. * RADIANS or DEGREES.
  12862. * <br><br>
  12863. * Objects are always rotated around their relative position to the
  12864. * origin and positive numbers rotate objects in a clockwise direction.
  12865. * Transformations apply to everything that happens after and subsequent
  12866. * calls to the function accumulates the effect. For example, calling
  12867. * rotate(HALF_PI) and then rotate(HALF_PI) is the same as rotate(PI).
  12868. * All tranformations are reset when draw() begins again.
  12869. * <br><br>
  12870. * Technically, rotate() multiplies the current transformation matrix
  12871. * by a rotation matrix. This function can be further controlled by
  12872. * the push() and pop().
  12873. *
  12874. * @method rotate
  12875. * @param {Number} angle the angle of rotation, specified in radians
  12876. * or degrees, depending on current angleMode
  12877. * @return {p5} the p5 object
  12878. * @example
  12879. * <div>
  12880. * <code>
  12881. * translate(width/2, height/2);
  12882. * rotate(PI/3.0);
  12883. * rect(-26, -26, 52, 52);
  12884. * </code>
  12885. * </div>
  12886. *
  12887. * @alt
  12888. * white 52x52 rect with black outline at center rotated counter 45 degrees
  12889. *
  12890. */
  12891. /**
  12892. * @method rotate
  12893. * @param {Number} rad angle in radians
  12894. * @param {p5.Vector | Array} axis axis to rotate around
  12895. * @return {p5.RendererGL} [description]
  12896. */
  12897. p5.prototype.rotate = function() {
  12898. var args = new Array(arguments.length);
  12899. var r;
  12900. for (var i = 0; i < args.length; ++i) {
  12901. args[i] = arguments[i];
  12902. }
  12903. if (this._angleMode === constants.DEGREES) {
  12904. r = this.radians(args[0]);
  12905. } else if (this._angleMode === constants.RADIANS){
  12906. r = args[0];
  12907. }
  12908. //in webgl mode
  12909. if(args.length > 1){
  12910. this._renderer.rotate(r, args[1]);
  12911. }
  12912. else {
  12913. this._renderer.rotate(r);
  12914. }
  12915. return this;
  12916. };
  12917. /**
  12918. * Rotates around X axis.
  12919. * @method rotateX
  12920. * @param {Number} rad angles in radians
  12921. * @return {[type]} [description]
  12922. */
  12923. p5.prototype.rotateX = function(rad) {
  12924. if (this._renderer.isP3D) {
  12925. this._renderer.rotateX(rad);
  12926. } else {
  12927. throw 'not supported in p2d. Please use webgl mode';
  12928. }
  12929. return this;
  12930. };
  12931. /**
  12932. * Rotates around Y axis.
  12933. * @method rotateY
  12934. * @param {Number} rad angles in radians
  12935. * @return {[type]} [description]
  12936. */
  12937. p5.prototype.rotateY = function(rad) {
  12938. if (this._renderer.isP3D) {
  12939. this._renderer.rotateY(rad);
  12940. } else {
  12941. throw 'not supported in p2d. Please use webgl mode';
  12942. }
  12943. return this;
  12944. };
  12945. /**
  12946. * Rotates around Z axis. Webgl mode only.
  12947. * @method rotateZ
  12948. * @param {Number} rad angles in radians
  12949. * @return {[type]} [description]
  12950. */
  12951. p5.prototype.rotateZ = function(rad) {
  12952. if (this._renderer.isP3D) {
  12953. this._renderer.rotateZ(rad);
  12954. } else {
  12955. throw 'not supported in p2d. Please use webgl mode';
  12956. }
  12957. return this;
  12958. };
  12959. /**
  12960. * Increases or decreases the size of a shape by expanding and contracting
  12961. * vertices. Objects always scale from their relative origin to the
  12962. * coordinate system. Scale values are specified as decimal percentages.
  12963. * For example, the function call scale(2.0) increases the dimension of a
  12964. * shape by 200%.
  12965. * <br><br>
  12966. * Transformations apply to everything that happens after and subsequent
  12967. * calls to the function multiply the effect. For example, calling scale(2.0)
  12968. * and then scale(1.5) is the same as scale(3.0). If scale() is called
  12969. * within draw(), the transformation is reset when the loop begins again.
  12970. * <br><br>
  12971. * Using this function with the z parameter is only available in WEBGL mode.
  12972. * This function can be further controlled with push() and pop().
  12973. *
  12974. * @method scale
  12975. * @param {Number | p5.Vector | Array} s
  12976. * percent to scale the object, or percentage to
  12977. * scale the object in the x-axis if multiple arguments
  12978. * are given
  12979. * @param {Number} [y] percent to scale the object in the y-axis
  12980. * @param {Number} [z] percent to scale the object in the z-axis (webgl only)
  12981. * @return {p5} the p5 object
  12982. * @example
  12983. * <div>
  12984. * <code>
  12985. * translate(width/2, height/2);
  12986. * rotate(PI/3.0);
  12987. * rect(-26, -26, 52, 52);
  12988. * </code>
  12989. * </div>
  12990. *
  12991. * <div>
  12992. * <code>
  12993. * rect(30, 20, 50, 50);
  12994. * scale(0.5, 1.3);
  12995. * rect(30, 20, 50, 50);
  12996. * </code>
  12997. * </div>
  12998. *
  12999. * @alt
  13000. * white 52x52 rect with black outline at center rotated counter 45 degrees
  13001. * 2 white rects with black outline- 1 50x50 at center. other 25x65 bottom left
  13002. *
  13003. */
  13004. p5.prototype.scale = function() {
  13005. var x,y,z;
  13006. var args = new Array(arguments.length);
  13007. for(var i = 0; i < args.length; i++) {
  13008. args[i] = arguments[i];
  13009. }
  13010. if(args[0] instanceof p5.Vector){
  13011. x = args[0].x;
  13012. y = args[0].y;
  13013. z = args[0].z;
  13014. }
  13015. else if(args[0] instanceof Array){
  13016. x = args[0][0];
  13017. y = args[0][1];
  13018. z = args[0][2] || 1;
  13019. }
  13020. else {
  13021. if(args.length === 1){
  13022. x = y = z = args[0];
  13023. }
  13024. else {
  13025. x = args[0];
  13026. y = args[1];
  13027. z = args[2] || 1;
  13028. }
  13029. }
  13030. if(this._renderer.isP3D){
  13031. this._renderer.scale.call(this._renderer, x,y,z);
  13032. }
  13033. else {
  13034. this._renderer.scale.call(this._renderer, x,y);
  13035. }
  13036. return this;
  13037. };
  13038. /**
  13039. * Shears a shape around the x-axis the amount specified by the angle
  13040. * parameter. Angles should be specified in the current angleMode.
  13041. * Objects are always sheared around their relative position to the origin
  13042. * and positive numbers shear objects in a clockwise direction.
  13043. * <br><br>
  13044. * Transformations apply to everything that happens after and subsequent
  13045. * calls to the function accumulates the effect. For example, calling
  13046. * shearX(PI/2) and then shearX(PI/2) is the same as shearX(PI).
  13047. * If shearX() is called within the draw(), the transformation is reset when
  13048. * the loop begins again.
  13049. * <br><br>
  13050. * Technically, shearX() multiplies the current transformation matrix by a
  13051. * rotation matrix. This function can be further controlled by the
  13052. * push() and pop() functions.
  13053. *
  13054. * @method shearX
  13055. * @param {Number} angle angle of shear specified in radians or degrees,
  13056. * depending on current angleMode
  13057. * @return {p5} the p5 object
  13058. * @example
  13059. * <div>
  13060. * <code>
  13061. * translate(width/4, height/4);
  13062. * shearX(PI/4.0);
  13063. * rect(0, 0, 30, 30);
  13064. * </code>
  13065. * </div>
  13066. *
  13067. * @alt
  13068. * white irregular quadrilateral with black outline at top middle.
  13069. *
  13070. */
  13071. p5.prototype.shearX = function(angle) {
  13072. if (this._angleMode === constants.DEGREES) {
  13073. angle = this.radians(angle);
  13074. }
  13075. this._renderer.shearX(angle);
  13076. return this;
  13077. };
  13078. /**
  13079. * Shears a shape around the y-axis the amount specified by the angle
  13080. * parameter. Angles should be specified in the current angleMode. Objects
  13081. * are always sheared around their relative position to the origin and
  13082. * positive numbers shear objects in a clockwise direction.
  13083. * <br><br>
  13084. * Transformations apply to everything that happens after and subsequent
  13085. * calls to the function accumulates the effect. For example, calling
  13086. * shearY(PI/2) and then shearY(PI/2) is the same as shearY(PI). If
  13087. * shearY() is called within the draw(), the transformation is reset when
  13088. * the loop begins again.
  13089. * <br><br>
  13090. * Technically, shearY() multiplies the current transformation matrix by a
  13091. * rotation matrix. This function can be further controlled by the
  13092. * push() and pop() functions.
  13093. *
  13094. * @method shearY
  13095. * @param {Number} angle angle of shear specified in radians or degrees,
  13096. * depending on current angleMode
  13097. * @return {p5} the p5 object
  13098. * @example
  13099. * <div>
  13100. * <code>
  13101. * translate(width/4, height/4);
  13102. * shearY(PI/4.0);
  13103. * rect(0, 0, 30, 30);
  13104. * </code>
  13105. * </div>
  13106. *
  13107. * @alt
  13108. * white irregular quadrilateral with black outline at middle bottom.
  13109. *
  13110. */
  13111. p5.prototype.shearY = function(angle) {
  13112. if (this._angleMode === constants.DEGREES) {
  13113. angle = this.radians(angle);
  13114. }
  13115. this._renderer.shearY(angle);
  13116. return this;
  13117. };
  13118. /**
  13119. * Specifies an amount to displace objects within the display window.
  13120. * The x parameter specifies left/right translation, the y parameter
  13121. * specifies up/down translation.
  13122. * <br><br>
  13123. * Transformations are cumulative and apply to everything that happens after
  13124. * and subsequent calls to the function accumulates the effect. For example,
  13125. * calling translate(50, 0) and then translate(20, 0) is the same as
  13126. * translate(70, 0). If translate() is called within draw(), the
  13127. * transformation is reset when the loop begins again. This function can be
  13128. * further controlled by using push() and pop().
  13129. *
  13130. * @method translate
  13131. * @param {Number} x left/right translation
  13132. * @param {Number} y up/down translation
  13133. * @param {Number} [z] forward/backward translation (webgl only)
  13134. * @return {p5} the p5 object
  13135. * @example
  13136. * <div>
  13137. * <code>
  13138. * translate(30, 20);
  13139. * rect(0, 0, 55, 55);
  13140. * </code>
  13141. * </div>
  13142. *
  13143. * <div>
  13144. * <code>
  13145. * rect(0, 0, 55, 55); // Draw rect at original 0,0
  13146. * translate(30, 20);
  13147. * rect(0, 0, 55, 55); // Draw rect at new 0,0
  13148. * translate(14, 14);
  13149. * rect(0, 0, 55, 55); // Draw rect at new 0,0
  13150. * </code>
  13151. * </div>
  13152. *
  13153. * @alt
  13154. * white 55x55 rect with black outline at center right.
  13155. * 3 white 55x55 rects with black outlines at top-l, center-r and bottom-r.
  13156. *
  13157. */
  13158. p5.prototype.translate = function(x, y, z) {
  13159. if (this._renderer.isP3D) {
  13160. this._renderer.translate(x, y, z);
  13161. } else {
  13162. this._renderer.translate(x, y);
  13163. }
  13164. return this;
  13165. };
  13166. module.exports = p5;
  13167. },{"./constants":36,"./core":37}],49:[function(_dereq_,module,exports){
  13168. /**
  13169. * @module Shape
  13170. * @submodule Vertex
  13171. * @for p5
  13172. * @requires core
  13173. * @requires constants
  13174. */
  13175. 'use strict';
  13176. var p5 = _dereq_('./core');
  13177. var constants = _dereq_('./constants');
  13178. var shapeKind = null;
  13179. var vertices = [];
  13180. var contourVertices = [];
  13181. var isBezier = false;
  13182. var isCurve = false;
  13183. var isQuadratic = false;
  13184. var isContour = false;
  13185. var isFirstContour = true;
  13186. /**
  13187. * Use the beginContour() and endContour() functions to create negative
  13188. * shapes within shapes such as the center of the letter 'O'. beginContour()
  13189. * begins recording vertices for the shape and endContour() stops recording.
  13190. * The vertices that define a negative shape must "wind" in the opposite
  13191. * direction from the exterior shape. First draw vertices for the exterior
  13192. * clockwise order, then for internal shapes, draw vertices
  13193. * shape in counter-clockwise.
  13194. * <br><br>
  13195. * These functions can only be used within a beginShape()/endShape() pair and
  13196. * transformations such as translate(), rotate(), and scale() do not work
  13197. * within a beginContour()/endContour() pair. It is also not possible to use
  13198. * other shapes, such as ellipse() or rect() within.
  13199. *
  13200. * @method beginContour
  13201. * @return {Object} the p5 object
  13202. * @example
  13203. * <div>
  13204. * <code>
  13205. * translate(50, 50);
  13206. * stroke(255, 0, 0);
  13207. * beginShape();
  13208. * // Exterior part of shape, clockwise winding
  13209. * vertex(-40, -40);
  13210. * vertex(40, -40);
  13211. * vertex(40, 40);
  13212. * vertex(-40, 40);
  13213. * // Interior part of shape, counter-clockwise winding
  13214. * beginContour();
  13215. * vertex(-20, -20);
  13216. * vertex(-20, 20);
  13217. * vertex(20, 20);
  13218. * vertex(20, -20);
  13219. * endContour();
  13220. * endShape(CLOSE);
  13221. * </code>
  13222. * </div>
  13223. *
  13224. * @alt
  13225. * white rect and smaller grey rect with red outlines in center of canvas.
  13226. *
  13227. */
  13228. p5.prototype.beginContour = function() {
  13229. contourVertices = [];
  13230. isContour = true;
  13231. return this;
  13232. };
  13233. /**
  13234. * Using the beginShape() and endShape() functions allow creating more
  13235. * complex forms. beginShape() begins recording vertices for a shape and
  13236. * endShape() stops recording. The value of the kind parameter tells it which
  13237. * types of shapes to create from the provided vertices. With no mode
  13238. * specified, the shape can be any irregular polygon.
  13239. * <br><br>
  13240. * The parameters available for beginShape() are POINTS, LINES, TRIANGLES,
  13241. * TRIANGLE_FAN, TRIANGLE_STRIP, QUADS, and QUAD_STRIP. After calling the
  13242. * beginShape() function, a series of vertex() commands must follow. To stop
  13243. * drawing the shape, call endShape(). Each shape will be outlined with the
  13244. * current stroke color and filled with the fill color.
  13245. * <br><br>
  13246. * Transformations such as translate(), rotate(), and scale() do not work
  13247. * within beginShape(). It is also not possible to use other shapes, such as
  13248. * ellipse() or rect() within beginShape().
  13249. *
  13250. * @method beginShape
  13251. * @param {Constant} kind either POINTS, LINES, TRIANGLES, TRIANGLE_FAN
  13252. * TRIANGLE_STRIP, QUADS, or QUAD_STRIP
  13253. * @return {Object} the p5 object
  13254. * @example
  13255. * <div>
  13256. * <code>
  13257. * beginShape();
  13258. * vertex(30, 20);
  13259. * vertex(85, 20);
  13260. * vertex(85, 75);
  13261. * vertex(30, 75);
  13262. * endShape(CLOSE);
  13263. * </code>
  13264. * </div>
  13265. *
  13266. * <div>
  13267. * <code>
  13268. * // currently not working
  13269. * beginShape(POINTS);
  13270. * vertex(30, 20);
  13271. * vertex(85, 20);
  13272. * vertex(85, 75);
  13273. * vertex(30, 75);
  13274. * endShape();
  13275. * </code>
  13276. * </div>
  13277. *
  13278. * <div>
  13279. * <code>
  13280. * beginShape(LINES);
  13281. * vertex(30, 20);
  13282. * vertex(85, 20);
  13283. * vertex(85, 75);
  13284. * vertex(30, 75);
  13285. * endShape();
  13286. * </code>
  13287. * </div>
  13288. *
  13289. * <div>
  13290. * <code>
  13291. * noFill();
  13292. * beginShape();
  13293. * vertex(30, 20);
  13294. * vertex(85, 20);
  13295. * vertex(85, 75);
  13296. * vertex(30, 75);
  13297. * endShape();
  13298. * </code>
  13299. * </div>
  13300. *
  13301. * <div>
  13302. * <code>
  13303. * noFill();
  13304. * beginShape();
  13305. * vertex(30, 20);
  13306. * vertex(85, 20);
  13307. * vertex(85, 75);
  13308. * vertex(30, 75);
  13309. * endShape(CLOSE);
  13310. * </code>
  13311. * </div>
  13312. *
  13313. * <div>
  13314. * <code>
  13315. * beginShape(TRIANGLES);
  13316. * vertex(30, 75);
  13317. * vertex(40, 20);
  13318. * vertex(50, 75);
  13319. * vertex(60, 20);
  13320. * vertex(70, 75);
  13321. * vertex(80, 20);
  13322. * endShape();
  13323. * </code>
  13324. * </div>
  13325. *
  13326. * <div>
  13327. * <code>
  13328. * beginShape(TRIANGLE_STRIP);
  13329. * vertex(30, 75);
  13330. * vertex(40, 20);
  13331. * vertex(50, 75);
  13332. * vertex(60, 20);
  13333. * vertex(70, 75);
  13334. * vertex(80, 20);
  13335. * vertex(90, 75);
  13336. * endShape();
  13337. * </code>
  13338. * </div>
  13339. *
  13340. * <div>
  13341. * <code>
  13342. * beginShape(TRIANGLE_FAN);
  13343. * vertex(57.5, 50);
  13344. * vertex(57.5, 15);
  13345. * vertex(92, 50);
  13346. * vertex(57.5, 85);
  13347. * vertex(22, 50);
  13348. * vertex(57.5, 15);
  13349. * endShape();
  13350. * </code>
  13351. * </div>
  13352. *
  13353. * <div>
  13354. * <code>
  13355. * beginShape(QUADS);
  13356. * vertex(30, 20);
  13357. * vertex(30, 75);
  13358. * vertex(50, 75);
  13359. * vertex(50, 20);
  13360. * vertex(65, 20);
  13361. * vertex(65, 75);
  13362. * vertex(85, 75);
  13363. * vertex(85, 20);
  13364. * endShape();
  13365. * </code>
  13366. * </div>
  13367. *
  13368. * <div>
  13369. * <code>
  13370. * beginShape(QUAD_STRIP);
  13371. * vertex(30, 20);
  13372. * vertex(30, 75);
  13373. * vertex(50, 20);
  13374. * vertex(50, 75);
  13375. * vertex(65, 20);
  13376. * vertex(65, 75);
  13377. * vertex(85, 20);
  13378. * vertex(85, 75);
  13379. * endShape();
  13380. * </code>
  13381. * </div>
  13382. *
  13383. * <div>
  13384. * <code>
  13385. * beginShape();
  13386. * vertex(20, 20);
  13387. * vertex(40, 20);
  13388. * vertex(40, 40);
  13389. * vertex(60, 40);
  13390. * vertex(60, 60);
  13391. * vertex(20, 60);
  13392. * endShape(CLOSE);
  13393. * </code>
  13394. * </div>
  13395. * @alt
  13396. * white square-shape with black outline in middle-right of canvas.
  13397. * 4 black points in a square shape in middle-right of canvas.
  13398. * 2 horizontal black lines. In the top-right and bottom-right of canvas.
  13399. * 3 line shape with horizontal on top, vertical in middle and horizontal bottom.
  13400. * square line shape in middle-right of canvas.
  13401. * 2 white triangle shapes mid-right canvas. left one pointing up and right down.
  13402. * 5 horizontal interlocking and alternating white triangles in mid-right canvas.
  13403. * 4 interlocking white triangles in 45 degree rotated square-shape.
  13404. * 2 white rectangle shapes in mid-right canvas. Both 20x55.
  13405. * 3 side-by-side white rectangles center rect is smaller in mid-right canvas.
  13406. * Thick white l-shape with black outline mid-top-left of canvas.
  13407. *
  13408. */
  13409. p5.prototype.beginShape = function(kind) {
  13410. if (kind === constants.POINTS ||
  13411. kind === constants.LINES ||
  13412. kind === constants.TRIANGLES ||
  13413. kind === constants.TRIANGLE_FAN ||
  13414. kind === constants.TRIANGLE_STRIP ||
  13415. kind === constants.QUADS ||
  13416. kind === constants.QUAD_STRIP) {
  13417. shapeKind = kind;
  13418. } else {
  13419. shapeKind = null;
  13420. }
  13421. if(this._renderer.isP3D){
  13422. this._renderer.beginShape(kind);
  13423. } else {
  13424. vertices = [];
  13425. contourVertices = [];
  13426. }
  13427. return this;
  13428. };
  13429. /**
  13430. * Specifies vertex coordinates for Bezier curves. Each call to
  13431. * bezierVertex() defines the position of two control points and
  13432. * one anchor point of a Bezier curve, adding a new segment to a
  13433. * line or shape.
  13434. * <br><br>
  13435. * The first time bezierVertex() is used within a
  13436. * beginShape() call, it must be prefaced with a call to vertex()
  13437. * to set the first anchor point. This function must be used between
  13438. * beginShape() and endShape() and only when there is no MODE
  13439. * parameter specified to beginShape().
  13440. *
  13441. * @method bezierVertex
  13442. * @param {Number} x2 x-coordinate for the first control point
  13443. * @param {Number} y2 y-coordinate for the first control point
  13444. * @param {Number} x3 x-coordinate for the second control point
  13445. * @param {Number} y3 y-coordinate for the second control point
  13446. * @param {Number} x4 x-coordinate for the anchor point
  13447. * @param {Number} y4 y-coordinate for the anchor point
  13448. * @return {Object} the p5 object
  13449. * @example
  13450. * <div>
  13451. * <code>
  13452. * noFill();
  13453. * beginShape();
  13454. * vertex(30, 20);
  13455. * bezierVertex(80, 0, 80, 75, 30, 75);
  13456. * endShape();
  13457. * </code>
  13458. * </div>
  13459. *
  13460. * <div>
  13461. * <code>
  13462. * beginShape();
  13463. * vertex(30, 20);
  13464. * bezierVertex(80, 0, 80, 75, 30, 75);
  13465. * bezierVertex(50, 80, 60, 25, 30, 20);
  13466. * endShape();
  13467. * </code>
  13468. * </div>
  13469. *
  13470. * @alt
  13471. * crescent-shaped line in middle of canvas. Points facing left.
  13472. * white crescent shape in middle of canvas. Points facing left.
  13473. *
  13474. */
  13475. p5.prototype.bezierVertex = function(x2, y2, x3, y3, x4, y4) {
  13476. if (vertices.length === 0) {
  13477. throw 'vertex() must be used once before calling bezierVertex()';
  13478. } else {
  13479. isBezier = true;
  13480. var vert = [];
  13481. for (var i = 0; i < arguments.length; i++) {
  13482. vert[i] = arguments[i];
  13483. }
  13484. vert.isVert = false;
  13485. if (isContour) {
  13486. contourVertices.push(vert);
  13487. } else {
  13488. vertices.push(vert);
  13489. }
  13490. }
  13491. return this;
  13492. };
  13493. /**
  13494. * Specifies vertex coordinates for curves. This function may only
  13495. * be used between beginShape() and endShape() and only when there
  13496. * is no MODE parameter specified to beginShape().
  13497. * <br><br>
  13498. * The first and last points in a series of curveVertex() lines will be used to
  13499. * guide the beginning and end of a the curve. A minimum of four
  13500. * points is required to draw a tiny curve between the second and
  13501. * third points. Adding a fifth point with curveVertex() will draw
  13502. * the curve between the second, third, and fourth points. The
  13503. * curveVertex() function is an implementation of Catmull-Rom
  13504. * splines.
  13505. *
  13506. * @method curveVertex
  13507. * @param {Number} x x-coordinate of the vertex
  13508. * @param {Number} y y-coordinate of the vertex
  13509. * @return {Object} the p5 object
  13510. * @example
  13511. * <div>
  13512. * <code>
  13513. * noFill();
  13514. * beginShape();
  13515. * curveVertex(84, 91);
  13516. * curveVertex(84, 91);
  13517. * curveVertex(68, 19);
  13518. * curveVertex(21, 17);
  13519. * curveVertex(32, 100);
  13520. * curveVertex(32, 100);
  13521. * endShape();
  13522. * </code>
  13523. * </div>
  13524. *
  13525. * @alt
  13526. * Upside-down u-shape line, mid canvas. left point extends beyond canvas view.
  13527. *
  13528. */
  13529. p5.prototype.curveVertex = function(x,y) {
  13530. isCurve = true;
  13531. this.vertex(x, y);
  13532. return this;
  13533. };
  13534. /**
  13535. * Use the beginContour() and endContour() functions to create negative
  13536. * shapes within shapes such as the center of the letter 'O'. beginContour()
  13537. * begins recording vertices for the shape and endContour() stops recording.
  13538. * The vertices that define a negative shape must "wind" in the opposite
  13539. * direction from the exterior shape. First draw vertices for the exterior
  13540. * clockwise order, then for internal shapes, draw vertices
  13541. * shape in counter-clockwise.
  13542. * <br><br>
  13543. * These functions can only be used within a beginShape()/endShape() pair and
  13544. * transformations such as translate(), rotate(), and scale() do not work
  13545. * within a beginContour()/endContour() pair. It is also not possible to use
  13546. * other shapes, such as ellipse() or rect() within.
  13547. *
  13548. * @method endContour
  13549. * @return {Object} the p5 object
  13550. * @example
  13551. * <div>
  13552. * <code>
  13553. * translate(50, 50);
  13554. * stroke(255, 0, 0);
  13555. * beginShape();
  13556. * // Exterior part of shape, clockwise winding
  13557. * vertex(-40, -40);
  13558. * vertex(40, -40);
  13559. * vertex(40, 40);
  13560. * vertex(-40, 40);
  13561. * // Interior part of shape, counter-clockwise winding
  13562. * beginContour();
  13563. * vertex(-20, -20);
  13564. * vertex(-20, 20);
  13565. * vertex(20, 20);
  13566. * vertex(20, -20);
  13567. * endContour();
  13568. * endShape(CLOSE);
  13569. * </code>
  13570. * </div>
  13571. *
  13572. * @alt
  13573. * white rect and smaller grey rect with red outlines in center of canvas.
  13574. *
  13575. */
  13576. p5.prototype.endContour = function() {
  13577. var vert = contourVertices[0].slice(); // copy all data
  13578. vert.isVert = contourVertices[0].isVert;
  13579. vert.moveTo = false;
  13580. contourVertices.push(vert);
  13581. // prevent stray lines with multiple contours
  13582. if (isFirstContour) {
  13583. vertices.push(vertices[0]);
  13584. isFirstContour = false;
  13585. }
  13586. for (var i = 0; i < contourVertices.length; i++) {
  13587. vertices.push(contourVertices[i]);
  13588. }
  13589. return this;
  13590. };
  13591. /**
  13592. * The endShape() function is the companion to beginShape() and may only be
  13593. * called after beginShape(). When endshape() is called, all of image data
  13594. * defined since the previous call to beginShape() is written into the image
  13595. * buffer. The constant CLOSE as the value for the MODE parameter to close
  13596. * the shape (to connect the beginning and the end).
  13597. *
  13598. * @method endShape
  13599. * @param {Constant} mode use CLOSE to close the shape
  13600. * @return {Object} the p5 object
  13601. * @example
  13602. * <div>
  13603. * <code>
  13604. * noFill();
  13605. *
  13606. * beginShape();
  13607. * vertex(20, 20);
  13608. * vertex(45, 20);
  13609. * vertex(45, 80);
  13610. * endShape(CLOSE);
  13611. *
  13612. * beginShape();
  13613. * vertex(50, 20);
  13614. * vertex(75, 20);
  13615. * vertex(75, 80);
  13616. * endShape();
  13617. * </code>
  13618. * </div>
  13619. *
  13620. * @alt
  13621. * Triangle line shape with smallest interior angle on bottom and upside-down L.
  13622. *
  13623. */
  13624. p5.prototype.endShape = function(mode) {
  13625. if(this._renderer.isP3D){
  13626. this._renderer.endShape(mode, isCurve, isBezier,
  13627. isQuadratic, isContour, shapeKind);
  13628. }else{
  13629. if (vertices.length === 0) { return this; }
  13630. if (!this._renderer._doStroke && !this._renderer._doFill) { return this; }
  13631. var closeShape = mode === constants.CLOSE;
  13632. // if the shape is closed, the first element is also the last element
  13633. if (closeShape && !isContour) {
  13634. vertices.push(vertices[0]);
  13635. }
  13636. this._renderer.endShape(mode, vertices, isCurve, isBezier,
  13637. isQuadratic, isContour, shapeKind);
  13638. // Reset some settings
  13639. isCurve = false;
  13640. isBezier = false;
  13641. isQuadratic = false;
  13642. isContour = false;
  13643. isFirstContour = true;
  13644. // If the shape is closed, the first element was added as last element.
  13645. // We must remove it again to prevent the list of vertices from growing
  13646. // over successive calls to endShape(CLOSE)
  13647. if (closeShape) {
  13648. vertices.pop();
  13649. }
  13650. }
  13651. return this;
  13652. };
  13653. /**
  13654. * Specifies vertex coordinates for quadratic Bezier curves. Each call to
  13655. * quadraticVertex() defines the position of one control points and one
  13656. * anchor point of a Bezier curve, adding a new segment to a line or shape.
  13657. * The first time quadraticVertex() is used within a beginShape() call, it
  13658. * must be prefaced with a call to vertex() to set the first anchor point.
  13659. * This function must be used between beginShape() and endShape() and only
  13660. * when there is no MODE parameter specified to beginShape().
  13661. *
  13662. * @method quadraticVertex
  13663. * @param {Number} cx x-coordinate for the control point
  13664. * @param {Number} cy y-coordinate for the control point
  13665. * @param {Number} x3 x-coordinate for the anchor point
  13666. * @param {Number} y3 y-coordinate for the anchor point
  13667. * @return {Object} the p5 object
  13668. * @example
  13669. * <div>
  13670. * <code>
  13671. * noFill();
  13672. * strokeWeight(4);
  13673. * beginShape();
  13674. * vertex(20, 20);
  13675. * quadraticVertex(80, 20, 50, 50);
  13676. * endShape();
  13677. * </code>
  13678. * </div>
  13679. *
  13680. * <div>
  13681. * <code>
  13682. * noFill();
  13683. * strokeWeight(4);
  13684. * beginShape();
  13685. * vertex(20, 20);
  13686. * quadraticVertex(80, 20, 50, 50);
  13687. * quadraticVertex(20, 80, 80, 80);
  13688. * vertex(80, 60);
  13689. * endShape();
  13690. * </code>
  13691. * </div>
  13692. *
  13693. * @alt
  13694. * arched-shaped black line with 4 pixel thick stroke weight.
  13695. * backwards s-shaped black line with 4 pixel thick stroke weight.
  13696. *
  13697. */
  13698. p5.prototype.quadraticVertex = function(cx, cy, x3, y3) {
  13699. //if we're drawing a contour, put the points into an
  13700. // array for inside drawing
  13701. if(this._contourInited) {
  13702. var pt = {};
  13703. pt.x = cx;
  13704. pt.y = cy;
  13705. pt.x3 = x3;
  13706. pt.y3 = y3;
  13707. pt.type = constants.QUADRATIC;
  13708. this._contourVertices.push(pt);
  13709. return this;
  13710. }
  13711. if (vertices.length > 0) {
  13712. isQuadratic = true;
  13713. var vert = [];
  13714. for (var i = 0; i < arguments.length; i++) {
  13715. vert[i] = arguments[i];
  13716. }
  13717. vert.isVert = false;
  13718. if (isContour) {
  13719. contourVertices.push(vert);
  13720. } else {
  13721. vertices.push(vert);
  13722. }
  13723. } else {
  13724. throw 'vertex() must be used once before calling quadraticVertex()';
  13725. }
  13726. return this;
  13727. };
  13728. /**
  13729. * All shapes are constructed by connecting a series of vertices. vertex()
  13730. * is used to specify the vertex coordinates for points, lines, triangles,
  13731. * quads, and polygons. It is used exclusively within the beginShape() and
  13732. * endShape() functions.
  13733. *
  13734. * @method vertex
  13735. * @param {Number} x x-coordinate of the vertex
  13736. * @param {Number} y y-coordinate of the vertex
  13737. * @return {Object} the p5 object
  13738. * @example
  13739. * <div>
  13740. * <code>
  13741. * beginShape(POINTS);
  13742. * vertex(30, 20);
  13743. * vertex(85, 20);
  13744. * vertex(85, 75);
  13745. * vertex(30, 75);
  13746. * endShape();
  13747. * </code>
  13748. * </div>
  13749. *
  13750. * @alt
  13751. * 4 black points in a square shape in middle-right of canvas.
  13752. *
  13753. */
  13754. p5.prototype.vertex = function(x, y, moveTo) {
  13755. if(this._renderer.isP3D){
  13756. this._renderer.vertex(x, y, moveTo);
  13757. }else{
  13758. var vert = [];
  13759. vert.isVert = true;
  13760. vert[0] = x;
  13761. vert[1] = y;
  13762. vert[2] = 0;
  13763. vert[3] = 0;
  13764. vert[4] = 0;
  13765. vert[5] = this._renderer._getFill();
  13766. vert[6] = this._renderer._getStroke();
  13767. if (moveTo) {
  13768. vert.moveTo = moveTo;
  13769. }
  13770. if (isContour) {
  13771. if (contourVertices.length === 0) {
  13772. vert.moveTo = true;
  13773. }
  13774. contourVertices.push(vert);
  13775. } else {
  13776. vertices.push(vert);
  13777. }
  13778. }
  13779. return this;
  13780. };
  13781. module.exports = p5;
  13782. },{"./constants":36,"./core":37}],50:[function(_dereq_,module,exports){
  13783. /**
  13784. * @module Events
  13785. * @submodule Acceleration
  13786. * @for p5
  13787. * @requires core
  13788. */
  13789. 'use strict';
  13790. var p5 = _dereq_('../core/core');
  13791. /**
  13792. * The system variable deviceOrientation always contains the orientation of
  13793. * the device. The value of this variable will either be set 'landscape'
  13794. * or 'portrait'. If no data is available it will be set to 'undefined'.
  13795. *
  13796. * @property deviceOrientation
  13797. */
  13798. p5.prototype.deviceOrientation = undefined;
  13799. /**
  13800. * The system variable accelerationX always contains the acceleration of the
  13801. * device along the x axis. Value is represented as meters per second squared.
  13802. *
  13803. * @property accelerationX
  13804. */
  13805. p5.prototype.accelerationX = 0;
  13806. /**
  13807. * The system variable accelerationY always contains the acceleration of the
  13808. * device along the y axis. Value is represented as meters per second squared.
  13809. *
  13810. * @property accelerationY
  13811. */
  13812. p5.prototype.accelerationY = 0;
  13813. /**
  13814. * The system variable accelerationZ always contains the acceleration of the
  13815. * device along the z axis. Value is represented as meters per second squared.
  13816. *
  13817. * @property accelerationZ
  13818. */
  13819. p5.prototype.accelerationZ = 0;
  13820. /**
  13821. * The system variable pAccelerationX always contains the acceleration of the
  13822. * device along the x axis in the frame previous to the current frame. Value
  13823. * is represented as meters per second squared.
  13824. *
  13825. * @property pAccelerationX
  13826. */
  13827. p5.prototype.pAccelerationX = 0;
  13828. /**
  13829. * The system variable pAccelerationY always contains the acceleration of the
  13830. * device along the y axis in the frame previous to the current frame. Value
  13831. * is represented as meters per second squared.
  13832. *
  13833. * @property pAccelerationY
  13834. */
  13835. p5.prototype.pAccelerationY = 0;
  13836. /**
  13837. * The system variable pAccelerationZ always contains the acceleration of the
  13838. * device along the z axis in the frame previous to the current frame. Value
  13839. * is represented as meters per second squared.
  13840. *
  13841. * @property pAccelerationZ
  13842. */
  13843. p5.prototype.pAccelerationZ = 0;
  13844. /**
  13845. * _updatePAccelerations updates the pAcceleration values
  13846. *
  13847. * @private
  13848. */
  13849. p5.prototype._updatePAccelerations = function(){
  13850. this._setProperty('pAccelerationX', this.accelerationX);
  13851. this._setProperty('pAccelerationY', this.accelerationY);
  13852. this._setProperty('pAccelerationZ', this.accelerationZ);
  13853. };
  13854. /**
  13855. * The system variable rotationX always contains the rotation of the
  13856. * device along the x axis. Value is represented as 0 to +/-180 degrees.
  13857. * <br><br>
  13858. * Note: The order the rotations are called is important, ie. if used
  13859. * together, it must be called in the order Z-X-Y or there might be
  13860. * unexpected behaviour.
  13861. *
  13862. * @example
  13863. * <div>
  13864. * <code>
  13865. * function setup(){
  13866. * createCanvas(100, 100, WEBGL);
  13867. * }
  13868. *
  13869. * function draw(){
  13870. * background(200);
  13871. * //rotateZ(radians(rotationZ));
  13872. * rotateX(radians(rotationX));
  13873. * //rotateY(radians(rotationY));
  13874. * box(200, 200, 200);
  13875. * }
  13876. * </code>
  13877. * </div>
  13878. *
  13879. * @property rotationX
  13880. *
  13881. * @alt
  13882. * red horizontal line right, green vertical line bottom. black background.
  13883. *
  13884. */
  13885. p5.prototype.rotationX = 0;
  13886. /**
  13887. * The system variable rotationY always contains the rotation of the
  13888. * device along the y axis. Value is represented as 0 to +/-90 degrees.
  13889. * <br><br>
  13890. * Note: The order the rotations are called is important, ie. if used
  13891. * together, it must be called in the order Z-X-Y or there might be
  13892. * unexpected behaviour.
  13893. *
  13894. * @example
  13895. * <div>
  13896. * <code>
  13897. * function setup(){
  13898. * createCanvas(100, 100, WEBGL);
  13899. * }
  13900. *
  13901. * function draw(){
  13902. * background(200);
  13903. * //rotateZ(radians(rotationZ));
  13904. * //rotateX(radians(rotationX));
  13905. * rotateY(radians(rotationY));
  13906. * box(200, 200, 200);
  13907. * }
  13908. * </code>
  13909. * </div>
  13910. *
  13911. * @property rotationY
  13912. *
  13913. * @alt
  13914. * red horizontal line right, green vertical line bottom. black background.
  13915. */
  13916. p5.prototype.rotationY = 0;
  13917. /**
  13918. * The system variable rotationZ always contains the rotation of the
  13919. * device along the z axis. Value is represented as 0 to 359 degrees.
  13920. * <br><br>
  13921. * Unlike rotationX and rotationY, this variable is available for devices
  13922. * with a built-in compass only.
  13923. * <br><br>
  13924. * Note: The order the rotations are called is important, ie. if used
  13925. * together, it must be called in the order Z-X-Y or there might be
  13926. * unexpected behaviour.
  13927. *
  13928. * @example
  13929. * <div>
  13930. * <code>
  13931. * function setup(){
  13932. * createCanvas(100, 100, WEBGL);
  13933. * }
  13934. *
  13935. * function draw(){
  13936. * background(200);
  13937. * rotateZ(radians(rotationZ));
  13938. * //rotateX(radians(rotationX));
  13939. * //rotateY(radians(rotationY));
  13940. * box(200, 200, 200);
  13941. * }
  13942. * </code>
  13943. * </div>
  13944. *
  13945. * @property rotationZ
  13946. *
  13947. * @alt
  13948. * red horizontal line right, green vertical line bottom. black background.
  13949. */
  13950. p5.prototype.rotationZ = 0;
  13951. /**
  13952. * The system variable pRotationX always contains the rotation of the
  13953. * device along the x axis in the frame previous to the current frame. Value
  13954. * is represented as 0 to +/-180 degrees.
  13955. * <br><br>
  13956. * pRotationX can also be used with rotationX to determine the rotate
  13957. * direction of the device along the X-axis.
  13958. * @example
  13959. * <div class='norender'>
  13960. * <code>
  13961. * // A simple if statement looking at whether
  13962. * // rotationX - pRotationX < 0 is true or not will be
  13963. * // sufficient for determining the rotate direction
  13964. * // in most cases.
  13965. *
  13966. * // Some extra logic is needed to account for cases where
  13967. * // the angles wrap around.
  13968. * var rotateDirection = 'clockwise';
  13969. *
  13970. * // Simple range conversion to make things simpler.
  13971. * // This is not absolutely neccessary but the logic
  13972. * // will be different in that case.
  13973. *
  13974. * var rX = rotationX + 180;
  13975. * var pRX = pRotationX + 180;
  13976. *
  13977. * if ((rX - pRX > 0 && rX - pRX < 270)|| rX - pRX < -270){
  13978. * rotateDirection = 'clockwise';
  13979. * } else if (rX - pRX < 0 || rX - pRX > 270){
  13980. * rotateDirection = 'counter-clockwise';
  13981. * }
  13982. * </code>
  13983. * </div>
  13984. *
  13985. * @alt
  13986. * no image to display.
  13987. *
  13988. *
  13989. * @property pRotationX
  13990. */
  13991. p5.prototype.pRotationX = 0;
  13992. /**
  13993. * The system variable pRotationY always contains the rotation of the
  13994. * device along the y axis in the frame previous to the current frame. Value
  13995. * is represented as 0 to +/-90 degrees.
  13996. * <br><br>
  13997. * pRotationY can also be used with rotationY to determine the rotate
  13998. * direction of the device along the Y-axis.
  13999. * @example
  14000. * <div class='norender'>
  14001. * <code>
  14002. * // A simple if statement looking at whether
  14003. * // rotationY - pRotationY < 0 is true or not will be
  14004. * // sufficient for determining the rotate direction
  14005. * // in most cases.
  14006. *
  14007. * // Some extra logic is needed to account for cases where
  14008. * // the angles wrap around.
  14009. * var rotateDirection = 'clockwise';
  14010. *
  14011. * // Simple range conversion to make things simpler.
  14012. * // This is not absolutely neccessary but the logic
  14013. * // will be different in that case.
  14014. *
  14015. * var rY = rotationY + 180;
  14016. * var pRY = pRotationY + 180;
  14017. *
  14018. * if ((rY - pRY > 0 && rY - pRY < 270)|| rY - pRY < -270){
  14019. * rotateDirection = 'clockwise';
  14020. * } else if (rY - pRY < 0 || rY - pRY > 270){
  14021. * rotateDirection = 'counter-clockwise';
  14022. * }
  14023. * </code>
  14024. * </div>
  14025. *
  14026. * @alt
  14027. * no image to display.
  14028. *
  14029. *
  14030. * @property pRotationY
  14031. */
  14032. p5.prototype.pRotationY = 0;
  14033. /**
  14034. * The system variable pRotationZ always contains the rotation of the
  14035. * device along the z axis in the frame previous to the current frame. Value
  14036. * is represented as 0 to 359 degrees.
  14037. * <br><br>
  14038. * pRotationZ can also be used with rotationZ to determine the rotate
  14039. * direction of the device along the Z-axis.
  14040. * @example
  14041. * <div class='norender'>
  14042. * <code>
  14043. * // A simple if statement looking at whether
  14044. * // rotationZ - pRotationZ < 0 is true or not will be
  14045. * // sufficient for determining the rotate direction
  14046. * // in most cases.
  14047. *
  14048. * // Some extra logic is needed to account for cases where
  14049. * // the angles wrap around.
  14050. * var rotateDirection = 'clockwise';
  14051. *
  14052. * if ((rotationZ - pRotationZ > 0 &&
  14053. * rotationZ - pRotationZ < 270)||
  14054. * rotationZ - pRotationZ < -270){
  14055. *
  14056. * rotateDirection = 'clockwise';
  14057. *
  14058. * } else if (rotationZ - pRotationZ < 0 ||
  14059. * rotationZ - pRotationZ > 270){
  14060. *
  14061. * rotateDirection = 'counter-clockwise';
  14062. *
  14063. * }
  14064. * </code>
  14065. * </div>
  14066. *
  14067. * @alt
  14068. * no image to display.
  14069. *
  14070. *
  14071. * @property pRotationZ
  14072. */
  14073. p5.prototype.pRotationZ = 0;
  14074. var startAngleX = 0;
  14075. var startAngleY = 0;
  14076. var startAngleZ = 0;
  14077. var rotateDirectionX = 'clockwise';
  14078. var rotateDirectionY = 'clockwise';
  14079. var rotateDirectionZ = 'clockwise';
  14080. var pRotateDirectionX;
  14081. var pRotateDirectionY;
  14082. var pRotateDirectionZ;
  14083. p5.prototype._updatePRotations = function(){
  14084. this._setProperty('pRotationX', this.rotationX);
  14085. this._setProperty('pRotationY', this.rotationY);
  14086. this._setProperty('pRotationZ', this.rotationZ);
  14087. };
  14088. p5.prototype.turnAxis = undefined;
  14089. var move_threshold = 0.5;
  14090. var shake_threshold = 30;
  14091. /**
  14092. * The setMoveThreshold() function is used to set the movement threshold for
  14093. * the deviceMoved() function. The default threshold is set to 0.5.
  14094. *
  14095. * @method setMoveThreshold
  14096. * @param {number} value The threshold value
  14097. */
  14098. p5.prototype.setMoveThreshold = function(val){
  14099. if(typeof val === 'number'){
  14100. move_threshold = val;
  14101. }
  14102. };
  14103. /**
  14104. * The setShakeThreshold() function is used to set the movement threshold for
  14105. * the deviceShaken() function. The default threshold is set to 30.
  14106. *
  14107. * @method setShakeThreshold
  14108. * @param {number} value The threshold value
  14109. */
  14110. p5.prototype.setShakeThreshold = function(val){
  14111. if(typeof val === 'number'){
  14112. shake_threshold = val;
  14113. }
  14114. };
  14115. /**
  14116. * The deviceMoved() function is called when the device is moved by more than
  14117. * the threshold value along X, Y or Z axis. The default threshold is set to
  14118. * 0.5.
  14119. * @method deviceMoved
  14120. * @example
  14121. * <div class="norender">
  14122. * <code>
  14123. * // Run this example on a mobile device
  14124. * // Move the device around
  14125. * // to change the value.
  14126. *
  14127. * var value = 0;
  14128. * function draw() {
  14129. * fill(value);
  14130. * rect(25, 25, 50, 50);
  14131. * }
  14132. * function deviceMoved() {
  14133. * value = value + 5;
  14134. * if (value > 255) {
  14135. * value = 0;
  14136. * }
  14137. * }
  14138. * </code>
  14139. * </div>
  14140. *
  14141. * @alt
  14142. * 50x50 black rect in center of canvas. turns white on mobile when device moves
  14143. *
  14144. */
  14145. /**
  14146. * The deviceTurned() function is called when the device rotates by
  14147. * more than 90 degrees continuously.
  14148. * <br><br>
  14149. * The axis that triggers the deviceTurned() method is stored in the turnAxis
  14150. * variable. The deviceTurned() method can be locked to trigger on any axis:
  14151. * X, Y or Z by comparing the turnAxis variable to 'X', 'Y' or 'Z'.
  14152. *
  14153. * @method deviceTurned
  14154. * @example
  14155. * <div class="norender">
  14156. * <code>
  14157. * // Run this example on a mobile device
  14158. * // Rotate the device by 90 degrees
  14159. * // to change the value.
  14160. *
  14161. * var value = 0;
  14162. * function draw() {
  14163. * fill(value);
  14164. * rect(25, 25, 50, 50);
  14165. * }
  14166. * function deviceTurned() {
  14167. * if (value == 0){
  14168. * value = 255
  14169. * } else if (value == 255) {
  14170. * value = 0;
  14171. * }
  14172. * }
  14173. * </code>
  14174. * </div>
  14175. * <div>
  14176. * <code>
  14177. * // Run this example on a mobile device
  14178. * // Rotate the device by 90 degrees in the
  14179. * // X-axis to change the value.
  14180. *
  14181. * var value = 0;
  14182. * function draw() {
  14183. * fill(value);
  14184. * rect(25, 25, 50, 50);
  14185. * }
  14186. * function deviceTurned() {
  14187. * if (turnAxis == 'X'){
  14188. * if (value == 0){
  14189. * value = 255
  14190. * } else if (value == 255) {
  14191. * value = 0;
  14192. * }
  14193. * }
  14194. * }
  14195. * </code>
  14196. * </div>
  14197. *
  14198. * @alt
  14199. * 50x50 black rect in center of canvas. turns white on mobile when device turns
  14200. * 50x50 black rect in center of canvas. turns white on mobile when x-axis turns
  14201. *
  14202. */
  14203. /**
  14204. * The deviceShaken() function is called when the device total acceleration
  14205. * changes of accelerationX and accelerationY values is more than
  14206. * the threshold value. The default threshold is set to 30.
  14207. * @method deviceShaken
  14208. * @example
  14209. * <div class="norender">
  14210. * <code>
  14211. * // Run this example on a mobile device
  14212. * // Shake the device to change the value.
  14213. *
  14214. * var value = 0;
  14215. * function draw() {
  14216. * fill(value);
  14217. * rect(25, 25, 50, 50);
  14218. * }
  14219. * function deviceShaken() {
  14220. * value = value + 5;
  14221. * if (value > 255) {
  14222. * value = 0;
  14223. * }
  14224. * }
  14225. * </code>
  14226. * </div>
  14227. *
  14228. * @alt
  14229. * 50x50 black rect in center of canvas. turns white on mobile when device shakes
  14230. *
  14231. */
  14232. p5.prototype._ondeviceorientation = function (e) {
  14233. this._updatePRotations();
  14234. this._setProperty('rotationX', e.beta);
  14235. this._setProperty('rotationY', e.gamma);
  14236. this._setProperty('rotationZ', e.alpha);
  14237. this._handleMotion();
  14238. };
  14239. p5.prototype._ondevicemotion = function (e) {
  14240. this._updatePAccelerations();
  14241. this._setProperty('accelerationX', e.acceleration.x * 2);
  14242. this._setProperty('accelerationY', e.acceleration.y * 2);
  14243. this._setProperty('accelerationZ', e.acceleration.z * 2);
  14244. this._handleMotion();
  14245. };
  14246. p5.prototype._handleMotion = function() {
  14247. if (window.orientation === 90 || window.orientation === -90) {
  14248. this._setProperty('deviceOrientation', 'landscape');
  14249. } else if (window.orientation === 0) {
  14250. this._setProperty('deviceOrientation', 'portrait');
  14251. } else if (window.orientation === undefined) {
  14252. this._setProperty('deviceOrientation', 'undefined');
  14253. }
  14254. var deviceMoved = this.deviceMoved || window.deviceMoved;
  14255. if (typeof deviceMoved === 'function') {
  14256. if (Math.abs(this.accelerationX - this.pAccelerationX) > move_threshold ||
  14257. Math.abs(this.accelerationY - this.pAccelerationY) > move_threshold ||
  14258. Math.abs(this.accelerationZ - this.pAccelerationZ) > move_threshold) {
  14259. deviceMoved();
  14260. }
  14261. }
  14262. var deviceTurned = this.deviceTurned || window.deviceTurned;
  14263. if (typeof deviceTurned === 'function') {
  14264. // The angles given by rotationX etc is from range -180 to 180.
  14265. // The following will convert them to 0 to 360 for ease of calculation
  14266. // of cases when the angles wrapped around.
  14267. // _startAngleX will be converted back at the end and updated.
  14268. var wRX = this.rotationX + 180;
  14269. var wPRX = this.pRotationX + 180;
  14270. var wSAX = startAngleX + 180;
  14271. if ((wRX - wPRX > 0 && wRX - wPRX < 270)|| wRX - wPRX < -270){
  14272. rotateDirectionX = 'clockwise';
  14273. } else if (wRX - wPRX < 0 || wRX - wPRX > 270){
  14274. rotateDirectionX = 'counter-clockwise';
  14275. }
  14276. if (rotateDirectionX !== pRotateDirectionX){
  14277. wSAX = wRX;
  14278. }
  14279. if (Math.abs(wRX - wSAX) > 90 && Math.abs(wRX - wSAX) < 270){
  14280. wSAX = wRX;
  14281. this._setProperty('turnAxis', 'X');
  14282. deviceTurned();
  14283. }
  14284. pRotateDirectionX = rotateDirectionX;
  14285. startAngleX = wSAX - 180;
  14286. // Y-axis is identical to X-axis except for changing some names.
  14287. var wRY = this.rotationY + 180;
  14288. var wPRY = this.pRotationY + 180;
  14289. var wSAY = startAngleY + 180;
  14290. if ((wRY - wPRY > 0 && wRY - wPRY < 270)|| wRY - wPRY < -270){
  14291. rotateDirectionY = 'clockwise';
  14292. } else if (wRY - wPRY < 0 || wRY - this.pRotationY > 270){
  14293. rotateDirectionY = 'counter-clockwise';
  14294. }
  14295. if (rotateDirectionY !== pRotateDirectionY){
  14296. wSAY = wRY;
  14297. }
  14298. if (Math.abs(wRY - wSAY) > 90 && Math.abs(wRY - wSAY) < 270){
  14299. wSAY = wRY;
  14300. this._setProperty('turnAxis', 'Y');
  14301. deviceTurned();
  14302. }
  14303. pRotateDirectionY = rotateDirectionY;
  14304. startAngleY = wSAY - 180;
  14305. // Z-axis is already in the range 0 to 360
  14306. // so no conversion is needed.
  14307. if ((this.rotationZ - this.pRotationZ > 0 &&
  14308. this.rotationZ - this.pRotationZ < 270)||
  14309. this.rotationZ - this.pRotationZ < -270){
  14310. rotateDirectionZ = 'clockwise';
  14311. } else if (this.rotationZ - this.pRotationZ < 0 ||
  14312. this.rotationZ - this.pRotationZ > 270){
  14313. rotateDirectionZ = 'counter-clockwise';
  14314. }
  14315. if (rotateDirectionZ !== pRotateDirectionZ){
  14316. startAngleZ = this.rotationZ;
  14317. }
  14318. if (Math.abs(this.rotationZ - startAngleZ) > 90 &&
  14319. Math.abs(this.rotationZ - startAngleZ) < 270){
  14320. startAngleZ = this.rotationZ;
  14321. this._setProperty('turnAxis', 'Z');
  14322. deviceTurned();
  14323. }
  14324. pRotateDirectionZ = rotateDirectionZ;
  14325. this._setProperty('turnAxis', undefined);
  14326. }
  14327. var deviceShaken = this.deviceShaken || window.deviceShaken;
  14328. if (typeof deviceShaken === 'function') {
  14329. var accelerationChangeX;
  14330. var accelerationChangeY;
  14331. // Add accelerationChangeZ if acceleration change on Z is needed
  14332. if (this.pAccelerationX !== null) {
  14333. accelerationChangeX = Math.abs(this.accelerationX - this.pAccelerationX);
  14334. accelerationChangeY = Math.abs(this.accelerationY - this.pAccelerationY);
  14335. }
  14336. if (accelerationChangeX + accelerationChangeY > shake_threshold) {
  14337. deviceShaken();
  14338. }
  14339. }
  14340. };
  14341. module.exports = p5;
  14342. },{"../core/core":37}],51:[function(_dereq_,module,exports){
  14343. /**
  14344. * @module Events
  14345. * @submodule Keyboard
  14346. * @for p5
  14347. * @requires core
  14348. */
  14349. 'use strict';
  14350. var p5 = _dereq_('../core/core');
  14351. /**
  14352. * Holds the key codes of currently pressed keys.
  14353. * @private
  14354. */
  14355. var downKeys = {};
  14356. /**
  14357. * The boolean system variable keyIsPressed is true if any key is pressed
  14358. * and false if no keys are pressed.
  14359. *
  14360. * @property keyIsPressed
  14361. * @example
  14362. * <div>
  14363. * <code>
  14364. * var value = 0;
  14365. * function draw() {
  14366. * if (keyIsPressed === true) {
  14367. * fill(0);
  14368. * } else {
  14369. * fill(255);
  14370. * }
  14371. * rect(25, 25, 50, 50);
  14372. * }
  14373. * </code>
  14374. * </div>
  14375. *
  14376. * @alt
  14377. * 50x50 white rect that turns black on keypress.
  14378. *
  14379. */
  14380. p5.prototype.isKeyPressed = false;
  14381. p5.prototype.keyIsPressed = false; // khan
  14382. /**
  14383. * The system variable key always contains the value of the most recent
  14384. * key on the keyboard that was typed. To get the proper capitalization, it
  14385. * is best to use it within keyTyped(). For non-ASCII keys, use the keyCode
  14386. * variable.
  14387. *
  14388. * @property key
  14389. * @example
  14390. * <div><code>
  14391. * // Click any key to display it!
  14392. * // (Not Guaranteed to be Case Sensitive)
  14393. * function setup() {
  14394. * fill(245, 123, 158);
  14395. * textSize(50);
  14396. * }
  14397. *
  14398. * function draw() {
  14399. * background(200);
  14400. * text(key, 33,65); // Display last key pressed.
  14401. * }
  14402. * </div></code>
  14403. *
  14404. * @alt
  14405. * canvas displays any key value that is pressed in pink font.
  14406. *
  14407. */
  14408. p5.prototype.key = '';
  14409. /**
  14410. * The variable keyCode is used to detect special keys such as BACKSPACE,
  14411. * DELETE, ENTER, RETURN, TAB, ESCAPE, SHIFT, CONTROL, OPTION, ALT, UP_ARROW,
  14412. * DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW.
  14413. * You can also check for custom keys by looking up the keyCode of any key
  14414. * on a site like this: <a href="http://keycode.info/">keycode.info</a>.
  14415. *
  14416. * @property keyCode
  14417. * @example
  14418. * <div><code>
  14419. * var fillVal = 126;
  14420. * function draw() {
  14421. * fill(fillVal);
  14422. * rect(25, 25, 50, 50);
  14423. * }
  14424. *
  14425. * function keyPressed() {
  14426. * if (keyCode == UP_ARROW) {
  14427. * fillVal = 255;
  14428. * } else if (keyCode == DOWN_ARROW) {
  14429. * fillVal = 0;
  14430. * }
  14431. * return false; // prevent default
  14432. * }
  14433. * </code></div>
  14434. *
  14435. * @alt
  14436. * Grey rect center. turns white when up arrow pressed and black when down
  14437. *
  14438. */
  14439. p5.prototype.keyCode = 0;
  14440. /**
  14441. * The keyPressed() function is called once every time a key is pressed. The
  14442. * keyCode for the key that was pressed is stored in the keyCode variable.
  14443. * <br><br>
  14444. * For non-ASCII keys, use the keyCode variable. You can check if the keyCode
  14445. * equals BACKSPACE, DELETE, ENTER, RETURN, TAB, ESCAPE, SHIFT, CONTROL,
  14446. * OPTION, ALT, UP_ARROW, DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW.
  14447. * <br><br>
  14448. * For ASCII keys that was pressed is stored in the key variable. However, it
  14449. * does not distinguish between uppercase and lowercase. For this reason, it
  14450. * is recommended to use keyTyped() to read the key variable, in which the
  14451. * case of the variable will be distinguished.
  14452. * <br><br>
  14453. * Because of how operating systems handle key repeats, holding down a key
  14454. * may cause multiple calls to keyTyped() (and keyReleased() as well). The
  14455. * rate of repeat is set by the operating system and how each computer is
  14456. * configured.<br><br>
  14457. * Browsers may have different default
  14458. * behaviors attached to various key events. To prevent any default
  14459. * behavior for this event, add "return false" to the end of the method.
  14460. *
  14461. * @method keyPressed
  14462. * @example
  14463. * <div>
  14464. * <code>
  14465. * var value = 0;
  14466. * function draw() {
  14467. * fill(value);
  14468. * rect(25, 25, 50, 50);
  14469. * }
  14470. * function keyPressed() {
  14471. * if (value === 0) {
  14472. * value = 255;
  14473. * } else {
  14474. * value = 0;
  14475. * }
  14476. * }
  14477. * </code>
  14478. * </div>
  14479. * <div>
  14480. * <code>
  14481. * var value = 0;
  14482. * function draw() {
  14483. * fill(value);
  14484. * rect(25, 25, 50, 50);
  14485. * }
  14486. * function keyPressed() {
  14487. * if (keyCode === LEFT_ARROW) {
  14488. * value = 255;
  14489. * } else if (keyCode === RIGHT_ARROW) {
  14490. * value = 0;
  14491. * }
  14492. * }
  14493. * </code>
  14494. * </div>
  14495. * <div class="norender">
  14496. * <code>
  14497. * function keyPressed(){
  14498. * // Do something
  14499. * return false; // prevent any default behaviour
  14500. * }
  14501. * </code>
  14502. *
  14503. * @alt
  14504. * black rect center. turns white when key pressed and black when released
  14505. * black rect center. turns white when left arrow pressed and black when right.
  14506. *
  14507. * </div>
  14508. */
  14509. p5.prototype._onkeydown = function (e) {
  14510. if (downKeys[e.which]) { // prevent multiple firings
  14511. return;
  14512. }
  14513. this._setProperty('isKeyPressed', true);
  14514. this._setProperty('keyIsPressed', true);
  14515. this._setProperty('keyCode', e.which);
  14516. downKeys[e.which] = true;
  14517. var key = String.fromCharCode(e.which);
  14518. if (!key) {
  14519. key = e.which;
  14520. }
  14521. this._setProperty('key', key);
  14522. var keyPressed = this.keyPressed || window.keyPressed;
  14523. if (typeof keyPressed === 'function' && !e.charCode) {
  14524. var executeDefault = keyPressed(e);
  14525. if(executeDefault === false) {
  14526. e.preventDefault();
  14527. }
  14528. }
  14529. };
  14530. /**
  14531. * The keyReleased() function is called once every time a key is released.
  14532. * See key and keyCode for more information.<br><br>
  14533. * Browsers may have different default
  14534. * behaviors attached to various key events. To prevent any default
  14535. * behavior for this event, add "return false" to the end of the method.
  14536. *
  14537. * @method keyReleased
  14538. * @example
  14539. * <div>
  14540. * <code>
  14541. * var value = 0;
  14542. * function draw() {
  14543. * fill(value);
  14544. * rect(25, 25, 50, 50);
  14545. * }
  14546. * function keyReleased() {
  14547. * if (value === 0) {
  14548. * value = 255;
  14549. * } else {
  14550. * value = 0;
  14551. * }
  14552. * return false; // prevent any default behavior
  14553. * }
  14554. * </code>
  14555. * </div>
  14556. *
  14557. * @alt
  14558. * black rect center. turns white when key pressed and black when pressed again
  14559. *
  14560. */
  14561. p5.prototype._onkeyup = function (e) {
  14562. var keyReleased = this.keyReleased || window.keyReleased;
  14563. downKeys[e.which] = false;
  14564. //delete this._downKeys[e.which];
  14565. var key = String.fromCharCode(e.which);
  14566. if(areDownKeys()) {
  14567. this._setProperty('isKeyPressed', false);
  14568. this._setProperty('keyIsPressed', false);
  14569. }
  14570. this._setProperty('_lastKeyCodeTyped', null);
  14571. if (!key) {
  14572. key = e.which;
  14573. }
  14574. this._setProperty('key', key);
  14575. this._setProperty('keyCode', e.which);
  14576. if (typeof keyReleased === 'function') {
  14577. var executeDefault = keyReleased(e);
  14578. if(executeDefault === false) {
  14579. e.preventDefault();
  14580. }
  14581. }
  14582. };
  14583. /**
  14584. * The keyTyped() function is called once every time a key is pressed, but
  14585. * action keys such as Ctrl, Shift, and Alt are ignored. The most recent
  14586. * key pressed will be stored in the key variable.
  14587. * <br><br>
  14588. * Because of how operating systems handle key repeats, holding down a key
  14589. * will cause multiple calls to keyTyped() (and keyReleased() as well). The
  14590. * rate of repeat is set by the operating system and how each computer is
  14591. * configured.<br><br>
  14592. * Browsers may have different default behaviors attached to various key
  14593. * events. To prevent any default behavior for this event, add "return false"
  14594. * to the end of the method.
  14595. *
  14596. * @method keyTyped
  14597. * @example
  14598. * <div>
  14599. * <code>
  14600. * var value = 0;
  14601. * function draw() {
  14602. * fill(value);
  14603. * rect(25, 25, 50, 50);
  14604. * }
  14605. * function keyTyped() {
  14606. * if (key === 'a') {
  14607. * value = 255;
  14608. * } else if (key === 'b') {
  14609. * value = 0;
  14610. * }
  14611. * // uncomment to prevent any default behavior
  14612. * // return false;
  14613. * }
  14614. * </code>
  14615. * </div>
  14616. *
  14617. * @alt
  14618. * black rect center. turns white when 'a' key typed and black when 'b' pressed
  14619. *
  14620. */
  14621. p5.prototype._onkeypress = function (e) {
  14622. if (e.which === this._lastKeyCodeTyped) { // prevent multiple firings
  14623. return;
  14624. }
  14625. this._setProperty('keyCode', e.which);
  14626. this._setProperty('_lastKeyCodeTyped', e.which); // track last keyCode
  14627. this._setProperty('key', String.fromCharCode(e.which));
  14628. var keyTyped = this.keyTyped || window.keyTyped;
  14629. if (typeof keyTyped === 'function') {
  14630. var executeDefault = keyTyped(e);
  14631. if(executeDefault === false) {
  14632. e.preventDefault();
  14633. }
  14634. }
  14635. };
  14636. /**
  14637. * The onblur function is called when the user is no longer focused
  14638. * on the p5 element. Because the keyup events will not fire if the user is
  14639. * not focused on the element we must assume all keys currently down have
  14640. * been released.
  14641. */
  14642. p5.prototype._onblur = function (e) {
  14643. downKeys = {};
  14644. };
  14645. /**
  14646. * The keyIsDown() function checks if the key is currently down, i.e. pressed.
  14647. * It can be used if you have an object that moves, and you want several keys
  14648. * to be able to affect its behaviour simultaneously, such as moving a
  14649. * sprite diagonally. You can put in any number representing the keyCode of
  14650. * the key, or use any of the variable keyCode names listed
  14651. * <a href="http://p5js.org/reference/#p5/keyCode">here</a>.
  14652. *
  14653. * @method keyIsDown
  14654. * @param {Number} code The key to check for.
  14655. * @return {Boolean} whether key is down or not
  14656. * @example
  14657. * <div><code>
  14658. * var x = 100;
  14659. * var y = 100;
  14660. *
  14661. * function setup() {
  14662. * createCanvas(512, 512);
  14663. * }
  14664. *
  14665. * function draw() {
  14666. * if (keyIsDown(LEFT_ARROW))
  14667. * x-=5;
  14668. *
  14669. * if (keyIsDown(RIGHT_ARROW))
  14670. * x+=5;
  14671. *
  14672. * if (keyIsDown(UP_ARROW))
  14673. * y-=5;
  14674. *
  14675. * if (keyIsDown(DOWN_ARROW))
  14676. * y+=5;
  14677. *
  14678. * clear();
  14679. * fill(255, 0, 0);
  14680. * ellipse(x, y, 50, 50);
  14681. * }
  14682. * </code></div>
  14683. *
  14684. * @alt
  14685. * 50x50 red ellipse moves left, right, up and down with arrow presses.
  14686. *
  14687. */
  14688. p5.prototype.keyIsDown = function(code) {
  14689. return downKeys[code];
  14690. };
  14691. /**
  14692. * The checkDownKeys function returns a boolean true if any keys pressed
  14693. * and a false if no keys are currently pressed.
  14694. * Helps avoid instances where a multiple keys are pressed simultaneously and
  14695. * releasing a single key will then switch the
  14696. * keyIsPressed property to true.
  14697. * @private
  14698. **/
  14699. function areDownKeys() {
  14700. for (var key in downKeys) {
  14701. if (downKeys[key] === true ) {
  14702. return true;
  14703. }
  14704. }
  14705. return false;
  14706. }
  14707. module.exports = p5;
  14708. },{"../core/core":37}],52:[function(_dereq_,module,exports){
  14709. /**
  14710. * @module Events
  14711. * @submodule Mouse
  14712. * @for p5
  14713. * @requires core
  14714. * @requires constants
  14715. */
  14716. 'use strict';
  14717. var p5 = _dereq_('../core/core');
  14718. var constants = _dereq_('../core/constants');
  14719. /*
  14720. * This is a flag which is false until the first time
  14721. * we receive a mouse event. The pmouseX and pmouseY
  14722. * values will match the mouseX and mouseY values until
  14723. * this interaction takes place.
  14724. */
  14725. p5.prototype._hasMouseInteracted = false;
  14726. /**
  14727. * The system variable mouseX always contains the current horizontal
  14728. * position of the mouse, relative to (0, 0) of the canvas. If touch is
  14729. * used instead of mouse input, mouseX will hold the x value of the most
  14730. * recent touch point.
  14731. *
  14732. * @property mouseX
  14733. *
  14734. * @example
  14735. * <div>
  14736. * <code>
  14737. * // Move the mouse across the canvas
  14738. * function draw() {
  14739. * background(244, 248, 252);
  14740. * line(mouseX, 0, mouseX, 100);
  14741. * }
  14742. * </code>
  14743. * </div>
  14744. *
  14745. * @alt
  14746. * horizontal black line moves left and right with mouse x-position
  14747. *
  14748. */
  14749. p5.prototype.mouseX = 0;
  14750. /**
  14751. * The system variable mouseY always contains the current vertical position
  14752. * of the mouse, relative to (0, 0) of the canvas. If touch is
  14753. * used instead of mouse input, mouseY will hold the y value of the most
  14754. * recent touch point.
  14755. *
  14756. * @property mouseY
  14757. *
  14758. * @example
  14759. * <div>
  14760. * <code>
  14761. * // Move the mouse across the canvas
  14762. * function draw() {
  14763. * background(244, 248, 252);
  14764. * line(0, mouseY, 100, mouseY);
  14765. *}
  14766. * </code>
  14767. * </div>
  14768. *
  14769. * @alt
  14770. * vertical black line moves up and down with mouse y-position
  14771. *
  14772. */
  14773. p5.prototype.mouseY = 0;
  14774. /**
  14775. * The system variable pmouseX always contains the horizontal position of
  14776. * the mouse or finger in the frame previous to the current frame, relative to
  14777. * (0, 0) of the canvas.
  14778. *
  14779. * @property pmouseX
  14780. *
  14781. * @example
  14782. * <div>
  14783. * <code>
  14784. * // Move the mouse across the canvas to leave a trail
  14785. * function setup() {
  14786. * //slow down the frameRate to make it more visible
  14787. * frameRate(10);
  14788. * }
  14789. *
  14790. * function draw() {
  14791. * background(244, 248, 252);
  14792. * line(mouseX, mouseY, pmouseX, pmouseY);
  14793. * print(pmouseX + " -> " + mouseX);
  14794. * }
  14795. *
  14796. * </code>
  14797. * </div>
  14798. *
  14799. * @alt
  14800. * line trail is created from cursor movements. faster movement make longer line.
  14801. *
  14802. */
  14803. p5.prototype.pmouseX = 0;
  14804. /**
  14805. * The system variable pmouseY always contains the vertical position of the
  14806. * mouse or finger in the frame previous to the current frame, relative to
  14807. * (0, 0) of the canvas.
  14808. *
  14809. * @property pmouseY
  14810. *
  14811. * @example
  14812. * <div>
  14813. * <code>
  14814. * function draw() {
  14815. * background(237, 34, 93);
  14816. * fill(0);
  14817. * //draw a square only if the mouse is not moving
  14818. * if(mouseY == pmouseY && mouseX == pmouseX)
  14819. * rect(20,20,60,60);
  14820. *
  14821. * print(pmouseY + " -> " + mouseY);
  14822. * }
  14823. *
  14824. * </code>
  14825. * </div>
  14826. *
  14827. * @alt
  14828. * 60x60 black rect center, fuschia background. rect flickers on mouse movement
  14829. *
  14830. */
  14831. p5.prototype.pmouseY = 0;
  14832. /**
  14833. * The system variable winMouseX always contains the current horizontal
  14834. * position of the mouse, relative to (0, 0) of the window.
  14835. *
  14836. * @property winMouseX
  14837. *
  14838. * @example
  14839. * <div>
  14840. * <code>
  14841. * var myCanvas;
  14842. *
  14843. * function setup() {
  14844. * //use a variable to store a pointer to the canvas
  14845. * myCanvas = createCanvas(100, 100);
  14846. * }
  14847. *
  14848. * function draw() {
  14849. * background(237, 34, 93);
  14850. * fill(0);
  14851. *
  14852. * //move the canvas to the horizontal mouse position
  14853. * //relative to the window
  14854. * myCanvas.position(winMouseX+1, windowHeight/2);
  14855. *
  14856. * //the y of the square is relative to the canvas
  14857. * rect(20,mouseY,60,60);
  14858. * }
  14859. *
  14860. * </code>
  14861. * </div>
  14862. *
  14863. * @alt
  14864. * 60x60 black rect y moves with mouse y and fuschia canvas moves with mouse x
  14865. *
  14866. */
  14867. p5.prototype.winMouseX = 0;
  14868. /**
  14869. * The system variable winMouseY always contains the current vertical
  14870. * position of the mouse, relative to (0, 0) of the window.
  14871. *
  14872. * @property winMouseY
  14873. *
  14874. * @example
  14875. * <div>
  14876. * <code>
  14877. *var myCanvas;
  14878. *
  14879. * function setup() {
  14880. * //use a variable to store a pointer to the canvas
  14881. * myCanvas = createCanvas(100, 100);
  14882. * }
  14883. *
  14884. * function draw() {
  14885. * background(237, 34, 93);
  14886. * fill(0);
  14887. *
  14888. * //move the canvas to the vertical mouse position
  14889. * //relative to the window
  14890. * myCanvas.position(windowWidth/2, winMouseY+1);
  14891. *
  14892. * //the x of the square is relative to the canvas
  14893. * rect(mouseX,20,60,60);
  14894. * }
  14895. *
  14896. * </code>
  14897. * </div>
  14898. *
  14899. * @alt
  14900. * 60x60 black rect x moves with mouse x and fuschia canvas y moves with mouse y
  14901. *
  14902. */
  14903. p5.prototype.winMouseY = 0;
  14904. /**
  14905. * The system variable pwinMouseX always contains the horizontal position
  14906. * of the mouse in the frame previous to the current frame, relative to
  14907. * (0, 0) of the window.
  14908. *
  14909. * @property pwinMouseX
  14910. *
  14911. * @example
  14912. * <div>
  14913. * <code>
  14914. *
  14915. * var myCanvas;
  14916. *
  14917. * function setup() {
  14918. * //use a variable to store a pointer to the canvas
  14919. * myCanvas = createCanvas(100, 100);
  14920. * noStroke();
  14921. * fill(237, 34, 93);
  14922. * }
  14923. *
  14924. * function draw() {
  14925. * clear();
  14926. * //the difference between previous and
  14927. * //current x position is the horizontal mouse speed
  14928. * var speed = abs(winMouseX-pwinMouseX);
  14929. * //change the size of the circle
  14930. * //according to the horizontal speed
  14931. * ellipse(50, 50, 10+speed*5, 10+speed*5);
  14932. * //move the canvas to the mouse position
  14933. * myCanvas.position( winMouseX+1, winMouseY+1);
  14934. * }
  14935. *
  14936. * </code>
  14937. * </div>
  14938. *
  14939. * @alt
  14940. * fuschia ellipse moves with mouse x and y. Grows and shrinks with mouse speed
  14941. *
  14942. */
  14943. p5.prototype.pwinMouseX = 0;
  14944. /**
  14945. * The system variable pwinMouseY always contains the vertical position of
  14946. * the mouse in the frame previous to the current frame, relative to (0, 0)
  14947. * of the window.
  14948. *
  14949. * @property pwinMouseY
  14950. *
  14951. *
  14952. * @example
  14953. * <div>
  14954. * <code>
  14955. *
  14956. * var myCanvas;
  14957. *
  14958. * function setup() {
  14959. * //use a variable to store a pointer to the canvas
  14960. * myCanvas = createCanvas(100, 100);
  14961. * noStroke();
  14962. * fill(237, 34, 93);
  14963. * }
  14964. *
  14965. * function draw() {
  14966. * clear();
  14967. * //the difference between previous and
  14968. * //current y position is the vertical mouse speed
  14969. * var speed = abs(winMouseY-pwinMouseY);
  14970. * //change the size of the circle
  14971. * //according to the vertical speed
  14972. * ellipse(50, 50, 10+speed*5, 10+speed*5);
  14973. * //move the canvas to the mouse position
  14974. * myCanvas.position( winMouseX+1, winMouseY+1);
  14975. * }
  14976. *
  14977. * </code>
  14978. * </div>
  14979. *
  14980. * @alt
  14981. * fuschia ellipse moves with mouse x and y. Grows and shrinks with mouse speed
  14982. *
  14983. */
  14984. p5.prototype.pwinMouseY = 0;
  14985. /**
  14986. * Processing automatically tracks if the mouse button is pressed and which
  14987. * button is pressed. The value of the system variable mouseButton is either
  14988. * LEFT, RIGHT, or CENTER depending on which button was pressed last.
  14989. * Warning: different browsers may track mouseButton differently.
  14990. *
  14991. * @property mouseButton
  14992. *
  14993. * @example
  14994. * <div>
  14995. * <code>
  14996. * function draw() {
  14997. * background(237, 34, 93);
  14998. * fill(0);
  14999. *
  15000. * if (mouseIsPressed) {
  15001. * if (mouseButton == LEFT)
  15002. * ellipse(50, 50, 50, 50);
  15003. * if (mouseButton == RIGHT)
  15004. * rect(25, 25, 50, 50);
  15005. * if (mouseButton == CENTER)
  15006. * triangle(23, 75, 50, 20, 78, 75);
  15007. * }
  15008. *
  15009. * print(mouseButton);
  15010. * }
  15011. * </code>
  15012. * </div>
  15013. *
  15014. * @alt
  15015. * 50x50 black ellipse appears on center of fuschia canvas on mouse click/press.
  15016. *
  15017. */
  15018. p5.prototype.mouseButton = 0;
  15019. /**
  15020. * The boolean system variable mouseIsPressed is true if the mouse is pressed
  15021. * and false if not.
  15022. *
  15023. * @property mouseIsPressed
  15024. *
  15025. * @example
  15026. * <div>
  15027. * <code>
  15028. * function draw() {
  15029. * background(237, 34, 93);
  15030. * fill(0);
  15031. *
  15032. * if (mouseIsPressed)
  15033. * ellipse(50, 50, 50, 50);
  15034. * else
  15035. * rect(25, 25, 50, 50);
  15036. *
  15037. * print(mouseIsPressed);
  15038. * }
  15039. * </code>
  15040. * </div>
  15041. *
  15042. * @alt
  15043. * black 50x50 rect becomes ellipse with mouse click/press. fuschia background.
  15044. *
  15045. */
  15046. p5.prototype.mouseIsPressed = false;
  15047. p5.prototype.isMousePressed = false; // both are supported
  15048. p5.prototype._updateNextMouseCoords = function(e) {
  15049. if(this._curElement !== null && (!e.touches || e.touches.length>0)) {
  15050. var mousePos = getMousePos(this._curElement.elt, this.width, this.height, e);
  15051. this._setProperty('mouseX', mousePos.x);
  15052. this._setProperty('mouseY', mousePos.y);
  15053. this._setProperty('winMouseX', mousePos.winX);
  15054. this._setProperty('winMouseY', mousePos.winY);
  15055. }
  15056. if (!this._hasMouseInteracted) {
  15057. // For first draw, make previous and next equal
  15058. this._updateMouseCoords();
  15059. this._setProperty('_hasMouseInteracted', true);
  15060. }
  15061. };
  15062. p5.prototype._updateMouseCoords = function() {
  15063. this._setProperty('pmouseX', this.mouseX);
  15064. this._setProperty('pmouseY', this.mouseY);
  15065. this._setProperty('pwinMouseX', this.winMouseX);
  15066. this._setProperty('pwinMouseY', this.winMouseY);
  15067. };
  15068. function getMousePos(canvas, w, h, evt) {
  15069. if (evt && !evt.clientX) { // use touches if touch and not mouse
  15070. if (evt.touches) {
  15071. evt = evt.touches[0];
  15072. } else if (evt.changedTouches) {
  15073. evt = evt.changedTouches[0];
  15074. }
  15075. }
  15076. var rect = canvas.getBoundingClientRect();
  15077. var sx = canvas.scrollWidth / w;
  15078. var sy = canvas.scrollHeight / h;
  15079. return {
  15080. x: (evt.clientX - rect.left) / sx,
  15081. y: (evt.clientY - rect.top) / sy,
  15082. winX: evt.clientX,
  15083. winY: evt.clientY,
  15084. id: evt.identifier
  15085. };
  15086. }
  15087. p5.prototype._setMouseButton = function(e) {
  15088. if (e.button === 1) {
  15089. this._setProperty('mouseButton', constants.CENTER);
  15090. } else if (e.button === 2) {
  15091. this._setProperty('mouseButton', constants.RIGHT);
  15092. } else {
  15093. this._setProperty('mouseButton', constants.LEFT);
  15094. }
  15095. };
  15096. /**
  15097. * The mouseMoved() function is called every time the mouse moves and a mouse
  15098. * button is not pressed.<br><br>
  15099. * Browsers may have different default
  15100. * behaviors attached to various mouse events. To prevent any default
  15101. * behavior for this event, add "return false" to the end of the method.
  15102. *
  15103. * @method mouseMoved
  15104. * @example
  15105. * <div>
  15106. * <code>
  15107. * // Move the mouse across the page
  15108. * // to change its value
  15109. *
  15110. * var value = 0;
  15111. * function draw() {
  15112. * fill(value);
  15113. * rect(25, 25, 50, 50);
  15114. * }
  15115. * function mouseMoved() {
  15116. * value = value + 5;
  15117. * if (value > 255) {
  15118. * value = 0;
  15119. * }
  15120. * }
  15121. * </code>
  15122. * </div>
  15123. *
  15124. * <div class="norender">
  15125. * <code>
  15126. * function mouseMoved() {
  15127. * ellipse(mouseX, mouseY, 5, 5);
  15128. * // prevent default
  15129. * return false;
  15130. * }
  15131. * </code>
  15132. * </div>
  15133. *
  15134. * @alt
  15135. * black 50x50 rect becomes lighter with mouse movements until white then resets
  15136. * no image displayed
  15137. *
  15138. */
  15139. /**
  15140. * The mouseDragged() function is called once every time the mouse moves and
  15141. * a mouse button is pressed. If no mouseDragged() function is defined, the
  15142. * touchMoved() function will be called instead if it is defined.<br><br>
  15143. * Browsers may have different default
  15144. * behaviors attached to various mouse events. To prevent any default
  15145. * behavior for this event, add "return false" to the end of the method.
  15146. *
  15147. * @method mouseDragged
  15148. * @example
  15149. * <div>
  15150. * <code>
  15151. * // Drag the mouse across the page
  15152. * // to change its value
  15153. *
  15154. * var value = 0;
  15155. * function draw() {
  15156. * fill(value);
  15157. * rect(25, 25, 50, 50);
  15158. * }
  15159. * function mouseDragged() {
  15160. * value = value + 5;
  15161. * if (value > 255) {
  15162. * value = 0;
  15163. * }
  15164. * }
  15165. * </code>
  15166. * </div>
  15167. *
  15168. * <div class="norender">
  15169. * <code>
  15170. * function mouseDragged() {
  15171. * ellipse(mouseX, mouseY, 5, 5);
  15172. * // prevent default
  15173. * return false;
  15174. * }
  15175. * </code>
  15176. * </div>
  15177. *
  15178. * @alt
  15179. * black 50x50 rect turns lighter with mouse click and drag until white, resets
  15180. * no image displayed
  15181. *
  15182. */
  15183. p5.prototype._onmousemove = function(e){
  15184. var context = this._isGlobal ? window : this;
  15185. var executeDefault;
  15186. this._updateNextMouseCoords(e);
  15187. if (!this.isMousePressed) {
  15188. if (typeof context.mouseMoved === 'function') {
  15189. executeDefault = context.mouseMoved(e);
  15190. if(executeDefault === false) {
  15191. e.preventDefault();
  15192. }
  15193. }
  15194. }
  15195. else {
  15196. if (typeof context.mouseDragged === 'function') {
  15197. executeDefault = context.mouseDragged(e);
  15198. if(executeDefault === false) {
  15199. e.preventDefault();
  15200. }
  15201. } else if (typeof context.touchMoved === 'function') {
  15202. executeDefault = context.touchMoved(e);
  15203. if(executeDefault === false) {
  15204. e.preventDefault();
  15205. }
  15206. }
  15207. }
  15208. };
  15209. /**
  15210. * The mousePressed() function is called once after every time a mouse button
  15211. * is pressed. The mouseButton variable (see the related reference entry)
  15212. * can be used to determine which button has been pressed. If no
  15213. * mousePressed() function is defined, the touchStarted() function will be
  15214. * called instead if it is defined.<br><br>
  15215. * Browsers may have different default
  15216. * behaviors attached to various mouse events. To prevent any default
  15217. * behavior for this event, add "return false" to the end of the method.
  15218. *
  15219. * @method mousePressed
  15220. * @example
  15221. * <div>
  15222. * <code>
  15223. * // Click within the image to change
  15224. * // the value of the rectangle
  15225. *
  15226. * var value = 0;
  15227. * function draw() {
  15228. * fill(value);
  15229. * rect(25, 25, 50, 50);
  15230. * }
  15231. * function mousePressed() {
  15232. * if (value == 0) {
  15233. * value = 255;
  15234. * } else {
  15235. * value = 0;
  15236. * }
  15237. * }
  15238. * </code>
  15239. * </div>
  15240. *
  15241. * <div class="norender">
  15242. * <code>
  15243. * function mousePressed() {
  15244. * ellipse(mouseX, mouseY, 5, 5);
  15245. * // prevent default
  15246. * return false;
  15247. * }
  15248. * </code>
  15249. * </div>
  15250. *
  15251. * @alt
  15252. * black 50x50 rect turns white with mouse click/press.
  15253. * no image displayed
  15254. *
  15255. */
  15256. p5.prototype._onmousedown = function(e) {
  15257. var context = this._isGlobal ? window : this;
  15258. var executeDefault;
  15259. this._setProperty('isMousePressed', true);
  15260. this._setProperty('mouseIsPressed', true);
  15261. this._setMouseButton(e);
  15262. this._updateNextMouseCoords(e);
  15263. if (typeof context.mousePressed === 'function') {
  15264. executeDefault = context.mousePressed(e);
  15265. if(executeDefault === false) {
  15266. e.preventDefault();
  15267. }
  15268. } else if (typeof context.touchStarted === 'function') {
  15269. executeDefault = context.touchStarted(e);
  15270. if(executeDefault === false) {
  15271. e.preventDefault();
  15272. }
  15273. }
  15274. };
  15275. /**
  15276. * The mouseReleased() function is called every time a mouse button is
  15277. * released. If no mouseReleased() function is defined, the touchEnded()
  15278. * function will be called instead if it is defined.<br><br>
  15279. * Browsers may have different default
  15280. * behaviors attached to various mouse events. To prevent any default
  15281. * behavior for this event, add "return false" to the end of the method.
  15282. *
  15283. *
  15284. * @method mouseReleased
  15285. * @example
  15286. * <div>
  15287. * <code>
  15288. * // Click within the image to change
  15289. * // the value of the rectangle
  15290. * // after the mouse has been clicked
  15291. *
  15292. * var value = 0;
  15293. * function draw() {
  15294. * fill(value);
  15295. * rect(25, 25, 50, 50);
  15296. * }
  15297. * function mouseReleased() {
  15298. * if (value == 0) {
  15299. * value = 255;
  15300. * } else {
  15301. * value = 0;
  15302. * }
  15303. * }
  15304. * </code>
  15305. * </div>
  15306. *
  15307. * <div class="norender">
  15308. * <code>
  15309. * function mouseReleased() {
  15310. * ellipse(mouseX, mouseY, 5, 5);
  15311. * // prevent default
  15312. * return false;
  15313. * }
  15314. * </code>
  15315. * </div>
  15316. *
  15317. * @alt
  15318. * black 50x50 rect turns white with mouse click/press.
  15319. * no image displayed
  15320. *
  15321. */
  15322. p5.prototype._onmouseup = function(e) {
  15323. var context = this._isGlobal ? window : this;
  15324. var executeDefault;
  15325. this._setProperty('isMousePressed', false);
  15326. this._setProperty('mouseIsPressed', false);
  15327. if (typeof context.mouseReleased === 'function') {
  15328. executeDefault = context.mouseReleased(e);
  15329. if(executeDefault === false) {
  15330. e.preventDefault();
  15331. }
  15332. } else if (typeof context.touchEnded === 'function') {
  15333. executeDefault = context.touchEnded(e);
  15334. if(executeDefault === false) {
  15335. e.preventDefault();
  15336. }
  15337. }
  15338. };
  15339. p5.prototype._ondragend = p5.prototype._onmouseup;
  15340. p5.prototype._ondragover = p5.prototype._onmousemove;
  15341. /**
  15342. * The mouseClicked() function is called once after a mouse button has been
  15343. * pressed and then released.<br><br>
  15344. * Browsers may have different default
  15345. * behaviors attached to various mouse events. To prevent any default
  15346. * behavior for this event, add "return false" to the end of the method.
  15347. *
  15348. * @method mouseClicked
  15349. * @example
  15350. * <div>
  15351. * <code>
  15352. * // Click within the image to change
  15353. * // the value of the rectangle
  15354. * // after the mouse has been clicked
  15355. *
  15356. * var value = 0;
  15357. * function draw() {
  15358. * fill(value);
  15359. * rect(25, 25, 50, 50);
  15360. * }
  15361. * function mouseClicked() {
  15362. * if (value == 0) {
  15363. * value = 255;
  15364. * } else {
  15365. * value = 0;
  15366. * }
  15367. * }
  15368. * </code>
  15369. * </div>
  15370. *
  15371. * <div class="norender">
  15372. * <code>
  15373. * function mouseClicked() {
  15374. * ellipse(mouseX, mouseY, 5, 5);
  15375. * // prevent default
  15376. * return false;
  15377. * }
  15378. * </code>
  15379. * </div>
  15380. *
  15381. * @alt
  15382. * black 50x50 rect turns white with mouse click/press.
  15383. * no image displayed
  15384. *
  15385. */
  15386. p5.prototype._onclick = function(e) {
  15387. var context = this._isGlobal ? window : this;
  15388. if (typeof context.mouseClicked === 'function') {
  15389. var executeDefault = context.mouseClicked(e);
  15390. if(executeDefault === false) {
  15391. e.preventDefault();
  15392. }
  15393. }
  15394. };
  15395. /**
  15396. * The function mouseWheel() is executed every time a vertical mouse wheel
  15397. * event is detected either triggered by an actual mouse wheel or by a
  15398. * touchpad.<br><br>
  15399. * The event.delta property returns the amount the mouse wheel
  15400. * have scrolled. The values can be positive or negative depending on the
  15401. * scroll direction (on OS X with "natural" scrolling enabled, the signs
  15402. * are inverted).<br><br>
  15403. * Browsers may have different default behaviors attached to various
  15404. * mouse events. To prevent any default behavior for this event, add
  15405. * "return false" to the end of the method.<br><br>
  15406. * Due to the current support of the "wheel" event on Safari, the function
  15407. * may only work as expected if "return false" is included while using Safari.
  15408. *
  15409. * @method mouseWheel
  15410. *
  15411. * @example
  15412. * <div>
  15413. * <code>
  15414. * var pos = 25;
  15415. *
  15416. * function draw() {
  15417. * background(237, 34, 93);
  15418. * fill(0);
  15419. * rect(25, pos, 50, 50);
  15420. * }
  15421. *
  15422. * function mouseWheel(event) {
  15423. * print(event.delta);
  15424. * //move the square according to the vertical scroll amount
  15425. * pos += event.delta;
  15426. * //uncomment to block page scrolling
  15427. * //return false;
  15428. * }
  15429. * </code>
  15430. * </div>
  15431. *
  15432. * @alt
  15433. * black 50x50 rect moves up and down with vertical scroll. fuschia background
  15434. *
  15435. */
  15436. p5.prototype._onwheel = function(e) {
  15437. var context = this._isGlobal ? window : this;
  15438. if (typeof context.mouseWheel === 'function') {
  15439. e.delta = e.deltaY;
  15440. var executeDefault = context.mouseWheel(e);
  15441. if(executeDefault === false) {
  15442. e.preventDefault();
  15443. }
  15444. }
  15445. };
  15446. module.exports = p5;
  15447. },{"../core/constants":36,"../core/core":37}],53:[function(_dereq_,module,exports){
  15448. /**
  15449. * @module Events
  15450. * @submodule Touch
  15451. * @for p5
  15452. * @requires core
  15453. */
  15454. 'use strict';
  15455. var p5 = _dereq_('../core/core');
  15456. /**
  15457. * The system variable touches[] contains an array of the positions of all
  15458. * current touch points, relative to (0, 0) of the canvas, and IDs identifying a
  15459. * unique touch as it moves. Each element in the array is an object with x, y,
  15460. * and id properties.
  15461. *
  15462. * @property touches[]
  15463. */
  15464. p5.prototype.touches = [];
  15465. p5.prototype._updateTouchCoords = function(e) {
  15466. if (this._curElement !== null) {
  15467. var touches = [];
  15468. for(var i = 0; i < e.touches.length; i++){
  15469. touches[i] = getTouchInfo(this._curElement.elt,
  15470. this.width, this.height, e, i);
  15471. }
  15472. this._setProperty('touches', touches);
  15473. }
  15474. };
  15475. function getTouchInfo(canvas, w, h, e, i) {
  15476. i = i || 0;
  15477. var rect = canvas.getBoundingClientRect();
  15478. var sx = canvas.scrollWidth / w;
  15479. var sy = canvas.scrollHeight / h;
  15480. var touch = e.touches[i] || e.changedTouches[i];
  15481. return {
  15482. x: (touch.clientX - rect.left) / sx,
  15483. y: (touch.clientY - rect.top) / sy,
  15484. winX: touch.clientX,
  15485. winY: touch.clientY,
  15486. id: touch.identifier
  15487. };
  15488. }
  15489. /**
  15490. * The touchStarted() function is called once after every time a touch is
  15491. * registered. If no touchStarted() function is defined, the mousePressed()
  15492. * function will be called instead if it is defined.<br><br>
  15493. * Browsers may have different default behaviors attached to various touch
  15494. * events. To prevent any default behavior for this event, add "return false"
  15495. * to the end of the method.
  15496. *
  15497. * @method touchStarted
  15498. * @example
  15499. * <div>
  15500. * <code>
  15501. * // Touch within the image to change
  15502. * // the value of the rectangle
  15503. *
  15504. * var value = 0;
  15505. * function draw() {
  15506. * fill(value);
  15507. * rect(25, 25, 50, 50);
  15508. * }
  15509. * function touchStarted() {
  15510. * if (value == 0) {
  15511. * value = 255;
  15512. * } else {
  15513. * value = 0;
  15514. * }
  15515. * }
  15516. * </code>
  15517. * </div>
  15518. *
  15519. * <div class="norender">
  15520. * <code>
  15521. * function touchStarted() {
  15522. * ellipse(mouseX, mouseY, 5, 5);
  15523. * // prevent default
  15524. * return false;
  15525. * }
  15526. * </code>
  15527. * </div>
  15528. *
  15529. * @alt
  15530. * 50x50 black rect turns white with touch event.
  15531. * no image displayed
  15532. */
  15533. p5.prototype._ontouchstart = function(e) {
  15534. var context = this._isGlobal ? window : this;
  15535. var executeDefault;
  15536. this._updateTouchCoords(e);
  15537. this._updateNextMouseCoords(e);
  15538. if(typeof context.touchStarted === 'function') {
  15539. executeDefault = context.touchStarted(e);
  15540. if(executeDefault === false) {
  15541. e.preventDefault();
  15542. }
  15543. } else if (typeof context.mousePressed === 'function') {
  15544. executeDefault = context.mousePressed(e);
  15545. if(executeDefault === false) {
  15546. e.preventDefault();
  15547. }
  15548. //this._setMouseButton(e);
  15549. }
  15550. };
  15551. /**
  15552. * The touchMoved() function is called every time a touch move is registered.
  15553. * If no touchMoved() function is defined, the mouseDragged() function will
  15554. * be called instead if it is defined.<br><br>
  15555. * Browsers may have different default behaviors attached to various touch
  15556. * events. To prevent any default behavior for this event, add "return false"
  15557. * to the end of the method.
  15558. *
  15559. * @method touchMoved
  15560. * @example
  15561. * <div>
  15562. * <code>
  15563. * // Move your finger across the page
  15564. * // to change its value
  15565. *
  15566. * var value = 0;
  15567. * function draw() {
  15568. * fill(value);
  15569. * rect(25, 25, 50, 50);
  15570. * }
  15571. * function touchMoved() {
  15572. * value = value + 5;
  15573. * if (value > 255) {
  15574. * value = 0;
  15575. * }
  15576. * }
  15577. * </code>
  15578. * </div>
  15579. *
  15580. * <div class="norender">
  15581. * <code>
  15582. * function touchMoved() {
  15583. * ellipse(mouseX, mouseY, 5, 5);
  15584. * // prevent default
  15585. * return false;
  15586. * }
  15587. * </code>
  15588. * </div>
  15589. *
  15590. * @alt
  15591. * 50x50 black rect turns lighter with touch until white. resets
  15592. * no image displayed
  15593. *
  15594. */
  15595. p5.prototype._ontouchmove = function(e) {
  15596. var context = this._isGlobal ? window : this;
  15597. var executeDefault;
  15598. this._updateTouchCoords(e);
  15599. this._updateNextMouseCoords(e);
  15600. if (typeof context.touchMoved === 'function') {
  15601. executeDefault = context.touchMoved(e);
  15602. if(executeDefault === false) {
  15603. e.preventDefault();
  15604. }
  15605. } else if (typeof context.mouseDragged === 'function') {
  15606. executeDefault = context.mouseDragged(e);
  15607. if(executeDefault === false) {
  15608. e.preventDefault();
  15609. }
  15610. }
  15611. };
  15612. /**
  15613. * The touchEnded() function is called every time a touch ends. If no
  15614. * touchEnded() function is defined, the mouseReleased() function will be
  15615. * called instead if it is defined.<br><br>
  15616. * Browsers may have different default behaviors attached to various touch
  15617. * events. To prevent any default behavior for this event, add "return false"
  15618. * to the end of the method.
  15619. *
  15620. * @method touchEnded
  15621. * @example
  15622. * <div>
  15623. * <code>
  15624. * // Release touch within the image to
  15625. * // change the value of the rectangle
  15626. *
  15627. * var value = 0;
  15628. * function draw() {
  15629. * fill(value);
  15630. * rect(25, 25, 50, 50);
  15631. * }
  15632. * function touchEnded() {
  15633. * if (value == 0) {
  15634. * value = 255;
  15635. * } else {
  15636. * value = 0;
  15637. * }
  15638. * }
  15639. * </code>
  15640. * </div>
  15641. *
  15642. * <div class="norender">
  15643. * <code>
  15644. * function touchEnded() {
  15645. * ellipse(mouseX, mouseY, 5, 5);
  15646. * // prevent default
  15647. * return false;
  15648. * }
  15649. * </code>
  15650. * </div>
  15651. *
  15652. * @alt
  15653. * 50x50 black rect turns white with touch.
  15654. * no image displayed
  15655. *
  15656. */
  15657. p5.prototype._ontouchend = function(e) {
  15658. this._updateTouchCoords(e);
  15659. this._updateNextMouseCoords(e);
  15660. if (this.touches.length === 0) {
  15661. this._setProperty('touchIsDown', false);
  15662. }
  15663. var context = this._isGlobal ? window : this;
  15664. var executeDefault;
  15665. if (typeof context.touchEnded === 'function') {
  15666. executeDefault = context.touchEnded(e);
  15667. if(executeDefault === false) {
  15668. e.preventDefault();
  15669. }
  15670. } else if (typeof context.mouseReleased === 'function') {
  15671. executeDefault = context.mouseReleased(e);
  15672. if(executeDefault === false) {
  15673. e.preventDefault();
  15674. }
  15675. }
  15676. };
  15677. module.exports = p5;
  15678. },{"../core/core":37}],54:[function(_dereq_,module,exports){
  15679. /*global ImageData:false */
  15680. /**
  15681. * This module defines the filters for use with image buffers.
  15682. *
  15683. * This module is basically a collection of functions stored in an object
  15684. * as opposed to modules. The functions are destructive, modifying
  15685. * the passed in canvas rather than creating a copy.
  15686. *
  15687. * Generally speaking users of this module will use the Filters.apply method
  15688. * on a canvas to create an effect.
  15689. *
  15690. * A number of functions are borrowed/adapted from
  15691. * http://www.html5rocks.com/en/tutorials/canvas/imagefilters/
  15692. * or the java processing implementation.
  15693. */
  15694. 'use strict';
  15695. var Filters = {};
  15696. /*
  15697. * Helper functions
  15698. */
  15699. /**
  15700. * Returns the pixel buffer for a canvas
  15701. *
  15702. * @private
  15703. *
  15704. * @param {Canvas|ImageData} canvas the canvas to get pixels from
  15705. * @return {Uint8ClampedArray} a one-dimensional array containing
  15706. * the data in thc RGBA order, with integer
  15707. * values between 0 and 255
  15708. */
  15709. Filters._toPixels = function (canvas) {
  15710. if (canvas instanceof ImageData) {
  15711. return canvas.data;
  15712. } else {
  15713. return canvas.getContext('2d').getImageData(
  15714. 0,
  15715. 0,
  15716. canvas.width,
  15717. canvas.height
  15718. ).data;
  15719. }
  15720. };
  15721. /**
  15722. * Returns a 32 bit number containing ARGB data at ith pixel in the
  15723. * 1D array containing pixels data.
  15724. *
  15725. * @private
  15726. *
  15727. * @param {Uint8ClampedArray} data array returned by _toPixels()
  15728. * @param {Integer} i index of a 1D Image Array
  15729. * @return {Integer} 32 bit integer value representing
  15730. * ARGB value.
  15731. */
  15732. Filters._getARGB = function (data, i) {
  15733. var offset = i * 4;
  15734. return (data[offset+3] << 24) & 0xff000000 |
  15735. (data[offset] << 16) & 0x00ff0000 |
  15736. (data[offset+1] << 8) & 0x0000ff00 |
  15737. data[offset+2] & 0x000000ff;
  15738. };
  15739. /**
  15740. * Modifies pixels RGBA values to values contained in the data object.
  15741. *
  15742. * @private
  15743. *
  15744. * @param {Uint8ClampedArray} pixels array returned by _toPixels()
  15745. * @param {Int32Array} data source 1D array where each value
  15746. * represents ARGB values
  15747. */
  15748. Filters._setPixels = function (pixels, data) {
  15749. var offset = 0;
  15750. for( var i = 0, al = pixels.length; i < al; i++) {
  15751. offset = i*4;
  15752. pixels[offset + 0] = (data[i] & 0x00ff0000)>>>16;
  15753. pixels[offset + 1] = (data[i] & 0x0000ff00)>>>8;
  15754. pixels[offset + 2] = (data[i] & 0x000000ff);
  15755. pixels[offset + 3] = (data[i] & 0xff000000)>>>24;
  15756. }
  15757. };
  15758. /**
  15759. * Returns the ImageData object for a canvas
  15760. * https://developer.mozilla.org/en-US/docs/Web/API/ImageData
  15761. *
  15762. * @private
  15763. *
  15764. * @param {Canvas|ImageData} canvas canvas to get image data from
  15765. * @return {ImageData} Holder of pixel data (and width and
  15766. * height) for a canvas
  15767. */
  15768. Filters._toImageData = function (canvas) {
  15769. if (canvas instanceof ImageData) {
  15770. return canvas;
  15771. } else {
  15772. return canvas.getContext('2d').getImageData(
  15773. 0,
  15774. 0,
  15775. canvas.width,
  15776. canvas.height
  15777. );
  15778. }
  15779. };
  15780. /**
  15781. * Returns a blank ImageData object.
  15782. *
  15783. * @private
  15784. *
  15785. * @param {Integer} width
  15786. * @param {Integer} height
  15787. * @return {ImageData}
  15788. */
  15789. Filters._createImageData = function (width, height) {
  15790. Filters._tmpCanvas = document.createElement('canvas');
  15791. Filters._tmpCtx = Filters._tmpCanvas.getContext('2d');
  15792. return this._tmpCtx.createImageData(width, height);
  15793. };
  15794. /**
  15795. * Applys a filter function to a canvas.
  15796. *
  15797. * The difference between this and the actual filter functions defined below
  15798. * is that the filter functions generally modify the pixel buffer but do
  15799. * not actually put that data back to the canvas (where it would actually
  15800. * update what is visible). By contrast this method does make the changes
  15801. * actually visible in the canvas.
  15802. *
  15803. * The apply method is the method that callers of this module would generally
  15804. * use. It has been separated from the actual filters to support an advanced
  15805. * use case of creating a filter chain that executes without actually updating
  15806. * the canvas in between everystep.
  15807. *
  15808. * @param {[type]} func [description]
  15809. * @param {[type]} canvas [description]
  15810. * @param {[type]} level [description]
  15811. * @return {[type]} [description]
  15812. */
  15813. Filters.apply = function (canvas, func, filterParam) {
  15814. var ctx = canvas.getContext('2d');
  15815. var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
  15816. //Filters can either return a new ImageData object, or just modify
  15817. //the one they received.
  15818. var newImageData = func(imageData, filterParam);
  15819. if (newImageData instanceof ImageData) {
  15820. ctx.putImageData(newImageData, 0, 0, 0, 0, canvas.width, canvas.height);
  15821. } else {
  15822. ctx.putImageData(imageData, 0, 0, 0, 0, canvas.width, canvas.height);
  15823. }
  15824. };
  15825. /*
  15826. * Filters
  15827. */
  15828. /**
  15829. * Converts the image to black and white pixels depending if they are above or
  15830. * below the threshold defined by the level parameter. The parameter must be
  15831. * between 0.0 (black) and 1.0 (white). If no level is specified, 0.5 is used.
  15832. *
  15833. * Borrowed from http://www.html5rocks.com/en/tutorials/canvas/imagefilters/
  15834. *
  15835. * @param {Canvas} canvas
  15836. * @param {Float} level
  15837. */
  15838. Filters.threshold = function (canvas, level) {
  15839. var pixels = Filters._toPixels(canvas);
  15840. if (level === undefined) {
  15841. level = 0.5;
  15842. }
  15843. var thresh = Math.floor(level * 255);
  15844. for (var i = 0; i < pixels.length; i += 4) {
  15845. var r = pixels[i];
  15846. var g = pixels[i + 1];
  15847. var b = pixels[i + 2];
  15848. var gray = (0.2126 * r + 0.7152 * g + 0.0722 * b);
  15849. var val;
  15850. if (gray >= thresh) {
  15851. val = 255;
  15852. } else {
  15853. val = 0;
  15854. }
  15855. pixels[i] = pixels[i + 1] = pixels[i + 2] = val;
  15856. }
  15857. };
  15858. /**
  15859. * Converts any colors in the image to grayscale equivalents.
  15860. * No parameter is used.
  15861. *
  15862. * Borrowed from http://www.html5rocks.com/en/tutorials/canvas/imagefilters/
  15863. *
  15864. * @param {Canvas} canvas
  15865. */
  15866. Filters.gray = function (canvas) {
  15867. var pixels = Filters._toPixels(canvas);
  15868. for (var i = 0; i < pixels.length; i += 4) {
  15869. var r = pixels[i];
  15870. var g = pixels[i + 1];
  15871. var b = pixels[i + 2];
  15872. // CIE luminance for RGB
  15873. var gray = (0.2126 * r + 0.7152 * g + 0.0722 * b);
  15874. pixels[i] = pixels[i + 1] = pixels[i + 2] = gray;
  15875. }
  15876. };
  15877. /**
  15878. * Sets the alpha channel to entirely opaque. No parameter is used.
  15879. *
  15880. * @param {Canvas} canvas
  15881. */
  15882. Filters.opaque = function (canvas) {
  15883. var pixels = Filters._toPixels(canvas);
  15884. for (var i = 0; i < pixels.length; i += 4) {
  15885. pixels[i + 3] = 255;
  15886. }
  15887. return pixels;
  15888. };
  15889. /**
  15890. * Sets each pixel to its inverse value. No parameter is used.
  15891. * @param {Invert}
  15892. */
  15893. Filters.invert = function (canvas) {
  15894. var pixels = Filters._toPixels(canvas);
  15895. for (var i = 0; i < pixels.length; i += 4) {
  15896. pixels[i] = 255 - pixels[i];
  15897. pixels[i + 1] = 255 - pixels[i + 1];
  15898. pixels[i + 2] = 255 - pixels[i + 2];
  15899. }
  15900. };
  15901. /**
  15902. * Limits each channel of the image to the number of colors specified as
  15903. * the parameter. The parameter can be set to values between 2 and 255, but
  15904. * results are most noticeable in the lower ranges.
  15905. *
  15906. * Adapted from java based processing implementation
  15907. *
  15908. * @param {Canvas} canvas
  15909. * @param {Integer} level
  15910. */
  15911. Filters.posterize = function (canvas, level) {
  15912. var pixels = Filters._toPixels(canvas);
  15913. if ((level < 2) || (level > 255)) {
  15914. throw new Error(
  15915. 'Level must be greater than 2 and less than 255 for posterize'
  15916. );
  15917. }
  15918. var levels1 = level - 1;
  15919. for (var i = 0; i < pixels.length; i+=4) {
  15920. var rlevel = pixels[i];
  15921. var glevel = pixels[i + 1];
  15922. var blevel = pixels[i + 2];
  15923. pixels[i] = (((rlevel * level) >> 8) * 255) / levels1;
  15924. pixels[i + 1] = (((glevel * level) >> 8) * 255) / levels1;
  15925. pixels[i + 2] = (((blevel * level) >> 8) * 255) / levels1;
  15926. }
  15927. };
  15928. /**
  15929. * reduces the bright areas in an image
  15930. * @param {Canvas} canvas
  15931. *
  15932. */
  15933. Filters.dilate = function (canvas) {
  15934. var pixels = Filters._toPixels(canvas);
  15935. var currIdx = 0;
  15936. var maxIdx = pixels.length ? pixels.length/4 : 0;
  15937. var out = new Int32Array(maxIdx);
  15938. var currRowIdx, maxRowIdx, colOrig, colOut, currLum;
  15939. var idxRight, idxLeft, idxUp, idxDown,
  15940. colRight, colLeft, colUp, colDown,
  15941. lumRight, lumLeft, lumUp, lumDown;
  15942. while(currIdx < maxIdx) {
  15943. currRowIdx = currIdx;
  15944. maxRowIdx = currIdx + canvas.width;
  15945. while (currIdx < maxRowIdx) {
  15946. colOrig = colOut = Filters._getARGB(pixels, currIdx);
  15947. idxLeft = currIdx - 1;
  15948. idxRight = currIdx + 1;
  15949. idxUp = currIdx - canvas.width;
  15950. idxDown = currIdx + canvas.width;
  15951. if (idxLeft < currRowIdx) {
  15952. idxLeft = currIdx;
  15953. }
  15954. if (idxRight >= maxRowIdx) {
  15955. idxRight = currIdx;
  15956. }
  15957. if (idxUp < 0){
  15958. idxUp = 0;
  15959. }
  15960. if (idxDown >= maxIdx) {
  15961. idxDown = currIdx;
  15962. }
  15963. colUp = Filters._getARGB(pixels, idxUp);
  15964. colLeft = Filters._getARGB(pixels, idxLeft);
  15965. colDown = Filters._getARGB(pixels, idxDown);
  15966. colRight = Filters._getARGB(pixels, idxRight);
  15967. //compute luminance
  15968. currLum = 77*(colOrig>>16&0xff) +
  15969. 151*(colOrig>>8&0xff) +
  15970. 28*(colOrig&0xff);
  15971. lumLeft = 77*(colLeft>>16&0xff) +
  15972. 151*(colLeft>>8&0xff) +
  15973. 28*(colLeft&0xff);
  15974. lumRight = 77*(colRight>>16&0xff) +
  15975. 151*(colRight>>8&0xff) +
  15976. 28*(colRight&0xff);
  15977. lumUp = 77*(colUp>>16&0xff) +
  15978. 151*(colUp>>8&0xff) +
  15979. 28*(colUp&0xff);
  15980. lumDown = 77*(colDown>>16&0xff) +
  15981. 151*(colDown>>8&0xff) +
  15982. 28*(colDown&0xff);
  15983. if (lumLeft > currLum) {
  15984. colOut = colLeft;
  15985. currLum = lumLeft;
  15986. }
  15987. if (lumRight > currLum) {
  15988. colOut = colRight;
  15989. currLum = lumRight;
  15990. }
  15991. if (lumUp > currLum) {
  15992. colOut = colUp;
  15993. currLum = lumUp;
  15994. }
  15995. if (lumDown > currLum) {
  15996. colOut = colDown;
  15997. currLum = lumDown;
  15998. }
  15999. out[currIdx++]=colOut;
  16000. }
  16001. }
  16002. Filters._setPixels(pixels, out);
  16003. };
  16004. /**
  16005. * increases the bright areas in an image
  16006. * @param {Canvas} canvas
  16007. *
  16008. */
  16009. Filters.erode = function(canvas) {
  16010. var pixels = Filters._toPixels(canvas);
  16011. var currIdx = 0;
  16012. var maxIdx = pixels.length ? pixels.length/4 : 0;
  16013. var out = new Int32Array(maxIdx);
  16014. var currRowIdx, maxRowIdx, colOrig, colOut, currLum;
  16015. var idxRight, idxLeft, idxUp, idxDown,
  16016. colRight, colLeft, colUp, colDown,
  16017. lumRight, lumLeft, lumUp, lumDown;
  16018. while(currIdx < maxIdx) {
  16019. currRowIdx = currIdx;
  16020. maxRowIdx = currIdx + canvas.width;
  16021. while (currIdx < maxRowIdx) {
  16022. colOrig = colOut = Filters._getARGB(pixels, currIdx);
  16023. idxLeft = currIdx - 1;
  16024. idxRight = currIdx + 1;
  16025. idxUp = currIdx - canvas.width;
  16026. idxDown = currIdx + canvas.width;
  16027. if (idxLeft < currRowIdx) {
  16028. idxLeft = currIdx;
  16029. }
  16030. if (idxRight >= maxRowIdx) {
  16031. idxRight = currIdx;
  16032. }
  16033. if (idxUp < 0) {
  16034. idxUp = 0;
  16035. }
  16036. if (idxDown >= maxIdx) {
  16037. idxDown = currIdx;
  16038. }
  16039. colUp = Filters._getARGB(pixels, idxUp);
  16040. colLeft = Filters._getARGB(pixels, idxLeft);
  16041. colDown = Filters._getARGB(pixels, idxDown);
  16042. colRight = Filters._getARGB(pixels, idxRight);
  16043. //compute luminance
  16044. currLum = 77*(colOrig>>16&0xff) +
  16045. 151*(colOrig>>8&0xff) +
  16046. 28*(colOrig&0xff);
  16047. lumLeft = 77*(colLeft>>16&0xff) +
  16048. 151*(colLeft>>8&0xff) +
  16049. 28*(colLeft&0xff);
  16050. lumRight = 77*(colRight>>16&0xff) +
  16051. 151*(colRight>>8&0xff) +
  16052. 28*(colRight&0xff);
  16053. lumUp = 77*(colUp>>16&0xff) +
  16054. 151*(colUp>>8&0xff) +
  16055. 28*(colUp&0xff);
  16056. lumDown = 77*(colDown>>16&0xff) +
  16057. 151*(colDown>>8&0xff) +
  16058. 28*(colDown&0xff);
  16059. if (lumLeft < currLum) {
  16060. colOut = colLeft;
  16061. currLum = lumLeft;
  16062. }
  16063. if (lumRight < currLum) {
  16064. colOut = colRight;
  16065. currLum = lumRight;
  16066. }
  16067. if (lumUp < currLum) {
  16068. colOut = colUp;
  16069. currLum = lumUp;
  16070. }
  16071. if (lumDown < currLum) {
  16072. colOut = colDown;
  16073. currLum = lumDown;
  16074. }
  16075. out[currIdx++]=colOut;
  16076. }
  16077. }
  16078. Filters._setPixels(pixels, out);
  16079. };
  16080. // BLUR
  16081. // internal kernel stuff for the gaussian blur filter
  16082. var blurRadius;
  16083. var blurKernelSize;
  16084. var blurKernel;
  16085. var blurMult;
  16086. /*
  16087. * Port of https://github.com/processing/processing/blob/
  16088. * master/core/src/processing/core/PImage.java#L1250
  16089. *
  16090. * Optimized code for building the blur kernel.
  16091. * further optimized blur code (approx. 15% for radius=20)
  16092. * bigger speed gains for larger radii (~30%)
  16093. * added support for various image types (ALPHA, RGB, ARGB)
  16094. * [toxi 050728]
  16095. */
  16096. function buildBlurKernel(r) {
  16097. var radius = (r * 3.5)|0;
  16098. radius = (radius < 1) ? 1 : ((radius < 248) ? radius : 248);
  16099. if (blurRadius !== radius) {
  16100. blurRadius = radius;
  16101. blurKernelSize = 1 + blurRadius<<1;
  16102. blurKernel = new Int32Array(blurKernelSize);
  16103. blurMult = new Array(blurKernelSize);
  16104. for(var l = 0; l < blurKernelSize; l++){
  16105. blurMult[l] = new Int32Array(256);
  16106. }
  16107. var bk,bki;
  16108. var bm,bmi;
  16109. for (var i = 1, radiusi = radius - 1; i < radius; i++) {
  16110. blurKernel[radius+i] = blurKernel[radiusi] = bki = radiusi * radiusi;
  16111. bm = blurMult[radius+i];
  16112. bmi = blurMult[radiusi--];
  16113. for (var j = 0; j < 256; j++){
  16114. bm[j] = bmi[j] = bki * j;
  16115. }
  16116. }
  16117. bk = blurKernel[radius] = radius * radius;
  16118. bm = blurMult[radius];
  16119. for (var k = 0; k < 256; k++){
  16120. bm[k] = bk * k;
  16121. }
  16122. }
  16123. }
  16124. // Port of https://github.com/processing/processing/blob/
  16125. // master/core/src/processing/core/PImage.java#L1433
  16126. function blurARGB(canvas, radius) {
  16127. var pixels = Filters._toPixels(canvas);
  16128. var width = canvas.width;
  16129. var height = canvas.height;
  16130. var numPackedPixels = width * height;
  16131. var argb = new Int32Array(numPackedPixels);
  16132. for (var j = 0; j < numPackedPixels; j++) {
  16133. argb[j] = Filters._getARGB(pixels, j);
  16134. }
  16135. var sum, cr, cg, cb, ca;
  16136. var read, ri, ym, ymi, bk0;
  16137. var a2 = new Int32Array(numPackedPixels);
  16138. var r2 = new Int32Array(numPackedPixels);
  16139. var g2 = new Int32Array(numPackedPixels);
  16140. var b2 = new Int32Array(numPackedPixels);
  16141. var yi = 0;
  16142. buildBlurKernel(radius);
  16143. var x, y, i;
  16144. var bm;
  16145. for (y = 0; y < height; y++) {
  16146. for (x = 0; x < width; x++) {
  16147. cb = cg = cr = ca = sum = 0;
  16148. read = x - blurRadius;
  16149. if (read < 0) {
  16150. bk0 = -read;
  16151. read = 0;
  16152. } else {
  16153. if (read >= width) {
  16154. break;
  16155. }
  16156. bk0 = 0;
  16157. }
  16158. for (i = bk0; i < blurKernelSize; i++) {
  16159. if (read >= width) {
  16160. break;
  16161. }
  16162. var c = argb[read + yi];
  16163. bm = blurMult[i];
  16164. ca += bm[(c & -16777216) >>> 24];
  16165. cr += bm[(c & 16711680) >> 16];
  16166. cg += bm[(c & 65280) >> 8];
  16167. cb += bm[c & 255];
  16168. sum += blurKernel[i];
  16169. read++;
  16170. }
  16171. ri = yi + x;
  16172. a2[ri] = ca / sum;
  16173. r2[ri] = cr / sum;
  16174. g2[ri] = cg / sum;
  16175. b2[ri] = cb / sum;
  16176. }
  16177. yi += width;
  16178. }
  16179. yi = 0;
  16180. ym = -blurRadius;
  16181. ymi = ym * width;
  16182. for (y = 0; y < height; y++) {
  16183. for (x = 0; x < width; x++) {
  16184. cb = cg = cr = ca = sum = 0;
  16185. if (ym < 0) {
  16186. bk0 = ri = -ym;
  16187. read = x;
  16188. } else {
  16189. if (ym >= height) {
  16190. break;
  16191. }
  16192. bk0 = 0;
  16193. ri = ym;
  16194. read = x + ymi;
  16195. }
  16196. for (i = bk0; i < blurKernelSize; i++) {
  16197. if (ri >= height) {
  16198. break;
  16199. }
  16200. bm = blurMult[i];
  16201. ca += bm[a2[read]];
  16202. cr += bm[r2[read]];
  16203. cg += bm[g2[read]];
  16204. cb += bm[b2[read]];
  16205. sum += blurKernel[i];
  16206. ri++;
  16207. read += width;
  16208. }
  16209. argb[x + yi] = (ca/sum)<<24 | (cr/sum)<<16 | (cg/sum)<<8 | (cb/sum);
  16210. }
  16211. yi += width;
  16212. ymi += width;
  16213. ym++;
  16214. }
  16215. Filters._setPixels(pixels, argb);
  16216. }
  16217. Filters.blur = function(canvas, radius){
  16218. blurARGB(canvas, radius);
  16219. };
  16220. module.exports = Filters;
  16221. },{}],55:[function(_dereq_,module,exports){
  16222. /**
  16223. * @module Image
  16224. * @submodule Image
  16225. * @for p5
  16226. * @requires core
  16227. */
  16228. /**
  16229. * This module defines the p5 methods for the p5.Image class
  16230. * for drawing images to the main display canvas.
  16231. */
  16232. 'use strict';
  16233. var p5 = _dereq_('../core/core');
  16234. /* global frames:true */// This is not global, but JSHint is not aware that
  16235. // this module is implicitly enclosed with Browserify: this overrides the
  16236. // redefined-global error and permits using the name "frames" for the array
  16237. // of saved animation frames.
  16238. var frames = [];
  16239. /**
  16240. * Creates a new p5.Image (the datatype for storing images). This provides a
  16241. * fresh buffer of pixels to play with. Set the size of the buffer with the
  16242. * width and height parameters.
  16243. * <br><br>
  16244. * .pixels gives access to an array containing the values for all the pixels
  16245. * in the display window.
  16246. * These values are numbers. This array is the size (including an appropriate
  16247. * factor for the pixelDensity) of the display window x4,
  16248. * representing the R, G, B, A values in order for each pixel, moving from
  16249. * left to right across each row, then down each column. See .pixels for
  16250. * more info. It may also be simpler to use set() or get().
  16251. * <br><br>
  16252. * Before accessing the pixels of an image, the data must loaded with the
  16253. * loadPixels() function. After the array data has been modified, the
  16254. * updatePixels() function must be run to update the changes.
  16255. *
  16256. * @method createImage
  16257. * @param {Integer} width width in pixels
  16258. * @param {Integer} height height in pixels
  16259. * @return {p5.Image} the p5.Image object
  16260. * @example
  16261. * <div>
  16262. * <code>
  16263. * img = createImage(66, 66);
  16264. * img.loadPixels();
  16265. * for (i = 0; i < img.width; i++) {
  16266. * for (j = 0; j < img.height; j++) {
  16267. * img.set(i, j, color(0, 90, 102));
  16268. * }
  16269. * }
  16270. * img.updatePixels();
  16271. * image(img, 17, 17);
  16272. * </code>
  16273. * </div>
  16274. *
  16275. * <div>
  16276. * <code>
  16277. * img = createImage(66, 66);
  16278. * img.loadPixels();
  16279. * for (i = 0; i < img.width; i++) {
  16280. * for (j = 0; j < img.height; j++) {
  16281. * img.set(i, j, color(0, 90, 102, i % img.width * 2));
  16282. * }
  16283. * }
  16284. * img.updatePixels();
  16285. * image(img, 17, 17);
  16286. * image(img, 34, 34);
  16287. * </code>
  16288. * </div>
  16289. *
  16290. * <div>
  16291. * <code>
  16292. * var pink = color(255, 102, 204);
  16293. * img = createImage(66, 66);
  16294. * img.loadPixels();
  16295. * var d = pixelDensity();
  16296. * var halfImage = 4 * (width * d) * (height/2 * d);
  16297. * for (var i = 0; i < halfImage; i+=4) {
  16298. * img.pixels[i] = red(pink);
  16299. * img.pixels[i+1] = green(pink);
  16300. * img.pixels[i+2] = blue(pink);
  16301. * img.pixels[i+3] = alpha(pink);
  16302. * }
  16303. * img.updatePixels();
  16304. * image(img, 17, 17);
  16305. * </code>
  16306. * </div>
  16307. *
  16308. * @alt
  16309. * 66x66 dark turquoise rect in center of canvas.
  16310. * 2 gradated dark turquoise rects fade left. 1 center 1 bottom right of canvas
  16311. * no image displayed
  16312. *
  16313. */
  16314. p5.prototype.createImage = function(width, height) {
  16315. return new p5.Image(width, height);
  16316. };
  16317. /**
  16318. * Save the current canvas as an image. In Safari, this will open the
  16319. * image in the window and the user must provide their own
  16320. * filename on save-as. Other browsers will either save the
  16321. * file immediately, or prompt the user with a dialogue window.
  16322. *
  16323. * @method saveCanvas
  16324. * @param {[selectedCanvas]} canvas a variable representing a
  16325. * specific html5 canvas (optional)
  16326. * @param {[String]} filename
  16327. * @param {[String]} extension 'jpg' or 'png'
  16328. * @example
  16329. * <div class='norender'><code>
  16330. * function setup() {
  16331. * var c = createCanvas(100, 100);
  16332. * background(255, 0, 0);
  16333. * saveCanvas(c, 'myCanvas', 'jpg');
  16334. * }
  16335. * </code></div>
  16336. * <div class='norender'><code>
  16337. * // note that this example has the same result as above
  16338. * // if no canvas is specified, defaults to main canvas
  16339. * function setup() {
  16340. * createCanvas(100, 100);
  16341. * background(255, 0, 0);
  16342. * saveCanvas('myCanvas', 'jpg');
  16343. * }
  16344. * </code></div>
  16345. * <div class='norender'><code>
  16346. * // all of the following are valid
  16347. * saveCanvas(c, 'myCanvas', 'jpg');
  16348. * saveCanvas(c, 'myCanvas');
  16349. * saveCanvas(c);
  16350. * saveCanvas('myCanvas', 'png');
  16351. * saveCanvas('myCanvas');
  16352. * saveCanvas();
  16353. * </code></div>
  16354. *
  16355. * @alt
  16356. * no image displayed
  16357. * no image displayed
  16358. * no image displayed
  16359. *
  16360. */
  16361. p5.prototype.saveCanvas = function() {
  16362. var cnv, filename, extension;
  16363. if (arguments.length === 3) {
  16364. cnv = arguments[0];
  16365. filename = arguments[1];
  16366. extension = arguments[2];
  16367. } else if (arguments.length === 2) {
  16368. if (typeof arguments[0] === 'object') {
  16369. cnv = arguments[0];
  16370. filename = arguments[1];
  16371. } else {
  16372. filename = arguments[0];
  16373. extension = arguments[1];
  16374. }
  16375. } else if (arguments.length === 1) {
  16376. if (typeof arguments[0] === 'object') {
  16377. cnv = arguments[0];
  16378. } else {
  16379. filename = arguments[0];
  16380. }
  16381. }
  16382. if (cnv instanceof p5.Element) {
  16383. cnv = cnv.elt;
  16384. }
  16385. if (!(cnv instanceof HTMLCanvasElement)) {
  16386. cnv = null;
  16387. }
  16388. if (!extension) {
  16389. extension = p5.prototype._checkFileExtension(filename, extension)[1];
  16390. if (extension === '') {
  16391. extension = 'png';
  16392. }
  16393. }
  16394. if (!cnv) {
  16395. if (this._curElement && this._curElement.elt) {
  16396. cnv = this._curElement.elt;
  16397. }
  16398. }
  16399. if ( p5.prototype._isSafari() ) {
  16400. var aText = 'Hello, Safari user!\n';
  16401. aText += 'Now capturing a screenshot...\n';
  16402. aText += 'To save this image,\n';
  16403. aText += 'go to File --> Save As.\n';
  16404. alert(aText);
  16405. window.location.href = cnv.toDataURL();
  16406. } else {
  16407. var mimeType;
  16408. if (typeof(extension) === 'undefined') {
  16409. extension = 'png';
  16410. mimeType = 'image/png';
  16411. }
  16412. else {
  16413. switch(extension){
  16414. case 'png':
  16415. mimeType = 'image/png';
  16416. break;
  16417. case 'jpeg':
  16418. mimeType = 'image/jpeg';
  16419. break;
  16420. case 'jpg':
  16421. mimeType = 'image/jpeg';
  16422. break;
  16423. default:
  16424. mimeType = 'image/png';
  16425. break;
  16426. }
  16427. }
  16428. var downloadMime = 'image/octet-stream';
  16429. var imageData = cnv.toDataURL(mimeType);
  16430. imageData = imageData.replace(mimeType, downloadMime);
  16431. p5.prototype.downloadFile(imageData, filename, extension);
  16432. }
  16433. };
  16434. /**
  16435. * Capture a sequence of frames that can be used to create a movie.
  16436. * Accepts a callback. For example, you may wish to send the frames
  16437. * to a server where they can be stored or converted into a movie.
  16438. * If no callback is provided, the browser will pop up save dialogues in an
  16439. * attempt to download all of the images that have just been created. With the
  16440. * callback provided the image data isn't saved by default but instead passed
  16441. * as an argument to the callback function as an array of objects, with the
  16442. * size of array equal to the total number of frames.
  16443. *
  16444. * @method saveFrames
  16445. * @param {String} filename
  16446. * @param {String} extension 'jpg' or 'png'
  16447. * @param {Number} duration Duration in seconds to save the frames for.
  16448. * @param {Number} framerate Framerate to save the frames in.
  16449. * @param {Function} [callback] A callback function that will be executed
  16450. to handle the image data. This function
  16451. should accept an array as argument. The
  16452. array will contain the specified number of
  16453. frames of objects. Each object has three
  16454. properties: imageData - an
  16455. image/octet-stream, filename and extension.
  16456. * @example
  16457. * <div><code>
  16458. * function draw() {
  16459. * background(mouseX);
  16460. * }
  16461. *
  16462. * function mousePressed() {
  16463. * saveFrames("out", "png", 1, 25, function(data){
  16464. * print(data);
  16465. * });
  16466. * }
  16467. * </code></div>
  16468. *
  16469. * @alt
  16470. * canvas background goes from light to dark with mouse x.
  16471. *
  16472. */
  16473. p5.prototype.saveFrames = function(fName, ext, _duration, _fps, callback) {
  16474. var duration = _duration || 3;
  16475. duration = p5.prototype.constrain(duration, 0, 15);
  16476. duration = duration * 1000;
  16477. var fps = _fps || 15;
  16478. fps = p5.prototype.constrain(fps, 0, 22);
  16479. var count = 0;
  16480. var makeFrame = p5.prototype._makeFrame;
  16481. var cnv = this._curElement.elt;
  16482. var frameFactory = setInterval(function(){
  16483. makeFrame(fName + count, ext, cnv);
  16484. count++;
  16485. },1000/fps);
  16486. setTimeout(function(){
  16487. clearInterval(frameFactory);
  16488. if (callback) {
  16489. callback(frames);
  16490. }
  16491. else {
  16492. for (var i = 0; i < frames.length; i++) {
  16493. var f = frames[i];
  16494. p5.prototype.downloadFile(f.imageData, f.filename, f.ext);
  16495. }
  16496. }
  16497. frames = []; // clear frames
  16498. }, duration + 0.01);
  16499. };
  16500. p5.prototype._makeFrame = function(filename, extension, _cnv) {
  16501. var cnv;
  16502. if (this) {
  16503. cnv = this._curElement.elt;
  16504. } else {
  16505. cnv = _cnv;
  16506. }
  16507. var mimeType;
  16508. if (!extension) {
  16509. extension = 'png';
  16510. mimeType = 'image/png';
  16511. }
  16512. else {
  16513. switch(extension.toLowerCase()){
  16514. case 'png':
  16515. mimeType = 'image/png';
  16516. break;
  16517. case 'jpeg':
  16518. mimeType = 'image/jpeg';
  16519. break;
  16520. case 'jpg':
  16521. mimeType = 'image/jpeg';
  16522. break;
  16523. default:
  16524. mimeType = 'image/png';
  16525. break;
  16526. }
  16527. }
  16528. var downloadMime = 'image/octet-stream';
  16529. var imageData = cnv.toDataURL(mimeType);
  16530. imageData = imageData.replace(mimeType, downloadMime);
  16531. var thisFrame = {};
  16532. thisFrame.imageData = imageData;
  16533. thisFrame.filename = filename;
  16534. thisFrame.ext = extension;
  16535. frames.push(thisFrame);
  16536. };
  16537. module.exports = p5;
  16538. },{"../core/core":37}],56:[function(_dereq_,module,exports){
  16539. /**
  16540. * @module Image
  16541. * @submodule Loading & Displaying
  16542. * @for p5
  16543. * @requires core
  16544. */
  16545. 'use strict';
  16546. var p5 = _dereq_('../core/core');
  16547. var Filters = _dereq_('./filters');
  16548. var canvas = _dereq_('../core/canvas');
  16549. var constants = _dereq_('../core/constants');
  16550. _dereq_('../core/error_helpers');
  16551. /**
  16552. * Loads an image from a path and creates a p5.Image from it.
  16553. * <br><br>
  16554. * The image may not be immediately available for rendering
  16555. * If you want to ensure that the image is ready before doing
  16556. * anything with it, place the loadImage() call in preload().
  16557. * You may also supply a callback function to handle the image when it's ready.
  16558. * <br><br>
  16559. * The path to the image should be relative to the HTML file
  16560. * that links in your sketch. Loading an from a URL or other
  16561. * remote location may be blocked due to your browser's built-in
  16562. * security.
  16563. *
  16564. * @method loadImage
  16565. * @param {String} path Path of the image to be loaded
  16566. * @param {Function(p5.Image)} [successCallback] Function to be called once
  16567. * the image is loaded. Will be passed the
  16568. * p5.Image.
  16569. * @param {Function(Event)} [failureCallback] called with event error if
  16570. * the image fails to load.
  16571. * @return {p5.Image} the p5.Image object
  16572. * @example
  16573. * <div>
  16574. * <code>
  16575. * var img;
  16576. * function preload() {
  16577. * img = loadImage("assets/laDefense.jpg");
  16578. * }
  16579. * function setup() {
  16580. * image(img, 0, 0);
  16581. * }
  16582. * </code>
  16583. * </div>
  16584. * <div>
  16585. * <code>
  16586. * function setup() {
  16587. * // here we use a callback to display the image after loading
  16588. * loadImage("assets/laDefense.jpg", function(img) {
  16589. * image(img, 0, 0);
  16590. * });
  16591. * }
  16592. * </code>
  16593. * </div>
  16594. *
  16595. * @alt
  16596. * image of the underside of a white umbrella and grided ceililng above
  16597. * image of the underside of a white umbrella and grided ceililng above
  16598. *
  16599. */
  16600. p5.prototype.loadImage = function(path, successCallback, failureCallback) {
  16601. var img = new Image();
  16602. var pImg = new p5.Image(1, 1, this);
  16603. var decrementPreload = p5._getDecrementPreload.apply(this, arguments);
  16604. img.onload = function() {
  16605. pImg.width = pImg.canvas.width = img.width;
  16606. pImg.height = pImg.canvas.height = img.height;
  16607. // Draw the image into the backing canvas of the p5.Image
  16608. pImg.drawingContext.drawImage(img, 0, 0);
  16609. if (typeof successCallback === 'function') {
  16610. successCallback(pImg);
  16611. }
  16612. if (decrementPreload && (successCallback !== decrementPreload)) {
  16613. decrementPreload();
  16614. }
  16615. };
  16616. img.onerror = function(e) {
  16617. p5._friendlyFileLoadError(0,img.src);
  16618. // don't get failure callback mixed up with decrementPreload
  16619. if ((typeof failureCallback === 'function') &&
  16620. (failureCallback !== decrementPreload)) {
  16621. failureCallback(e);
  16622. }
  16623. };
  16624. //set crossOrigin in case image is served which CORS headers
  16625. //this will let us draw to canvas without tainting it.
  16626. //see https://developer.mozilla.org/en-US/docs/HTML/CORS_Enabled_Image
  16627. // When using data-uris the file will be loaded locally
  16628. // so we don't need to worry about crossOrigin with base64 file types
  16629. if(path.indexOf('data:image/') !== 0) {
  16630. img.crossOrigin = 'Anonymous';
  16631. }
  16632. //start loading the image
  16633. img.src = path;
  16634. return pImg;
  16635. };
  16636. /**
  16637. * Validates clipping params. Per drawImage spec sWidth and sHight cannot be
  16638. * negative or greater than image intrinsic width and height
  16639. * @private
  16640. * @param {Number} sVal
  16641. * @param {Number} iVal
  16642. * @returns {Number}
  16643. * @private
  16644. */
  16645. function _sAssign(sVal, iVal) {
  16646. if (sVal > 0 && sVal < iVal) {
  16647. return sVal;
  16648. }
  16649. else {
  16650. return iVal;
  16651. }
  16652. }
  16653. /**
  16654. * Draw an image to the main canvas of the p5js sketch
  16655. *
  16656. * @method image
  16657. * @param {p5.Image} img the image to display
  16658. * @param {Number} x the x-coordinate at which to place the top-left
  16659. * corner of the source image
  16660. * @param {Number} y the y-coordinate at which to place the top-left
  16661. * corner of the source image
  16662. * @param {Number} width the width to draw the image
  16663. * @param {Number} height the height to draw the image
  16664. * @example
  16665. * <div>
  16666. * <code>
  16667. * var img;
  16668. * function preload() {
  16669. * img = loadImage("assets/laDefense.jpg");
  16670. * }
  16671. * function setup() {
  16672. * image(img, 0, 0);
  16673. * image(img, 0, 0, 100, 100);
  16674. * image(img, 0, 0, 100, 100, 0, 0, 100, 100);
  16675. * }
  16676. * </code>
  16677. * </div>
  16678. * <div>
  16679. * <code>
  16680. * function setup() {
  16681. * // here we use a callback to display the image after loading
  16682. * loadImage("assets/laDefense.jpg", function(img) {
  16683. * image(img, 0, 0);
  16684. * });
  16685. * }
  16686. * </code>
  16687. * </div>
  16688. *
  16689. * @alt
  16690. * image of the underside of a white umbrella and grided ceiling above
  16691. * image of the underside of a white umbrella and grided ceiling above
  16692. *
  16693. */
  16694. /**
  16695. * @method image
  16696. * @param {p5.Image} img
  16697. * @param {Number} dx the x-coordinate in the destination canvas at
  16698. * which to place the top-left corner of the
  16699. * source image
  16700. * @param {Number} dy the y-coordinate in the destination canvas at
  16701. * which to place the top-left corner of the
  16702. * source image
  16703. * @param {Number} dWidth the width to draw the image in the destination
  16704. * canvas
  16705. * @param {Number} dHeight the height to draw the image in the destination
  16706. * canvas
  16707. * @param {Number} sx the x-coordinate of the top left corner of the
  16708. * sub-rectangle of the source image to draw into
  16709. * the destination canvas
  16710. * @param {Number} sy the y-coordinate of the top left corner of the
  16711. * sub-rectangle of the source image to draw into
  16712. * the destination canvas
  16713. * @param {Number} [sWidth] the width of the sub-rectangle of the
  16714. * source image to draw into the destination
  16715. * canvas
  16716. * @param {Number} [sHeight] the height of the sub-rectangle of the
  16717. * source image to draw into the destination context
  16718. */
  16719. p5.prototype.image =
  16720. function(img, dx, dy, dWidth, dHeight, sx, sy, sWidth, sHeight) {
  16721. // set defaults per spec: https://goo.gl/3ykfOq
  16722. var defW = img.width;
  16723. var defH = img.height;
  16724. if (img.elt && img.elt.videoWidth && !img.canvas) { // video no canvas
  16725. var actualW = img.elt.videoWidth;
  16726. var actualH = img.elt.videoHeight;
  16727. defW = img.elt.videoWidth;
  16728. defH = img.elt.width*actualH/actualW;
  16729. }
  16730. var _dx = dx;
  16731. var _dy = dy;
  16732. var _dw = dWidth || defW;
  16733. var _dh = dHeight || defH;
  16734. var _sx = sx || 0;
  16735. var _sy = sy || 0;
  16736. var _sw = sWidth || defW;
  16737. var _sh = sHeight || defH;
  16738. _sw = _sAssign(_sw, defW);
  16739. _sh = _sAssign(_sh, defH);
  16740. // This part needs cleanup and unit tests
  16741. // see issues https://github.com/processing/p5.js/issues/1741
  16742. // and https://github.com/processing/p5.js/issues/1673
  16743. var pd = 1;
  16744. if (img.elt && img.elt.videoWidth && img.elt.style.width && !img.canvas) {
  16745. pd = img.elt.videoWidth / parseInt(img.elt.style.width, 10);
  16746. }
  16747. else if (img.elt && img.elt.width && img.elt.style.width) {
  16748. pd = img.elt.width / parseInt(img.elt.style.width, 10);
  16749. }
  16750. _sx *= pd;
  16751. _sy *= pd;
  16752. _sh *= pd;
  16753. _sw *= pd;
  16754. var vals = canvas.modeAdjust(_dx, _dy, _dw, _dh,
  16755. this._renderer._imageMode);
  16756. // tint the image if there is a tint
  16757. this._renderer.image(img, _sx, _sy, _sw, _sh, vals.x, vals.y, vals.w,
  16758. vals.h);
  16759. };
  16760. /**
  16761. * Sets the fill value for displaying images. Images can be tinted to
  16762. * specified colors or made transparent by including an alpha value.
  16763. * <br><br>
  16764. * To apply transparency to an image without affecting its color, use
  16765. * white as the tint color and specify an alpha value. For instance,
  16766. * tint(255, 128) will make an image 50% transparent (assuming the default
  16767. * alpha range of 0-255, which can be changed with colorMode()).
  16768. * <br><br>
  16769. * The value for the gray parameter must be less than or equal to the current
  16770. * maximum value as specified by colorMode(). The default maximum value is
  16771. * 255.
  16772. *
  16773. * @method tint
  16774. * @param {Number|Array} v1 gray value, red or hue value (depending on the
  16775. * current color mode), or color Array
  16776. * @param {Number|Array} [v2] green or saturation value (depending on the
  16777. * current color mode)
  16778. * @param {Number|Array} [v3] blue or brightness value (depending on the
  16779. * current color mode)
  16780. * @param {Number|Array} [a] opacity of the background
  16781. * @example
  16782. * <div>
  16783. * <code>
  16784. * var img;
  16785. * function preload() {
  16786. * img = loadImage("assets/laDefense.jpg");
  16787. * }
  16788. * function setup() {
  16789. * image(img, 0, 0);
  16790. * tint(0, 153, 204); // Tint blue
  16791. * image(img, 50, 0);
  16792. * }
  16793. * </code>
  16794. * </div>
  16795. *
  16796. * <div>
  16797. * <code>
  16798. * var img;
  16799. * function preload() {
  16800. * img = loadImage("assets/laDefense.jpg");
  16801. * }
  16802. * function setup() {
  16803. * image(img, 0, 0);
  16804. * tint(0, 153, 204, 126); // Tint blue and set transparency
  16805. * image(img, 50, 0);
  16806. * }
  16807. * </code>
  16808. * </div>
  16809. *
  16810. * <div>
  16811. * <code>
  16812. * var img;
  16813. * function preload() {
  16814. * img = loadImage("assets/laDefense.jpg");
  16815. * }
  16816. * function setup() {
  16817. * image(img, 0, 0);
  16818. * tint(255, 126); // Apply transparency without changing color
  16819. * image(img, 50, 0);
  16820. * }
  16821. * </code>
  16822. * </div>
  16823. *
  16824. * @alt
  16825. * 2 side by side images of umbrella and ceiling, one image with blue tint
  16826. * Images of umbrella and ceiling, one half of image with blue tint
  16827. * 2 side by side images of umbrella and ceiling, one image translucent
  16828. *
  16829. */
  16830. p5.prototype.tint = function () {
  16831. var c = this.color.apply(this, arguments);
  16832. this._renderer._tint = c.levels;
  16833. };
  16834. /**
  16835. * Removes the current fill value for displaying images and reverts to
  16836. * displaying images with their original hues.
  16837. *
  16838. * @method noTint
  16839. * @example
  16840. * <div>
  16841. * <code>
  16842. * var img;
  16843. * function preload() {
  16844. * img = loadImage("assets/bricks.jpg");
  16845. * }
  16846. * function setup() {
  16847. * tint(0, 153, 204); // Tint blue
  16848. * image(img, 0, 0);
  16849. * noTint(); // Disable tint
  16850. * image(img, 50, 0);
  16851. * }
  16852. * </code>
  16853. * </div>
  16854. *
  16855. * @alt
  16856. * 2 side by side images of bricks, left image with blue tint
  16857. *
  16858. */
  16859. p5.prototype.noTint = function() {
  16860. this._renderer._tint = null;
  16861. };
  16862. /**
  16863. * Apply the current tint color to the input image, return the resulting
  16864. * canvas.
  16865. *
  16866. * @param {p5.Image} The image to be tinted
  16867. * @return {canvas} The resulting tinted canvas
  16868. *
  16869. */
  16870. p5.prototype._getTintedImageCanvas = function(img) {
  16871. if (!img.canvas) {
  16872. return img;
  16873. }
  16874. var pixels = Filters._toPixels(img.canvas);
  16875. var tmpCanvas = document.createElement('canvas');
  16876. tmpCanvas.width = img.canvas.width;
  16877. tmpCanvas.height = img.canvas.height;
  16878. var tmpCtx = tmpCanvas.getContext('2d');
  16879. var id = tmpCtx.createImageData(img.canvas.width, img.canvas.height);
  16880. var newPixels = id.data;
  16881. for(var i = 0; i < pixels.length; i += 4) {
  16882. var r = pixels[i];
  16883. var g = pixels[i+1];
  16884. var b = pixels[i+2];
  16885. var a = pixels[i+3];
  16886. newPixels[i] = r*this._renderer._tint[0]/255;
  16887. newPixels[i+1] = g*this._renderer._tint[1]/255;
  16888. newPixels[i+2] = b*this._renderer._tint[2]/255;
  16889. newPixels[i+3] = a*this._renderer._tint[3]/255;
  16890. }
  16891. tmpCtx.putImageData(id, 0, 0);
  16892. return tmpCanvas;
  16893. };
  16894. /**
  16895. * Set image mode. Modifies the location from which images are drawn by
  16896. * changing the way in which parameters given to image() are interpreted.
  16897. * The default mode is imageMode(CORNER), which interprets the second and
  16898. * third parameters of image() as the upper-left corner of the image. If
  16899. * two additional parameters are specified, they are used to set the image's
  16900. * width and height.
  16901. * <br><br>
  16902. * imageMode(CORNERS) interprets the second and third parameters of image()
  16903. * as the location of one corner, and the fourth and fifth parameters as the
  16904. * opposite corner.
  16905. * <br><br>
  16906. * imageMode(CENTER) interprets the second and third parameters of image()
  16907. * as the image's center point. If two additional parameters are specified,
  16908. * they are used to set the image's width and height.
  16909. *
  16910. * @method imageMode
  16911. * @param {Constant} mode either CORNER, CORNERS, or CENTER
  16912. * @example
  16913. *
  16914. * <div>
  16915. * <code>
  16916. * var img;
  16917. * function preload() {
  16918. * img = loadImage("assets/bricks.jpg");
  16919. * }
  16920. * function setup() {
  16921. * imageMode(CORNER);
  16922. * image(img, 10, 10, 50, 50);
  16923. * }
  16924. * </code>
  16925. * </div>
  16926. *
  16927. * <div>
  16928. * <code>
  16929. * var img;
  16930. * function preload() {
  16931. * img = loadImage("assets/bricks.jpg");
  16932. * }
  16933. * function setup() {
  16934. * imageMode(CORNERS);
  16935. * image(img, 10, 10, 90, 40);
  16936. * }
  16937. * </code>
  16938. * </div>
  16939. *
  16940. * <div>
  16941. * <code>
  16942. * var img;
  16943. * function preload() {
  16944. * img = loadImage("assets/bricks.jpg");
  16945. * }
  16946. * function setup() {
  16947. * imageMode(CENTER);
  16948. * image(img, 50, 50, 80, 80);
  16949. * }
  16950. * </code>
  16951. * </div>
  16952. *
  16953. * @alt
  16954. * small square image of bricks
  16955. * horizontal rectangle image of bricks
  16956. * large square image of bricks
  16957. *
  16958. */
  16959. p5.prototype.imageMode = function(m) {
  16960. if (m === constants.CORNER ||
  16961. m === constants.CORNERS ||
  16962. m === constants.CENTER) {
  16963. this._renderer._imageMode = m;
  16964. }
  16965. };
  16966. module.exports = p5;
  16967. },{"../core/canvas":35,"../core/constants":36,"../core/core":37,"../core/error_helpers":40,"./filters":54}],57:[function(_dereq_,module,exports){
  16968. /**
  16969. * @module Image
  16970. * @submodule Image
  16971. * @requires core
  16972. * @requires constants
  16973. * @requires filters
  16974. */
  16975. /**
  16976. * This module defines the p5.Image class and P5 methods for
  16977. * drawing images to the main display canvas.
  16978. */
  16979. 'use strict';
  16980. var p5 = _dereq_('../core/core');
  16981. var Filters = _dereq_('./filters');
  16982. /*
  16983. * Class methods
  16984. */
  16985. /**
  16986. * Creates a new p5.Image. A p5.Image is a canvas backed representation of an
  16987. * image.
  16988. * <br><br>
  16989. * p5 can display .gif, .jpg and .png images. Images may be displayed
  16990. * in 2D and 3D space. Before an image is used, it must be loaded with the
  16991. * loadImage() function. The p5.Image class contains fields for the width and
  16992. * height of the image, as well as an array called pixels[] that contains the
  16993. * values for every pixel in the image.
  16994. * <br><br>
  16995. * The methods described below allow easy access to the image's pixels and
  16996. * alpha channel and simplify the process of compositing.
  16997. * <br><br>
  16998. * Before using the pixels[] array, be sure to use the loadPixels() method on
  16999. * the image to make sure that the pixel data is properly loaded.
  17000. *
  17001. * @class p5.Image
  17002. * @constructor
  17003. * @param {Number} width
  17004. * @param {Number} height
  17005. * @param {Object} pInst An instance of a p5 sketch.
  17006. */
  17007. p5.Image = function(width, height){
  17008. /**
  17009. * Image width.
  17010. * @property width
  17011. * @example
  17012. * <div><code>
  17013. * var img;
  17014. * function preload() {
  17015. * img = loadImage("assets/rockies.jpg");
  17016. * }
  17017. *
  17018. * function setup() {
  17019. * createCanvas(100, 100);
  17020. * image(img, 0, 0);
  17021. * for (var i=0; i < img.width; i++) {
  17022. * var c = img.get(i, img.height/2);
  17023. * stroke(c);
  17024. * line(i, height/2, i, height);
  17025. * }
  17026. * }
  17027. * </code></div>
  17028. *
  17029. * @alt
  17030. * rocky mountains in top and horizontal lines in corresponding colors in bottom.
  17031. *
  17032. */
  17033. this.width = width;
  17034. /**
  17035. * Image height.
  17036. * @property height
  17037. * @example
  17038. * <div><code>
  17039. * var img;
  17040. * function preload() {
  17041. * img = loadImage("assets/rockies.jpg");
  17042. * }
  17043. *
  17044. * function setup() {
  17045. * createCanvas(100, 100);
  17046. * image(img, 0, 0);
  17047. * for (var i=0; i < img.height; i++) {
  17048. * var c = img.get(img.width/2, i);
  17049. * stroke(c);
  17050. * line(0, i, width/2, i);
  17051. * }
  17052. * }
  17053. * </code></div>
  17054. *
  17055. * @alt
  17056. * rocky mountains on right and vertical lines in corresponding colors on left.
  17057. *
  17058. */
  17059. this.height = height;
  17060. this.canvas = document.createElement('canvas');
  17061. this.canvas.width = this.width;
  17062. this.canvas.height = this.height;
  17063. this.drawingContext = this.canvas.getContext('2d');
  17064. this._pixelDensity = 1;
  17065. //used for webgl texturing only
  17066. this.isTexture = false;
  17067. /**
  17068. * Array containing the values for all the pixels in the display window.
  17069. * These values are numbers. This array is the size (include an appropriate
  17070. * factor for pixelDensity) of the display window x4,
  17071. * representing the R, G, B, A values in order for each pixel, moving from
  17072. * left to right across each row, then down each column. Retina and other
  17073. * high denisty displays may have more pixels[] (by a factor of
  17074. * pixelDensity^2).
  17075. * For example, if the image is 100x100 pixels, there will be 40,000. With
  17076. * pixelDensity = 2, there will be 160,000. The first four values
  17077. * (indices 0-3) in the array will be the R, G, B, A values of the pixel at
  17078. * (0, 0). The second four values (indices 4-7) will contain the R, G, B, A
  17079. * values of the pixel at (1, 0). More generally, to set values for a pixel
  17080. * at (x, y):
  17081. * ```javascript
  17082. * var d = pixelDensity;
  17083. * for (var i = 0; i < d; i++) {
  17084. * for (var j = 0; j < d; j++) {
  17085. * // loop over
  17086. * idx = 4 * ((y * d + j) * width * d + (x * d + i));
  17087. * pixels[idx] = r;
  17088. * pixels[idx+1] = g;
  17089. * pixels[idx+2] = b;
  17090. * pixels[idx+3] = a;
  17091. * }
  17092. * }
  17093. * ```
  17094. * <br><br>
  17095. * Before accessing this array, the data must loaded with the loadPixels()
  17096. * function. After the array data has been modified, the updatePixels()
  17097. * function must be run to update the changes.
  17098. * @property pixels[]
  17099. * @example
  17100. * <div>
  17101. * <code>
  17102. * img = createImage(66, 66);
  17103. * img.loadPixels();
  17104. * for (i = 0; i < img.width; i++) {
  17105. * for (j = 0; j < img.height; j++) {
  17106. * img.set(i, j, color(0, 90, 102));
  17107. * }
  17108. * }
  17109. * img.updatePixels();
  17110. * image(img, 17, 17);
  17111. * </code>
  17112. * </div>
  17113. * <div>
  17114. * <code>
  17115. * var pink = color(255, 102, 204);
  17116. * img = createImage(66, 66);
  17117. * img.loadPixels();
  17118. * for (var i = 0; i < 4*(width*height/2); i+=4) {
  17119. * img.pixels[i] = red(pink);
  17120. * img.pixels[i+1] = green(pink);
  17121. * img.pixels[i+2] = blue(pink);
  17122. * img.pixels[i+3] = alpha(pink);
  17123. * }
  17124. * img.updatePixels();
  17125. * image(img, 17, 17);
  17126. * </code>
  17127. * </div>
  17128. *
  17129. * @alt
  17130. * 66x66 turquoise rect in center of canvas
  17131. * 66x66 pink rect in center of canvas
  17132. *
  17133. */
  17134. this.pixels = [];
  17135. };
  17136. /**
  17137. * Helper fxn for sharing pixel methods
  17138. *
  17139. */
  17140. p5.Image.prototype._setProperty = function (prop, value) {
  17141. this[prop] = value;
  17142. };
  17143. /**
  17144. * Loads the pixels data for this image into the [pixels] attribute.
  17145. *
  17146. * @method loadPixels
  17147. * @example
  17148. * <div><code>
  17149. * var myImage;
  17150. * var halfImage;
  17151. *
  17152. * function preload() {
  17153. * myImage = loadImage("assets/rockies.jpg");
  17154. * }
  17155. *
  17156. * function setup() {
  17157. * myImage.loadPixels();
  17158. * halfImage = 4 * width * height/2;
  17159. * for(var i = 0; i < halfImage; i++){
  17160. * myImage.pixels[i+halfImage] = myImage.pixels[i];
  17161. * }
  17162. * myImage.updatePixels();
  17163. * }
  17164. *
  17165. * function draw() {
  17166. * image(myImage, 0, 0);
  17167. * }
  17168. * </code></div>
  17169. *
  17170. * @alt
  17171. * 2 images of rocky mountains vertically stacked
  17172. *
  17173. */
  17174. p5.Image.prototype.loadPixels = function(){
  17175. p5.Renderer2D.prototype.loadPixels.call(this);
  17176. };
  17177. /**
  17178. * Updates the backing canvas for this image with the contents of
  17179. * the [pixels] array.
  17180. *
  17181. * @method updatePixels
  17182. * @param {Integer|undefined} x x-offset of the target update area for the
  17183. * underlying canvas
  17184. * @param {Integer|undefined} y y-offset of the target update area for the
  17185. * underlying canvas
  17186. * @param {Integer|undefined} w height of the target update area for the
  17187. * underlying canvas
  17188. * @param {Integer|undefined} h height of the target update area for the
  17189. * underlying canvas
  17190. * @example
  17191. * <div><code>
  17192. * var myImage;
  17193. * var halfImage;
  17194. *
  17195. * function preload() {
  17196. * myImage = loadImage("assets/rockies.jpg");
  17197. * }
  17198. *
  17199. * function setup() {
  17200. * myImage.loadPixels();
  17201. * halfImage = 4 * width * height/2;
  17202. * for(var i = 0; i < halfImage; i++){
  17203. * myImage.pixels[i+halfImage] = myImage.pixels[i];
  17204. * }
  17205. * myImage.updatePixels();
  17206. * }
  17207. *
  17208. * function draw() {
  17209. * image(myImage, 0, 0);
  17210. * }
  17211. * </code></div>
  17212. *
  17213. * @alt
  17214. * 2 images of rocky mountains vertically stacked
  17215. *
  17216. */
  17217. p5.Image.prototype.updatePixels = function(x, y, w, h){
  17218. p5.Renderer2D.prototype.updatePixels.call(this, x, y, w, h);
  17219. };
  17220. /**
  17221. * Get a region of pixels from an image.
  17222. *
  17223. * If no params are passed, those whole image is returned,
  17224. * if x and y are the only params passed a single pixel is extracted
  17225. * if all params are passed a rectangle region is extracted and a p5.Image
  17226. * is returned.
  17227. *
  17228. * Returns undefined if the region is outside the bounds of the image
  17229. *
  17230. * @method get
  17231. * @param {Number} [x] x-coordinate of the pixel
  17232. * @param {Number} [y] y-coordinate of the pixel
  17233. * @param {Number} [w] width
  17234. * @param {Number} [h] height
  17235. * @return {Array/Color | p5.Image} color of pixel at x,y in array format
  17236. * [R, G, B, A] or p5.Image
  17237. * @example
  17238. * <div><code>
  17239. * var myImage;
  17240. * var c;
  17241. *
  17242. * function preload() {
  17243. * myImage = loadImage("assets/rockies.jpg");
  17244. * }
  17245. *
  17246. * function setup() {
  17247. * background(myImage);
  17248. * noStroke();
  17249. * c = myImage.get(60, 90);
  17250. * fill(c);
  17251. * rect(25, 25, 50, 50);
  17252. * }
  17253. *
  17254. * //get() returns color here
  17255. * </code></div>
  17256. *
  17257. * @alt
  17258. * image of rocky mountains with 50x50 green rect in front
  17259. *
  17260. */
  17261. p5.Image.prototype.get = function(x, y, w, h){
  17262. return p5.Renderer2D.prototype.get.call(this, x, y, w, h);
  17263. };
  17264. /**
  17265. * Set the color of a single pixel or write an image into
  17266. * this p5.Image.
  17267. *
  17268. * Note that for a large number of pixels this will
  17269. * be slower than directly manipulating the pixels array
  17270. * and then calling updatePixels().
  17271. *
  17272. * @method set
  17273. * @param {Number} x x-coordinate of the pixel
  17274. * @param {Number} y y-coordinate of the pixel
  17275. * @param {Number|Array|Object} a grayscale value | pixel array |
  17276. * a p5.Color | image to copy
  17277. * @example
  17278. * <div>
  17279. * <code>
  17280. * img = createImage(66, 66);
  17281. * img.loadPixels();
  17282. * for (i = 0; i < img.width; i++) {
  17283. * for (j = 0; j < img.height; j++) {
  17284. * img.set(i, j, color(0, 90, 102, i % img.width * 2));
  17285. * }
  17286. * }
  17287. * img.updatePixels();
  17288. * image(img, 17, 17);
  17289. * image(img, 34, 34);
  17290. * </code>
  17291. * </div>
  17292. *
  17293. * @alt
  17294. * 2 gradated dark turquoise rects fade left. 1 center 1 bottom right of canvas
  17295. *
  17296. */
  17297. p5.Image.prototype.set = function(x, y, imgOrCol){
  17298. p5.Renderer2D.prototype.set.call(this, x, y, imgOrCol);
  17299. };
  17300. /**
  17301. * Resize the image to a new width and height. To make the image scale
  17302. * proportionally, use 0 as the value for the wide or high parameter.
  17303. * For instance, to make the width of an image 150 pixels, and change
  17304. * the height using the same proportion, use resize(150, 0).
  17305. *
  17306. * @method resize
  17307. * @param {Number} width the resized image width
  17308. * @param {Number} height the resized image height
  17309. * @example
  17310. * <div><code>
  17311. * var img;
  17312. *
  17313. * function setup() {
  17314. * img = loadImage("assets/rockies.jpg");
  17315. * }
  17316. * function draw() {
  17317. * image(img, 0, 0);
  17318. * }
  17319. *
  17320. * function mousePressed() {
  17321. * img.resize(50, 100);
  17322. * }
  17323. * </code></div>
  17324. *
  17325. * @alt
  17326. * image of rocky mountains. zoomed in
  17327. *
  17328. */
  17329. p5.Image.prototype.resize = function(width, height){
  17330. // Copy contents to a temporary canvas, resize the original
  17331. // and then copy back.
  17332. //
  17333. // There is a faster approach that involves just one copy and swapping the
  17334. // this.canvas reference. We could switch to that approach if (as i think
  17335. // is the case) there an expectation that the user would not hold a
  17336. // reference to the backing canvas of a p5.Image. But since we do not
  17337. // enforce that at the moment, I am leaving in the slower, but safer
  17338. // implementation.
  17339. // auto-resize
  17340. if (width === 0 && height === 0) {
  17341. width = this.canvas.width;
  17342. height = this.canvas.height;
  17343. } else if (width === 0) {
  17344. width = this.canvas.width * height / this.canvas.height;
  17345. } else if (height === 0) {
  17346. height = this.canvas.height * width / this.canvas.width;
  17347. }
  17348. width = Math.floor(width);
  17349. height = Math.floor(height);
  17350. var tempCanvas = document.createElement('canvas');
  17351. tempCanvas.width = width;
  17352. tempCanvas.height = height;
  17353. tempCanvas.getContext('2d').drawImage(this.canvas,
  17354. 0, 0, this.canvas.width, this.canvas.height,
  17355. 0, 0, tempCanvas.width, tempCanvas.height
  17356. );
  17357. // Resize the original canvas, which will clear its contents
  17358. this.canvas.width = this.width = width;
  17359. this.canvas.height = this.height = height;
  17360. //Copy the image back
  17361. this.drawingContext.drawImage(tempCanvas,
  17362. 0, 0, width, height,
  17363. 0, 0, width, height
  17364. );
  17365. if(this.pixels.length > 0){
  17366. this.loadPixels();
  17367. }
  17368. };
  17369. /**
  17370. * Copies a region of pixels from one image to another. If no
  17371. * srcImage is specified this is used as the source. If the source
  17372. * and destination regions aren't the same size, it will
  17373. * automatically resize source pixels to fit the specified
  17374. * target region.
  17375. *
  17376. * @method copy
  17377. * @param {p5.Image|undefined} srcImage source image
  17378. * @param {Integer} sx X coordinate of the source's upper left corner
  17379. * @param {Integer} sy Y coordinate of the source's upper left corner
  17380. * @param {Integer} sw source image width
  17381. * @param {Integer} sh source image height
  17382. * @param {Integer} dx X coordinate of the destination's upper left corner
  17383. * @param {Integer} dy Y coordinate of the destination's upper left corner
  17384. * @param {Integer} dw destination image width
  17385. * @param {Integer} dh destination image height
  17386. * @example
  17387. * <div><code>
  17388. * var photo;
  17389. * var bricks;
  17390. * var x;
  17391. * var y;
  17392. *
  17393. * function preload() {
  17394. * photo = loadImage("assets/rockies.jpg");
  17395. * bricks = loadImage("assets/bricks.jpg");
  17396. * }
  17397. *
  17398. * function setup() {
  17399. * x = bricks.width/2;
  17400. * y = bricks.height/2;
  17401. * photo.copy(bricks, 0, 0, x, y, 0, 0, x, y);
  17402. * image(photo, 0, 0);
  17403. * }
  17404. * </code></div>
  17405. *
  17406. * @alt
  17407. * image of rocky mountains and smaller image on top of bricks at top left
  17408. *
  17409. */
  17410. p5.Image.prototype.copy = function () {
  17411. p5.prototype.copy.apply(this, arguments);
  17412. };
  17413. /**
  17414. * Masks part of an image from displaying by loading another
  17415. * image and using it's alpha channel as an alpha channel for
  17416. * this image.
  17417. *
  17418. * @method mask
  17419. * @param {p5.Image} srcImage source image
  17420. * @example
  17421. * <div><code>
  17422. * var photo, maskImage;
  17423. * function preload() {
  17424. * photo = loadImage("assets/rockies.jpg");
  17425. * maskImage = loadImage("assets/mask2.png");
  17426. * }
  17427. *
  17428. * function setup() {
  17429. * createCanvas(100, 100);
  17430. * photo.mask(maskImage);
  17431. * image(photo, 0, 0);
  17432. * }
  17433. * </code></div>
  17434. *
  17435. * @alt
  17436. * image of rocky mountains with white at right
  17437. *
  17438. *
  17439. * http://blogs.adobe.com/webplatform/2013/01/28/blending-features-in-canvas/
  17440. *
  17441. */
  17442. // TODO: - Accept an array of alpha values.
  17443. // - Use other channels of an image. p5 uses the
  17444. // blue channel (which feels kind of arbitrary). Note: at the
  17445. // moment this method does not match native processings original
  17446. // functionality exactly.
  17447. p5.Image.prototype.mask = function(p5Image) {
  17448. if(p5Image === undefined){
  17449. p5Image = this;
  17450. }
  17451. var currBlend = this.drawingContext.globalCompositeOperation;
  17452. var scaleFactor = 1;
  17453. if (p5Image instanceof p5.Renderer) {
  17454. scaleFactor = p5Image._pInst._pixelDensity;
  17455. }
  17456. var copyArgs = [
  17457. p5Image,
  17458. 0,
  17459. 0,
  17460. scaleFactor*p5Image.width,
  17461. scaleFactor*p5Image.height,
  17462. 0,
  17463. 0,
  17464. this.width,
  17465. this.height
  17466. ];
  17467. this.drawingContext.globalCompositeOperation = 'destination-in';
  17468. p5.Image.prototype.copy.apply(this, copyArgs);
  17469. this.drawingContext.globalCompositeOperation = currBlend;
  17470. };
  17471. /**
  17472. * Applies an image filter to a p5.Image
  17473. *
  17474. * @method filter
  17475. * @param {String} operation one of threshold, gray, invert, posterize and
  17476. * opaque see Filters.js for docs on each available
  17477. * filter
  17478. * @param {Number|undefined} value
  17479. * @example
  17480. * <div><code>
  17481. * var photo1;
  17482. * var photo2;
  17483. *
  17484. * function preload() {
  17485. * photo1 = loadImage("assets/rockies.jpg");
  17486. * photo2 = loadImage("assets/rockies.jpg");
  17487. * }
  17488. *
  17489. * function setup() {
  17490. * photo2.filter("gray");
  17491. * image(photo1, 0, 0);
  17492. * image(photo2, width/2, 0);
  17493. * }
  17494. * </code></div>
  17495. *
  17496. * @alt
  17497. * 2 images of rocky mountains left one in color, right in black and white
  17498. *
  17499. */
  17500. p5.Image.prototype.filter = function(operation, value) {
  17501. Filters.apply(this.canvas, Filters[operation.toLowerCase()], value);
  17502. };
  17503. /**
  17504. * Copies a region of pixels from one image to another, using a specified
  17505. * blend mode to do the operation.
  17506. *
  17507. * @method blend
  17508. * @param {p5.Image|undefined} srcImage source image
  17509. * @param {Integer} sx X coordinate of the source's upper left corner
  17510. * @param {Integer} sy Y coordinate of the source's upper left corner
  17511. * @param {Integer} sw source image width
  17512. * @param {Integer} sh source image height
  17513. * @param {Integer} dx X coordinate of the destination's upper left corner
  17514. * @param {Integer} dy Y coordinate of the destination's upper left corner
  17515. * @param {Integer} dw destination image width
  17516. * @param {Integer} dh destination image height
  17517. * @param {Integer} blendMode the blend mode
  17518. *
  17519. * Available blend modes are: normal | multiply | screen | overlay |
  17520. * darken | lighten | color-dodge | color-burn | hard-light |
  17521. * soft-light | difference | exclusion | hue | saturation |
  17522. * color | luminosity
  17523. *
  17524. *
  17525. * http://blogs.adobe.com/webplatform/2013/01/28/blending-features-in-canvas/
  17526. * @example
  17527. * <div><code>
  17528. * var mountains;
  17529. * var bricks;
  17530. *
  17531. * function preload() {
  17532. * mountains = loadImage("assets/rockies.jpg");
  17533. * bricks = loadImage("assets/bricks_third.jpg");
  17534. * }
  17535. *
  17536. * function setup() {
  17537. * mountains.blend(bricks, 0, 0, 33, 100, 67, 0, 33, 100, ADD);
  17538. * image(mountains, 0, 0);
  17539. * image(bricks, 0, 0);
  17540. * }
  17541. * </code></div>
  17542. * <div><code>
  17543. * var mountains;
  17544. * var bricks;
  17545. *
  17546. * function preload() {
  17547. * mountains = loadImage("assets/rockies.jpg");
  17548. * bricks = loadImage("assets/bricks_third.jpg");
  17549. * }
  17550. *
  17551. * function setup() {
  17552. * mountains.blend(bricks, 0, 0, 33, 100, 67, 0, 33, 100, DARKEST);
  17553. * image(mountains, 0, 0);
  17554. * image(bricks, 0, 0);
  17555. * }
  17556. * </code></div>
  17557. * <div><code>
  17558. * var mountains;
  17559. * var bricks;
  17560. *
  17561. * function preload() {
  17562. * mountains = loadImage("assets/rockies.jpg");
  17563. * bricks = loadImage("assets/bricks_third.jpg");
  17564. * }
  17565. *
  17566. * function setup() {
  17567. * mountains.blend(bricks, 0, 0, 33, 100, 67, 0, 33, 100, LIGHTEST);
  17568. * image(mountains, 0, 0);
  17569. * image(bricks, 0, 0);
  17570. * }
  17571. * </code></div>
  17572. *
  17573. * @alt
  17574. * image of rocky mountains. Brick images on left and right. Right overexposed
  17575. * image of rockies. Brickwall images on left and right. Right mortar transparent
  17576. * image of rockies. Brickwall images on left and right. Right translucent
  17577. *
  17578. */
  17579. p5.Image.prototype.blend = function() {
  17580. p5.prototype.blend.apply(this, arguments);
  17581. };
  17582. /**
  17583. * Saves the image to a file and force the browser to download it.
  17584. * Accepts two strings for filename and file extension
  17585. * Supports png (default) and jpg.
  17586. *
  17587. * @method save
  17588. * @param {String} filename give your file a name
  17589. * @param {String} extension 'png' or 'jpg'
  17590. * @example
  17591. * <div><code>
  17592. * var photo;
  17593. *
  17594. * function preload() {
  17595. * photo = loadImage("assets/rockies.jpg");
  17596. * }
  17597. *
  17598. * function draw() {
  17599. * image(photo, 0, 0);
  17600. * }
  17601. *
  17602. * function keyTyped() {
  17603. * if (key == 's') {
  17604. * photo.save("photo", "png");
  17605. * }
  17606. * }
  17607. * </code></div>
  17608. *
  17609. * @alt
  17610. * image of rocky mountains.
  17611. *
  17612. */
  17613. p5.Image.prototype.save = function(filename, extension) {
  17614. var mimeType;
  17615. if (!extension) {
  17616. extension = 'png';
  17617. mimeType = 'image/png';
  17618. }
  17619. else {
  17620. // en.wikipedia.org/wiki/Comparison_of_web_browsers#Image_format_support
  17621. switch(extension.toLowerCase()){
  17622. case 'png':
  17623. mimeType = 'image/png';
  17624. break;
  17625. case 'jpeg':
  17626. mimeType = 'image/jpeg';
  17627. break;
  17628. case 'jpg':
  17629. mimeType = 'image/jpeg';
  17630. break;
  17631. default:
  17632. mimeType = 'image/png';
  17633. break;
  17634. }
  17635. }
  17636. var downloadMime = 'image/octet-stream';
  17637. var imageData = this.canvas.toDataURL(mimeType);
  17638. imageData = imageData.replace(mimeType, downloadMime);
  17639. //Make the browser download the file
  17640. p5.prototype.downloadFile(imageData, filename, extension);
  17641. };
  17642. module.exports = p5.Image;
  17643. },{"../core/core":37,"./filters":54}],58:[function(_dereq_,module,exports){
  17644. /**
  17645. * @module Image
  17646. * @submodule Pixels
  17647. * @for p5
  17648. * @requires core
  17649. */
  17650. 'use strict';
  17651. var p5 = _dereq_('../core/core');
  17652. var Filters = _dereq_('./filters');
  17653. _dereq_('../color/p5.Color');
  17654. /**
  17655. * <a href='https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference
  17656. * /Global_Objects/Uint8ClampedArray' target='_blank'>Uint8ClampedArray</a>
  17657. * containing the values for all the pixels in the display window.
  17658. * These values are numbers. This array is the size (include an appropriate
  17659. * factor for pixelDensity) of the display window x4,
  17660. * representing the R, G, B, A values in order for each pixel, moving from
  17661. * left to right across each row, then down each column. Retina and other
  17662. * high denisty displays will have more pixels[] (by a factor of
  17663. * pixelDensity^2).
  17664. * For example, if the image is 100x100 pixels, there will be 40,000. On a
  17665. * retina display, there will be 160,000.
  17666. * <br><br>
  17667. * The first four values (indices 0-3) in the array will be the R, G, B, A
  17668. * values of the pixel at (0, 0). The second four values (indices 4-7) will
  17669. * contain the R, G, B, A values of the pixel at (1, 0). More generally, to
  17670. * set values for a pixel at (x, y):
  17671. * ```javascript
  17672. * var d = pixelDensity;
  17673. * for (var i = 0; i < d; i++) {
  17674. * for (var j = 0; j < d; j++) {
  17675. * // loop over
  17676. * idx = 4 * ((y * d + j) * width * d + (x * d + i));
  17677. * pixels[idx] = r;
  17678. * pixels[idx+1] = g;
  17679. * pixels[idx+2] = b;
  17680. * pixels[idx+3] = a;
  17681. * }
  17682. * }
  17683. * ```
  17684. * <p>While the above method is complex, it is flexible enough to work with
  17685. * any pixelDensity. Note that set() will automatically take care of
  17686. * setting all the appropriate values in pixels[] for a given (x, y) at
  17687. * any pixelDensity, but the performance may not be as fast when lots of
  17688. * modifications are made to the pixel array.
  17689. * <br><br>
  17690. * Before accessing this array, the data must loaded with the loadPixels()
  17691. * function. After the array data has been modified, the updatePixels()
  17692. * function must be run to update the changes.
  17693. * <br><br>
  17694. * Note that this is not a standard javascript array. This means that
  17695. * standard javascript functions such as <code>slice()</code> or
  17696. * <code>arrayCopy()</code> do not
  17697. * work.</p>
  17698. *
  17699. * @property pixels[]
  17700. * @example
  17701. * <div>
  17702. * <code>
  17703. * var pink = color(255, 102, 204);
  17704. * loadPixels();
  17705. * var d = pixelDensity();
  17706. * var halfImage = 4 * (width * d) * (height/2 * d);
  17707. * for (var i = 0; i < halfImage; i+=4) {
  17708. * pixels[i] = red(pink);
  17709. * pixels[i+1] = green(pink);
  17710. * pixels[i+2] = blue(pink);
  17711. * pixels[i+3] = alpha(pink);
  17712. * }
  17713. * updatePixels();
  17714. * </code>
  17715. * </div>
  17716. *
  17717. * @alt
  17718. * top half of canvas pink, bottom grey
  17719. *
  17720. */
  17721. p5.prototype.pixels = [];
  17722. /**
  17723. * Copies a region of pixels from one image to another, using a specified
  17724. * blend mode to do the operation.<br><br>
  17725. * Available blend modes are: BLEND | DARKEST | LIGHTEST | DIFFERENCE |
  17726. * MULTIPLY| EXCLUSION | SCREEN | REPLACE | OVERLAY | HARD_LIGHT |
  17727. * SOFT_LIGHT | DODGE | BURN | ADD | NORMAL
  17728. *
  17729. *
  17730. * @method blend
  17731. * @param {p5.Image|undefined} srcImage source image
  17732. * @param {Integer} sx X coordinate of the source's upper left corner
  17733. * @param {Integer} sy Y coordinate of the source's upper left corner
  17734. * @param {Integer} sw source image width
  17735. * @param {Integer} sh source image height
  17736. * @param {Integer} dx X coordinate of the destination's upper left corner
  17737. * @param {Integer} dy Y coordinate of the destination's upper left corner
  17738. * @param {Integer} dw destination image width
  17739. * @param {Integer} dh destination image height
  17740. * @param {Integer} blendMode the blend mode
  17741. *
  17742. * @example
  17743. * <div><code>
  17744. * var img0;
  17745. * var img1;
  17746. *
  17747. * function preload() {
  17748. * img0 = loadImage("assets/rockies.jpg");
  17749. * img1 = loadImage("assets/bricks_third.jpg");
  17750. * }
  17751. *
  17752. * function setup() {
  17753. * background(img0);
  17754. * image(img1, 0, 0);
  17755. * blend(img1, 0, 0, 33, 100, 67, 0, 33, 100, LIGHTEST);
  17756. * }
  17757. * </code></div>
  17758. * <div><code>
  17759. * var img0;
  17760. * var img1;
  17761. *
  17762. * function preload() {
  17763. * img0 = loadImage("assets/rockies.jpg");
  17764. * img1 = loadImage("assets/bricks_third.jpg");
  17765. * }
  17766. *
  17767. * function setup() {
  17768. * background(img0);
  17769. * image(img1, 0, 0);
  17770. * blend(img1, 0, 0, 33, 100, 67, 0, 33, 100, DARKEST);
  17771. * }
  17772. * </code></div>
  17773. * <div><code>
  17774. * var img0;
  17775. * var img1;
  17776. *
  17777. * function preload() {
  17778. * img0 = loadImage("assets/rockies.jpg");
  17779. * img1 = loadImage("assets/bricks_third.jpg");
  17780. * }
  17781. *
  17782. * function setup() {
  17783. * background(img0);
  17784. * image(img1, 0, 0);
  17785. * blend(img1, 0, 0, 33, 100, 67, 0, 33, 100, ADD);
  17786. * }
  17787. * </code></div>
  17788. *
  17789. * @alt
  17790. * image of rocky mountains. Brick images on left and right. Right overexposed
  17791. * image of rockies. Brickwall images on left and right. Right mortar transparent
  17792. * image of rockies. Brickwall images on left and right. Right translucent
  17793. *
  17794. *
  17795. */
  17796. p5.prototype.blend = function() {
  17797. if (this._renderer) {
  17798. this._renderer.blend.apply(this._renderer, arguments);
  17799. } else {
  17800. p5.Renderer2D.prototype.blend.apply(this, arguments);
  17801. }
  17802. };
  17803. /**
  17804. * Copies a region of the canvas to another region of the canvas
  17805. * and copies a region of pixels from an image used as the srcImg parameter
  17806. * into the canvas srcImage is specified this is used as the source. If
  17807. * the source and destination regions aren't the same size, it will
  17808. * automatically resize source pixels to fit the specified
  17809. * target region.
  17810. *
  17811. * @method copy
  17812. * @param {p5.Image|undefined} srcImage source image
  17813. * @param {Integer} sx X coordinate of the source's upper left corner
  17814. * @param {Integer} sy Y coordinate of the source's upper left corner
  17815. * @param {Integer} sw source image width
  17816. * @param {Integer} sh source image height
  17817. * @param {Integer} dx X coordinate of the destination's upper left corner
  17818. * @param {Integer} dy Y coordinate of the destination's upper left corner
  17819. * @param {Integer} dw destination image width
  17820. * @param {Integer} dh destination image height
  17821. *
  17822. * @example
  17823. * <div><code>
  17824. * var img;
  17825. *
  17826. * function preload() {
  17827. * img = loadImage("assets/rockies.jpg");
  17828. * }
  17829. *
  17830. * function setup() {
  17831. * background(img);
  17832. * copy(img, 7, 22, 10, 10, 35, 25, 50, 50);
  17833. * stroke(255);
  17834. * noFill();
  17835. * // Rectangle shows area being copied
  17836. * rect(7, 22, 10, 10);
  17837. * }
  17838. * </code></div>
  17839. *
  17840. * @alt
  17841. * image of rocky mountains. Brick images on left and right. Right overexposed
  17842. * image of rockies. Brickwall images on left and right. Right mortar transparent
  17843. * image of rockies. Brickwall images on left and right. Right translucent
  17844. *
  17845. */
  17846. p5.prototype.copy = function () {
  17847. p5.Renderer2D._copyHelper.apply(this, arguments);
  17848. };
  17849. /**
  17850. * Applies a filter to the canvas.
  17851. * <br><br>
  17852. *
  17853. * The presets options are:
  17854. * <br><br>
  17855. *
  17856. * THRESHOLD
  17857. * Converts the image to black and white pixels depending if they are above or
  17858. * below the threshold defined by the level parameter. The parameter must be
  17859. * between 0.0 (black) and 1.0 (white). If no level is specified, 0.5 is used.
  17860. * <br><br>
  17861. *
  17862. * GRAY
  17863. * Converts any colors in the image to grayscale equivalents. No parameter
  17864. * is used.
  17865. * <br><br>
  17866. *
  17867. * OPAQUE
  17868. * Sets the alpha channel to entirely opaque. No parameter is used.
  17869. * <br><br>
  17870. *
  17871. * INVERT
  17872. * Sets each pixel to its inverse value. No parameter is used.
  17873. * <br><br>
  17874. *
  17875. * POSTERIZE
  17876. * Limits each channel of the image to the number of colors specified as the
  17877. * parameter. The parameter can be set to values between 2 and 255, but
  17878. * results are most noticeable in the lower ranges.
  17879. * <br><br>
  17880. *
  17881. * BLUR
  17882. * Executes a Guassian blur with the level parameter specifying the extent
  17883. * of the blurring. If no parameter is used, the blur is equivalent to
  17884. * Guassian blur of radius 1. Larger values increase the blur.
  17885. * <br><br>
  17886. *
  17887. * ERODE
  17888. * Reduces the light areas. No parameter is used.
  17889. * <br><br>
  17890. *
  17891. * DILATE
  17892. * Increases the light areas. No parameter is used.
  17893. *
  17894. * @method filter
  17895. * @param {Constant} filterType
  17896. * @param {Number} filterParam an optional parameter unique
  17897. * to each filter, see above
  17898. *
  17899. *
  17900. * @example
  17901. * <div>
  17902. * <code>
  17903. * var img;
  17904. * function preload() {
  17905. * img = loadImage("assets/bricks.jpg");
  17906. * }
  17907. * function setup() {
  17908. * image(img, 0, 0);
  17909. * filter(THRESHOLD);
  17910. * }
  17911. * </code>
  17912. * </div>
  17913. *
  17914. * <div>
  17915. * <code>
  17916. * var img;
  17917. * function preload() {
  17918. * img = loadImage("assets/bricks.jpg");
  17919. * }
  17920. * function setup() {
  17921. * image(img, 0, 0);
  17922. * filter(GRAY);
  17923. * }
  17924. * </code>
  17925. * </div>
  17926. *
  17927. * <div>
  17928. * <code>
  17929. * var img;
  17930. * function preload() {
  17931. * img = loadImage("assets/bricks.jpg");
  17932. * }
  17933. * function setup() {
  17934. * image(img, 0, 0);
  17935. * filter(OPAQUE);
  17936. * }
  17937. * </code>
  17938. * </div>
  17939. *
  17940. * <div>
  17941. * <code>
  17942. * var img;
  17943. * function preload() {
  17944. * img = loadImage("assets/bricks.jpg");
  17945. * }
  17946. * function setup() {
  17947. * image(img, 0, 0);
  17948. * filter(INVERT);
  17949. * }
  17950. * </code>
  17951. * </div>
  17952. *
  17953. * <div>
  17954. * <code>
  17955. * var img;
  17956. * function preload() {
  17957. * img = loadImage("assets/bricks.jpg");
  17958. * }
  17959. * function setup() {
  17960. * image(img, 0, 0);
  17961. * filter(POSTERIZE,3);
  17962. * }
  17963. * </code>
  17964. * </div>
  17965. *
  17966. * <div>
  17967. * <code>
  17968. * var img;
  17969. * function preload() {
  17970. * img = loadImage("assets/bricks.jpg");
  17971. * }
  17972. * function setup() {
  17973. * image(img, 0, 0);
  17974. * filter(DILATE);
  17975. * }
  17976. * </code>
  17977. * </div>
  17978. *
  17979. * <div>
  17980. * <code>
  17981. * var img;
  17982. * function preload() {
  17983. * img = loadImage("assets/bricks.jpg");
  17984. * }
  17985. * function setup() {
  17986. * image(img, 0, 0);
  17987. * filter(BLUR,3);
  17988. * }
  17989. * </code>
  17990. * </div>
  17991. *
  17992. * <div>
  17993. * <code>
  17994. * var img;
  17995. * function preload() {
  17996. * img = loadImage("assets/bricks.jpg");
  17997. * }
  17998. * function setup() {
  17999. * image(img, 0, 0);
  18000. * filter(ERODE);
  18001. * }
  18002. * </code>
  18003. * </div>
  18004. *
  18005. * @alt
  18006. * black and white image of a brick wall.
  18007. * greyscale image of a brickwall
  18008. * image of a brickwall
  18009. * jade colored image of a brickwall
  18010. * red and pink image of a brickwall
  18011. * image of a brickwall
  18012. * blurry image of a brickwall
  18013. * image of a brickwall
  18014. * image of a brickwall with less detail
  18015. *
  18016. */
  18017. p5.prototype.filter = function(operation, value) {
  18018. if(this.canvas !== undefined) {
  18019. Filters.apply(this.canvas, Filters[operation.toLowerCase()], value);
  18020. }
  18021. else {
  18022. Filters.apply(this.elt, Filters[operation.toLowerCase()], value);
  18023. }
  18024. };
  18025. /**
  18026. * Returns an array of [R,G,B,A] values for any pixel or grabs a section of
  18027. * an image. If no parameters are specified, the entire image is returned.
  18028. * Use the x and y parameters to get the value of one pixel. Get a section of
  18029. * the display window by specifying additional w and h parameters. When
  18030. * getting an image, the x and y parameters define the coordinates for the
  18031. * upper-left corner of the image, regardless of the current imageMode().
  18032. * <br><br>
  18033. * If the pixel requested is outside of the image window, [0,0,0,255] is
  18034. * returned. To get the numbers scaled according to the current color ranges
  18035. * and taking into account colorMode, use getColor instead of get.
  18036. * <br><br>
  18037. * Getting the color of a single pixel with get(x, y) is easy, but not as fast
  18038. * as grabbing the data directly from pixels[]. The equivalent statement to
  18039. * get(x, y) using pixels[] with pixel density d is
  18040. * <code>
  18041. * var off = (y * width + x) * d * 4;
  18042. * [pixels[off],
  18043. * pixels[off+1],
  18044. * pixels[off+2],
  18045. * pixels[off+3]]</code>
  18046. * <br><br>
  18047. * See the reference for pixels[] for more information.
  18048. *
  18049. * @method get
  18050. * @param {Number} [x] x-coordinate of the pixel
  18051. * @param {Number} [y] y-coordinate of the pixel
  18052. * @param {Number} [w] width
  18053. * @param {Number} [h] height
  18054. * @return {Array|p5.Image} values of pixel at x,y in array format
  18055. * [R, G, B, A] or p5.Image
  18056. * @example
  18057. * <div>
  18058. * <code>
  18059. * var img;
  18060. * function preload() {
  18061. * img = loadImage("assets/rockies.jpg");
  18062. * }
  18063. * function setup() {
  18064. * image(img, 0, 0);
  18065. * var c = get();
  18066. * image(c, width/2, 0);
  18067. * }
  18068. * </code>
  18069. * </div>
  18070. *
  18071. * <div>
  18072. * <code>
  18073. * var img;
  18074. * function preload() {
  18075. * img = loadImage("assets/rockies.jpg");
  18076. * }
  18077. * function setup() {
  18078. * image(img, 0, 0);
  18079. * var c = get(50, 90);
  18080. * fill(c);
  18081. * noStroke();
  18082. * rect(25, 25, 50, 50);
  18083. * }
  18084. * </code>
  18085. * </div>
  18086. *
  18087. * @alt
  18088. * 2 images of the rocky mountains, side-by-side
  18089. * Image of the rocky mountains with 50x50 green rect in center of canvas
  18090. *
  18091. */
  18092. p5.prototype.get = function(x, y, w, h){
  18093. return this._renderer.get(x, y, w, h);
  18094. };
  18095. /**
  18096. * Loads the pixel data for the display window into the pixels[] array. This
  18097. * function must always be called before reading from or writing to pixels[].
  18098. *
  18099. * @method loadPixels
  18100. * @example
  18101. * <div>
  18102. * <code>
  18103. * var img;
  18104. * function preload() {
  18105. * img = loadImage("assets/rockies.jpg");
  18106. * }
  18107. *
  18108. * function setup() {
  18109. * image(img, 0, 0);
  18110. * var d = pixelDensity();
  18111. * var halfImage = 4 * (img.width * d) *
  18112. (img.height/2 * d);
  18113. * loadPixels();
  18114. * for (var i = 0; i < halfImage; i++) {
  18115. * pixels[i+halfImage] = pixels[i];
  18116. * }
  18117. * updatePixels();
  18118. * }
  18119. * </code>
  18120. * </div>
  18121. *
  18122. * @alt
  18123. * two images of the rocky mountains. one on top, one on bottom of canvas.
  18124. *
  18125. */
  18126. p5.prototype.loadPixels = function() {
  18127. this._renderer.loadPixels();
  18128. };
  18129. /**
  18130. * <p>Changes the color of any pixel, or writes an image directly to the
  18131. * display window.</p>
  18132. * <p>The x and y parameters specify the pixel to change and the c parameter
  18133. * specifies the color value. This can be a p5.Color object, or [R, G, B, A]
  18134. * pixel array. It can also be a single grayscale value.
  18135. * When setting an image, the x and y parameters define the coordinates for
  18136. * the upper-left corner of the image, regardless of the current imageMode().
  18137. * </p>
  18138. * <p>
  18139. * After using set(), you must call updatePixels() for your changes to
  18140. * appear. This should be called once all pixels have been set.
  18141. * </p>
  18142. * <p>Setting the color of a single pixel with set(x, y) is easy, but not as
  18143. * fast as putting the data directly into pixels[]. Setting the pixels[]
  18144. * values directly may be complicated when working with a retina display,
  18145. * but will perform better when lots of pixels need to be set directly on
  18146. * every loop.</p>
  18147. * <p>See the reference for pixels[] for more information.</p>
  18148. *
  18149. * @method set
  18150. * @param {Number} x x-coordinate of the pixel
  18151. * @param {Number} y y-coordinate of the pixel
  18152. * @param {Number|Array|Object} c insert a grayscale value | a pixel array |
  18153. * a p5.Color object | a p5.Image to copy
  18154. * @example
  18155. * <div>
  18156. * <code>
  18157. * var black = color(0);
  18158. * set(30, 20, black);
  18159. * set(85, 20, black);
  18160. * set(85, 75, black);
  18161. * set(30, 75, black);
  18162. * updatePixels();
  18163. * </code>
  18164. * </div>
  18165. *
  18166. * <div>
  18167. * <code>
  18168. * for (var i = 30; i < width-15; i++) {
  18169. * for (var j = 20; j < height-25; j++) {
  18170. * var c = color(204-j, 153-i, 0);
  18171. * set(i, j, c);
  18172. * }
  18173. * }
  18174. * updatePixels();
  18175. * </code>
  18176. * </div>
  18177. *
  18178. * <div>
  18179. * <code>
  18180. * var img;
  18181. * function preload() {
  18182. * img = loadImage("assets/rockies.jpg");
  18183. * }
  18184. *
  18185. * function setup() {
  18186. * set(0, 0, img);
  18187. * updatePixels();
  18188. * line(0, 0, width, height);
  18189. * line(0, height, width, 0);
  18190. * }
  18191. * </code>
  18192. * </div>
  18193. *
  18194. * @alt
  18195. * 4 black points in the shape of a square middle-right of canvas.
  18196. * square with orangey-brown gradient lightening at bottom right.
  18197. * image of the rocky mountains. with lines like an 'x' through the center.
  18198. */
  18199. p5.prototype.set = function (x, y, imgOrCol) {
  18200. this._renderer.set(x, y, imgOrCol);
  18201. };
  18202. /**
  18203. * Updates the display window with the data in the pixels[] array.
  18204. * Use in conjunction with loadPixels(). If you're only reading pixels from
  18205. * the array, there's no need to call updatePixels() — updating is only
  18206. * necessary to apply changes. updatePixels() should be called anytime the
  18207. * pixels array is manipulated or set() is called.
  18208. *
  18209. * @method updatePixels
  18210. * @param {Number} [x] x-coordinate of the upper-left corner of region
  18211. * to update
  18212. * @param {Number} [y] y-coordinate of the upper-left corner of region
  18213. * to update
  18214. * @param {Number} [w] width of region to update
  18215. * @param {Number} [w] height of region to update
  18216. * @example
  18217. * <div>
  18218. * <code>
  18219. * var img;
  18220. * function preload() {
  18221. * img = loadImage("assets/rockies.jpg");
  18222. * }
  18223. *
  18224. * function setup() {
  18225. * image(img, 0, 0);
  18226. * var halfImage = 4 * (img.width * pixelDensity()) *
  18227. * (img.height * pixelDensity()/2);
  18228. * loadPixels();
  18229. * for (var i = 0; i < halfImage; i++) {
  18230. * pixels[i+halfImage] = pixels[i];
  18231. * }
  18232. * updatePixels();
  18233. * }
  18234. * </code>
  18235. * </div>
  18236. * @alt
  18237. * two images of the rocky mountains. one on top, one on bottom of canvas.
  18238. */
  18239. p5.prototype.updatePixels = function (x, y, w, h) {
  18240. // graceful fail - if loadPixels() or set() has not been called, pixel
  18241. // array will be empty, ignore call to updatePixels()
  18242. if (this.pixels.length === 0) {
  18243. return;
  18244. }
  18245. this._renderer.updatePixels(x, y, w, h);
  18246. };
  18247. module.exports = p5;
  18248. },{"../color/p5.Color":31,"../core/core":37,"./filters":54}],59:[function(_dereq_,module,exports){
  18249. /**
  18250. * @module IO
  18251. * @submodule Input
  18252. * @for p5
  18253. * @requires core
  18254. * @requires reqwest
  18255. */
  18256. 'use strict';
  18257. var p5 = _dereq_('../core/core');
  18258. var reqwest = _dereq_('reqwest');
  18259. var opentype = _dereq_('opentype.js');
  18260. _dereq_('../core/error_helpers');
  18261. /**
  18262. * Checks if we are in preload and returns the last arg which will be the
  18263. * _decrementPreload function if called from a loadX() function. Should
  18264. * only be used in loadX() functions.
  18265. * @private
  18266. */
  18267. p5._getDecrementPreload = function () {
  18268. var decrementPreload = arguments[arguments.length - 1];
  18269. // when in preload decrementPreload will always be the last arg as it is set
  18270. // with args.push() before invocation in _wrapPreload
  18271. if ((window.preload || (this && this.preload)) &&
  18272. typeof decrementPreload === 'function') {
  18273. return decrementPreload;
  18274. } else {
  18275. return null;
  18276. }
  18277. };
  18278. /**
  18279. * Loads an opentype font file (.otf, .ttf) from a file or a URL,
  18280. * and returns a PFont Object. This method is asynchronous,
  18281. * meaning it may not finish before the next line in your sketch
  18282. * is executed.
  18283. * <br><br>
  18284. * The path to the font should be relative to the HTML file
  18285. * that links in your sketch. Loading an from a URL or other
  18286. * remote location may be blocked due to your browser's built-in
  18287. * security.
  18288. *
  18289. * @method loadFont
  18290. * @param {String} path name of the file or url to load
  18291. * @param {Function} [callback] function to be executed after
  18292. * loadFont()
  18293. * completes
  18294. * @return {Object} p5.Font object
  18295. * @example
  18296. *
  18297. * <p>Calling loadFont() inside preload() guarantees that the load
  18298. * operation will have completed before setup() and draw() are called.</p>
  18299. *
  18300. * <div><code>
  18301. * var myFont;
  18302. * function preload() {
  18303. * myFont = loadFont('assets/AvenirNextLTPro-Demi.otf');
  18304. * }
  18305. *
  18306. * function setup() {
  18307. * fill('#ED225D');
  18308. * textFont(myFont);
  18309. * textSize(36);
  18310. * text('p5*js', 10, 50);
  18311. * }
  18312. * </code></div>
  18313. *
  18314. * Outside of preload(), you may supply a callback function to handle the
  18315. * object:
  18316. *
  18317. * <div><code>
  18318. * function setup() {
  18319. * loadFont('assets/AvenirNextLTPro-Demi.otf', drawText);
  18320. * }
  18321. *
  18322. * function drawText(font) {
  18323. * fill('#ED225D');
  18324. * textFont(font, 36);
  18325. * text('p5*js', 10, 50);
  18326. * }
  18327. *
  18328. * </code></div>
  18329. *
  18330. * <p>You can also use the string name of the font to style other HTML
  18331. * elements.</p>
  18332. *
  18333. * <div><code>
  18334. * var myFont;
  18335. *
  18336. * function preload() {
  18337. * myFont = loadFont('assets/Avenir.otf');
  18338. * }
  18339. *
  18340. * function setup() {
  18341. * var myDiv = createDiv('hello there');
  18342. * myDiv.style('font-family', 'Avenir');
  18343. * }
  18344. * </code></div>
  18345. *
  18346. * @alt
  18347. * p5*js in p5's theme dark pink
  18348. * p5*js in p5's theme dark pink
  18349. *
  18350. */
  18351. p5.prototype.loadFont = function (path, onSuccess, onError) {
  18352. var p5Font = new p5.Font(this);
  18353. var decrementPreload = p5._getDecrementPreload.apply(this, arguments);
  18354. opentype.load(path, function (err, font) {
  18355. if (err) {
  18356. if ((typeof onError !== 'undefined') && (onError !== decrementPreload)) {
  18357. return onError(err);
  18358. }
  18359. p5._friendlyFileLoadError(4, path);
  18360. console.error(err, path);
  18361. return;
  18362. }
  18363. p5Font.font = font;
  18364. if (typeof onSuccess !== 'undefined') {
  18365. onSuccess(p5Font);
  18366. }
  18367. if (decrementPreload && (onSuccess !== decrementPreload)) {
  18368. decrementPreload();
  18369. }
  18370. // check that we have an acceptable font type
  18371. var validFontTypes = [ 'ttf', 'otf', 'woff', 'woff2' ],
  18372. fileNoPath = path.split('\\').pop().split('/').pop(),
  18373. lastDotIdx = fileNoPath.lastIndexOf('.'), fontFamily, newStyle,
  18374. fileExt = lastDotIdx < 1 ? null : fileNoPath.substr(lastDotIdx + 1);
  18375. // if so, add it to the DOM (name-only) for use with p5.dom
  18376. if (validFontTypes.indexOf(fileExt) > -1) {
  18377. fontFamily = fileNoPath.substr(0, lastDotIdx);
  18378. newStyle = document.createElement('style');
  18379. newStyle.appendChild(document.createTextNode('\n@font-face {' +
  18380. '\nfont-family: ' + fontFamily + ';\nsrc: url(' + path + ');\n}\n'));
  18381. document.head.appendChild(newStyle);
  18382. }
  18383. });
  18384. return p5Font;
  18385. };
  18386. //BufferedReader
  18387. p5.prototype.createInput = function () {
  18388. // TODO
  18389. throw 'not yet implemented';
  18390. };
  18391. p5.prototype.createReader = function () {
  18392. // TODO
  18393. throw 'not yet implemented';
  18394. };
  18395. p5.prototype.loadBytes = function () {
  18396. // TODO
  18397. throw 'not yet implemented';
  18398. };
  18399. /**
  18400. * Loads a JSON file from a file or a URL, and returns an Object or Array.
  18401. * This method is asynchronous, meaning it may not finish before the next
  18402. * line in your sketch is executed.
  18403. *
  18404. * @method loadJSON
  18405. * @param {String} path name of the file or url to load
  18406. * @param {Function} [callback] function to be executed after
  18407. * loadJSON() completes, data is passed
  18408. * in as first argument
  18409. * @param {Function} [errorCallback] function to be executed if
  18410. * there is an error, response is passed
  18411. * in as first argument
  18412. * @param {String} [datatype] "json" or "jsonp"
  18413. * @return {Object|Array} JSON data
  18414. * @example
  18415. *
  18416. * <p>Calling loadJSON() inside preload() guarantees to complete the
  18417. * operation before setup() and draw() are called.</p>
  18418. *
  18419. * <div><code>
  18420. * var weather;
  18421. * function preload() {
  18422. * var url = 'http://api.openweathermap.org/data/2.5/weather?q=London,UK'+
  18423. * '&APPID=7bbbb47522848e8b9c26ba35c226c734';
  18424. * weather = loadJSON(url);
  18425. * }
  18426. *
  18427. * function setup() {
  18428. * noLoop();
  18429. * }
  18430. *
  18431. * function draw() {
  18432. * background(200);
  18433. * // get the humidity value out of the loaded JSON
  18434. * var humidity = weather.main.humidity;
  18435. * fill(0, humidity); // use the humidity value to set the alpha
  18436. * ellipse(width/2, height/2, 50, 50);
  18437. * }
  18438. * </code></div>
  18439. *
  18440. *
  18441. * <p>Outside of preload(), you may supply a callback function to handle the
  18442. * object:</p>
  18443. * <div><code>
  18444. * function setup() {
  18445. * noLoop();
  18446. * var url = 'http://api.openweathermap.org/data/2.5/weather?q=NewYork'+
  18447. * '&APPID=7bbbb47522848e8b9c26ba35c226c734';
  18448. * loadJSON(url, drawWeather);
  18449. * }
  18450. *
  18451. * function draw() {
  18452. * background(200);
  18453. * }
  18454. *
  18455. * function drawWeather(weather) {
  18456. * // get the humidity value out of the loaded JSON
  18457. * var humidity = weather.main.humidity;
  18458. * fill(0, humidity); // use the humidity value to set the alpha
  18459. * ellipse(width/2, height/2, 50, 50);
  18460. * }
  18461. * </code></div>
  18462. *
  18463. * @alt
  18464. * 50x50 ellipse that changes from black to white depending on the current humidity
  18465. * 50x50 ellipse that changes from black to white depending on the current humidity
  18466. *
  18467. */
  18468. p5.prototype.loadJSON = function () {
  18469. var path = arguments[0];
  18470. var callback = arguments[1];
  18471. var errorCallback;
  18472. var decrementPreload = p5._getDecrementPreload.apply(this, arguments);
  18473. var ret = {}; // object needed for preload
  18474. // assume jsonp for URLs
  18475. var t = 'json'; //= path.indexOf('http') === -1 ? 'json' : 'jsonp';
  18476. // check for explicit data type argument
  18477. for (var i = 2; i < arguments.length; i++) {
  18478. var arg = arguments[i];
  18479. if (typeof arg === 'string') {
  18480. if (arg === 'jsonp' || arg === 'json') {
  18481. t = arg;
  18482. }
  18483. } else if (typeof arg === 'function') {
  18484. errorCallback = arg;
  18485. }
  18486. }
  18487. reqwest({
  18488. url: path,
  18489. type: t,
  18490. crossOrigin: true,
  18491. error: function (resp) {
  18492. // pass to error callback if defined
  18493. if (errorCallback) {
  18494. errorCallback(resp);
  18495. } else { // otherwise log error msg
  18496. console.log(resp.statusText);
  18497. }
  18498. },
  18499. success: function (resp) {
  18500. for (var k in resp) {
  18501. ret[k] = resp[k];
  18502. }
  18503. if (typeof callback !== 'undefined') {
  18504. callback(resp);
  18505. }
  18506. if (decrementPreload && (callback !== decrementPreload)) {
  18507. decrementPreload();
  18508. }
  18509. }
  18510. });
  18511. return ret;
  18512. };
  18513. /**
  18514. * Reads the contents of a file and creates a String array of its individual
  18515. * lines. If the name of the file is used as the parameter, as in the above
  18516. * example, the file must be located in the sketch directory/folder.
  18517. * <br><br>
  18518. * Alternatively, the file maybe be loaded from anywhere on the local
  18519. * computer using an absolute path (something that starts with / on Unix and
  18520. * Linux, or a drive letter on Windows), or the filename parameter can be a
  18521. * URL for a file found on a network.
  18522. * <br><br>
  18523. * This method is asynchronous, meaning it may not finish before the next
  18524. * line in your sketch is executed.
  18525. *
  18526. * @method loadStrings
  18527. * @param {String} filename name of the file or url to load
  18528. * @param {Function} [callback] function to be executed after loadStrings()
  18529. * completes, Array is passed in as first
  18530. * argument
  18531. * @param {Function} [errorCallback] function to be executed if
  18532. * there is an error, response is passed
  18533. * in as first argument
  18534. * @return {Array} Array of Strings
  18535. * @example
  18536. *
  18537. * <p>Calling loadStrings() inside preload() guarantees to complete the
  18538. * operation before setup() and draw() are called.</p>
  18539. *
  18540. * <div><code>
  18541. * var result;
  18542. * function preload() {
  18543. * result = loadStrings('assets/test.txt');
  18544. * }
  18545. * function setup() {
  18546. * background(200);
  18547. * var ind = floor(random(result.length));
  18548. * text(result[ind], 10, 10, 80, 80);
  18549. * }
  18550. * </code></div>
  18551. *
  18552. * <p>Outside of preload(), you may supply a callback function to handle the
  18553. * object:</p>
  18554. *
  18555. * <div><code>
  18556. * function setup() {
  18557. * loadStrings('assets/test.txt', pickString);
  18558. * }
  18559. *
  18560. * function pickString(result) {
  18561. * background(200);
  18562. * var ind = floor(random(result.length));
  18563. * text(result[ind], 10, 10, 80, 80);
  18564. * }
  18565. * </code></div>
  18566. *
  18567. * @alt
  18568. * randomly generated text from a file, for example "i smell like butter"
  18569. * randomly generated text from a file, for example "i have three feet"
  18570. *
  18571. */
  18572. p5.prototype.loadStrings = function (path, callback, errorCallback) {
  18573. var ret = [];
  18574. var req = new XMLHttpRequest();
  18575. var decrementPreload = p5._getDecrementPreload.apply(this, arguments);
  18576. req.addEventListener('error', function (resp) {
  18577. if (errorCallback) {
  18578. errorCallback(resp);
  18579. } else {
  18580. console.log(resp.responseText);
  18581. }
  18582. });
  18583. req.open('GET', path, true);
  18584. req.onreadystatechange = function () {
  18585. if (req.readyState === 4) {
  18586. if (req.status === 200) {
  18587. var arr = req.responseText.match(/[^\r\n]+/g);
  18588. for (var k in arr) {
  18589. ret[k] = arr[k];
  18590. }
  18591. if (typeof callback !== 'undefined') {
  18592. callback(ret);
  18593. }
  18594. if (decrementPreload && (callback !== decrementPreload)) {
  18595. decrementPreload();
  18596. }
  18597. } else {
  18598. if (errorCallback) {
  18599. errorCallback(req);
  18600. } else {
  18601. console.log(req.statusText);
  18602. }
  18603. //p5._friendlyFileLoadError(3, path);
  18604. }
  18605. }
  18606. };
  18607. req.send(null);
  18608. return ret;
  18609. };
  18610. /**
  18611. * <p>Reads the contents of a file or URL and creates a p5.Table object with
  18612. * its values. If a file is specified, it must be located in the sketch's
  18613. * "data" folder. The filename parameter can also be a URL to a file found
  18614. * online. By default, the file is assumed to be comma-separated (in CSV
  18615. * format). Table only looks for a header row if the 'header' option is
  18616. * included.</p>
  18617. *
  18618. * <p>Possible options include:
  18619. * <ul>
  18620. * <li>csv - parse the table as comma-separated values</li>
  18621. * <li>tsv - parse the table as tab-separated values</li>
  18622. * <li>header - this table has a header (title) row</li>
  18623. * </ul>
  18624. * </p>
  18625. *
  18626. * <p>When passing in multiple options, pass them in as separate parameters,
  18627. * seperated by commas. For example:
  18628. * <br><br>
  18629. * <code>
  18630. * loadTable("my_csv_file.csv", "csv", "header")
  18631. * </code>
  18632. * </p>
  18633. *
  18634. * <p> All files loaded and saved use UTF-8 encoding.</p>
  18635. *
  18636. * <p>This method is asynchronous, meaning it may not finish before the next
  18637. * line in your sketch is executed. Calling loadTable() inside preload()
  18638. * guarantees to complete the operation before setup() and draw() are called.
  18639. * <p>Outside of preload(), you may supply a callback function to handle the
  18640. * object:</p>
  18641. * </p>
  18642. *
  18643. * @method loadTable
  18644. * @param {String} filename name of the file or URL to load
  18645. * @param {String|Strings} [options] "header" "csv" "tsv"
  18646. * @param {Function} [callback] function to be executed after
  18647. * loadTable() completes. On success, the
  18648. * Table object is passed in as the
  18649. * first argument; otherwise, false
  18650. * is passed in.
  18651. * @return {Object} Table object containing data
  18652. *
  18653. * @example
  18654. * <div class="norender">
  18655. * <code>
  18656. * // Given the following CSV file called "mammals.csv"
  18657. * // located in the project's "assets" folder:
  18658. * //
  18659. * // id,species,name
  18660. * // 0,Capra hircus,Goat
  18661. * // 1,Panthera pardus,Leopard
  18662. * // 2,Equus zebra,Zebra
  18663. *
  18664. * var table;
  18665. *
  18666. * function preload() {
  18667. * //my table is comma separated value "csv"
  18668. * //and has a header specifying the columns labels
  18669. * table = loadTable("assets/mammals.csv", "csv", "header");
  18670. * //the file can be remote
  18671. * //table = loadTable("http://p5js.org/reference/assets/mammals.csv",
  18672. * // "csv", "header");
  18673. * }
  18674. *
  18675. * function setup() {
  18676. * //count the columns
  18677. * print(table.getRowCount() + " total rows in table");
  18678. * print(table.getColumnCount() + " total columns in table");
  18679. *
  18680. * print(table.getColumn("name"));
  18681. * //["Goat", "Leopard", "Zebra"]
  18682. *
  18683. * //cycle through the table
  18684. * for (var r = 0; r < table.getRowCount(); r++)
  18685. * for (var c = 0; c < table.getColumnCount(); c++) {
  18686. * print(table.getString(r, c));
  18687. * }
  18688. * }
  18689. * </code>
  18690. * </div>
  18691. *
  18692. * @alt
  18693. * randomly generated text from a file, for example "i smell like butter"
  18694. * randomly generated text from a file, for example "i have three feet"
  18695. *
  18696. */
  18697. p5.prototype.loadTable = function (path) {
  18698. var callback = null;
  18699. var options = [];
  18700. var header = false;
  18701. var sep = ',';
  18702. var separatorSet = false;
  18703. var decrementPreload = p5._getDecrementPreload.apply(this, arguments);
  18704. for (var i = 1; i < arguments.length; i++) {
  18705. if ((typeof (arguments[i]) === 'function') &&
  18706. (arguments[i] !== decrementPreload)) {
  18707. callback = arguments[i];
  18708. } else if (typeof (arguments[i]) === 'string') {
  18709. options.push(arguments[i]);
  18710. if (arguments[i] === 'header') {
  18711. header = true;
  18712. }
  18713. if (arguments[i] === 'csv') {
  18714. if (separatorSet) {
  18715. throw new Error('Cannot set multiple separator types.');
  18716. } else {
  18717. sep = ',';
  18718. separatorSet = true;
  18719. }
  18720. } else if (arguments[i] === 'tsv') {
  18721. if (separatorSet) {
  18722. throw new Error('Cannot set multiple separator types.');
  18723. } else {
  18724. sep = '\t';
  18725. separatorSet = true;
  18726. }
  18727. }
  18728. }
  18729. }
  18730. var t = new p5.Table();
  18731. reqwest({
  18732. url: path,
  18733. crossOrigin: true,
  18734. type: 'csv'
  18735. })
  18736. .then(function (resp) {
  18737. resp = resp.responseText;
  18738. var state = {};
  18739. // define constants
  18740. var PRE_TOKEN = 0,
  18741. MID_TOKEN = 1,
  18742. POST_TOKEN = 2,
  18743. POST_RECORD = 4;
  18744. var QUOTE = '\"',
  18745. CR = '\r',
  18746. LF = '\n';
  18747. var records = [];
  18748. var offset = 0;
  18749. var currentRecord = null;
  18750. var currentChar;
  18751. var recordBegin = function () {
  18752. state.escaped = false;
  18753. currentRecord = [];
  18754. tokenBegin();
  18755. };
  18756. var recordEnd = function () {
  18757. state.currentState = POST_RECORD;
  18758. records.push(currentRecord);
  18759. currentRecord = null;
  18760. };
  18761. var tokenBegin = function () {
  18762. state.currentState = PRE_TOKEN;
  18763. state.token = '';
  18764. };
  18765. var tokenEnd = function () {
  18766. currentRecord.push(state.token);
  18767. tokenBegin();
  18768. };
  18769. while (true) {
  18770. currentChar = resp[offset++];
  18771. // EOF
  18772. if (currentChar == null) {
  18773. if (state.escaped) {
  18774. throw new Error('Unclosed quote in file.');
  18775. }
  18776. if (currentRecord) {
  18777. tokenEnd();
  18778. recordEnd();
  18779. break;
  18780. }
  18781. }
  18782. if (currentRecord === null) {
  18783. recordBegin();
  18784. }
  18785. // Handle opening quote
  18786. if (state.currentState === PRE_TOKEN) {
  18787. if (currentChar === QUOTE) {
  18788. state.escaped = true;
  18789. state.currentState = MID_TOKEN;
  18790. continue;
  18791. }
  18792. state.currentState = MID_TOKEN;
  18793. }
  18794. // mid-token and escaped, look for sequences and end quote
  18795. if (state.currentState === MID_TOKEN && state.escaped) {
  18796. if (currentChar === QUOTE) {
  18797. if (resp[offset] === QUOTE) {
  18798. state.token += QUOTE;
  18799. offset++;
  18800. } else {
  18801. state.escaped = false;
  18802. state.currentState = POST_TOKEN;
  18803. }
  18804. } else {
  18805. state.token += currentChar;
  18806. }
  18807. continue;
  18808. }
  18809. // fall-through: mid-token or post-token, not escaped
  18810. if (currentChar === CR) {
  18811. if (resp[offset] === LF) {
  18812. offset++;
  18813. }
  18814. tokenEnd();
  18815. recordEnd();
  18816. } else if (currentChar === LF) {
  18817. tokenEnd();
  18818. recordEnd();
  18819. } else if (currentChar === sep) {
  18820. tokenEnd();
  18821. } else if (state.currentState === MID_TOKEN) {
  18822. state.token += currentChar;
  18823. }
  18824. }
  18825. // set up column names
  18826. if (header) {
  18827. t.columns = records.shift();
  18828. } else {
  18829. for (i = 0; i < records[0].length; i++) {
  18830. t.columns[i] = 'null';
  18831. }
  18832. }
  18833. var row;
  18834. for (i = 0; i < records.length; i++) {
  18835. //Handles row of 'undefined' at end of some CSVs
  18836. if (i === records.length - 1 && records[i].length === 1) {
  18837. if (records[i][0] === 'undefined') {
  18838. break;
  18839. }
  18840. }
  18841. row = new p5.TableRow();
  18842. row.arr = records[i];
  18843. row.obj = makeObject(records[i], t.columns);
  18844. t.addRow(row);
  18845. }
  18846. if (callback !== null) {
  18847. callback(t);
  18848. }
  18849. if (decrementPreload && (callback !== decrementPreload)) {
  18850. decrementPreload();
  18851. }
  18852. })
  18853. .fail(function (err, msg) {
  18854. p5._friendlyFileLoadError(2, path);
  18855. // don't get error callback mixed up with decrementPreload
  18856. if ((typeof callback === 'function') &&
  18857. (callback !== decrementPreload)) {
  18858. callback(false);
  18859. }
  18860. });
  18861. return t;
  18862. };
  18863. // helper function to turn a row into a JSON object
  18864. function makeObject(row, headers) {
  18865. var ret = {};
  18866. headers = headers || [];
  18867. if (typeof (headers) === 'undefined') {
  18868. for (var j = 0; j < row.length; j++) {
  18869. headers[j.toString()] = j;
  18870. }
  18871. }
  18872. for (var i = 0; i < headers.length; i++) {
  18873. var key = headers[i];
  18874. var val = row[i];
  18875. ret[key] = val;
  18876. }
  18877. return ret;
  18878. }
  18879. /*global parseXML */
  18880. p5.prototype.parseXML = function (two) {
  18881. var one = new p5.XML();
  18882. var i;
  18883. if (two.children.length) {
  18884. for ( i = 0; i < two.children.length; i++ ) {
  18885. var node = parseXML(two.children[i]);
  18886. one.addChild(node);
  18887. }
  18888. one.setName(two.nodeName);
  18889. one._setCont(two.textContent);
  18890. one._setAttributes(two);
  18891. for (var j = 0; j < one.children.length; j++) {
  18892. one.children[j].parent = one;
  18893. }
  18894. return one;
  18895. }
  18896. else {
  18897. one.setName(two.nodeName);
  18898. one._setCont(two.textContent);
  18899. one._setAttributes(two);
  18900. return one;
  18901. }
  18902. };
  18903. /**
  18904. * Reads the contents of a file and creates an XML object with its values.
  18905. * If the name of the file is used as the parameter, as in the above example,
  18906. * the file must be located in the sketch directory/folder.
  18907. *
  18908. * Alternatively, the file maybe be loaded from anywhere on the local
  18909. * computer using an absolute path (something that starts with / on Unix and
  18910. * Linux, or a drive letter on Windows), or the filename parameter can be a
  18911. * URL for a file found on a network.
  18912. *
  18913. * This method is asynchronous, meaning it may not finish before the next
  18914. * line in your sketch is executed. Calling loadXML() inside preload()
  18915. * guarantees to complete the operation before setup() and draw() are called.
  18916. *
  18917. * <p>Outside of preload(), you may supply a callback function to handle the
  18918. * object:</p>
  18919. *
  18920. * @method loadXML
  18921. * @param {String} filename name of the file or URL to load
  18922. * @param {Function} [callback] function to be executed after loadXML()
  18923. * completes, XML object is passed in as
  18924. * first argument
  18925. * @param {Function} [errorCallback] function to be executed if
  18926. * there is an error, response is passed
  18927. * in as first argument
  18928. * @return {Object} XML object containing data
  18929. */
  18930. p5.prototype.loadXML = function (path, callback, errorCallback) {
  18931. var ret = {};
  18932. var decrementPreload = p5._getDecrementPreload.apply(this, arguments);
  18933. reqwest({
  18934. url: path,
  18935. type: 'xml',
  18936. crossOrigin: true,
  18937. error: function (resp) {
  18938. // pass to error callback if defined
  18939. if (errorCallback) {
  18940. errorCallback(resp);
  18941. } else { // otherwise log error msg
  18942. console.log(resp.statusText);
  18943. }
  18944. //p5._friendlyFileLoadError(1,path);
  18945. }
  18946. })
  18947. .then(function (resp) {
  18948. var xml = parseXML(resp.documentElement);
  18949. for(var key in xml) {
  18950. ret[key] = xml[key];
  18951. }
  18952. if (typeof callback !== 'undefined') {
  18953. callback(ret);
  18954. }
  18955. if (decrementPreload && (callback !== decrementPreload)) {
  18956. decrementPreload();
  18957. }
  18958. });
  18959. return ret;
  18960. };
  18961. // name clash with window.open
  18962. // p5.prototype.open = function() {
  18963. // // TODO
  18964. // };
  18965. p5.prototype.selectFolder = function () {
  18966. // TODO
  18967. throw 'not yet implemented';
  18968. };
  18969. p5.prototype.selectInput = function () {
  18970. // TODO
  18971. throw 'not yet implemented';
  18972. };
  18973. /**
  18974. * Method for executing an HTTP GET request. If data type is not specified,
  18975. * p5 will try to guess based on the URL, defaulting to text.
  18976. *
  18977. * @method httpGet
  18978. * @param {String} path name of the file or url to load
  18979. * @param {Object} [data] param data passed sent with request
  18980. * @param {String} [datatype] "json", "jsonp", "xml", or "text"
  18981. * @param {Function} [callback] function to be executed after
  18982. * httpGet() completes, data is passed in
  18983. * as first argument
  18984. * @param {Function} [errorCallback] function to be executed if
  18985. * there is an error, response is passed
  18986. * in as first argument
  18987. */
  18988. p5.prototype.httpGet = function () {
  18989. var args = new Array(arguments.length);
  18990. for (var i = 0; i < args.length; ++i) {
  18991. args[i] = arguments[i];
  18992. }
  18993. args.push('GET');
  18994. p5.prototype.httpDo.apply(this, args);
  18995. };
  18996. /**
  18997. * Method for executing an HTTP POST request. If data type is not specified,
  18998. * p5 will try to guess based on the URL, defaulting to text.
  18999. *
  19000. * @method httpPost
  19001. * @param {String} path name of the file or url to load
  19002. * @param {Object} [data] param data passed sent with request
  19003. * @param {String} [datatype] "json", "jsonp", "xml", or "text"
  19004. * @param {Function} [callback] function to be executed after
  19005. * httpGet() completes, data is passed in
  19006. * as first argument
  19007. * @param {Function} [errorCallback] function to be executed if
  19008. * there is an error, response is passed
  19009. * in as first argument
  19010. */
  19011. p5.prototype.httpPost = function () {
  19012. var args = new Array(arguments.length);
  19013. for (var i = 0; i < args.length; ++i) {
  19014. args[i] = arguments[i];
  19015. }
  19016. args.push('POST');
  19017. p5.prototype.httpDo.apply(this, args);
  19018. };
  19019. /**
  19020. * Method for executing an HTTP request. If data type is not specified,
  19021. * p5 will try to guess based on the URL, defaulting to text.<br><br>
  19022. * You may also pass a single object specifying all parameters for the
  19023. * request following the examples inside the reqwest() calls here:
  19024. * <a href='https://github.com/ded/reqwest#api'>
  19025. * https://github.com/ded/reqwest#api</a>
  19026. *
  19027. * @method httpDo
  19028. * @param {String} path name of the file or url to load
  19029. * @param {String} [method] either "GET", "POST", or "PUT",
  19030. * defaults to "GET"
  19031. * @param {Object} [data] param data passed sent with request
  19032. * @param {String} [datatype] "json", "jsonp", "xml", or "text"
  19033. * @param {Function} [callback] function to be executed after
  19034. * httpGet() completes, data is passed in
  19035. * as first argument
  19036. * @param {Function} [errorCallback] function to be executed if
  19037. * there is an error, response is passed
  19038. * in as first argument
  19039. */
  19040. p5.prototype.httpDo = function () {
  19041. if (typeof arguments[0] === 'object') {
  19042. reqwest(arguments[0]);
  19043. } else {
  19044. var method = 'GET';
  19045. var path = arguments[0];
  19046. var data = {};
  19047. var type = '';
  19048. var callback;
  19049. var errorCallback;
  19050. for (var i = 1; i < arguments.length; i++) {
  19051. var a = arguments[i];
  19052. if (typeof a === 'string') {
  19053. if (a === 'GET' || a === 'POST' || a === 'PUT' || a === 'DELETE') {
  19054. method = a;
  19055. } else {
  19056. type = a;
  19057. }
  19058. } else if (typeof a === 'object') {
  19059. data = a;
  19060. } else if (typeof a === 'function') {
  19061. if (!callback) {
  19062. callback = a;
  19063. } else {
  19064. errorCallback = a;
  19065. }
  19066. }
  19067. }
  19068. // do some sort of smart type checking
  19069. if (type === '') {
  19070. if (path.indexOf('json') !== -1) {
  19071. type = 'json';
  19072. } else if (path.indexOf('xml') !== -1) {
  19073. type = 'xml';
  19074. } else {
  19075. type = 'text';
  19076. }
  19077. }
  19078. reqwest({
  19079. url: path,
  19080. method: method,
  19081. data: data,
  19082. type: type,
  19083. crossOrigin: true,
  19084. success: function (resp) {
  19085. if (typeof callback !== 'undefined') {
  19086. if (type === 'text') {
  19087. callback(resp.response);
  19088. } else {
  19089. callback(resp);
  19090. }
  19091. }
  19092. },
  19093. error: function (resp) {
  19094. if (errorCallback) {
  19095. errorCallback(resp);
  19096. } else {
  19097. console.log(resp.statusText);
  19098. }
  19099. }
  19100. });
  19101. }
  19102. };
  19103. /**
  19104. * @module IO
  19105. * @submodule Output
  19106. * @for p5
  19107. */
  19108. window.URL = window.URL || window.webkitURL;
  19109. // private array of p5.PrintWriter objects
  19110. p5.prototype._pWriters = [];
  19111. p5.prototype.beginRaw = function () {
  19112. // TODO
  19113. throw 'not yet implemented';
  19114. };
  19115. p5.prototype.beginRecord = function () {
  19116. // TODO
  19117. throw 'not yet implemented';
  19118. };
  19119. p5.prototype.createOutput = function () {
  19120. // TODO
  19121. throw 'not yet implemented';
  19122. };
  19123. p5.prototype.createWriter = function (name, extension) {
  19124. var newPW;
  19125. // check that it doesn't already exist
  19126. for (var i in p5.prototype._pWriters) {
  19127. if (p5.prototype._pWriters[i].name === name) {
  19128. // if a p5.PrintWriter w/ this name already exists...
  19129. // return p5.prototype._pWriters[i]; // return it w/ contents intact.
  19130. // or, could return a new, empty one with a unique name:
  19131. newPW = new p5.PrintWriter(name + window.millis(), extension);
  19132. p5.prototype._pWriters.push(newPW);
  19133. return newPW;
  19134. }
  19135. }
  19136. newPW = new p5.PrintWriter(name, extension);
  19137. p5.prototype._pWriters.push(newPW);
  19138. return newPW;
  19139. };
  19140. p5.prototype.endRaw = function () {
  19141. // TODO
  19142. throw 'not yet implemented';
  19143. };
  19144. p5.prototype.endRecord = function () {
  19145. // TODO
  19146. throw 'not yet implemented';
  19147. };
  19148. p5.PrintWriter = function (filename, extension) {
  19149. var self = this;
  19150. this.name = filename;
  19151. this.content = '';
  19152. this.print = function (data) {
  19153. this.content += data;
  19154. };
  19155. this.print = function (data) {
  19156. this.content += data + '\n';
  19157. };
  19158. this.flush = function () {
  19159. this.content = '';
  19160. };
  19161. this.close = function () {
  19162. // convert String to Array for the writeFile Blob
  19163. var arr = [];
  19164. arr.push(this.content);
  19165. p5.prototype.writeFile(arr, filename, extension);
  19166. // remove from _pWriters array and delete self
  19167. for (var i in p5.prototype._pWriters) {
  19168. if (p5.prototype._pWriters[i].name === this.name) {
  19169. // remove from _pWriters array
  19170. p5.prototype._pWriters.splice(i, 1);
  19171. }
  19172. }
  19173. self.flush();
  19174. self = {};
  19175. };
  19176. };
  19177. p5.prototype.saveBytes = function () {
  19178. // TODO
  19179. throw 'not yet implemented';
  19180. };
  19181. // object, filename, options --> saveJSON, saveStrings, saveTable
  19182. // filename, [extension] [canvas] --> saveImage
  19183. /**
  19184. * <p>Save an image, text, json, csv, wav, or html. Prompts download to
  19185. * the client's computer. <b>Note that it is not recommended to call save()
  19186. * within draw if it's looping, as the save() function will open a new save
  19187. * dialog every frame.</b></p>
  19188. * <p>The default behavior is to save the canvas as an image. You can
  19189. * optionally specify a filename.
  19190. * For example:</p>
  19191. * <pre class='language-javascript'><code>
  19192. * save();
  19193. * save('myCanvas.jpg'); // save a specific canvas with a filename
  19194. * </code></pre>
  19195. *
  19196. * <p>Alternately, the first parameter can be a pointer to a canvas
  19197. * p5.Element, an Array of Strings,
  19198. * an Array of JSON, a JSON object, a p5.Table, a p5.Image, or a
  19199. * p5.SoundFile (requires p5.sound). The second parameter is a filename
  19200. * (including extension). The third parameter is for options specific
  19201. * to this type of object. This method will save a file that fits the
  19202. * given paramaters. For example:</p>
  19203. *
  19204. * <pre class='language-javascript'><code>
  19205. *
  19206. * save('myCanvas.jpg'); // Saves canvas as an image
  19207. *
  19208. * var cnv = createCanvas(100, 100);
  19209. * save(cnv, 'myCanvas.jpg'); // Saves canvas as an image
  19210. *
  19211. * var gb = createGraphics(100, 100);
  19212. * save(gb, 'myGraphics.jpg'); // Saves p5.Renderer object as an image
  19213. *
  19214. * save(myTable, 'myTable.html'); // Saves table as html file
  19215. * save(myTable, 'myTable.csv',); // Comma Separated Values
  19216. * save(myTable, 'myTable.tsv'); // Tab Separated Values
  19217. *
  19218. * save(myJSON, 'my.json'); // Saves pretty JSON
  19219. * save(myJSON, 'my.json', true); // Optimizes JSON filesize
  19220. *
  19221. * save(img, 'my.png'); // Saves pImage as a png image
  19222. *
  19223. * save(arrayOfStrings, 'my.txt'); // Saves strings to a text file with line
  19224. * // breaks after each item in the array
  19225. * </code></pre>
  19226. *
  19227. * @method save
  19228. * @param {[Object|String]} objectOrFilename If filename is provided, will
  19229. * save canvas as an image with
  19230. * either png or jpg extension
  19231. * depending on the filename.
  19232. * If object is provided, will
  19233. * save depending on the object
  19234. * and filename (see examples
  19235. * above).
  19236. * @param {[String]} filename If an object is provided as the first
  19237. * parameter, then the second parameter
  19238. * indicates the filename,
  19239. * and should include an appropriate
  19240. * file extension (see examples above).
  19241. * @param {[Boolean/String]} options Additional options depend on
  19242. * filetype. For example, when saving JSON,
  19243. * <code>true</code> indicates that the
  19244. * output will be optimized for filesize,
  19245. * rather than readability.
  19246. */
  19247. p5.prototype.save = function (object, _filename, _options) {
  19248. // parse the arguments and figure out which things we are saving
  19249. var args = arguments;
  19250. // =================================================
  19251. // OPTION 1: saveCanvas...
  19252. // if no arguments are provided, save canvas
  19253. var cnv = this._curElement.elt;
  19254. if (args.length === 0) {
  19255. p5.prototype.saveCanvas(cnv);
  19256. return;
  19257. }
  19258. // otherwise, parse the arguments
  19259. // if first param is a p5Graphics, then saveCanvas
  19260. else if (args[0] instanceof p5.Renderer ||
  19261. args[0] instanceof p5.Graphics) {
  19262. p5.prototype.saveCanvas(args[0].elt, args[1], args[2]);
  19263. return;
  19264. }
  19265. // if 1st param is String and only one arg, assume it is canvas filename
  19266. else if (args.length === 1 && typeof (args[0]) === 'string') {
  19267. p5.prototype.saveCanvas(cnv, args[0]);
  19268. }
  19269. // =================================================
  19270. // OPTION 2: extension clarifies saveStrings vs. saveJSON
  19271. else {
  19272. var extension = _checkFileExtension(args[1], args[2])[1];
  19273. switch (extension) {
  19274. case 'json':
  19275. p5.prototype.saveJSON(args[0], args[1], args[2]);
  19276. return;
  19277. case 'txt':
  19278. p5.prototype.saveStrings(args[0], args[1], args[2]);
  19279. return;
  19280. // =================================================
  19281. // OPTION 3: decide based on object...
  19282. default:
  19283. if (args[0] instanceof Array) {
  19284. p5.prototype.saveStrings(args[0], args[1], args[2]);
  19285. } else if (args[0] instanceof p5.Table) {
  19286. p5.prototype.saveTable(args[0], args[1], args[2], args[3]);
  19287. } else if (args[0] instanceof p5.Image) {
  19288. p5.prototype.saveCanvas(args[0].canvas, args[1]);
  19289. } else if (args[0] instanceof p5.SoundFile) {
  19290. p5.prototype.saveSound(args[0], args[1], args[2], args[3]);
  19291. }
  19292. }
  19293. }
  19294. };
  19295. /**
  19296. * Writes the contents of an Array or a JSON object to a .json file.
  19297. * The file saving process and location of the saved file will
  19298. * vary between web browsers.
  19299. *
  19300. * @method saveJSON
  19301. * @param {Array|Object} json
  19302. * @param {String} filename
  19303. * @param {Boolean} [optimize] If true, removes line breaks
  19304. * and spaces from the output
  19305. * file to optimize filesize
  19306. * (but not readability).
  19307. * @example
  19308. * <div><code>
  19309. * var json;
  19310. *
  19311. * function setup() {
  19312. *
  19313. * json = {}; // new JSON Object
  19314. *
  19315. * json.id = 0;
  19316. * json.species = 'Panthera leo';
  19317. * json.name = 'Lion';
  19318. *
  19319. * // To save, un-comment the line below, then click 'run'
  19320. * // saveJSON(json, 'lion.json');
  19321. * }
  19322. *
  19323. * // Saves the following to a file called "lion.json":
  19324. * // {
  19325. * // "id": 0,
  19326. * // "species": "Panthera leo",
  19327. * // "name": "Lion"
  19328. * // }
  19329. * </div></code>
  19330. *
  19331. * @alt
  19332. * no image displayed
  19333. *
  19334. */
  19335. p5.prototype.saveJSON = function (json, filename, opt) {
  19336. var stringify;
  19337. if (opt) {
  19338. stringify = JSON.stringify(json);
  19339. } else {
  19340. stringify = JSON.stringify(json, undefined, 2);
  19341. }
  19342. console.log(stringify);
  19343. this.saveStrings(stringify.split('\n'), filename, 'json');
  19344. };
  19345. p5.prototype.saveJSONObject = p5.prototype.saveJSON;
  19346. p5.prototype.saveJSONArray = p5.prototype.saveJSON;
  19347. p5.prototype.saveStream = function () {
  19348. // TODO
  19349. throw 'not yet implemented';
  19350. };
  19351. /**
  19352. * Writes an array of Strings to a text file, one line per String.
  19353. * The file saving process and location of the saved file will
  19354. * vary between web browsers.
  19355. *
  19356. * @method saveStrings
  19357. * @param {Array} list string array to be written
  19358. * @param {String} filename filename for output
  19359. * @example
  19360. * <div><code>
  19361. * var words = 'apple bear cat dog';
  19362. *
  19363. * // .split() outputs an Array
  19364. * var list = split(words, ' ');
  19365. *
  19366. * // To save the file, un-comment next line and click 'run'
  19367. * // saveStrings(list, 'nouns.txt');
  19368. *
  19369. * // Saves the following to a file called 'nouns.txt':
  19370. * //
  19371. * // apple
  19372. * // bear
  19373. * // cat
  19374. * // dog
  19375. * </code></div>
  19376. *
  19377. * @alt
  19378. * no image displayed
  19379. *
  19380. */
  19381. p5.prototype.saveStrings = function (list, filename, extension) {
  19382. var ext = extension || 'txt';
  19383. var pWriter = this.createWriter(filename, ext);
  19384. for (var i = 0; i < list.length; i++) {
  19385. if (i < list.length - 1) {
  19386. pWriter.print(list[i]);
  19387. } else {
  19388. pWriter.print(list[i]);
  19389. }
  19390. }
  19391. pWriter.close();
  19392. pWriter.flush();
  19393. };
  19394. p5.prototype.saveXML = function () {
  19395. // TODO
  19396. throw 'not yet implemented';
  19397. };
  19398. p5.prototype.selectOutput = function () {
  19399. // TODO
  19400. throw 'not yet implemented';
  19401. };
  19402. // =======
  19403. // HELPERS
  19404. // =======
  19405. function escapeHelper(content) {
  19406. return content
  19407. .replace(/&/g, '&amp;')
  19408. .replace(/</g, '&lt;')
  19409. .replace(/>/g, '&gt;')
  19410. .replace(/"/g, '&quot;')
  19411. .replace(/'/g, '&#039;');
  19412. }
  19413. /**
  19414. * Writes the contents of a Table object to a file. Defaults to a
  19415. * text file with comma-separated-values ('csv') but can also
  19416. * use tab separation ('tsv'), or generate an HTML table ('html').
  19417. * The file saving process and location of the saved file will
  19418. * vary between web browsers.
  19419. *
  19420. * @method saveTable
  19421. * @param {p5.Table} Table the Table object to save to a file
  19422. * @param {String} filename the filename to which the Table should be saved
  19423. * @param {String} [options] can be one of "tsv", "csv", or "html"
  19424. * @example
  19425. * <div><code>
  19426. * var table;
  19427. *
  19428. * function setup() {
  19429. * table = new p5.Table();
  19430. *
  19431. * table.addColumn('id');
  19432. * table.addColumn('species');
  19433. * table.addColumn('name');
  19434. *
  19435. * var newRow = table.addRow();
  19436. * newRow.setNum('id', table.getRowCount() - 1);
  19437. * newRow.setString('species', 'Panthera leo');
  19438. * newRow.setString('name', 'Lion');
  19439. *
  19440. * // To save, un-comment next line then click 'run'
  19441. * // saveTable(table, 'new.csv');
  19442. * }
  19443. *
  19444. * // Saves the following to a file called 'new.csv':
  19445. * // id,species,name
  19446. * // 0,Panthera leo,Lion
  19447. * </code></div>
  19448. *
  19449. * @alt
  19450. * no image displayed
  19451. *
  19452. */
  19453. p5.prototype.saveTable = function (table, filename, options) {
  19454. var pWriter = this.createWriter(filename, options);
  19455. var header = table.columns;
  19456. var sep = ','; // default to CSV
  19457. if (options === 'tsv') {
  19458. sep = '\t';
  19459. }
  19460. if (options !== 'html') {
  19461. // make header if it has values
  19462. if (header[0] !== '0') {
  19463. for (var h = 0; h < header.length; h++) {
  19464. if (h < header.length - 1) {
  19465. pWriter.print(header[h] + sep);
  19466. } else {
  19467. pWriter.print(header[h]);
  19468. }
  19469. }
  19470. }
  19471. // make rows
  19472. for (var i = 0; i < table.rows.length; i++) {
  19473. var j;
  19474. for (j = 0; j < table.rows[i].arr.length; j++) {
  19475. if (j < table.rows[i].arr.length - 1) {
  19476. pWriter.print(table.rows[i].arr[j] + sep);
  19477. } else if (i < table.rows.length - 1) {
  19478. pWriter.print(table.rows[i].arr[j]);
  19479. } else {
  19480. pWriter.print(table.rows[i].arr[j]); // no line break
  19481. }
  19482. }
  19483. }
  19484. }
  19485. // otherwise, make HTML
  19486. else {
  19487. pWriter.print('<html>');
  19488. pWriter.print('<head>');
  19489. var str = ' <meta http-equiv=\"content-type\" content';
  19490. str += '=\"text/html;charset=utf-8\" />';
  19491. pWriter.print(str);
  19492. pWriter.print('</head>');
  19493. pWriter.print('<body>');
  19494. pWriter.print(' <table>');
  19495. // make header if it has values
  19496. if (header[0] !== '0') {
  19497. pWriter.print(' <tr>');
  19498. for (var k = 0; k < header.length; k++) {
  19499. var e = escapeHelper(header[k]);
  19500. pWriter.print(' <td>' + e);
  19501. pWriter.print(' </td>');
  19502. }
  19503. pWriter.print(' </tr>');
  19504. }
  19505. // make rows
  19506. for (var row = 0; row < table.rows.length; row++) {
  19507. pWriter.print(' <tr>');
  19508. for (var col = 0; col < table.columns.length; col++) {
  19509. var entry = table.rows[row].getString(col);
  19510. var htmlEntry = escapeHelper(entry);
  19511. pWriter.print(' <td>' + htmlEntry);
  19512. pWriter.print(' </td>');
  19513. }
  19514. pWriter.print(' </tr>');
  19515. }
  19516. pWriter.print(' </table>');
  19517. pWriter.print('</body>');
  19518. pWriter.print('</html>');
  19519. }
  19520. // close and flush the pWriter
  19521. pWriter.close();
  19522. pWriter.flush();
  19523. }; // end saveTable()
  19524. /**
  19525. * Generate a blob of file data as a url to prepare for download.
  19526. * Accepts an array of data, a filename, and an extension (optional).
  19527. * This is a private function because it does not do any formatting,
  19528. * but it is used by saveStrings, saveJSON, saveTable etc.
  19529. *
  19530. * @param {Array} dataToDownload
  19531. * @param {String} filename
  19532. * @param {[String]} extension
  19533. * @private
  19534. */
  19535. p5.prototype.writeFile = function (dataToDownload, filename, extension) {
  19536. var type = 'application\/octet-stream';
  19537. if (p5.prototype._isSafari()) {
  19538. type = 'text\/plain';
  19539. }
  19540. var blob = new Blob(dataToDownload, {
  19541. 'type': type
  19542. });
  19543. var href = window.URL.createObjectURL(blob);
  19544. p5.prototype.downloadFile(href, filename, extension);
  19545. };
  19546. /**
  19547. * Forces download. Accepts a url to filedata/blob, a filename,
  19548. * and an extension (optional).
  19549. * This is a private function because it does not do any formatting,
  19550. * but it is used by saveStrings, saveJSON, saveTable etc.
  19551. *
  19552. * @param {String} href i.e. an href generated by createObjectURL
  19553. * @param {[String]} filename
  19554. * @param {[String]} extension
  19555. */
  19556. p5.prototype.downloadFile = function (href, fName, extension) {
  19557. var fx = _checkFileExtension(fName, extension);
  19558. var filename = fx[0];
  19559. var ext = fx[1];
  19560. var a = document.createElement('a');
  19561. a.href = href;
  19562. a.download = filename;
  19563. // Firefox requires the link to be added to the DOM before click()
  19564. a.onclick = function(e) {
  19565. destroyClickedElement(e);
  19566. e.stopPropagation();
  19567. };
  19568. a.style.display = 'none';
  19569. document.body.appendChild(a);
  19570. // Safari will open this file in the same page as a confusing Blob.
  19571. if (p5.prototype._isSafari()) {
  19572. var aText = 'Hello, Safari user! To download this file...\n';
  19573. aText += '1. Go to File --> Save As.\n';
  19574. aText += '2. Choose "Page Source" as the Format.\n';
  19575. aText += '3. Name it with this extension: .\"' + ext + '\"';
  19576. alert(aText);
  19577. }
  19578. a.click();
  19579. href = null;
  19580. };
  19581. /**
  19582. * Returns a file extension, or another string
  19583. * if the provided parameter has no extension.
  19584. *
  19585. * @param {String} filename
  19586. * @return {Array} [fileName, fileExtension]
  19587. *
  19588. * @private
  19589. */
  19590. function _checkFileExtension(filename, extension) {
  19591. if (!extension || extension === true || extension === 'true') {
  19592. extension = '';
  19593. }
  19594. if (!filename) {
  19595. filename = 'untitled';
  19596. }
  19597. var ext = '';
  19598. // make sure the file will have a name, see if filename needs extension
  19599. if (filename && filename.indexOf('.') > -1) {
  19600. ext = filename.split('.').pop();
  19601. }
  19602. // append extension if it doesn't exist
  19603. if (extension) {
  19604. if (ext !== extension) {
  19605. ext = extension;
  19606. filename = filename + '.' + ext;
  19607. }
  19608. }
  19609. return [filename, ext];
  19610. }
  19611. p5.prototype._checkFileExtension = _checkFileExtension;
  19612. /**
  19613. * Returns true if the browser is Safari, false if not.
  19614. * Safari makes trouble for downloading files.
  19615. *
  19616. * @return {Boolean} [description]
  19617. * @private
  19618. */
  19619. p5.prototype._isSafari = function () {
  19620. var x = Object.prototype.toString.call(window.HTMLElement);
  19621. return x.indexOf('Constructor') > 0;
  19622. };
  19623. /**
  19624. * Helper function, a callback for download that deletes
  19625. * an invisible anchor element from the DOM once the file
  19626. * has been automatically downloaded.
  19627. *
  19628. * @private
  19629. */
  19630. function destroyClickedElement(event) {
  19631. document.body.removeChild(event.target);
  19632. }
  19633. module.exports = p5;
  19634. },{"../core/core":37,"../core/error_helpers":40,"opentype.js":8,"reqwest":27}],60:[function(_dereq_,module,exports){
  19635. /**
  19636. * @module IO
  19637. * @submodule Table
  19638. * @requires core
  19639. */
  19640. 'use strict';
  19641. var p5 = _dereq_('../core/core');
  19642. /**
  19643. * Table Options
  19644. * <p>Generic class for handling tabular data, typically from a
  19645. * CSV, TSV, or other sort of spreadsheet file.</p>
  19646. * <p>CSV files are
  19647. * <a href="http://en.wikipedia.org/wiki/Comma-separated_values">
  19648. * comma separated values</a>, often with the data in quotes. TSV
  19649. * files use tabs as separators, and usually don't bother with the
  19650. * quotes.</p>
  19651. * <p>File names should end with .csv if they're comma separated.</p>
  19652. * <p>A rough "spec" for CSV can be found
  19653. * <a href="http://tools.ietf.org/html/rfc4180">here</a>.</p>
  19654. * <p>To load files, use the loadTable method.</p>
  19655. * <p>To save tables to your computer, use the save method
  19656. * or the saveTable method.</p>
  19657. *
  19658. * Possible options include:
  19659. * <ul>
  19660. * <li>csv - parse the table as comma-separated values
  19661. * <li>tsv - parse the table as tab-separated values
  19662. * <li>header - this table has a header (title) row
  19663. * </ul>
  19664. */
  19665. /**
  19666. * Table objects store data with multiple rows and columns, much
  19667. * like in a traditional spreadsheet. Tables can be generated from
  19668. * scratch, dynamically, or using data from an existing file.
  19669. *
  19670. * @class p5.Table
  19671. * @constructor
  19672. * @param {Array} [rows] An array of p5.TableRow objects
  19673. * @return {p5.Table} p5.Table generated
  19674. */
  19675. p5.Table = function (rows) {
  19676. /**
  19677. * @property columns
  19678. * @type {Array}
  19679. */
  19680. this.columns = [];
  19681. /**
  19682. * @property rows
  19683. * @type {Array}
  19684. */
  19685. this.rows = [];
  19686. };
  19687. /**
  19688. * Use addRow() to add a new row of data to a p5.Table object. By default,
  19689. * an empty row is created. Typically, you would store a reference to
  19690. * the new row in a TableRow object (see newRow in the example above),
  19691. * and then set individual values using set().
  19692. *
  19693. * If a p5.TableRow object is included as a parameter, then that row is
  19694. * duplicated and added to the table.
  19695. *
  19696. * @method addRow
  19697. * @param {p5.TableRow} [row] row to be added to the table
  19698. *
  19699. * @example
  19700. * <div class="norender">
  19701. * <code>
  19702. * // Given the CSV file "mammals.csv"
  19703. * // in the project's "assets" folder:
  19704. * //
  19705. * // id,species,name
  19706. * // 0,Capra hircus,Goat
  19707. * // 1,Panthera pardus,Leopard
  19708. * // 2,Equus zebra,Zebra
  19709. *
  19710. * var table;
  19711. *
  19712. * function preload() {
  19713. * //my table is comma separated value "csv"
  19714. * //and has a header specifying the columns labels
  19715. * table = loadTable("assets/mammals.csv", "csv", "header");
  19716. * }
  19717. *
  19718. * function setup() {
  19719. * //add a row
  19720. * var newRow = table.addRow();
  19721. * newRow.setString("id", table.getRowCount() - 1);
  19722. * newRow.setString("species", "Canis Lupus");
  19723. * newRow.setString("name", "Wolf");
  19724. *
  19725. * //print the results
  19726. * for (var r = 0; r < table.getRowCount(); r++)
  19727. * for (var c = 0; c < table.getColumnCount(); c++)
  19728. * print(table.getString(r, c));
  19729. * }
  19730. * </code>
  19731. * </div>
  19732. *
  19733. * @alt
  19734. * no image displayed
  19735. *
  19736. */
  19737. p5.Table.prototype.addRow = function(row) {
  19738. // make sure it is a valid TableRow
  19739. var r = row || new p5.TableRow();
  19740. if (typeof(r.arr) === 'undefined' || typeof(r.obj) === 'undefined') {
  19741. //r = new p5.prototype.TableRow(r);
  19742. throw 'invalid TableRow: ' + r;
  19743. }
  19744. r.table = this;
  19745. this.rows.push(r);
  19746. return r;
  19747. };
  19748. /**
  19749. * Removes a row from the table object.
  19750. *
  19751. * @method removeRow
  19752. * @param {Number} id ID number of the row to remove
  19753. *
  19754. * @example
  19755. * <div class="norender">
  19756. * <code>
  19757. * // Given the CSV file "mammals.csv"
  19758. * // in the project's "assets" folder:
  19759. * //
  19760. * // id,species,name
  19761. * // 0,Capra hircus,Goat
  19762. * // 1,Panthera pardus,Leopard
  19763. * // 2,Equus zebra,Zebra
  19764. *
  19765. * var table;
  19766. *
  19767. * function preload() {
  19768. * //my table is comma separated value "csv"
  19769. * //and has a header specifying the columns labels
  19770. * table = loadTable("assets/mammals.csv", "csv", "header");
  19771. * }
  19772. *
  19773. * function setup() {
  19774. * //remove the first row
  19775. * var r = table.removeRow(0);
  19776. *
  19777. * //print the results
  19778. * for (var r = 0; r < table.getRowCount(); r++)
  19779. * for (var c = 0; c < table.getColumnCount(); c++)
  19780. * print(table.getString(r, c));
  19781. * }
  19782. * </code>
  19783. * </div>
  19784. *
  19785. * @alt
  19786. * no image displayed
  19787. *
  19788. */
  19789. p5.Table.prototype.removeRow = function(id) {
  19790. this.rows[id].table = null; // remove reference to table
  19791. var chunk = this.rows.splice(id+1, this.rows.length);
  19792. this.rows.pop();
  19793. this.rows = this.rows.concat(chunk);
  19794. };
  19795. /**
  19796. * Returns a reference to the specified p5.TableRow. The reference
  19797. * can then be used to get and set values of the selected row.
  19798. *
  19799. * @method getRow
  19800. * @param {Number} rowID ID number of the row to get
  19801. * @return {TableRow} p5.TableRow object
  19802. *
  19803. * @example
  19804. * <div class="norender">
  19805. * <code>
  19806. * // Given the CSV file "mammals.csv"
  19807. * // in the project's "assets" folder:
  19808. * //
  19809. * // id,species,name
  19810. * // 0,Capra hircus,Goat
  19811. * // 1,Panthera pardus,Leopard
  19812. * // 2,Equus zebra,Zebra
  19813. *
  19814. * var table;
  19815. *
  19816. * function preload() {
  19817. * //my table is comma separated value "csv"
  19818. * //and has a header specifying the columns labels
  19819. * table = loadTable("assets/mammals.csv", "csv", "header");
  19820. * }
  19821. *
  19822. * function setup() {
  19823. * var row = table.getRow(1);
  19824. * //print it column by column
  19825. * //note: a row is an object, not an array
  19826. * for (var c = 0; c < table.getColumnCount(); c++)
  19827. * print(row.getString(c));
  19828. * }
  19829. * </code>
  19830. * </div>
  19831. *
  19832. *@alt
  19833. * no image displayed
  19834. *
  19835. */
  19836. p5.Table.prototype.getRow = function(r) {
  19837. return this.rows[r];
  19838. };
  19839. /**
  19840. * Gets all rows from the table. Returns an array of p5.TableRows.
  19841. *
  19842. * @method getRows
  19843. * @return {Array} Array of p5.TableRows
  19844. *
  19845. * @example
  19846. * <div class="norender">
  19847. * <code>
  19848. * // Given the CSV file "mammals.csv"
  19849. * // in the project's "assets" folder:
  19850. * //
  19851. * // id,species,name
  19852. * // 0,Capra hircus,Goat
  19853. * // 1,Panthera pardus,Leopard
  19854. * // 2,Equus zebra,Zebra
  19855. *
  19856. * var table;
  19857. *
  19858. * function preload() {
  19859. * //my table is comma separated value "csv"
  19860. * //and has a header specifying the columns labels
  19861. * table = loadTable("assets/mammals.csv", "csv", "header");
  19862. * }
  19863. *
  19864. * function setup() {
  19865. * var rows = table.getRows();
  19866. *
  19867. * //warning: rows is an array of objects
  19868. * for (var r = 0; r < rows.length; r++)
  19869. * rows[r].set("name", "Unicorn");
  19870. *
  19871. * //print the results
  19872. * for (var r = 0; r < table.getRowCount(); r++)
  19873. * for (var c = 0; c < table.getColumnCount(); c++)
  19874. * print(table.getString(r, c));
  19875. * }
  19876. * </code>
  19877. * </div>
  19878. *
  19879. * @alt
  19880. * no image displayed
  19881. *
  19882. */
  19883. p5.Table.prototype.getRows = function() {
  19884. return this.rows;
  19885. };
  19886. /**
  19887. * Finds the first row in the Table that contains the value
  19888. * provided, and returns a reference to that row. Even if
  19889. * multiple rows are possible matches, only the first matching
  19890. * row is returned. The column to search may be specified by
  19891. * either its ID or title.
  19892. *
  19893. * @method findRow
  19894. * @param {String} value The value to match
  19895. * @param {Number|String} column ID number or title of the
  19896. * column to search
  19897. * @return {TableRow}
  19898. *
  19899. * @example
  19900. * <div class="norender">
  19901. * <code>
  19902. * // Given the CSV file "mammals.csv"
  19903. * // in the project's "assets" folder:
  19904. * //
  19905. * // id,species,name
  19906. * // 0,Capra hircus,Goat
  19907. * // 1,Panthera pardus,Leopard
  19908. * // 2,Equus zebra,Zebra
  19909. *
  19910. * var table;
  19911. *
  19912. * function preload() {
  19913. * //my table is comma separated value "csv"
  19914. * //and has a header specifying the columns labels
  19915. * table = loadTable("assets/mammals.csv", "csv", "header");
  19916. * }
  19917. *
  19918. * function setup() {
  19919. * //find the animal named zebra
  19920. * var row = table.findRow("Zebra", "name");
  19921. * //find the corresponding species
  19922. * print(row.getString("species"));
  19923. * }
  19924. * </code>
  19925. * </div>
  19926. *
  19927. * @alt
  19928. * no image displayed
  19929. *
  19930. */
  19931. p5.Table.prototype.findRow = function(value, column) {
  19932. // try the Object
  19933. if (typeof(column) === 'string') {
  19934. for (var i = 0; i < this.rows.length; i++){
  19935. if (this.rows[i].obj[column] === value) {
  19936. return this.rows[i];
  19937. }
  19938. }
  19939. }
  19940. // try the Array
  19941. else {
  19942. for (var j = 0; j < this.rows.length; j++){
  19943. if (this.rows[j].arr[column] === value) {
  19944. return this.rows[j];
  19945. }
  19946. }
  19947. }
  19948. // otherwise...
  19949. return null;
  19950. };
  19951. /**
  19952. * Finds the rows in the Table that contain the value
  19953. * provided, and returns references to those rows. Returns an
  19954. * Array, so for must be used to iterate through all the rows,
  19955. * as shown in the example above. The column to search may be
  19956. * specified by either its ID or title.
  19957. *
  19958. * @method findRows
  19959. * @param {String} value The value to match
  19960. * @param {Number|String} column ID number or title of the
  19961. * column to search
  19962. * @return {Array} An Array of TableRow objects
  19963. *
  19964. * @example
  19965. * <div class="norender">
  19966. * <code>
  19967. * // Given the CSV file "mammals.csv"
  19968. * // in the project's "assets" folder:
  19969. * //
  19970. * // id,species,name
  19971. * // 0,Capra hircus,Goat
  19972. * // 1,Panthera pardus,Leopard
  19973. * // 2,Equus zebra,Zebra
  19974. *
  19975. * var table;
  19976. *
  19977. * function preload() {
  19978. * //my table is comma separated value "csv"
  19979. * //and has a header specifying the columns labels
  19980. * table = loadTable("assets/mammals.csv", "csv", "header");
  19981. * }
  19982. *
  19983. * function setup() {
  19984. * //add another goat
  19985. * var newRow = table.addRow();
  19986. * newRow.setString("id", table.getRowCount() - 1);
  19987. * newRow.setString("species", "Scape Goat");
  19988. * newRow.setString("name", "Goat");
  19989. *
  19990. * //find the rows containing animals named Goat
  19991. * var rows = table.findRows("Goat", "name");
  19992. * print(rows.length + " Goats found");
  19993. * }
  19994. * </code>
  19995. * </div>
  19996. *
  19997. *@alt
  19998. * no image displayed
  19999. *
  20000. */
  20001. p5.Table.prototype.findRows = function(value, column) {
  20002. var ret = [];
  20003. if (typeof(column) === 'string') {
  20004. for (var i = 0; i < this.rows.length; i++){
  20005. if (this.rows[i].obj[column] === value) {
  20006. ret.push( this.rows[i] );
  20007. }
  20008. }
  20009. }
  20010. // try the Array
  20011. else {
  20012. for (var j = 0; j < this.rows.length; j++){
  20013. if (this.rows[j].arr[column] === value) {
  20014. ret.push( this.rows[j] );
  20015. }
  20016. }
  20017. }
  20018. return ret;
  20019. };
  20020. /**
  20021. * Finds the first row in the Table that matches the regular
  20022. * expression provided, and returns a reference to that row.
  20023. * Even if multiple rows are possible matches, only the first
  20024. * matching row is returned. The column to search may be
  20025. * specified by either its ID or title.
  20026. *
  20027. * @method matchRow
  20028. * @param {String} regexp The regular expression to match
  20029. * @param {String|Number} column The column ID (number) or
  20030. * title (string)
  20031. * @return {TableRow} TableRow object
  20032. */
  20033. p5.Table.prototype.matchRow = function(regexp, column) {
  20034. if (typeof(column) === 'number') {
  20035. for (var j = 0; j < this.rows.length; j++) {
  20036. if ( this.rows[j].arr[column].match(regexp) ) {
  20037. return this.rows[j];
  20038. }
  20039. }
  20040. }
  20041. else {
  20042. for (var i = 0; i < this.rows.length; i++) {
  20043. if ( this.rows[i].obj[column].match(regexp) ) {
  20044. return this.rows[i];
  20045. }
  20046. }
  20047. }
  20048. return null;
  20049. };
  20050. /**
  20051. * Finds the rows in the Table that match the regular expression provided,
  20052. * and returns references to those rows. Returns an array, so for must be
  20053. * used to iterate through all the rows, as shown in the example. The
  20054. * column to search may be specified by either its ID or title.
  20055. *
  20056. * @method matchRows
  20057. * @param {String} regexp The regular expression to match
  20058. * @param {String|Number} [column] The column ID (number) or
  20059. * title (string)
  20060. * @return {Array} An Array of TableRow objects
  20061. * @example
  20062. * var table;
  20063. *
  20064. * function setup() {
  20065. *
  20066. * table = new p5.Table();
  20067. *
  20068. * table.addColumn('name');
  20069. * table.addColumn('type');
  20070. *
  20071. * var newRow = table.addRow();
  20072. * newRow.setString('name', 'Lion');
  20073. * newRow.setString('type', 'Mammal');
  20074. *
  20075. * newRow = table.addRow();
  20076. * newRow.setString('name', 'Snake');
  20077. * newRow.setString('type', 'Reptile');
  20078. *
  20079. * newRow = table.addRow();
  20080. * newRow.setString('name', 'Mosquito');
  20081. * newRow.setString('type', 'Insect');
  20082. *
  20083. * newRow = table.addRow();
  20084. * newRow.setString('name', 'Lizard');
  20085. * newRow.setString('type', 'Reptile');
  20086. *
  20087. * var rows = table.matchRows('R.*', 'type');
  20088. * for (var i = 0; i < rows.length; i++) {
  20089. * print(rows[i].getString('name') + ': ' + rows[i].getString('type'));
  20090. * }
  20091. * }
  20092. * // Sketch prints:
  20093. * // Snake: Reptile
  20094. * // Lizard: Reptile
  20095. */
  20096. p5.Table.prototype.matchRows = function(regexp, column) {
  20097. var ret = [];
  20098. if (typeof(column) === 'number') {
  20099. for (var j = 0; j < this.rows.length; j++) {
  20100. if ( this.rows[j].arr[column].match(regexp) ) {
  20101. ret.push( this.rows[j] );
  20102. }
  20103. }
  20104. }
  20105. else {
  20106. for (var i = 0; i < this.rows.length; i++) {
  20107. if ( this.rows[i].obj[column].match(regexp) ) {
  20108. ret.push( this.rows[i] );
  20109. }
  20110. }
  20111. }
  20112. return ret;
  20113. };
  20114. /**
  20115. * Retrieves all values in the specified column, and returns them
  20116. * as an array. The column may be specified by either its ID or title.
  20117. *
  20118. * @method getColumn
  20119. * @param {String|Number} column String or Number of the column to return
  20120. * @return {Array} Array of column values
  20121. *
  20122. * @example
  20123. * <div class="norender">
  20124. * <code>
  20125. * // Given the CSV file "mammals.csv"
  20126. * // in the project's "assets" folder:
  20127. * //
  20128. * // id,species,name
  20129. * // 0,Capra hircus,Goat
  20130. * // 1,Panthera pardus,Leopard
  20131. * // 2,Equus zebra,Zebra
  20132. *
  20133. * var table;
  20134. *
  20135. * function preload() {
  20136. * //my table is comma separated value "csv"
  20137. * //and has a header specifying the columns labels
  20138. * table = loadTable("assets/mammals.csv", "csv", "header");
  20139. * }
  20140. *
  20141. * function setup() {
  20142. * //getColumn returns an array that can be printed directly
  20143. * print(table.getColumn("species"));
  20144. * //outputs ["Capra hircus", "Panthera pardus", "Equus zebra"]
  20145. * }
  20146. * </code>
  20147. * </div>
  20148. *
  20149. *@alt
  20150. * no image displayed
  20151. *
  20152. */
  20153. p5.Table.prototype.getColumn = function(value) {
  20154. var ret = [];
  20155. if (typeof(value) === 'string'){
  20156. for (var i = 0; i < this.rows.length; i++){
  20157. ret.push (this.rows[i].obj[value]);
  20158. }
  20159. } else {
  20160. for (var j = 0; j < this.rows.length; j++){
  20161. ret.push (this.rows[j].arr[value]);
  20162. }
  20163. }
  20164. return ret;
  20165. };
  20166. /**
  20167. * Removes all rows from a Table. While all rows are removed,
  20168. * columns and column titles are maintained.
  20169. *
  20170. * @method clearRows
  20171. *
  20172. * @example
  20173. * <div class="norender">
  20174. * <code>
  20175. * // Given the CSV file "mammals.csv"
  20176. * // in the project's "assets" folder:
  20177. * //
  20178. * // id,species,name
  20179. * // 0,Capra hircus,Goat
  20180. * // 1,Panthera pardus,Leopard
  20181. * // 2,Equus zebra,Zebra
  20182. *
  20183. * var table;
  20184. *
  20185. * function preload() {
  20186. * //my table is comma separated value "csv"
  20187. * //and has a header specifying the columns labels
  20188. * table = loadTable("assets/mammals.csv", "csv", "header");
  20189. * }
  20190. *
  20191. * function setup() {
  20192. * table.clearRows();
  20193. * print(table.getRowCount() + " total rows in table");
  20194. * print(table.getColumnCount() + " total columns in table");
  20195. * }
  20196. * </code>
  20197. * </div>
  20198. *
  20199. *@alt
  20200. * no image displayed
  20201. *
  20202. */
  20203. p5.Table.prototype.clearRows = function() {
  20204. delete this.rows;
  20205. this.rows = [];
  20206. };
  20207. /**
  20208. * Use addColumn() to add a new column to a Table object.
  20209. * Typically, you will want to specify a title, so the column
  20210. * may be easily referenced later by name. (If no title is
  20211. * specified, the new column's title will be null.)
  20212. *
  20213. * @method addColumn
  20214. * @param {String} [title] title of the given column
  20215. *
  20216. * @example
  20217. * <div class="norender">
  20218. * <code>
  20219. * // Given the CSV file "mammals.csv"
  20220. * // in the project's "assets" folder:
  20221. * //
  20222. * // id,species,name
  20223. * // 0,Capra hircus,Goat
  20224. * // 1,Panthera pardus,Leopard
  20225. * // 2,Equus zebra,Zebra
  20226. *
  20227. * var table;
  20228. *
  20229. * function preload() {
  20230. * //my table is comma separated value "csv"
  20231. * //and has a header specifying the columns labels
  20232. * table = loadTable("assets/mammals.csv", "csv", "header");
  20233. * }
  20234. *
  20235. * function setup() {
  20236. * table.addColumn("carnivore");
  20237. * table.set(0, "carnivore", "no");
  20238. * table.set(1, "carnivore", "yes");
  20239. * table.set(2, "carnivore", "no");
  20240. *
  20241. * //print the results
  20242. * for (var r = 0; r < table.getRowCount(); r++)
  20243. * for (var c = 0; c < table.getColumnCount(); c++)
  20244. * print(table.getString(r, c));
  20245. * }
  20246. * </code>
  20247. * </div>
  20248. *
  20249. *@alt
  20250. * no image displayed
  20251. *
  20252. */
  20253. p5.Table.prototype.addColumn = function(title) {
  20254. var t = title || null;
  20255. this.columns.push(t);
  20256. };
  20257. /**
  20258. * Returns the total number of columns in a Table.
  20259. *
  20260. * @return {Number} Number of columns in this table
  20261. */
  20262. p5.Table.prototype.getColumnCount = function() {
  20263. return this.columns.length;
  20264. };
  20265. /**
  20266. * Returns the total number of rows in a Table.
  20267. *
  20268. * @method getRowCount
  20269. * @return {Number} Number of rows in this table
  20270. */
  20271. p5.Table.prototype.getRowCount = function() {
  20272. return this.rows.length;
  20273. };
  20274. /**
  20275. * <p>Removes any of the specified characters (or "tokens").</p>
  20276. *
  20277. * <p>If no column is specified, then the values in all columns and
  20278. * rows are processed. A specific column may be referenced by
  20279. * either its ID or title.</p>
  20280. *
  20281. * @method removeTokens
  20282. * @param {String} chars String listing characters to be removed
  20283. * @param {String|Number} [column] Column ID (number)
  20284. * or name (string)
  20285. */
  20286. p5.Table.prototype.removeTokens = function(chars, column) {
  20287. var escape= function(s) {
  20288. return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
  20289. };
  20290. var charArray = [];
  20291. for (var i = 0; i < chars.length; i++) {
  20292. charArray.push( escape( chars.charAt(i) ) );
  20293. }
  20294. var regex = new RegExp(charArray.join('|'), 'g');
  20295. if (typeof(column) === 'undefined'){
  20296. for (var c = 0; c < this.columns.length; c++) {
  20297. for (var d = 0; d < this.rows.length; d++) {
  20298. var s = this.rows[d].arr[c];
  20299. s = s.replace(regex, '');
  20300. this.rows[d].arr[c] = s;
  20301. this.rows[d].obj[this.columns[c]] = s;
  20302. }
  20303. }
  20304. }
  20305. else if (typeof(column) === 'string'){
  20306. for (var j = 0; j < this.rows.length; j++) {
  20307. var val = this.rows[j].obj[column];
  20308. val = val.replace(regex, '');
  20309. this.rows[j].obj[column] = val;
  20310. var pos = this.columns.indexOf(column);
  20311. this.rows[j].arr[pos] = val;
  20312. }
  20313. }
  20314. else {
  20315. for (var k = 0; k < this.rows.length; k++) {
  20316. var str = this.rows[k].arr[column];
  20317. str = str.replace(regex, '');
  20318. this.rows[k].arr[column] = str;
  20319. this.rows[k].obj[this.columns[column]] = str;
  20320. }
  20321. }
  20322. };
  20323. /**
  20324. * Trims leading and trailing whitespace, such as spaces and tabs,
  20325. * from String table values. If no column is specified, then the
  20326. * values in all columns and rows are trimmed. A specific column
  20327. * may be referenced by either its ID or title.
  20328. *
  20329. * @method trim
  20330. * @param {String|Number} column Column ID (number)
  20331. * or name (string)
  20332. */
  20333. p5.Table.prototype.trim = function(column) {
  20334. var regex = new RegExp( (' '), 'g');
  20335. if (typeof(column) === 'undefined'){
  20336. for (var c = 0; c < this.columns.length; c++) {
  20337. for (var d = 0; d < this.rows.length; d++) {
  20338. var s = this.rows[d].arr[c];
  20339. s = s.replace(regex, '');
  20340. this.rows[d].arr[c] = s;
  20341. this.rows[d].obj[this.columns[c]] = s;
  20342. }
  20343. }
  20344. }
  20345. else if (typeof(column) === 'string'){
  20346. for (var j = 0; j < this.rows.length; j++) {
  20347. var val = this.rows[j].obj[column];
  20348. val = val.replace(regex, '');
  20349. this.rows[j].obj[column] = val;
  20350. var pos = this.columns.indexOf(column);
  20351. this.rows[j].arr[pos] = val;
  20352. }
  20353. }
  20354. else {
  20355. for (var k = 0; k < this.rows.length; k++) {
  20356. var str = this.rows[k].arr[column];
  20357. str = str.replace(regex, '');
  20358. this.rows[k].arr[column] = str;
  20359. this.rows[k].obj[this.columns[column]] = str;
  20360. }
  20361. }
  20362. };
  20363. /**
  20364. * Use removeColumn() to remove an existing column from a Table
  20365. * object. The column to be removed may be identified by either
  20366. * its title (a String) or its index value (an int).
  20367. * removeColumn(0) would remove the first column, removeColumn(1)
  20368. * would remove the second column, and so on.
  20369. *
  20370. * @method removeColumn
  20371. * @param {String|Number} column columnName (string) or ID (number)
  20372. *
  20373. * @example
  20374. * <div class="norender">
  20375. * <code>
  20376. * // Given the CSV file "mammals.csv"
  20377. * // in the project's "assets" folder:
  20378. * //
  20379. * // id,species,name
  20380. * // 0,Capra hircus,Goat
  20381. * // 1,Panthera pardus,Leopard
  20382. * // 2,Equus zebra,Zebra
  20383. *
  20384. * var table;
  20385. *
  20386. * function preload() {
  20387. * //my table is comma separated value "csv"
  20388. * //and has a header specifying the columns labels
  20389. * table = loadTable("assets/mammals.csv", "csv", "header");
  20390. * }
  20391. *
  20392. * function setup() {
  20393. * table.removeColumn("id");
  20394. * print(table.getColumnCount());
  20395. * }
  20396. * </code>
  20397. * </div>
  20398. *
  20399. *@alt
  20400. * no image displayed
  20401. *
  20402. */
  20403. p5.Table.prototype.removeColumn = function(c) {
  20404. var cString;
  20405. var cNumber;
  20406. if (typeof(c) === 'string') {
  20407. // find the position of c in the columns
  20408. cString = c;
  20409. cNumber = this.columns.indexOf(c);
  20410. console.log('string');
  20411. }
  20412. else{
  20413. cNumber = c;
  20414. cString = this.columns[c];
  20415. }
  20416. var chunk = this.columns.splice(cNumber+1, this.columns.length);
  20417. this.columns.pop();
  20418. this.columns = this.columns.concat(chunk);
  20419. for (var i = 0; i < this.rows.length; i++){
  20420. var tempR = this.rows[i].arr;
  20421. var chip = tempR.splice(cNumber+1, tempR.length);
  20422. tempR.pop();
  20423. this.rows[i].arr = tempR.concat(chip);
  20424. delete this.rows[i].obj[cString];
  20425. }
  20426. };
  20427. /**
  20428. * Stores a value in the Table's specified row and column.
  20429. * The row is specified by its ID, while the column may be specified
  20430. * by either its ID or title.
  20431. *
  20432. * @method set
  20433. * @param {String|Number} column column ID (Number)
  20434. * or title (String)
  20435. * @param {String|Number} value value to assign
  20436. *
  20437. * @example
  20438. * <div class="norender">
  20439. * <code>
  20440. * // Given the CSV file "mammals.csv"
  20441. * // in the project's "assets" folder:
  20442. * //
  20443. * // id,species,name
  20444. * // 0,Capra hircus,Goat
  20445. * // 1,Panthera pardus,Leopard
  20446. * // 2,Equus zebra,Zebra
  20447. *
  20448. * var table;
  20449. *
  20450. * function preload() {
  20451. * //my table is comma separated value "csv"
  20452. * //and has a header specifying the columns labels
  20453. * table = loadTable("assets/mammals.csv", "csv", "header");
  20454. * }
  20455. *
  20456. * function setup() {
  20457. * table.set(0, "species", "Canis Lupus");
  20458. * table.set(0, "name", "Wolf");
  20459. *
  20460. * //print the results
  20461. * for (var r = 0; r < table.getRowCount(); r++)
  20462. * for (var c = 0; c < table.getColumnCount(); c++)
  20463. * print(table.getString(r, c));
  20464. * }
  20465. * </code>
  20466. * </div>
  20467. *
  20468. *@alt
  20469. * no image displayed
  20470. *
  20471. */
  20472. p5.Table.prototype.set = function(row, column, value) {
  20473. this.rows[row].set(column, value);
  20474. };
  20475. /**
  20476. * Stores a Float value in the Table's specified row and column.
  20477. * The row is specified by its ID, while the column may be specified
  20478. * by either its ID or title.
  20479. *
  20480. * @method setNum
  20481. * @param {Number} row row ID
  20482. * @param {String|Number} column column ID (Number)
  20483. * or title (String)
  20484. * @param {Number} value value to assign
  20485. *
  20486. * @example
  20487. * <div class="norender">
  20488. * <code>
  20489. * // Given the CSV file "mammals.csv"
  20490. * // in the project's "assets" folder:
  20491. * //
  20492. * // id,species,name
  20493. * // 0,Capra hircus,Goat
  20494. * // 1,Panthera pardus,Leopard
  20495. * // 2,Equus zebra,Zebra
  20496. *
  20497. * var table;
  20498. *
  20499. * function preload() {
  20500. * //my table is comma separated value "csv"
  20501. * //and has a header specifying the columns labels
  20502. * table = loadTable("assets/mammals.csv", "csv", "header");
  20503. * }
  20504. *
  20505. * function setup() {
  20506. * table.setNum(1, "id", 1);
  20507. *
  20508. * print(table.getColumn(0));
  20509. * //["0", 1, "2"]
  20510. * }
  20511. * </code>
  20512. * </div>
  20513. *
  20514. *@alt
  20515. * no image displayed
  20516. */
  20517. p5.Table.prototype.setNum = function(row, column, value){
  20518. this.rows[row].setNum(column, value);
  20519. };
  20520. /**
  20521. * Stores a String value in the Table's specified row and column.
  20522. * The row is specified by its ID, while the column may be specified
  20523. * by either its ID or title.
  20524. *
  20525. * @method setString
  20526. * @param {Number} row row ID
  20527. * @param {String|Number} column column ID (Number)
  20528. * or title (String)
  20529. * @param {String} value value to assign
  20530. */
  20531. p5.Table.prototype.setString = function(row, column, value){
  20532. this.rows[row].setString(column, value);
  20533. };
  20534. /**
  20535. * Retrieves a value from the Table's specified row and column.
  20536. * The row is specified by its ID, while the column may be specified by
  20537. * either its ID or title.
  20538. *
  20539. * @method get
  20540. * @param {Number} row row ID
  20541. * @param {String|Number} column columnName (string) or
  20542. * ID (number)
  20543. * @return {String|Number}
  20544. *
  20545. * @example
  20546. * <div class="norender">
  20547. * <code>
  20548. * // Given the CSV file "mammals.csv"
  20549. * // in the project's "assets" folder:
  20550. * //
  20551. * // id,species,name
  20552. * // 0,Capra hircus,Goat
  20553. * // 1,Panthera pardus,Leopard
  20554. * // 2,Equus zebra,Zebra
  20555. *
  20556. * var table;
  20557. *
  20558. * function preload() {
  20559. * //my table is comma separated value "csv"
  20560. * //and has a header specifying the columns labels
  20561. * table = loadTable("assets/mammals.csv", "csv", "header");
  20562. * }
  20563. *
  20564. * function setup() {
  20565. * print(table.get(0, 1));
  20566. * //Capra hircus
  20567. * print(table.get(0, "species"));
  20568. * //Capra hircus
  20569. * }
  20570. * </code>
  20571. * </div>
  20572. *
  20573. *@alt
  20574. * no image displayed
  20575. *
  20576. */
  20577. p5.Table.prototype.get = function(row, column) {
  20578. return this.rows[row].get(column);
  20579. };
  20580. /**
  20581. * Retrieves a Float value from the Table's specified row and column.
  20582. * The row is specified by its ID, while the column may be specified by
  20583. * either its ID or title.
  20584. *
  20585. * @method getNum
  20586. * @param {Number} row row ID
  20587. * @param {String|Number} column columnName (string) or
  20588. * ID (number)
  20589. * @return {Number}
  20590. *
  20591. * @example
  20592. * <div class="norender">
  20593. * <code>
  20594. * // Given the CSV file "mammals.csv"
  20595. * // in the project's "assets" folder:
  20596. * //
  20597. * // id,species,name
  20598. * // 0,Capra hircus,Goat
  20599. * // 1,Panthera pardus,Leopard
  20600. * // 2,Equus zebra,Zebra
  20601. *
  20602. * var table;
  20603. *
  20604. * function preload() {
  20605. * //my table is comma separated value "csv"
  20606. * //and has a header specifying the columns labels
  20607. * table = loadTable("assets/mammals.csv", "csv", "header");
  20608. * }
  20609. *
  20610. * function setup() {
  20611. * print(table.getNum(1, 0) + 100);
  20612. * //id 1 + 100 = 101
  20613. * }
  20614. * </code>
  20615. * </div>
  20616. *
  20617. *@alt
  20618. * no image displayed
  20619. *
  20620. */
  20621. p5.Table.prototype.getNum = function(row, column) {
  20622. return this.rows[row].getNum(column);
  20623. };
  20624. /**
  20625. * Retrieves a String value from the Table's specified row and column.
  20626. * The row is specified by its ID, while the column may be specified by
  20627. * either its ID or title.
  20628. *
  20629. * @method getString
  20630. * @param {Number} row row ID
  20631. * @param {String|Number} column columnName (string) or
  20632. * ID (number)
  20633. * @return {String}
  20634. *
  20635. * @example
  20636. * <div class="norender">
  20637. * <code>
  20638. * // Given the CSV file "mammals.csv"
  20639. * // in the project's "assets" folder:
  20640. * //
  20641. * // id,species,name
  20642. * // 0,Capra hircus,Goat
  20643. * // 1,Panthera pardus,Leopard
  20644. * // 2,Equus zebra,Zebra
  20645. *
  20646. * var table;
  20647. *
  20648. * function preload() {
  20649. * //my table is comma separated value "csv"
  20650. * //and has a header specifying the columns labels
  20651. * table = loadTable("assets/mammals.csv", "csv", "header");
  20652. * }
  20653. *
  20654. * function setup() {
  20655. * var tableArray = table.getArray();
  20656. *
  20657. * //output each row as array
  20658. * for (var i = 0; i < tableArray.length; i++)
  20659. * print(tableArray[i]);
  20660. * }
  20661. * </code>
  20662. * </div>
  20663. *
  20664. *@alt
  20665. * no image displayed
  20666. *
  20667. */
  20668. p5.Table.prototype.getString = function(row, column) {
  20669. return this.rows[row].getString(column);
  20670. };
  20671. /**
  20672. * Retrieves all table data and returns as an object. If a column name is
  20673. * passed in, each row object will be stored with that attribute as its
  20674. * title.
  20675. *
  20676. * @method getObject
  20677. * @param {String} headerColumn Name of the column which should be used to
  20678. * title each row object (optional)
  20679. * @return {Object}
  20680. *
  20681. * @example
  20682. * <div class="norender">
  20683. * <code>
  20684. * // Given the CSV file "mammals.csv"
  20685. * // in the project's "assets" folder:
  20686. * //
  20687. * // id,species,name
  20688. * // 0,Capra hircus,Goat
  20689. * // 1,Panthera pardus,Leopard
  20690. * // 2,Equus zebra,Zebra
  20691. *
  20692. * var table;
  20693. *
  20694. * function preload() {
  20695. * //my table is comma separated value "csv"
  20696. * //and has a header specifying the columns labels
  20697. * table = loadTable("assets/mammals.csv", "csv", "header");
  20698. * }
  20699. *
  20700. * function setup() {
  20701. * var tableObject = table.getObject();
  20702. *
  20703. * print(tableObject);
  20704. * //outputs an object
  20705. * }
  20706. * </code>
  20707. * </div>
  20708. *
  20709. *@alt
  20710. * no image displayed
  20711. *
  20712. */
  20713. p5.Table.prototype.getObject = function (headerColumn) {
  20714. var tableObject = {};
  20715. var obj, cPos, index;
  20716. for(var i = 0; i < this.rows.length; i++) {
  20717. obj = this.rows[i].obj;
  20718. if (typeof(headerColumn) === 'string'){
  20719. cPos = this.columns.indexOf(headerColumn); // index of columnID
  20720. if (cPos >= 0) {
  20721. index = obj[headerColumn];
  20722. tableObject[index] = obj;
  20723. } else {
  20724. throw 'This table has no column named "' + headerColumn +'"';
  20725. }
  20726. } else {
  20727. tableObject[i] = this.rows[i].obj;
  20728. }
  20729. }
  20730. return tableObject;
  20731. };
  20732. /**
  20733. * Retrieves all table data and returns it as a multidimensional array.
  20734. *
  20735. * @method getArray
  20736. * @return {Array}
  20737. */
  20738. p5.Table.prototype.getArray = function () {
  20739. var tableArray = [];
  20740. for(var i = 0; i < this.rows.length; i++) {
  20741. tableArray.push(this.rows[i].arr);
  20742. }
  20743. return tableArray;
  20744. };
  20745. module.exports = p5.Table;
  20746. },{"../core/core":37}],61:[function(_dereq_,module,exports){
  20747. /**
  20748. * @module IO
  20749. * @submodule Table
  20750. * @requires core
  20751. */
  20752. 'use strict';
  20753. var p5 = _dereq_('../core/core');
  20754. /**
  20755. * A TableRow object represents a single row of data values,
  20756. * stored in columns, from a table.
  20757. *
  20758. * A Table Row contains both an ordered array, and an unordered
  20759. * JSON object.
  20760. *
  20761. * @class p5.TableRow
  20762. * @constructor
  20763. * @param {String} [str] optional: populate the row with a
  20764. * string of values, separated by the
  20765. * separator
  20766. * @param {String} [separator] comma separated values (csv) by default
  20767. */
  20768. p5.TableRow = function (str, separator) {
  20769. var arr = [];
  20770. var obj = {};
  20771. if (str){
  20772. separator = separator || ',';
  20773. arr = str.split(separator);
  20774. }
  20775. for (var i = 0; i < arr.length; i++){
  20776. var key = i;
  20777. var val = arr[i];
  20778. obj[key] = val;
  20779. }
  20780. this.arr = arr;
  20781. this.obj = obj;
  20782. this.table = null;
  20783. };
  20784. /**
  20785. * Stores a value in the TableRow's specified column.
  20786. * The column may be specified by either its ID or title.
  20787. *
  20788. * @method set
  20789. * @param {String|Number} column Column ID (Number)
  20790. * or Title (String)
  20791. * @param {String|Number} value The value to be stored
  20792. */
  20793. p5.TableRow.prototype.set = function(column, value) {
  20794. // if typeof column is string, use .obj
  20795. if (typeof(column) === 'string'){
  20796. var cPos = this.table.columns.indexOf(column); // index of columnID
  20797. if (cPos >= 0) {
  20798. this.obj[column] = value;
  20799. this.arr[cPos] = value;
  20800. }
  20801. else {
  20802. throw 'This table has no column named "' + column +'"';
  20803. }
  20804. }
  20805. // if typeof column is number, use .arr
  20806. else {
  20807. if (column < this.table.columns.length) {
  20808. this.arr[column] = value;
  20809. var cTitle = this.table.columns[column];
  20810. this.obj[cTitle] = value;
  20811. }
  20812. else {
  20813. throw 'Column #' + column + ' is out of the range of this table';
  20814. }
  20815. }
  20816. };
  20817. /**
  20818. * Stores a Float value in the TableRow's specified column.
  20819. * The column may be specified by either its ID or title.
  20820. *
  20821. * @method setNum
  20822. * @param {String|Number} column Column ID (Number)
  20823. * or Title (String)
  20824. * @param {Number} value The value to be stored
  20825. * as a Float
  20826. */
  20827. p5.TableRow.prototype.setNum = function(column, value){
  20828. var floatVal = parseFloat(value, 10);
  20829. this.set(column, floatVal);
  20830. };
  20831. /**
  20832. * Stores a String value in the TableRow's specified column.
  20833. * The column may be specified by either its ID or title.
  20834. *
  20835. * @method setString
  20836. * @param {String|Number} column Column ID (Number)
  20837. * or Title (String)
  20838. * @param {String} value The value to be stored
  20839. * as a String
  20840. */
  20841. p5.TableRow.prototype.setString = function(column, value){
  20842. var stringVal = value.toString();
  20843. this.set(column, stringVal);
  20844. };
  20845. /**
  20846. * Retrieves a value from the TableRow's specified column.
  20847. * The column may be specified by either its ID or title.
  20848. *
  20849. * @method get
  20850. * @param {String|Number} column columnName (string) or
  20851. * ID (number)
  20852. * @return {String|Number}
  20853. */
  20854. p5.TableRow.prototype.get = function(column) {
  20855. if (typeof(column) === 'string'){
  20856. return this.obj[column];
  20857. } else {
  20858. return this.arr[column];
  20859. }
  20860. };
  20861. /**
  20862. * Retrieves a Float value from the TableRow's specified
  20863. * column. The column may be specified by either its ID or
  20864. * title.
  20865. *
  20866. * @method getNum
  20867. * @param {String|Number} column columnName (string) or
  20868. * ID (number)
  20869. * @return {Number} Float Floating point number
  20870. */
  20871. p5.TableRow.prototype.getNum = function(column) {
  20872. var ret;
  20873. if (typeof(column) === 'string'){
  20874. ret = parseFloat(this.obj[column], 10);
  20875. } else {
  20876. ret = parseFloat(this.arr[column], 10);
  20877. }
  20878. if (ret.toString() === 'NaN') {
  20879. throw 'Error: ' + this.obj[column]+ ' is NaN (Not a Number)';
  20880. }
  20881. return ret;
  20882. };
  20883. /**
  20884. * Retrieves an String value from the TableRow's specified
  20885. * column. The column may be specified by either its ID or
  20886. * title.
  20887. *
  20888. * @method getString
  20889. * @param {String|Number} column columnName (string) or
  20890. * ID (number)
  20891. * @return {String} String
  20892. */
  20893. p5.TableRow.prototype.getString = function(column) {
  20894. if (typeof(column) === 'string'){
  20895. return this.obj[column].toString();
  20896. } else {
  20897. return this.arr[column].toString();
  20898. }
  20899. };
  20900. module.exports = p5.TableRow;
  20901. },{"../core/core":37}],62:[function(_dereq_,module,exports){
  20902. /**
  20903. * @module IO
  20904. * @submodule XML
  20905. * @requires core
  20906. */
  20907. 'use strict';
  20908. var p5 = _dereq_('../core/core');
  20909. /**
  20910. * XML is a representation of an XML object, able to parse XML code. Use
  20911. * loadXML() to load external XML files and create XML objects.
  20912. *
  20913. * @class p5.XML
  20914. * @constructor
  20915. * @return {p5.XML} p5.XML object generated
  20916. * @example
  20917. * <div class='norender'><code>
  20918. * // The following short XML file called "mammals.xml" is parsed
  20919. * // in the code below.
  20920. * //
  20921. * // <?xml version="1.0"?>
  20922. * // &lt;mammals&gt;
  20923. * // &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
  20924. * // &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
  20925. * // &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
  20926. * // &lt;/mammals&gt;
  20927. *
  20928. * var xml;
  20929. *
  20930. * function preload() {
  20931. * xml = loadXML("assets/mammals.xml");
  20932. * }
  20933. *
  20934. * function setup() {
  20935. * var children = xml.getChildren("animal");
  20936. *
  20937. * for (var i = 0; i < children.length; i++) {
  20938. * var id = children[i].getNumber("id");
  20939. * var coloring = children[i].getString("species");
  20940. * var name = children[i].getContent();
  20941. * print(id + ", " + coloring + ", " + name);
  20942. * }
  20943. * }
  20944. *
  20945. * // Sketch prints:
  20946. * // 0, Capra hircus, Goat
  20947. * // 1, Panthera pardus, Leopard
  20948. * // 2, Equus zebra, Zebra
  20949. * </code></div>
  20950. *
  20951. * @alt
  20952. * no image displayed
  20953. *
  20954. */
  20955. p5.XML = function () {
  20956. this.name = null; //done
  20957. this.attributes = {}; //done
  20958. this.children = [];
  20959. this.parent = null;
  20960. this.content = null; //done
  20961. };
  20962. /**
  20963. * Gets a copy of the element's parent. Returns the parent as another
  20964. * p5.XML object.
  20965. *
  20966. * @method getParent
  20967. * @return {Object} element parent
  20968. * @example
  20969. * <div class='norender'><code>
  20970. * // The following short XML file called "mammals.xml" is parsed
  20971. * // in the code below.
  20972. * //
  20973. * // <?xml version="1.0"?>
  20974. * // &lt;mammals&gt;
  20975. * // &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
  20976. * // &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
  20977. * // &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
  20978. * // &lt;/mammals&gt;
  20979. *
  20980. * var xml;
  20981. *
  20982. * function preload() {
  20983. * xml = loadXML("assets/mammals.xml");
  20984. * }
  20985. *
  20986. * function setup() {
  20987. * var children = xml.getChildren("animal");
  20988. * var parent = children[1].getParent();
  20989. * print(parent.getName());
  20990. * }
  20991. *
  20992. * // Sketch prints:
  20993. * // mammals
  20994. * </code></div>
  20995. */
  20996. p5.XML.prototype.getParent = function() {
  20997. return this.parent;
  20998. };
  20999. /**
  21000. * Gets the element's full name, which is returned as a String.
  21001. *
  21002. * @method getName
  21003. * @return {String} the name of the node
  21004. * @example&lt;animal
  21005. * <div class='norender'><code>
  21006. * // The following short XML file called "mammals.xml" is parsed
  21007. * // in the code below.
  21008. * //
  21009. * // <?xml version="1.0"?>
  21010. * // &lt;mammals&gt;
  21011. * // &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
  21012. * // &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
  21013. * // &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
  21014. * // &lt;/mammals&gt;
  21015. *
  21016. * var xml;
  21017. *
  21018. * function preload() {
  21019. * xml = loadXML("assets/mammals.xml");
  21020. * }
  21021. *
  21022. * function setup() {
  21023. * print(xml.getName());
  21024. * }
  21025. *
  21026. * // Sketch prints:
  21027. * // mammals
  21028. * </code></div>
  21029. */
  21030. p5.XML.prototype.getName = function() {
  21031. return this.name;
  21032. };
  21033. /**
  21034. * Sets the element's name, which is specified as a String.
  21035. *
  21036. * @method setName
  21037. * @param {String} the new name of the node
  21038. * @example&lt;animal
  21039. * <div class='norender'><code>
  21040. * // The following short XML file called "mammals.xml" is parsed
  21041. * // in the code below.
  21042. * //
  21043. * // <?xml version="1.0"?>
  21044. * // &lt;mammals&gt;
  21045. * // &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
  21046. * // &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
  21047. * // &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
  21048. * // &lt;/mammals&gt;
  21049. *
  21050. * var xml;
  21051. *
  21052. * function preload() {
  21053. * xml = loadXML("assets/mammals.xml");
  21054. * }
  21055. *
  21056. * function setup() {
  21057. * print(xml.getName());
  21058. * xml.setName("fish");
  21059. * print(xml.getName());
  21060. * }
  21061. *
  21062. * // Sketch prints:
  21063. * // mammals
  21064. * // fish
  21065. * </code></div>
  21066. */
  21067. p5.XML.prototype.setName = function(name) {
  21068. this.name = name;
  21069. };
  21070. /**
  21071. * Checks whether or not the element has any children, and returns the result
  21072. * as a boolean.
  21073. *
  21074. * @method hasChildren
  21075. * @return {boolean}
  21076. * @example&lt;animal
  21077. * <div class='norender'><code>
  21078. * // The following short XML file called "mammals.xml" is parsed
  21079. * // in the code below.
  21080. * //
  21081. * // <?xml version="1.0"?>
  21082. * // &lt;mammals&gt;
  21083. * // &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
  21084. * // &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
  21085. * // &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
  21086. * // &lt;/mammals&gt;
  21087. *
  21088. * var xml;
  21089. *
  21090. * function preload() {
  21091. * xml = loadXML("assets/mammals.xml");
  21092. * }
  21093. *
  21094. * function setup() {
  21095. * print(xml.hasChildren());
  21096. * }
  21097. *
  21098. * // Sketch prints:
  21099. * // true
  21100. * </code></div>
  21101. */
  21102. p5.XML.prototype.hasChildren = function() {
  21103. return this.children.length > 0;
  21104. };
  21105. /**
  21106. * Get the names of all of the element's children, and returns the names as an
  21107. * array of Strings. This is the same as looping through and calling getName()
  21108. * on each child element individually.
  21109. *
  21110. * @method listChildren
  21111. * @return {Array} names of the children of the element
  21112. * @example&lt;animal
  21113. * <div class='norender'><code>
  21114. * // The following short XML file called "mammals.xml" is parsed
  21115. * // in the code below.
  21116. * //
  21117. * // <?xml version="1.0"?>
  21118. * // &lt;mammals&gt;
  21119. * // &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
  21120. * // &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
  21121. * // &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
  21122. * // &lt;/mammals&gt;
  21123. *
  21124. * var xml;
  21125. *
  21126. * function preload() {
  21127. * xml = loadXML("assets/mammals.xml");
  21128. * }
  21129. *
  21130. * function setup() {
  21131. * print(xml.listChildren());
  21132. * }
  21133. *
  21134. * // Sketch prints:
  21135. * // ["animal", "animal", "animal"]
  21136. * </code></div>
  21137. */
  21138. p5.XML.prototype.listChildren = function() {
  21139. return this.children.map(function(c) { return c.name; });
  21140. };
  21141. /**
  21142. * Returns all of the element's children as an array of p5.XML objects. When
  21143. * the name parameter is specified, then it will return all children that match
  21144. * that name.
  21145. *
  21146. * @method getChildren
  21147. * @param {String} [name] element name
  21148. * @return {Array} children of the element
  21149. * @example&lt;animal
  21150. * <div class='norender'><code>
  21151. * // The following short XML file called "mammals.xml" is parsed
  21152. * // in the code below.
  21153. * //
  21154. * // <?xml version="1.0"?>
  21155. * // &lt;mammals&gt;
  21156. * // &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
  21157. * // &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
  21158. * // &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
  21159. * // &lt;/mammals&gt;
  21160. *
  21161. * var xml;
  21162. *
  21163. * function preload() {
  21164. * xml = loadXML("assets/mammals.xml");
  21165. * }
  21166. *
  21167. * function setup() {
  21168. * var animals = xml.getChildren("animal");
  21169. *
  21170. * for (var i = 0; i < animals.length; i++) {
  21171. * print(animals[i].getContent());
  21172. * }
  21173. * }
  21174. *
  21175. * // Sketch prints:
  21176. * // "Goat"
  21177. * // "Leopard"
  21178. * // "Zebra"
  21179. * </code></div>
  21180. */
  21181. p5.XML.prototype.getChildren = function(param) {
  21182. if (param) {
  21183. return this.children.filter(function(c) { return c.name === param; });
  21184. }
  21185. else {
  21186. return this.children;
  21187. }
  21188. };
  21189. /**
  21190. * Returns the first of the element's children that matches the name parameter
  21191. * or the child of the given index.It returns undefined if no matching
  21192. * child is found.
  21193. *
  21194. * @method getChild
  21195. * @param {String|Number} name element name or index
  21196. * @return {p5.XML}
  21197. * @example&lt;animal
  21198. * <div class='norender'><code>
  21199. * // The following short XML file called "mammals.xml" is parsed
  21200. * // in the code below.
  21201. * //
  21202. * // <?xml version="1.0"?>
  21203. * // &lt;mammals&gt;
  21204. * // &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
  21205. * // &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
  21206. * // &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
  21207. * // &lt;/mammals&gt;
  21208. *
  21209. * var xml;
  21210. *
  21211. * function preload() {
  21212. * xml = loadXML("assets/mammals.xml");
  21213. * }
  21214. *
  21215. * function setup() {
  21216. * var firstChild = xml.getChild("animal");
  21217. * print(firstChild.getContent());
  21218. * }
  21219. *
  21220. * // Sketch prints:
  21221. * // "Goat"
  21222. * </code></div>
  21223. * <div class='norender'><code>
  21224. * var xml;
  21225. *
  21226. * function preload() {
  21227. * xml = loadXML("assets/mammals.xml");
  21228. * }
  21229. *
  21230. * function setup() {
  21231. * var secondChild = xml.getChild(1);
  21232. * print(secondChild.getContent());
  21233. * }
  21234. *
  21235. * // Sketch prints:
  21236. * // "Leopard"
  21237. * </code></div>
  21238. */
  21239. p5.XML.prototype.getChild = function(param) {
  21240. if(typeof param === 'string') {
  21241. return this.children.find(function(c) {
  21242. return c.name === param;
  21243. });
  21244. }
  21245. else {
  21246. return this.children[param];
  21247. }
  21248. };
  21249. /**
  21250. * Appends a new child to the element. The child can be specified with
  21251. * either a String, which will be used as the new tag's name, or as a
  21252. * reference to an existing p5.XML object.
  21253. * A reference to the newly created child is returned as an p5.XML object.
  21254. *
  21255. * @method addChild
  21256. * @param {Object} a p5.XML Object which will be the child to be added
  21257. */
  21258. p5.XML.prototype.addChild = function(node) {
  21259. if (node instanceof p5.XML) {
  21260. this.children.push(node);
  21261. } else {
  21262. // PEND
  21263. }
  21264. };
  21265. /**
  21266. * Removes the element specified by name or index.
  21267. *
  21268. * @method removeChild
  21269. * @param {String|Number} name element name or index
  21270. * @example
  21271. * <div class='norender'><code>
  21272. * // The following short XML file called "mammals.xml" is parsed
  21273. * // in the code below.
  21274. * //
  21275. * // <?xml version="1.0"?>
  21276. * // &lt;mammals&gt;
  21277. * // &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
  21278. * // &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
  21279. * // &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
  21280. * // &lt;/mammals&gt;
  21281. *
  21282. * var xml;
  21283. *
  21284. * function preload() {
  21285. * xml = loadXML("assets/mammals.xml");
  21286. * }
  21287. *
  21288. * function setup() {
  21289. * xml.removeChild("animal");
  21290. * var children = xml.getChildren();
  21291. * for (var i=0; i<children.length; i++) {
  21292. * print(children[i].getContent());
  21293. * }
  21294. * }
  21295. *
  21296. * // Sketch prints:
  21297. * // "Leopard"
  21298. * // "Zebra"
  21299. * </code></div>
  21300. * <div class='norender'><code>
  21301. * var xml;
  21302. *
  21303. * function preload() {
  21304. * xml = loadXML("assets/mammals.xml");
  21305. * }
  21306. *
  21307. * function setup() {
  21308. * xml.removeChild(1);
  21309. * var children = xml.getChildren();
  21310. * for (var i=0; i<children.length; i++) {
  21311. * print(children[i].getContent());
  21312. * }
  21313. * }
  21314. *
  21315. * // Sketch prints:
  21316. * // "Goat"
  21317. * // "Zebra"
  21318. * </code></div>
  21319. */
  21320. p5.XML.prototype.removeChild = function(param) {
  21321. var ind = -1;
  21322. if(typeof param === 'string') {
  21323. for (var i=0; i<this.children.length; i++) {
  21324. if (this.children[i].name === param) {
  21325. ind = i;
  21326. break;
  21327. }
  21328. }
  21329. } else {
  21330. ind = param;
  21331. }
  21332. if (ind !== -1) {
  21333. this.children.splice(ind, 1);
  21334. }
  21335. };
  21336. /**
  21337. * Counts the specified element's number of attributes, returned as an Number.
  21338. *
  21339. * @method getAttributeCount
  21340. * @return {Number}
  21341. * @example
  21342. * <div class='norender'><code>
  21343. * // The following short XML file called "mammals.xml" is parsed
  21344. * // in the code below.
  21345. * //
  21346. * // <?xml version="1.0"?>
  21347. * // &lt;mammals&gt;
  21348. * // &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
  21349. * // &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
  21350. * // &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
  21351. * // &lt;/mammals&gt;
  21352. *
  21353. * var xml;
  21354. *
  21355. * function preload() {
  21356. * xml = loadXML("assets/mammals.xml");
  21357. * }
  21358. *
  21359. * function setup() {
  21360. * var firstChild = xml.getChild("animal");
  21361. * print(firstChild.getAttributeCount());
  21362. * }
  21363. *
  21364. * // Sketch prints:
  21365. * // 2
  21366. * </code></div>
  21367. */
  21368. p5.XML.prototype.getAttributeCount = function() {
  21369. return Object.keys(this.attributes).length;
  21370. };
  21371. /**
  21372. * Gets all of the specified element's attributes, and returns them as an
  21373. * array of Strings.
  21374. *
  21375. * @method listAttributes
  21376. * @return {Array} an array of strings containing the names of attributes
  21377. * @example
  21378. * <div class='norender'><code>
  21379. * // The following short XML file called "mammals.xml" is parsed
  21380. * // in the code below.
  21381. * //
  21382. * // <?xml version="1.0"?>
  21383. * // &lt;mammals&gt;
  21384. * // &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
  21385. * // &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
  21386. * // &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
  21387. * // &lt;/mammals&gt;
  21388. *
  21389. * var xml;
  21390. *
  21391. * function preload() {
  21392. * xml = loadXML("assets/mammals.xml");
  21393. * }
  21394. *
  21395. * function setup() {
  21396. * var firstChild = xml.getChild("animal");
  21397. * print(firstChild.listAttributes());
  21398. * }
  21399. *
  21400. * // Sketch prints:
  21401. * // ["id", "species"]
  21402. * </code></div>
  21403. */
  21404. p5.XML.prototype.listAttributes = function() {
  21405. return Object.keys(this.attributes);
  21406. };
  21407. /**
  21408. * Checks whether or not an element has the specified attribute.
  21409. *
  21410. * @method hasAttribute
  21411. * @param {String} the attribute to be checked
  21412. * @return {boolean} true if attribute found else false
  21413. * @example
  21414. * <div class='norender'><code>
  21415. * // The following short XML file called "mammals.xml" is parsed
  21416. * // in the code below.
  21417. * //
  21418. * // <?xml version="1.0"?>
  21419. * // &lt;mammals&gt;
  21420. * // &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
  21421. * // &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
  21422. * // &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
  21423. * // &lt;/mammals&gt;
  21424. *
  21425. * var xml;
  21426. *
  21427. * function preload() {
  21428. * xml = loadXML("assets/mammals.xml");
  21429. * }
  21430. *
  21431. * function setup() {
  21432. * var firstChild = xml.getChild("animal");
  21433. * print(firstChild.hasAttribute("species"));
  21434. * print(firstChild.hasAttribute("color"));
  21435. * }
  21436. *
  21437. * // Sketch prints:
  21438. * // true
  21439. * // false
  21440. * </code></div>
  21441. */
  21442. p5.XML.prototype.hasAttribute = function(name) {
  21443. return this.attributes[name] ? true : false;
  21444. };
  21445. /**
  21446. * Returns an attribute value of the element as an Number. If the defaultValue
  21447. * parameter is specified and the attribute doesn't exist, then defaultValue
  21448. * is returned. If no defaultValue is specified and the attribute doesn't
  21449. * exist, the value 0 is returned.
  21450. *
  21451. * @method getNumber
  21452. * @param {String} name the non-null full name of the attribute
  21453. * @param {Number} [defaultValue] the default value of the attribute
  21454. * @return {Number}
  21455. * @example
  21456. * <div class='norender'><code>
  21457. * // The following short XML file called "mammals.xml" is parsed
  21458. * // in the code below.
  21459. * //
  21460. * // <?xml version="1.0"?>
  21461. * // &lt;mammals&gt;
  21462. * // &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
  21463. * // &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
  21464. * // &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
  21465. * // &lt;/mammals&gt;
  21466. *
  21467. * var xml;
  21468. *
  21469. * function preload() {
  21470. * xml = loadXML("assets/mammals.xml");
  21471. * }
  21472. *
  21473. * function setup() {
  21474. * var firstChild = xml.getChild("animal");
  21475. * print(firstChild.getNumber("id"));
  21476. * }
  21477. *
  21478. * // Sketch prints:
  21479. * // 0
  21480. * </code></div>
  21481. */
  21482. p5.XML.prototype.getNumber = function(name, defaultValue) {
  21483. return Number(this.attributes[name]) || defaultValue || 0;
  21484. };
  21485. /**
  21486. * Returns an attribute value of the element as an String. If the defaultValue
  21487. * parameter is specified and the attribute doesn't exist, then defaultValue
  21488. * is returned. If no defaultValue is specified and the attribute doesn't
  21489. * exist, null is returned.
  21490. *
  21491. * @method getString
  21492. * @param {String} name the non-null full name of the attribute
  21493. * @param {Number} [defaultValue] the default value of the attribute
  21494. * @return {Number}
  21495. * @example
  21496. * <div class='norender'><code>
  21497. * // The following short XML file called "mammals.xml" is parsed
  21498. * // in the code below.
  21499. * //
  21500. * // <?xml version="1.0"?>
  21501. * // &lt;mammals&gt;
  21502. * // &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
  21503. * // &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
  21504. * // &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
  21505. * // &lt;/mammals&gt;
  21506. *
  21507. * var xml;
  21508. *
  21509. * function preload() {
  21510. * xml = loadXML("assets/mammals.xml");
  21511. * }
  21512. *
  21513. * function setup() {
  21514. * var firstChild = xml.getChild("animal");
  21515. * print(firstChild.getString("species"));
  21516. * }
  21517. *
  21518. * // Sketch prints:
  21519. * // "Capra hircus"
  21520. * </code></div>
  21521. */
  21522. p5.XML.prototype.getString = function(name, defaultValue) {
  21523. return String(this.attributes[name]) || defaultValue || null;
  21524. };
  21525. /**
  21526. * Sets the content of an element's attribute. The first parameter specifies
  21527. * the attribute name, while the second specifies the new content.
  21528. *
  21529. * @method setAttribute
  21530. * @param {String} name the full name of the attribute
  21531. * @param {Number} value the value of the attribute
  21532. * @example
  21533. * <div class='norender'><code>
  21534. * // The following short XML file called "mammals.xml" is parsed
  21535. * // in the code below.
  21536. * //
  21537. * // <?xml version="1.0"?>
  21538. * // &lt;mammals&gt;
  21539. * // &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
  21540. * // &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
  21541. * // &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
  21542. * // &lt;/mammals&gt;
  21543. *
  21544. * var xml;
  21545. *
  21546. * function preload() {
  21547. * xml = loadXML("assets/mammals.xml");
  21548. * }
  21549. *
  21550. * function setup() {
  21551. * var firstChild = xml.getChild("animal");
  21552. * print(firstChild.getString("species"));
  21553. * firstChild.setAttribute("species", "Jamides zebra");
  21554. * print(firstChild.getString("species"));
  21555. * }
  21556. *
  21557. * // Sketch prints:
  21558. * // "Capra hircus"
  21559. * // "Jamides zebra"
  21560. * </code></div>
  21561. */
  21562. p5.XML.prototype.setAttribute = function(name, value) {
  21563. if (this.attributes[name]) {
  21564. this.attributes[name] = value;
  21565. }
  21566. };
  21567. /**
  21568. * Returns the content of an element. If there is no such content,
  21569. * defaultValue is returned if specified, otherwise null is returned.
  21570. *
  21571. * @method getContent
  21572. * @param {String} [defaultValue] value returned if no content is found
  21573. * @return {String}
  21574. * @example
  21575. * <div class='norender'><code>
  21576. * // The following short XML file called "mammals.xml" is parsed
  21577. * // in the code below.
  21578. * //
  21579. * // <?xml version="1.0"?>
  21580. * // &lt;mammals&gt;
  21581. * // &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
  21582. * // &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
  21583. * // &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
  21584. * // &lt;/mammals&gt;
  21585. *
  21586. * var xml;
  21587. *
  21588. * function preload() {
  21589. * xml = loadXML("assets/mammals.xml");
  21590. * }
  21591. *
  21592. * function setup() {
  21593. * var firstChild = xml.getChild("animal");
  21594. * print(firstChild.getContent());
  21595. * }
  21596. *
  21597. * // Sketch prints:
  21598. * // "Goat"
  21599. * </code></div>
  21600. */
  21601. p5.XML.prototype.getContent = function(defaultValue) {
  21602. return this.content || defaultValue || null;
  21603. };
  21604. /**
  21605. * Sets the element's content.
  21606. *
  21607. * @method setContent
  21608. * @param {String} text the new content
  21609. * @example
  21610. * <div class='norender'><code>
  21611. * // The following short XML file called "mammals.xml" is parsed
  21612. * // in the code below.
  21613. * //
  21614. * // <?xml version="1.0"?>
  21615. * // &lt;mammals&gt;
  21616. * // &lt;animal id="0" species="Capra hircus">Goat&lt;/animal&gt;
  21617. * // &lt;animal id="1" species="Panthera pardus">Leopard&lt;/animal&gt;
  21618. * // &lt;animal id="2" species="Equus zebra">Zebra&lt;/animal&gt;
  21619. * // &lt;/mammals&gt;
  21620. *
  21621. * var xml;
  21622. *
  21623. * function preload() {
  21624. * xml = loadXML("assets/mammals.xml");
  21625. * }
  21626. *
  21627. * function setup() {
  21628. * var firstChild = xml.getChild("animal");
  21629. * print(firstChild.getContent());
  21630. * firstChild.setContent("Mountain Goat");
  21631. * print(firstChild.getContent());
  21632. * }
  21633. *
  21634. * // Sketch prints:
  21635. * // "Goat"
  21636. * // "Mountain Goat"
  21637. * </code></div>
  21638. */
  21639. p5.XML.prototype.setContent = function( content ) {
  21640. if(!this.children.length) {
  21641. this.content = content;
  21642. }
  21643. };
  21644. /* HELPERS */
  21645. /**
  21646. * This method is called while the parsing of XML (when loadXML() is
  21647. * called). The difference between this method and the setContent()
  21648. * method defined later is that this one is used to set the content
  21649. * when the node in question has more nodes under it and so on and
  21650. * not directly text content. While in the other one is used when
  21651. * the node in question directly has text inside it.
  21652. *
  21653. */
  21654. p5.XML.prototype._setCont = function(content) {
  21655. var str;
  21656. str = content;
  21657. str = str.replace(/\s\s+/g, ',');
  21658. //str = str.split(',');
  21659. this.content = str;
  21660. };
  21661. /**
  21662. * This method is called while the parsing of XML (when loadXML() is
  21663. * called). The XML node is passed and its attributes are stored in the
  21664. * p5.XML's attribute Object.
  21665. *
  21666. */
  21667. p5.XML.prototype._setAttributes = function(node) {
  21668. var i, att = {};
  21669. for( i = 0; i < node.attributes.length; i++) {
  21670. att[node.attributes[i].nodeName] = node.attributes[i].nodeValue;
  21671. }
  21672. this.attributes = att;
  21673. };
  21674. module.exports = p5.XML;
  21675. },{"../core/core":37}],63:[function(_dereq_,module,exports){
  21676. /**
  21677. * @module Math
  21678. * @submodule Calculation
  21679. * @for p5
  21680. * @requires core
  21681. */
  21682. 'use strict';
  21683. var p5 = _dereq_('../core/core');
  21684. /**
  21685. * Calculates the absolute value (magnitude) of a number. Maps to Math.abs().
  21686. * The absolute value of a number is always positive.
  21687. *
  21688. * @method abs
  21689. * @param {Number} n number to compute
  21690. * @return {Number} absolute value of given number
  21691. * @example
  21692. * <div class = "norender"><code>
  21693. * function setup() {
  21694. * var x = -3;
  21695. * var y = abs(x);
  21696. *
  21697. * print(x); // -3
  21698. * print(y); // 3
  21699. * }
  21700. * </code></div>
  21701. *
  21702. * @alt
  21703. * no image displayed
  21704. *
  21705. */
  21706. p5.prototype.abs = Math.abs;
  21707. /**
  21708. * Calculates the closest int value that is greater than or equal to the
  21709. * value of the parameter. Maps to Math.ceil(). For example, ceil(9.03)
  21710. * returns the value 10.
  21711. *
  21712. * @method ceil
  21713. * @param {Number} n number to round up
  21714. * @return {Number} rounded up number
  21715. * @example
  21716. * <div><code>
  21717. * function draw() {
  21718. * background(200);
  21719. * // map, mouseX between 0 and 5.
  21720. * var ax = map(mouseX, 0, 100, 0, 5);
  21721. * var ay = 66;
  21722. *
  21723. * //Get the ceiling of the mapped number.
  21724. * var bx = ceil(map(mouseX, 0, 100, 0,5));
  21725. * var by = 33;
  21726. *
  21727. * // Multiply the mapped numbers by 20 to more easily
  21728. * // see the changes.
  21729. * stroke(0);
  21730. * fill(0);
  21731. * line(0, ay, ax * 20, ay);
  21732. * line(0, by, bx * 20, by);
  21733. *
  21734. * // Reformat the float returned by map and draw it.
  21735. * noStroke();
  21736. * text(nfc(ax, 2,2), ax, ay - 5);
  21737. * text(nfc(bx,1,1), bx, by - 5);
  21738. * }
  21739. * </code></div>
  21740. *
  21741. * @alt
  21742. * 2 horizontal lines & number sets. increase with mouse x. bottom to 2 decimals
  21743. *
  21744. */
  21745. p5.prototype.ceil = Math.ceil;
  21746. /**
  21747. * Constrains a value between a minimum and maximum value.
  21748. *
  21749. * @method constrain
  21750. * @param {Number} n number to constrain
  21751. * @param {Number} low minimum limit
  21752. * @param {Number} high maximum limit
  21753. * @return {Number} constrained number
  21754. * @example
  21755. * <div><code>
  21756. * function draw() {
  21757. * background(200);
  21758. *
  21759. * var leftWall = 25;
  21760. * var rightWall = 75;
  21761. *
  21762. * // xm is just the mouseX, while
  21763. * // xc is the mouseX, but constrained
  21764. * // between the leftWall and rightWall!
  21765. * var xm = mouseX;
  21766. * var xc = constrain(mouseX, leftWall, rightWall);
  21767. *
  21768. * // Draw the walls.
  21769. * stroke(150);
  21770. * line(leftWall, 0, leftWall, height);
  21771. * line(rightWall, 0, rightWall, height);
  21772. *
  21773. * // Draw xm and xc as circles.
  21774. * noStroke();
  21775. * fill(150);
  21776. * ellipse(xm, 33, 9,9); // Not Constrained
  21777. * fill(0);
  21778. * ellipse(xc, 66, 9,9); // Constrained
  21779. * }
  21780. * </code></div>
  21781. *
  21782. * @alt
  21783. * 2 vertical lines. 2 ellipses move with mouse X 1 does not move passed lines
  21784. *
  21785. */
  21786. p5.prototype.constrain = function(n, low, high) {
  21787. return Math.max(Math.min(n, high), low);
  21788. };
  21789. /**
  21790. * Calculates the distance between two points.
  21791. *
  21792. * @method dist
  21793. * @param {Number} x1 x-coordinate of the first point
  21794. * @param {Number} y1 y-coordinate of the first point
  21795. * @param {Number} [z1] z-coordinate of the first point
  21796. * @param {Number} x2 x-coordinate of the second point
  21797. * @param {Number} y2 y-coordinate of the second point
  21798. * @param {Number} [z2] z-coordinate of the second point
  21799. * @return {Number} distance between the two points
  21800. * @example
  21801. * <div><code>
  21802. * // Move your mouse inside the canvas to see the
  21803. * // change in distance between two points!
  21804. * function draw() {
  21805. * background(200);
  21806. * fill(0);
  21807. *
  21808. * var x1 = 10;
  21809. * var y1 = 90;
  21810. * var x2 = mouseX;
  21811. * var y2 = mouseY;
  21812. *
  21813. * line(x1, y1, x2, y2);
  21814. * ellipse(x1, y1, 7, 7);
  21815. * ellipse(x2, y2, 7, 7);
  21816. *
  21817. * // d is the length of the line
  21818. * // the distance from point 1 to point 2.
  21819. * var d = int(dist(x1, y1, x2, y2));
  21820. *
  21821. * // Let's write d along the line we are drawing!
  21822. * push();
  21823. * translate( (x1+x2)/2, (y1+y2)/2 );
  21824. * rotate( atan2(y2-y1,x2-x1) );
  21825. * text(nfc(d,1,1), 0, -5);
  21826. * pop();
  21827. * // Fancy!
  21828. * }
  21829. * </code></div>
  21830. *
  21831. * @alt
  21832. * 2 ellipses joined by line. 1 ellipse moves with mouse X&Y. Distance displayed.
  21833. *
  21834. */
  21835. p5.prototype.dist = function(x1, y1, z1, x2, y2, z2) {
  21836. if (arguments.length === 4) {
  21837. // In the case of 2d: z1 means x2 and x2 means y2
  21838. return hypot(z1-x1, x2-y1);
  21839. } else if (arguments.length === 6) {
  21840. return hypot(x2-x1, y2-y1, z2-z1);
  21841. }
  21842. };
  21843. /**
  21844. * Returns Euler's number e (2.71828...) raised to the power of the n
  21845. * parameter. Maps to Math.exp().
  21846. *
  21847. * @method exp
  21848. * @param {Number} n exponent to raise
  21849. * @return {Number} e^n
  21850. * @example
  21851. * <div><code>
  21852. * function draw() {
  21853. * background(200);
  21854. *
  21855. * // Compute the exp() function with a value between 0 and 2
  21856. * var xValue = map(mouseX, 0, width, 0, 2);
  21857. * var yValue = exp(xValue);
  21858. *
  21859. * var y = map(yValue, 0, 8, height, 0);
  21860. *
  21861. * var legend = "exp (" + nfc(xValue, 3) +")\n= " + nf(yValue, 1, 4);
  21862. * stroke(150);
  21863. * line(mouseX, y, mouseX, height);
  21864. * fill(0);
  21865. * text(legend, 5, 15);
  21866. * noStroke();
  21867. * ellipse (mouseX,y, 7, 7);
  21868. *
  21869. * // Draw the exp(x) curve,
  21870. * // over the domain of x from 0 to 2
  21871. * noFill();
  21872. * stroke(0);
  21873. * beginShape();
  21874. * for (var x = 0; x < width; x++) {
  21875. * xValue = map(x, 0, width, 0, 2);
  21876. * yValue = exp(xValue);
  21877. * y = map(yValue, 0, 8, height, 0);
  21878. * vertex(x, y);
  21879. * }
  21880. *
  21881. * endShape();
  21882. * line(0, 0, 0, height);
  21883. * line(0, height-1, width, height-1);
  21884. * }
  21885. * </code></div>
  21886. *
  21887. * @alt
  21888. * ellipse moves along a curve with mouse x. e^n displayed.
  21889. *
  21890. */
  21891. p5.prototype.exp = Math.exp;
  21892. /**
  21893. * Calculates the closest int value that is less than or equal to the
  21894. * value of the parameter. Maps to Math.floor().
  21895. *
  21896. * @method floor
  21897. * @param {Number} n number to round down
  21898. * @return {Number} rounded down number
  21899. * @example
  21900. * <div><code>
  21901. * function draw() {
  21902. * background(200);
  21903. * //map, mouseX between 0 and 5.
  21904. * var ax = map(mouseX, 0, 100, 0, 5);
  21905. * var ay = 66;
  21906. *
  21907. * //Get the floor of the mapped number.
  21908. * var bx = floor(map(mouseX, 0, 100, 0,5));
  21909. * var by = 33;
  21910. *
  21911. * // Multiply the mapped numbers by 20 to more easily
  21912. * // see the changes.
  21913. * stroke(0);
  21914. * fill(0);
  21915. * line(0, ay, ax * 20, ay);
  21916. * line(0, by, bx * 20, by);
  21917. *
  21918. * // Reformat the float returned by map and draw it.
  21919. * noStroke();
  21920. * text(nfc(ax, 2,2), ax, ay - 5);
  21921. * text(nfc(bx,1,1), bx, by - 5);
  21922. * }
  21923. * </code></div>
  21924. *
  21925. * @alt
  21926. * 2 horizontal lines & number sets. increase with mouse x. bottom to 2 decimals
  21927. *
  21928. */
  21929. p5.prototype.floor = Math.floor;
  21930. /**
  21931. * Calculates a number between two numbers at a specific increment. The amt
  21932. * parameter is the amount to interpolate between the two values where 0.0
  21933. * equal to the first point, 0.1 is very near the first point, 0.5 is
  21934. * half-way in between, etc. The lerp function is convenient for creating
  21935. * motion along a straight path and for drawing dotted lines.
  21936. *
  21937. * @method lerp
  21938. * @param {Number} start first value
  21939. * @param {Number} stop second value
  21940. * @param {Number} amt number between 0.0 and 1.0
  21941. * @return {Number} lerped value
  21942. * @example
  21943. * <div><code>
  21944. * function setup() {
  21945. * background(200);
  21946. * var a = 20;
  21947. * var b = 80;
  21948. * var c = lerp(a,b, .2);
  21949. * var d = lerp(a,b, .5);
  21950. * var e = lerp(a,b, .8);
  21951. *
  21952. * var y = 50
  21953. *
  21954. * strokeWeight(5);
  21955. * stroke(0); // Draw the original points in black
  21956. * point(a, y);
  21957. * point(b, y);
  21958. *
  21959. * stroke(100); // Draw the lerp points in gray
  21960. * point(c, y);
  21961. * point(d, y);
  21962. * point(e, y);
  21963. * }
  21964. * </code></div>
  21965. *
  21966. * @alt
  21967. * 5 points horizontally staggered mid-canvas. mid 3 are grey, outer black
  21968. *
  21969. */
  21970. p5.prototype.lerp = function(start, stop, amt) {
  21971. return amt*(stop-start)+start;
  21972. };
  21973. /**
  21974. * Calculates the natural logarithm (the base-e logarithm) of a number. This
  21975. * function expects the n parameter to be a value greater than 0.0. Maps to
  21976. * Math.log().
  21977. *
  21978. * @method log
  21979. * @param {Number} n number greater than 0
  21980. * @return {Number} natural logarithm of n
  21981. * @example
  21982. * <div><code>
  21983. * function draw() {
  21984. * background(200);
  21985. * var maxX = 2.8;
  21986. * var maxY = 1.5;
  21987. *
  21988. * // Compute the natural log of a value between 0 and maxX
  21989. * var xValue = map(mouseX, 0, width, 0, maxX);
  21990. * if (xValue > 0) { // Cannot take the log of a negative number.
  21991. * var yValue = log(xValue);
  21992. * var y = map(yValue, -maxY, maxY, height, 0);
  21993. *
  21994. * // Display the calculation occurring.
  21995. * var legend = "log(" + nf(xValue, 1, 2) + ")\n= " + nf(yValue, 1, 3);
  21996. * stroke(150);
  21997. * line(mouseX, y, mouseX, height);
  21998. * fill(0);
  21999. * text (legend, 5, 15);
  22000. * noStroke();
  22001. * ellipse (mouseX, y, 7, 7);
  22002. * }
  22003. *
  22004. * // Draw the log(x) curve,
  22005. * // over the domain of x from 0 to maxX
  22006. * noFill();
  22007. * stroke(0);
  22008. * beginShape();
  22009. * for(var x=0; x < width; x++) {
  22010. * xValue = map(x, 0, width, 0, maxX);
  22011. * yValue = log(xValue);
  22012. * y = map(yValue, -maxY, maxY, height, 0);
  22013. * vertex(x, y);
  22014. * }
  22015. * endShape();
  22016. * line(0,0,0,height);
  22017. * line(0,height/2,width, height/2);
  22018. * }
  22019. * </code></div>
  22020. *
  22021. * @alt
  22022. * ellipse moves along a curve with mouse x. natural logarithm of n displayed.
  22023. *
  22024. */
  22025. p5.prototype.log = Math.log;
  22026. /**
  22027. * Calculates the magnitude (or length) of a vector. A vector is a direction
  22028. * in space commonly used in computer graphics and linear algebra. Because it
  22029. * has no "start" position, the magnitude of a vector can be thought of as
  22030. * the distance from the coordinate 0,0 to its x,y value. Therefore, mag() is
  22031. * a shortcut for writing dist(0, 0, x, y).
  22032. *
  22033. * @method mag
  22034. * @param {Number} a first value
  22035. * @param {Number} b second value
  22036. * @return {Number} magnitude of vector from (0,0) to (a,b)
  22037. * @example
  22038. * <div><code>
  22039. * function setup() {
  22040. * var x1 = 20;
  22041. * var x2 = 80;
  22042. * var y1 = 30;
  22043. * var y2 = 70;
  22044. *
  22045. * line(0, 0, x1, y1);
  22046. * print(mag(x1, y1)); // Prints "36.05551275463989"
  22047. * line(0, 0, x2, y1);
  22048. * print(mag(x2, y1)); // Prints "85.44003745317531"
  22049. * line(0, 0, x1, y2);
  22050. * print(mag(x1, y2)); // Prints "72.80109889280519"
  22051. * line(0, 0, x2, y2);
  22052. * print(mag(x2, y2)); // Prints "106.3014581273465"
  22053. * }
  22054. * </code></div>
  22055. *
  22056. * @alt
  22057. * 4 lines of different length radiate from top left of canvas.
  22058. *
  22059. */
  22060. p5.prototype.mag = function(x, y) {
  22061. return hypot(x, y);
  22062. };
  22063. /**
  22064. * Re-maps a number from one range to another.
  22065. * <br><br>
  22066. * In the first example above, the number 25 is converted from a value in the
  22067. * range of 0 to 100 into a value that ranges from the left edge of the
  22068. * window (0) to the right edge (width).
  22069. *
  22070. * @method map
  22071. * @param {Number} value the incoming value to be converted
  22072. * @param {Number} start1 lower bound of the value's current range
  22073. * @param {Number} stop1 upper bound of the value's current range
  22074. * @param {Number} start2 lower bound of the value's target range
  22075. * @param {Number} stop2 upper bound of the value's target range
  22076. * @return {Number} remapped number
  22077. * @example
  22078. * <div><code>
  22079. * var value = 25;
  22080. * var m = map(value, 0, 100, 0, width);
  22081. * ellipse(m, 50, 10, 10);
  22082. * </code></div>
  22083. *
  22084. * <div><code>
  22085. * function setup() {
  22086. * noStroke();
  22087. * }
  22088. *
  22089. * function draw() {
  22090. * background(204);
  22091. * var x1 = map(mouseX, 0, width, 25, 75);
  22092. * ellipse(x1, 25, 25, 25);
  22093. * var x2 = map(mouseX, 0, width, 0, 100);
  22094. * ellipse(x2, 75, 25, 25);
  22095. * }
  22096. * </code></div>
  22097. *
  22098. * @alt
  22099. * 10 by 10 white ellipse with in mid left canvas
  22100. * 2 25 by 25 white ellipses move with mouse x. Bottom has more range from X
  22101. *
  22102. */
  22103. p5.prototype.map = function(n, start1, stop1, start2, stop2) {
  22104. return ((n-start1)/(stop1-start1))*(stop2-start2)+start2;
  22105. };
  22106. /**
  22107. * Determines the largest value in a sequence of numbers, and then returns
  22108. * that value. max() accepts any number of Number parameters, or an Array
  22109. * of any length.
  22110. *
  22111. * @method max
  22112. * @param {Number|Array} n0 Numbers to compare
  22113. * @return {Number} maximum Number
  22114. * @example
  22115. * <div><code>
  22116. * function setup() {
  22117. * // Change the elements in the array and run the sketch
  22118. * // to show how max() works!
  22119. * numArray = new Array(2,1,5,4,8,9);
  22120. * fill(0);
  22121. * noStroke();
  22122. * text("Array Elements", 0, 10);
  22123. * // Draw all numbers in the array
  22124. * var spacing = 15;
  22125. * var elemsY = 25;
  22126. * for(var i = 0; i < numArray.length; i++) {
  22127. * text(numArray[i], i * spacing, elemsY);
  22128. * }
  22129. * maxX = 33;
  22130. * maxY = 80;
  22131. * // Draw the Maximum value in the array.
  22132. * textSize(32);
  22133. * text(max(numArray), maxX, maxY);
  22134. * }
  22135. * </code></div>
  22136. *
  22137. * @alt
  22138. * Small text at top reads: Array Elements 2 1 5 4 8 9. Large text at center: 9
  22139. *
  22140. */
  22141. p5.prototype.max = function() {
  22142. if (arguments[0] instanceof Array) {
  22143. return Math.max.apply(null,arguments[0]);
  22144. } else {
  22145. return Math.max.apply(null,arguments);
  22146. }
  22147. };
  22148. /**
  22149. * Determines the smallest value in a sequence of numbers, and then returns
  22150. * that value. min() accepts any number of Number parameters, or an Array
  22151. * of any length.
  22152. *
  22153. * @method min
  22154. * @param {Number|Array} n0 Numbers to compare
  22155. * @return {Number} minimum Number
  22156. * @example
  22157. * <div><code>
  22158. * function setup() {
  22159. * // Change the elements in the array and run the sketch
  22160. * // to show how min() works!
  22161. * numArray = new Array(2,1,5,4,8,9);
  22162. * fill(0);
  22163. * noStroke();
  22164. * text("Array Elements", 0, 10);
  22165. * // Draw all numbers in the array
  22166. * var spacing = 15;
  22167. * var elemsY = 25;
  22168. * for(var i = 0; i < numArray.length; i++) {
  22169. * text(numArray[i], i * spacing, elemsY);
  22170. * }
  22171. * maxX = 33;
  22172. * maxY = 80;
  22173. * // Draw the Minimum value in the array.
  22174. * textSize(32);
  22175. * text(min(numArray), maxX, maxY);
  22176. * }
  22177. * </code></div>
  22178. *
  22179. * @alt
  22180. * Small text at top reads: Array Elements 2 1 5 4 8 9. Large text at center: 1
  22181. *
  22182. */
  22183. p5.prototype.min = function() {
  22184. if (arguments[0] instanceof Array) {
  22185. return Math.min.apply(null,arguments[0]);
  22186. } else {
  22187. return Math.min.apply(null,arguments);
  22188. }
  22189. };
  22190. /**
  22191. * Normalizes a number from another range into a value between 0 and 1.
  22192. * Identical to map(value, low, high, 0, 1).
  22193. * Numbers outside of the range are not clamped to 0 and 1, because
  22194. * out-of-range values are often intentional and useful. (See the second
  22195. * example above.)
  22196. *
  22197. * @method norm
  22198. * @param {Number} value incoming value to be normalized
  22199. * @param {Number} start lower bound of the value's current range
  22200. * @param {Number} stop upper bound of the value's current range
  22201. * @return {Number} normalized number
  22202. * @example
  22203. * <div><code>
  22204. * function draw() {
  22205. * background(200);
  22206. * currentNum = mouseX;
  22207. * lowerBound = 0;
  22208. * upperBound = width; //100;
  22209. * normalized = norm(currentNum, lowerBound, upperBound);
  22210. * lineY = 70
  22211. * line(0, lineY, width, lineY);
  22212. * //Draw an ellipse mapped to the non-normalized value.
  22213. * noStroke();
  22214. * fill(50)
  22215. * var s = 7; // ellipse size
  22216. * ellipse(currentNum, lineY, s, s);
  22217. *
  22218. * // Draw the guide
  22219. * guideY = lineY + 15;
  22220. * text("0", 0, guideY);
  22221. * textAlign(RIGHT);
  22222. * text("100", width, guideY);
  22223. *
  22224. * // Draw the normalized value
  22225. * textAlign(LEFT);
  22226. * fill(0);
  22227. * textSize(32);
  22228. * normalY = 40;
  22229. * normalX = 20;
  22230. * text(normalized, normalX, normalY);
  22231. * }
  22232. * </code></div>
  22233. *
  22234. * @alt
  22235. * ellipse moves with mouse. 0 shown left & 100 right and updating values center
  22236. *
  22237. */
  22238. p5.prototype.norm = function(n, start, stop) {
  22239. return this.map(n, start, stop, 0, 1);
  22240. };
  22241. /**
  22242. * Facilitates exponential expressions. The pow() function is an efficient
  22243. * way of multiplying numbers by themselves (or their reciprocals) in large
  22244. * quantities. For example, pow(3, 5) is equivalent to the expression
  22245. * 3*3*3*3*3 and pow(3, -5) is equivalent to 1 / 3*3*3*3*3. Maps to
  22246. * Math.pow().
  22247. *
  22248. * @method pow
  22249. * @param {Number} n base of the exponential expression
  22250. * @param {Number} e power by which to raise the base
  22251. * @return {Number} n^e
  22252. * @example
  22253. * <div><code>
  22254. * function setup() {
  22255. * //Exponentially increase the size of an ellipse.
  22256. * eSize = 3; // Original Size
  22257. * eLoc = 10; // Original Location
  22258. *
  22259. * ellipse(eLoc, eLoc, eSize, eSize);
  22260. *
  22261. * ellipse(eLoc*2, eLoc*2, pow(eSize, 2), pow(eSize, 2));
  22262. *
  22263. * ellipse(eLoc*4, eLoc*4, pow(eSize, 3), pow(eSize, 3));
  22264. *
  22265. * ellipse(eLoc*8, eLoc*8, pow(eSize, 4), pow(eSize, 4));
  22266. * }
  22267. * </code></div>
  22268. *
  22269. * @alt
  22270. * small to large ellipses radiating from top left of canvas
  22271. *
  22272. */
  22273. p5.prototype.pow = Math.pow;
  22274. /**
  22275. * Calculates the integer closest to the n parameter. For example,
  22276. * round(133.8) returns the value 134. Maps to Math.round().
  22277. *
  22278. * @method round
  22279. * @param {Number} n number to round
  22280. * @return {Number} rounded number
  22281. * @example
  22282. * <div><code>
  22283. * function draw() {
  22284. * background(200);
  22285. * //map, mouseX between 0 and 5.
  22286. * var ax = map(mouseX, 0, 100, 0, 5);
  22287. * var ay = 66;
  22288. *
  22289. * // Round the mapped number.
  22290. * var bx = round(map(mouseX, 0, 100, 0,5));
  22291. * var by = 33;
  22292. *
  22293. * // Multiply the mapped numbers by 20 to more easily
  22294. * // see the changes.
  22295. * stroke(0);
  22296. * fill(0);
  22297. * line(0, ay, ax * 20, ay);
  22298. * line(0, by, bx * 20, by);
  22299. *
  22300. * // Reformat the float returned by map and draw it.
  22301. * noStroke();
  22302. * text(nfc(ax, 2,2), ax, ay - 5);
  22303. * text(nfc(bx,1,1), bx, by - 5);
  22304. * }
  22305. * </code></div>
  22306. *
  22307. * @alt
  22308. * horizontal center line squared values displayed on top and regular on bottom.
  22309. *
  22310. */
  22311. p5.prototype.round = Math.round;
  22312. /**
  22313. * Squares a number (multiplies a number by itself). The result is always a
  22314. * positive number, as multiplying two negative numbers always yields a
  22315. * positive result. For example, -1 * -1 = 1.
  22316. *
  22317. * @method sq
  22318. * @param {Number} n number to square
  22319. * @return {Number} squared number
  22320. * @example
  22321. * <div><code>
  22322. * function draw() {
  22323. * background(200);
  22324. * eSize = 7;
  22325. * x1 = map(mouseX, 0, width, 0, 10);
  22326. * y1 = 80;
  22327. * x2 = sq(x1);
  22328. * y2 = 20;
  22329. *
  22330. * // Draw the non-squared.
  22331. * line(0, y1, width, y1);
  22332. * ellipse(x1, y1, eSize, eSize);
  22333. *
  22334. * // Draw the squared.
  22335. * line(0, y2, width, y2);
  22336. * ellipse(x2, y2, eSize, eSize);
  22337. *
  22338. * // Draw dividing line.
  22339. * stroke(100)
  22340. * line(0, height/2, width, height/2);
  22341. *
  22342. * // Draw text.
  22343. * var spacing = 15;
  22344. * noStroke();
  22345. * fill(0);
  22346. * text("x = " + x1, 0, y1 + spacing);
  22347. * text("sq(x) = " + x2, 0, y2 + spacing);
  22348. * }
  22349. * </code></div>
  22350. *
  22351. * @alt
  22352. * horizontal center line squared values displayed on top and regular on bottom.
  22353. *
  22354. */
  22355. p5.prototype.sq = function(n) { return n*n; };
  22356. /**
  22357. * Calculates the square root of a number. The square root of a number is
  22358. * always positive, even though there may be a valid negative root. The
  22359. * square root s of number a is such that s*s = a. It is the opposite of
  22360. * squaring. Maps to Math.sqrt().
  22361. *
  22362. * @method sqrt
  22363. * @param {Number} n non-negative number to square root
  22364. * @return {Number} square root of number
  22365. * @example
  22366. * <div><code>
  22367. * function draw() {
  22368. * background(200);
  22369. * eSize = 7;
  22370. * x1 = mouseX;
  22371. * y1 = 80;
  22372. * x2 = sqrt(x1);
  22373. * y2 = 20;
  22374. *
  22375. * // Draw the non-squared.
  22376. * line(0, y1, width, y1);
  22377. * ellipse(x1, y1, eSize, eSize);
  22378. *
  22379. * // Draw the squared.
  22380. * line(0, y2, width, y2);
  22381. * ellipse(x2, y2, eSize, eSize);
  22382. *
  22383. * // Draw dividing line.
  22384. * stroke(100)
  22385. * line(0, height/2, width, height/2);
  22386. *
  22387. * // Draw text.
  22388. * noStroke();
  22389. * fill(0);
  22390. * var spacing = 15;
  22391. * text("x = " + x1, 0, y1 + spacing);
  22392. * text("sqrt(x) = " + x2, 0, y2 + spacing);
  22393. * }
  22394. * </code></div>
  22395. *
  22396. * @alt
  22397. * horizontal center line squareroot values displayed on top and regular on bottom.
  22398. *
  22399. */
  22400. p5.prototype.sqrt = Math.sqrt;
  22401. // Calculate the length of the hypotenuse of a right triangle
  22402. // This won't under- or overflow in intermediate steps
  22403. // https://en.wikipedia.org/wiki/Hypot
  22404. function hypot(x, y, z) {
  22405. // Use the native implementation if it's available
  22406. if (typeof Math.hypot === 'function') {
  22407. return Math.hypot.apply(null, arguments);
  22408. }
  22409. // Otherwise use the V8 implementation
  22410. // https://github.com/v8/v8/blob/8cd3cf297287e581a49e487067f5cbd991b27123/src/js/math.js#L217
  22411. var length = arguments.length;
  22412. var args = [];
  22413. var max = 0;
  22414. for (var i = 0; i < length; i++) {
  22415. var n = arguments[i];
  22416. n = +n;
  22417. if (n === Infinity || n === -Infinity) {
  22418. return Infinity;
  22419. }
  22420. n = Math.abs(n);
  22421. if (n > max) {
  22422. max = n;
  22423. }
  22424. args[i] = n;
  22425. }
  22426. if (max === 0) {
  22427. max = 1;
  22428. }
  22429. var sum = 0;
  22430. var compensation = 0;
  22431. for (var j = 0; j < length; j++) {
  22432. var m = args[j] / max;
  22433. var summand = m * m - compensation;
  22434. var preliminary = sum + summand;
  22435. compensation = (preliminary - sum) - summand;
  22436. sum = preliminary;
  22437. }
  22438. return Math.sqrt(sum) * max;
  22439. }
  22440. module.exports = p5;
  22441. },{"../core/core":37}],64:[function(_dereq_,module,exports){
  22442. /**
  22443. * @module Math
  22444. * @submodule Math
  22445. * @for p5
  22446. * @requires core
  22447. */
  22448. 'use strict';
  22449. var p5 = _dereq_('../core/core');
  22450. /**
  22451. * Creates a new p5.Vector (the datatype for storing vectors). This provides a
  22452. * two or three dimensional vector, specifically a Euclidean (also known as
  22453. * geometric) vector. A vector is an entity that has both magnitude and
  22454. * direction.
  22455. *
  22456. * @method createVector
  22457. * @param {Number} [x] x component of the vector
  22458. * @param {Number} [y] y component of the vector
  22459. * @param {Number} [z] z component of the vector
  22460. */
  22461. p5.prototype.createVector = function (x, y, z) {
  22462. if (this instanceof p5) {
  22463. return new p5.Vector(this, arguments);
  22464. } else {
  22465. return new p5.Vector(x, y, z);
  22466. }
  22467. };
  22468. module.exports = p5;
  22469. },{"../core/core":37}],65:[function(_dereq_,module,exports){
  22470. //////////////////////////////////////////////////////////////
  22471. // http://mrl.nyu.edu/~perlin/noise/
  22472. // Adapting from PApplet.java
  22473. // which was adapted from toxi
  22474. // which was adapted from the german demo group farbrausch
  22475. // as used in their demo "art": http://www.farb-rausch.de/fr010src.zip
  22476. // someday we might consider using "improved noise"
  22477. // http://mrl.nyu.edu/~perlin/paper445.pdf
  22478. // See: https://github.com/shiffman/The-Nature-of-Code-Examples-p5.js/
  22479. // blob/master/introduction/Noise1D/noise.js
  22480. /**
  22481. * @module Math
  22482. * @submodule Noise
  22483. * @for p5
  22484. * @requires core
  22485. */
  22486. 'use strict';
  22487. var p5 = _dereq_('../core/core');
  22488. var PERLIN_YWRAPB = 4;
  22489. var PERLIN_YWRAP = 1<<PERLIN_YWRAPB;
  22490. var PERLIN_ZWRAPB = 8;
  22491. var PERLIN_ZWRAP = 1<<PERLIN_ZWRAPB;
  22492. var PERLIN_SIZE = 4095;
  22493. var perlin_octaves = 4; // default to medium smooth
  22494. var perlin_amp_falloff = 0.5; // 50% reduction/octave
  22495. var scaled_cosine = function(i) {
  22496. return 0.5*(1.0-Math.cos(i*Math.PI));
  22497. };
  22498. var perlin; // will be initialized lazily by noise() or noiseSeed()
  22499. /**
  22500. * Returns the Perlin noise value at specified coordinates. Perlin noise is
  22501. * a random sequence generator producing a more natural ordered, harmonic
  22502. * succession of numbers compared to the standard <b>random()</b> function.
  22503. * It was invented by Ken Perlin in the 1980s and been used since in
  22504. * graphical applications to produce procedural textures, natural motion,
  22505. * shapes, terrains etc.<br /><br /> The main difference to the
  22506. * <b>random()</b> function is that Perlin noise is defined in an infinite
  22507. * n-dimensional space where each pair of coordinates corresponds to a
  22508. * fixed semi-random value (fixed only for the lifespan of the program; see
  22509. * the noiseSeed() function). p5.js can compute 1D, 2D and 3D noise,
  22510. * depending on the number of coordinates given. The resulting value will
  22511. * always be between 0.0 and 1.0. The noise value can be animated by moving
  22512. * through the noise space as demonstrated in the example above. The 2nd
  22513. * and 3rd dimension can also be interpreted as time.<br /><br />The actual
  22514. * noise is structured similar to an audio signal, in respect to the
  22515. * function's use of frequencies. Similar to the concept of harmonics in
  22516. * physics, perlin noise is computed over several octaves which are added
  22517. * together for the final result. <br /><br />Another way to adjust the
  22518. * character of the resulting sequence is the scale of the input
  22519. * coordinates. As the function works within an infinite space the value of
  22520. * the coordinates doesn't matter as such, only the distance between
  22521. * successive coordinates does (eg. when using <b>noise()</b> within a
  22522. * loop). As a general rule the smaller the difference between coordinates,
  22523. * the smoother the resulting noise sequence will be. Steps of 0.005-0.03
  22524. * work best for most applications, but this will differ depending on use.
  22525. *
  22526. *
  22527. * @method noise
  22528. * @param {Number} x x-coordinate in noise space
  22529. * @param {Number} y y-coordinate in noise space
  22530. * @param {Number} z z-coordinate in noise space
  22531. * @return {Number} Perlin noise value (between 0 and 1) at specified
  22532. * coordinates
  22533. * @example
  22534. * <div>
  22535. * <code>var xoff = 0.0;
  22536. *
  22537. * function draw() {
  22538. * background(204);
  22539. * xoff = xoff + .01;
  22540. * var n = noise(xoff) * width;
  22541. * line(n, 0, n, height);
  22542. * }
  22543. * </code>
  22544. * </div>
  22545. * <div>
  22546. * <code>var noiseScale=0.02;
  22547. *
  22548. * function draw() {
  22549. * background(0);
  22550. * for (var x=0; x < width; x++) {
  22551. * var noiseVal = noise((mouseX+x)*noiseScale, mouseY*noiseScale);
  22552. * stroke(noiseVal*255);
  22553. * line(x, mouseY+noiseVal*80, x, height);
  22554. * }
  22555. * }
  22556. * </code>
  22557. * </div>
  22558. *
  22559. * @alt
  22560. * vertical line moves left to right with updating noise values.
  22561. * horizontal wave pattern effected by mouse x-position & updating noise values.
  22562. *
  22563. */
  22564. p5.prototype.noise = function(x,y,z) {
  22565. y = y || 0;
  22566. z = z || 0;
  22567. if (perlin == null) {
  22568. perlin = new Array(PERLIN_SIZE + 1);
  22569. for (var i = 0; i < PERLIN_SIZE + 1; i++) {
  22570. perlin[i] = Math.random();
  22571. }
  22572. }
  22573. if (x<0) { x=-x; }
  22574. if (y<0) { y=-y; }
  22575. if (z<0) { z=-z; }
  22576. var xi=Math.floor(x), yi=Math.floor(y), zi=Math.floor(z);
  22577. var xf = x - xi;
  22578. var yf = y - yi;
  22579. var zf = z - zi;
  22580. var rxf, ryf;
  22581. var r=0;
  22582. var ampl=0.5;
  22583. var n1,n2,n3;
  22584. for (var o=0; o<perlin_octaves; o++) {
  22585. var of=xi+(yi<<PERLIN_YWRAPB)+(zi<<PERLIN_ZWRAPB);
  22586. rxf = scaled_cosine(xf);
  22587. ryf = scaled_cosine(yf);
  22588. n1 = perlin[of&PERLIN_SIZE];
  22589. n1 += rxf*(perlin[(of+1)&PERLIN_SIZE]-n1);
  22590. n2 = perlin[(of+PERLIN_YWRAP)&PERLIN_SIZE];
  22591. n2 += rxf*(perlin[(of+PERLIN_YWRAP+1)&PERLIN_SIZE]-n2);
  22592. n1 += ryf*(n2-n1);
  22593. of += PERLIN_ZWRAP;
  22594. n2 = perlin[of&PERLIN_SIZE];
  22595. n2 += rxf*(perlin[(of+1)&PERLIN_SIZE]-n2);
  22596. n3 = perlin[(of+PERLIN_YWRAP)&PERLIN_SIZE];
  22597. n3 += rxf*(perlin[(of+PERLIN_YWRAP+1)&PERLIN_SIZE]-n3);
  22598. n2 += ryf*(n3-n2);
  22599. n1 += scaled_cosine(zf)*(n2-n1);
  22600. r += n1*ampl;
  22601. ampl *= perlin_amp_falloff;
  22602. xi<<=1;
  22603. xf*=2;
  22604. yi<<=1;
  22605. yf*=2;
  22606. zi<<=1;
  22607. zf*=2;
  22608. if (xf>=1.0) { xi++; xf--; }
  22609. if (yf>=1.0) { yi++; yf--; }
  22610. if (zf>=1.0) { zi++; zf--; }
  22611. }
  22612. return r;
  22613. };
  22614. /**
  22615. *
  22616. * Adjusts the character and level of detail produced by the Perlin noise
  22617. * function. Similar to harmonics in physics, noise is computed over
  22618. * several octaves. Lower octaves contribute more to the output signal and
  22619. * as such define the overall intensity of the noise, whereas higher octaves
  22620. * create finer grained details in the noise sequence.
  22621. * <br><br>
  22622. * By default, noise is computed over 4 octaves with each octave contributing
  22623. * exactly half than its predecessor, starting at 50% strength for the 1st
  22624. * octave. This falloff amount can be changed by adding an additional function
  22625. * parameter. Eg. a falloff factor of 0.75 means each octave will now have
  22626. * 75% impact (25% less) of the previous lower octave. Any value between
  22627. * 0.0 and 1.0 is valid, however note that values greater than 0.5 might
  22628. * result in greater than 1.0 values returned by <b>noise()</b>.
  22629. * <br><br>
  22630. * By changing these parameters, the signal created by the <b>noise()</b>
  22631. * function can be adapted to fit very specific needs and characteristics.
  22632. *
  22633. * @method noiseDetail
  22634. * @param {Number} lod number of octaves to be used by the noise
  22635. * @param {Number} falloff falloff factor for each octave
  22636. * @example
  22637. * <div>
  22638. * <code>
  22639. *
  22640. * var noiseVal;
  22641. * var noiseScale=0.02;
  22642. *
  22643. * function setup() {
  22644. * createCanvas(100,100);
  22645. * }
  22646. *
  22647. * function draw() {
  22648. * background(0);
  22649. * for (var y = 0; y < height; y++) {
  22650. * for (var x = 0; x < width/2; x++) {
  22651. * noiseDetail(2,0.2);
  22652. * noiseVal = noise((mouseX+x) * noiseScale,
  22653. * (mouseY+y) * noiseScale);
  22654. * stroke(noiseVal*255);
  22655. * point(x,y);
  22656. * noiseDetail(8,0.65);
  22657. * noiseVal = noise((mouseX + x + width/2) * noiseScale,
  22658. * (mouseY + y) * noiseScale);
  22659. * stroke(noiseVal*255);
  22660. * point(x + width/2, y);
  22661. * }
  22662. * }
  22663. * }
  22664. * </code>
  22665. * </div>
  22666. *
  22667. * @alt
  22668. * 2 vertical grey smokey patterns affected my mouse x-position and noise.
  22669. *
  22670. */
  22671. p5.prototype.noiseDetail = function(lod, falloff) {
  22672. if (lod>0) { perlin_octaves=lod; }
  22673. if (falloff>0) { perlin_amp_falloff=falloff; }
  22674. };
  22675. /**
  22676. * Sets the seed value for <b>noise()</b>. By default, <b>noise()</b>
  22677. * produces different results each time the program is run. Set the
  22678. * <b>value</b> parameter to a constant to return the same pseudo-random
  22679. * numbers each time the software is run.
  22680. *
  22681. * @method noiseSeed
  22682. * @param {Number} seed the seed value
  22683. * @example
  22684. * <div>
  22685. * <code>var xoff = 0.0;
  22686. *
  22687. * function setup() {
  22688. * noiseSeed(99);
  22689. * stroke(0, 10);
  22690. * }
  22691. *
  22692. * function draw() {
  22693. * xoff = xoff + .01;
  22694. * var n = noise(xoff) * width;
  22695. * line(n, 0, n, height);
  22696. * }
  22697. * </code>
  22698. * </div>
  22699. *
  22700. * @alt
  22701. * vertical grey lines drawing in pattern affected by noise.
  22702. *
  22703. */
  22704. p5.prototype.noiseSeed = function(seed) {
  22705. // Linear Congruential Generator
  22706. // Variant of a Lehman Generator
  22707. var lcg = (function() {
  22708. // Set to values from http://en.wikipedia.org/wiki/Numerical_Recipes
  22709. // m is basically chosen to be large (as it is the max period)
  22710. // and for its relationships to a and c
  22711. var m = 4294967296,
  22712. // a - 1 should be divisible by m's prime factors
  22713. a = 1664525,
  22714. // c and m should be co-prime
  22715. c = 1013904223,
  22716. seed, z;
  22717. return {
  22718. setSeed : function(val) {
  22719. // pick a random seed if val is undefined or null
  22720. // the >>> 0 casts the seed to an unsigned 32-bit integer
  22721. z = seed = (val == null ? Math.random() * m : val) >>> 0;
  22722. },
  22723. getSeed : function() {
  22724. return seed;
  22725. },
  22726. rand : function() {
  22727. // define the recurrence relationship
  22728. z = (a * z + c) % m;
  22729. // return a float in [0, 1)
  22730. // if z = m then z / m = 0 therefore (z % m) / m < 1 always
  22731. return z / m;
  22732. }
  22733. };
  22734. }());
  22735. lcg.setSeed(seed);
  22736. perlin = new Array(PERLIN_SIZE + 1);
  22737. for (var i = 0; i < PERLIN_SIZE + 1; i++) {
  22738. perlin[i] = lcg.rand();
  22739. }
  22740. };
  22741. module.exports = p5;
  22742. },{"../core/core":37}],66:[function(_dereq_,module,exports){
  22743. /**
  22744. * @module Math
  22745. * @submodule Math
  22746. * @requires constants
  22747. */
  22748. 'use strict';
  22749. var p5 = _dereq_('../core/core');
  22750. var polarGeometry = _dereq_('./polargeometry');
  22751. var constants = _dereq_('../core/constants');
  22752. /**
  22753. * A class to describe a two or three dimensional vector, specifically
  22754. * a Euclidean (also known as geometric) vector. A vector is an entity
  22755. * that has both magnitude and direction. The datatype, however, stores
  22756. * the components of the vector (x, y for 2D, and x, y, z for 3D). The magnitude
  22757. * and direction can be accessed via the methods mag() and heading().
  22758. * <br><br>
  22759. * In many of the p5.js examples, you will see p5.Vector used to describe a
  22760. * position, velocity, or acceleration. For example, if you consider a rectangle
  22761. * moving across the screen, at any given instant it has a position (a vector
  22762. * that points from the origin to its location), a velocity (the rate at which
  22763. * the object's position changes per time unit, expressed as a vector), and
  22764. * acceleration (the rate at which the object's velocity changes per time
  22765. * unit, expressed as a vector).
  22766. * <br><br>
  22767. * Since vectors represent groupings of values, we cannot simply use
  22768. * traditional addition/multiplication/etc. Instead, we'll need to do some
  22769. * "vector" math, which is made easy by the methods inside the p5.Vector class.
  22770. *
  22771. * @class p5.Vector
  22772. * @constructor
  22773. * @param {Number} [x] x component of the vector
  22774. * @param {Number} [y] y component of the vector
  22775. * @param {Number} [z] z component of the vector
  22776. * @example
  22777. * <div>
  22778. * <code>
  22779. * var v1 = createVector(40, 50);
  22780. * var v2 = createVector(40, 50);
  22781. *
  22782. * ellipse(v1.x, v1.y, 50, 50);
  22783. * ellipse(v2.x, v2.y, 50, 50);
  22784. * v1.add(v2);
  22785. * ellipse(v1.x, v1.y, 50, 50);
  22786. * </code>
  22787. * </div>
  22788. *
  22789. * @alt
  22790. * 2 white ellipses. One center-left the other bottom right and off canvas
  22791. *
  22792. */
  22793. p5.Vector = function() {
  22794. var x,y,z;
  22795. // This is how it comes in with createVector()
  22796. if(arguments[0] instanceof p5) {
  22797. // save reference to p5 if passed in
  22798. this.p5 = arguments[0];
  22799. x = arguments[1][0] || 0;
  22800. y = arguments[1][1] || 0;
  22801. z = arguments[1][2] || 0;
  22802. // This is what we'll get with new p5.Vector()
  22803. } else {
  22804. x = arguments[0] || 0;
  22805. y = arguments[1] || 0;
  22806. z = arguments[2] || 0;
  22807. }
  22808. /**
  22809. * The x component of the vector
  22810. * @property x
  22811. * @type {Number}
  22812. */
  22813. this.x = x;
  22814. /**
  22815. * The y component of the vector
  22816. * @property y
  22817. * @type {Number}
  22818. */
  22819. this.y = y;
  22820. /**
  22821. * The z component of the vector
  22822. * @property z
  22823. * @type {Number}
  22824. */
  22825. this.z = z;
  22826. };
  22827. /**
  22828. * Returns a string representation of a vector v by calling String(v)
  22829. * or v.toString(). This method is useful for logging vectors in the
  22830. * console.
  22831. * @method toString
  22832. * @example
  22833. * <div class = "norender"><code>
  22834. * function setup() {
  22835. * var v = createVector(20,30);
  22836. * print(String(v)); // prints "p5.Vector Object : [20, 30, 0]"
  22837. * }
  22838. * </div></code>
  22839. *
  22840. */
  22841. p5.Vector.prototype.toString = function p5VectorToString() {
  22842. return 'p5.Vector Object : ['+ this.x +', '+ this.y +', '+ this.z + ']';
  22843. };
  22844. /**
  22845. * Sets the x, y, and z component of the vector using two or three separate
  22846. * variables, the data from a p5.Vector, or the values from a float array.
  22847. * @method set
  22848. *
  22849. * @param {Number|p5.Vector|Array} [x] the x component of the vector or a
  22850. * p5.Vector or an Array
  22851. * @param {Number} [y] the y component of the vector
  22852. * @param {Number} [z] the z component of the vector
  22853. * @example
  22854. * <div class="norender">
  22855. * <code>
  22856. * function setup() {
  22857. * var v = createVector(1, 2, 3);
  22858. * v.set(4,5,6); // Sets vector to [4, 5, 6]
  22859. *
  22860. * var v1 = createVector(0, 0, 0);
  22861. * var arr = [1, 2, 3];
  22862. * v1.set(arr); // Sets vector to [1, 2, 3]
  22863. * }
  22864. * </code>
  22865. * </div>
  22866. */
  22867. p5.Vector.prototype.set = function (x, y, z) {
  22868. if (x instanceof p5.Vector) {
  22869. this.x = x.x || 0;
  22870. this.y = x.y || 0;
  22871. this.z = x.z || 0;
  22872. return this;
  22873. }
  22874. if (x instanceof Array) {
  22875. this.x = x[0] || 0;
  22876. this.y = x[1] || 0;
  22877. this.z = x[2] || 0;
  22878. return this;
  22879. }
  22880. this.x = x || 0;
  22881. this.y = y || 0;
  22882. this.z = z || 0;
  22883. return this;
  22884. };
  22885. /**
  22886. * Gets a copy of the vector, returns a p5.Vector object.
  22887. *
  22888. * @method copy
  22889. * @return {p5.Vector} the copy of the p5.Vector object
  22890. * @example
  22891. * <div class="norender">
  22892. * <code>
  22893. * var v1 = createVector(1, 2, 3);
  22894. * var v2 = v1.copy();
  22895. * print(v1.x == v2.x && v1.y == v2.y && v1.z == v2.z);
  22896. * // Prints "true"
  22897. * </code>
  22898. * </div>
  22899. */
  22900. p5.Vector.prototype.copy = function () {
  22901. if (this.p5) {
  22902. return new p5.Vector(this.p5,[this.x, this.y, this.z]);
  22903. } else {
  22904. return new p5.Vector(this.x,this.y,this.z);
  22905. }
  22906. };
  22907. /**
  22908. * Adds x, y, and z components to a vector, adds one vector to another, or
  22909. * adds two independent vectors together. The version of the method that adds
  22910. * two vectors together is a static method and returns a p5.Vector, the others
  22911. * acts directly on the vector. See the examples for more context.
  22912. *
  22913. * @method add
  22914. * @chainable
  22915. * @param {Number|p5.Vector|Array} x the x component of the vector to be
  22916. * added or a p5.Vector or an Array
  22917. * @param {Number} [y] the y component of the vector to be
  22918. * added
  22919. * @param {Number} [z] the z component of the vector to be
  22920. * added
  22921. * @return {p5.Vector} the p5.Vector object.
  22922. * @example
  22923. * <div class="norender">
  22924. * <code>
  22925. * var v = createVector(1, 2, 3);
  22926. * v.add(4,5,6);
  22927. * // v's components are set to [5, 7, 9]
  22928. * </code>
  22929. * </div>
  22930. * <div class="norender">
  22931. * <code>
  22932. * // Static method
  22933. * var v1 = createVector(1, 2, 3);
  22934. * var v2 = createVector(2, 3, 4);
  22935. *
  22936. * var v3 = p5.Vector.add(v1, v2);
  22937. * // v3 has components [3, 5, 7]
  22938. * </code>
  22939. * </div>
  22940. */
  22941. p5.Vector.prototype.add = function (x, y, z) {
  22942. if (x instanceof p5.Vector) {
  22943. this.x += x.x || 0;
  22944. this.y += x.y || 0;
  22945. this.z += x.z || 0;
  22946. return this;
  22947. }
  22948. if (x instanceof Array) {
  22949. this.x += x[0] || 0;
  22950. this.y += x[1] || 0;
  22951. this.z += x[2] || 0;
  22952. return this;
  22953. }
  22954. this.x += x || 0;
  22955. this.y += y || 0;
  22956. this.z += z || 0;
  22957. return this;
  22958. };
  22959. /**
  22960. * Subtracts x, y, and z components from a vector, subtracts one vector from
  22961. * another, or subtracts two independent vectors. The version of the method
  22962. * that subtracts two vectors is a static method and returns a p5.Vector, the
  22963. * other acts directly on the vector. See the examples for more context.
  22964. *
  22965. * @method sub
  22966. * @chainable
  22967. * @param {Number|p5.Vector|Array} x the x component of the vector or a
  22968. * p5.Vector or an Array
  22969. * @param {Number} [y] the y component of the vector
  22970. * @param {Number} [z] the z component of the vector
  22971. * @return {p5.Vector} p5.Vector object.
  22972. * @example
  22973. * <div class="norender">
  22974. * <code>
  22975. * var v = createVector(4, 5, 6);
  22976. * v.sub(1, 1, 1);
  22977. * // v's components are set to [3, 4, 5]
  22978. * </code>
  22979. * </div>
  22980. *
  22981. * <div class="norender">
  22982. * <code>
  22983. * // Static method
  22984. * var v1 = createVector(2, 3, 4);
  22985. * var v2 = createVector(1, 2, 3);
  22986. *
  22987. * var v3 = p5.Vector.sub(v1, v2);
  22988. * // v3 has components [1, 1, 1]
  22989. * </code>
  22990. * </div>
  22991. */
  22992. p5.Vector.prototype.sub = function (x, y, z) {
  22993. if (x instanceof p5.Vector) {
  22994. this.x -= x.x || 0;
  22995. this.y -= x.y || 0;
  22996. this.z -= x.z || 0;
  22997. return this;
  22998. }
  22999. if (x instanceof Array) {
  23000. this.x -= x[0] || 0;
  23001. this.y -= x[1] || 0;
  23002. this.z -= x[2] || 0;
  23003. return this;
  23004. }
  23005. this.x -= x || 0;
  23006. this.y -= y || 0;
  23007. this.z -= z || 0;
  23008. return this;
  23009. };
  23010. /**
  23011. * Multiply the vector by a scalar. The static version of this method
  23012. * creates a new p5.Vector while the non static version acts on the vector
  23013. * directly. See the examples for more context.
  23014. *
  23015. * @method mult
  23016. * @chainable
  23017. * @param {Number} n the number to multiply with the vector
  23018. * @return {p5.Vector} a reference to the p5.Vector object (allow chaining)
  23019. * @example
  23020. * <div class="norender">
  23021. * <code>
  23022. * var v = createVector(1, 2, 3);
  23023. * v.mult(2);
  23024. * // v's components are set to [2, 4, 6]
  23025. * </code>
  23026. * </div>
  23027. *
  23028. * <div class="norender">
  23029. * <code>
  23030. * // Static method
  23031. * var v1 = createVector(1, 2, 3);
  23032. * var v2 = p5.Vector.mult(v1, 2);
  23033. * // v2 has components [2, 4, 6]
  23034. * </code>
  23035. * </div>
  23036. */
  23037. p5.Vector.prototype.mult = function (n) {
  23038. this.x *= n || 0;
  23039. this.y *= n || 0;
  23040. this.z *= n || 0;
  23041. return this;
  23042. };
  23043. /**
  23044. * Divide the vector by a scalar. The static version of this method creates a
  23045. * new p5.Vector while the non static version acts on the vector directly.
  23046. * See the examples for more context.
  23047. *
  23048. * @method div
  23049. * @chainable
  23050. * @param {number} n the number to divide the vector by
  23051. * @return {p5.Vector} a reference to the p5.Vector object (allow chaining)
  23052. * @example
  23053. * <div class="norender">
  23054. * <code>
  23055. * var v = createVector(6, 4, 2);
  23056. * v.div(2); //v's components are set to [3, 2, 1]
  23057. * </code>
  23058. * </div>
  23059. *
  23060. * <div class="norender">
  23061. * <code>
  23062. * // Static method
  23063. * var v1 = createVector(6, 4, 2);
  23064. * var v2 = p5.Vector.div(v, 2);
  23065. * // v2 has components [3, 2, 1]
  23066. * </code>
  23067. * </div>
  23068. */
  23069. p5.Vector.prototype.div = function (n) {
  23070. this.x /= n;
  23071. this.y /= n;
  23072. this.z /= n;
  23073. return this;
  23074. };
  23075. /**
  23076. * Calculates the magnitude (length) of the vector and returns the result as
  23077. * a float (this is simply the equation sqrt(x*x + y*y + z*z).)
  23078. *
  23079. * @method mag
  23080. * @return {Number} magnitude of the vector
  23081. * @example
  23082. * <div class="norender">
  23083. * <code>
  23084. * var v = createVector(20.0, 30.0, 40.0);
  23085. * var m = v.mag();
  23086. * print(m); // Prints "53.85164807134504"
  23087. * </code>
  23088. * </div>
  23089. */
  23090. p5.Vector.prototype.mag = function () {
  23091. return Math.sqrt(this.magSq());
  23092. };
  23093. /**
  23094. * Calculates the squared magnitude of the vector and returns the result
  23095. * as a float (this is simply the equation <em>(x*x + y*y + z*z)</em>.)
  23096. * Faster if the real length is not required in the
  23097. * case of comparing vectors, etc.
  23098. *
  23099. * @method magSq
  23100. * @return {number} squared magnitude of the vector
  23101. * @example
  23102. * <div class="norender">
  23103. * <code>
  23104. * // Static method
  23105. * var v1 = createVector(6, 4, 2);
  23106. * print(v1.magSq()); // Prints "56"
  23107. * </code>
  23108. * </div>
  23109. */
  23110. p5.Vector.prototype.magSq = function () {
  23111. var x = this.x, y = this.y, z = this.z;
  23112. return (x * x + y * y + z * z);
  23113. };
  23114. /**
  23115. * Calculates the dot product of two vectors. The version of the method
  23116. * that computes the dot product of two independent vectors is a static
  23117. * method. See the examples for more context.
  23118. *
  23119. *
  23120. * @method dot
  23121. * @param {Number|p5.Vector} x x component of the vector or a p5.Vector
  23122. * @param {Number} [y] y component of the vector
  23123. * @param {Number} [z] z component of the vector
  23124. * @return {Number} the dot product
  23125. *
  23126. * @example
  23127. * <div class="norender">
  23128. * <code>
  23129. * var v1 = createVector(1, 2, 3);
  23130. * var v2 = createVector(2, 3, 4);
  23131. *
  23132. * print(v1.dot(v2)); // Prints "20"
  23133. * </code>
  23134. * </div>
  23135. *
  23136. * <div class="norender">
  23137. * <code>
  23138. * //Static method
  23139. * var v1 = createVector(1, 2, 3);
  23140. * var v2 = createVector(3, 2, 1);
  23141. * print (p5.Vector.dot(v1, v2)); // Prints "10"
  23142. * </code>
  23143. * </div>
  23144. */
  23145. p5.Vector.prototype.dot = function (x, y, z) {
  23146. if (x instanceof p5.Vector) {
  23147. return this.dot(x.x, x.y, x.z);
  23148. }
  23149. return this.x * (x || 0) +
  23150. this.y * (y || 0) +
  23151. this.z * (z || 0);
  23152. };
  23153. /**
  23154. * Calculates and returns a vector composed of the cross product between
  23155. * two vectors. Both the static and non static methods return a new p5.Vector.
  23156. * See the examples for more context.
  23157. *
  23158. * @method cross
  23159. * @param {p5.Vector} v p5.Vector to be crossed
  23160. * @return {p5.Vector} p5.Vector composed of cross product
  23161. * @example
  23162. * <div class="norender">
  23163. * <code>
  23164. * var v1 = createVector(1, 2, 3);
  23165. * var v2 = createVector(1, 2, 3);
  23166. *
  23167. * v1.cross(v2); // v's components are [0, 0, 0]
  23168. * </code>
  23169. * </div>
  23170. *
  23171. * <div class="norender">
  23172. * <code>
  23173. * // Static method
  23174. * var v1 = createVector(1, 0, 0);
  23175. * var v2 = createVector(0, 1, 0);
  23176. *
  23177. * var crossProduct = p5.Vector.cross(v1, v2);
  23178. * // crossProduct has components [0, 0, 1]
  23179. * </code>
  23180. * </div>
  23181. */
  23182. p5.Vector.prototype.cross = function (v) {
  23183. var x = this.y * v.z - this.z * v.y;
  23184. var y = this.z * v.x - this.x * v.z;
  23185. var z = this.x * v.y - this.y * v.x;
  23186. if (this.p5) {
  23187. return new p5.Vector(this.p5,[x,y,z]);
  23188. } else {
  23189. return new p5.Vector(x,y,z);
  23190. }
  23191. };
  23192. /**
  23193. * Calculates the Euclidean distance between two points (considering a
  23194. * point as a vector object).
  23195. *
  23196. * @method dist
  23197. * @param {p5.Vector} v the x, y, and z coordinates of a p5.Vector
  23198. * @return {Number} the distance
  23199. * @example
  23200. * <div class="norender">
  23201. * <code>
  23202. * var v1 = createVector(1, 0, 0);
  23203. * var v2 = createVector(0, 1, 0);
  23204. *
  23205. * var distance = v1.dist(v2); // distance is 1.4142...
  23206. * </code>
  23207. * </div>
  23208. * <div class="norender">
  23209. * <code>
  23210. * // Static method
  23211. * var v1 = createVector(1, 0, 0);
  23212. * var v2 = createVector(0, 1, 0);
  23213. *
  23214. * var distance = p5.Vector.dist(v1,v2);
  23215. * // distance is 1.4142...
  23216. * </code>
  23217. * </div>
  23218. */
  23219. p5.Vector.prototype.dist = function (v) {
  23220. var d = v.copy().sub(this);
  23221. return d.mag();
  23222. };
  23223. /**
  23224. * Normalize the vector to length 1 (make it a unit vector).
  23225. *
  23226. * @method normalize
  23227. * @return {p5.Vector} normalized p5.Vector
  23228. * @example
  23229. * <div class="norender">
  23230. * <code>
  23231. * var v = createVector(10, 20, 2);
  23232. * // v has components [10.0, 20.0, 2.0]
  23233. * v.normalize();
  23234. * // v's components are set to
  23235. * // [0.4454354, 0.8908708, 0.089087084]
  23236. * </code>
  23237. * </div>
  23238. *
  23239. */
  23240. p5.Vector.prototype.normalize = function () {
  23241. return this.mag() === 0 ? this : this.div(this.mag());
  23242. };
  23243. /**
  23244. * Limit the magnitude of this vector to the value used for the <b>max</b>
  23245. * parameter.
  23246. *
  23247. * @method limit
  23248. * @param {Number} max the maximum magnitude for the vector
  23249. * @return {p5.Vector} the modified p5.Vector
  23250. * @example
  23251. * <div class="norender">
  23252. * <code>
  23253. * var v = createVector(10, 20, 2);
  23254. * // v has components [10.0, 20.0, 2.0]
  23255. * v.limit(5);
  23256. * // v's components are set to
  23257. * // [2.2271771, 4.4543543, 0.4454354]
  23258. * </code>
  23259. * </div>
  23260. */
  23261. p5.Vector.prototype.limit = function (max) {
  23262. var mSq = this.magSq();
  23263. if(mSq > max*max) {
  23264. this.div(Math.sqrt(mSq)); //normalize it
  23265. this.mult(max);
  23266. }
  23267. return this;
  23268. };
  23269. /**
  23270. * Set the magnitude of this vector to the value used for the <b>len</b>
  23271. * parameter.
  23272. *
  23273. * @method setMag
  23274. * @param {number} len the new length for this vector
  23275. * @return {p5.Vector} the modified p5.Vector
  23276. * @example
  23277. * <div class="norender">
  23278. * <code>
  23279. * var v = createVector(10, 20, 2);
  23280. * // v has components [10.0, 20.0, 2.0]
  23281. * v.setMag(10);
  23282. * // v's components are set to [6.0, 8.0, 0.0]
  23283. * </code>
  23284. * </div>
  23285. */
  23286. p5.Vector.prototype.setMag = function (n) {
  23287. return this.normalize().mult(n);
  23288. };
  23289. /**
  23290. * Calculate the angle of rotation for this vector (only 2D vectors)
  23291. *
  23292. * @method heading
  23293. * @return {Number} the angle of rotation
  23294. * @example
  23295. * <div class = "norender"><code>
  23296. * function setup() {
  23297. * var v1 = createVector(30,50);
  23298. * print(v1.heading()); // 1.0303768265243125
  23299. *
  23300. * var v1 = createVector(40,50);
  23301. * print(v1.heading()); // 0.8960553845713439
  23302. *
  23303. * var v1 = createVector(30,70);
  23304. * print(v1.heading()); // 1.1659045405098132
  23305. * }
  23306. * </div></code>
  23307. */
  23308. p5.Vector.prototype.heading = function () {
  23309. var h = Math.atan2(this.y, this.x);
  23310. if (this.p5) {
  23311. if (this.p5._angleMode === constants.RADIANS) {
  23312. return h;
  23313. } else {
  23314. return polarGeometry.radiansToDegrees(h);
  23315. }
  23316. } else {
  23317. return h;
  23318. }
  23319. };
  23320. /**
  23321. * Rotate the vector by an angle (only 2D vectors), magnitude remains the
  23322. * same
  23323. *
  23324. * @method rotate
  23325. * @param {number} angle the angle of rotation
  23326. * @return {p5.Vector} the modified p5.Vector
  23327. * @example
  23328. * <div class="norender">
  23329. * <code>
  23330. * var v = createVector(10.0, 20.0);
  23331. * // v has components [10.0, 20.0, 0.0]
  23332. * v.rotate(HALF_PI);
  23333. * // v's components are set to [-20.0, 9.999999, 0.0]
  23334. * </code>
  23335. * </div>
  23336. */
  23337. p5.Vector.prototype.rotate = function (a) {
  23338. var newHeading = this.heading() + a;
  23339. if (this.p5) {
  23340. if (this.p5._angleMode === constants.DEGREES) {
  23341. newHeading = polarGeometry.degreesToRadians(newHeading);
  23342. }
  23343. }
  23344. var mag = this.mag();
  23345. this.x = Math.cos(newHeading) * mag;
  23346. this.y = Math.sin(newHeading) * mag;
  23347. return this;
  23348. };
  23349. /**
  23350. * Linear interpolate the vector to another vector
  23351. *
  23352. * @method lerp
  23353. * @param {p5.Vector} x the x component or the p5.Vector to lerp to
  23354. * @param {p5.Vector} [y] y the y component
  23355. * @param {p5.Vector} [z] z the z component
  23356. * @param {Number} amt the amount of interpolation; some value between 0.0
  23357. * (old vector) and 1.0 (new vector). 0.1 is very near
  23358. * the new vector. 0.5 is halfway in between.
  23359. * @return {p5.Vector} the modified p5.Vector
  23360. * @example
  23361. * <div class="norender">
  23362. * <code>
  23363. * var v = createVector(1, 1, 0);
  23364. *
  23365. * v.lerp(3, 3, 0, 0.5); // v now has components [2,2,0]
  23366. * </code>
  23367. * </div>
  23368. *
  23369. * <div class="norender">
  23370. * <code>
  23371. * var v1 = createVector(0, 0, 0);
  23372. * var v2 = createVector(100, 100, 0);
  23373. *
  23374. * var v3 = p5.Vector.lerp(v1, v2, 0.5);
  23375. * // v3 has components [50,50,0]
  23376. * </code>
  23377. * </div>
  23378. */
  23379. p5.Vector.prototype.lerp = function (x, y, z, amt) {
  23380. if (x instanceof p5.Vector) {
  23381. return this.lerp(x.x, x.y, x.z, y);
  23382. }
  23383. this.x += (x - this.x) * amt || 0;
  23384. this.y += (y - this.y) * amt || 0;
  23385. this.z += (z - this.z) * amt || 0;
  23386. return this;
  23387. };
  23388. /**
  23389. * Return a representation of this vector as a float array. This is only
  23390. * for temporary use. If used in any other fashion, the contents should be
  23391. * copied by using the <b>p5.Vector.copy()</b> method to copy into your own
  23392. * array.
  23393. *
  23394. * @method array
  23395. * @return {Array} an Array with the 3 values
  23396. * @example
  23397. * <div class = "norender"><code>
  23398. * function setup() {
  23399. * var v = createVector(20,30);
  23400. * print(v.array()); // Prints : Array [20, 30, 0]
  23401. * }
  23402. * </div></code>
  23403. * <div class="norender">
  23404. * <code>
  23405. * var v = createVector(10.0, 20.0, 30.0);
  23406. * var f = v.array();
  23407. * print(f[0]); // Prints "10.0"
  23408. * print(f[1]); // Prints "20.0"
  23409. * print(f[2]); // Prints "30.0"
  23410. * </code>
  23411. * </div>
  23412. */
  23413. p5.Vector.prototype.array = function () {
  23414. return [this.x || 0, this.y || 0, this.z || 0];
  23415. };
  23416. /**
  23417. * Equality check against a p5.Vector
  23418. *
  23419. * @method equals
  23420. * @param {Number|p5.Vector|Array} [x] the x component of the vector or a
  23421. * p5.Vector or an Array
  23422. * @param {Number} [y] the y component of the vector
  23423. * @param {Number} [z] the z component of the vector
  23424. * @return {Boolean} whether the vectors are equals
  23425. * @example
  23426. * <div class = "norender"><code>
  23427. * v1 = createVector(5,10,20);
  23428. * v2 = createVector(5,10,20);
  23429. * v3 = createVector(13,10,19);
  23430. *
  23431. * print(v1.equals(v2.x,v2.y,v2.z)); // true
  23432. * print(v1.equals(v3.x,v3.y,v3.z)); // false
  23433. * </div></code>
  23434. * <div class="norender">
  23435. * <code>
  23436. * var v1 = createVector(10.0, 20.0, 30.0);
  23437. * var v2 = createVector(10.0, 20.0, 30.0);
  23438. * var v3 = createVector(0.0, 0.0, 0.0);
  23439. * print (v1.equals(v2)) // true
  23440. * print (v1.equals(v3)) // false
  23441. * </code>
  23442. * </div>
  23443. */
  23444. p5.Vector.prototype.equals = function (x, y, z) {
  23445. var a, b, c;
  23446. if (x instanceof p5.Vector) {
  23447. a = x.x || 0;
  23448. b = x.y || 0;
  23449. c = x.z || 0;
  23450. } else if (x instanceof Array) {
  23451. a = x[0] || 0;
  23452. b = x[1] || 0;
  23453. c = x[2] || 0;
  23454. } else {
  23455. a = x || 0;
  23456. b = y || 0;
  23457. c = z || 0;
  23458. }
  23459. return this.x === a && this.y === b && this.z === c;
  23460. };
  23461. // Static Methods
  23462. /**
  23463. * Make a new 2D unit vector from an angle
  23464. *
  23465. * @method fromAngle
  23466. * @static
  23467. * @param {Number} angle the desired angle
  23468. * @return {p5.Vector} the new p5.Vector object
  23469. * @example
  23470. * <div>
  23471. * <code>
  23472. * function draw() {
  23473. * background (200);
  23474. *
  23475. * // Create a variable, proportional to the mouseX,
  23476. * // varying from 0-360, to represent an angle in degrees.
  23477. * angleMode(DEGREES);
  23478. * var myDegrees = map(mouseX, 0,width, 0,360);
  23479. *
  23480. * // Display that variable in an onscreen text.
  23481. * // (Note the nfc() function to truncate additional decimal places,
  23482. * // and the "\xB0" character for the degree symbol.)
  23483. * var readout = "angle = " + nfc(myDegrees,1,1) + "\xB0"
  23484. * noStroke();
  23485. * fill (0);
  23486. * text (readout, 5, 15);
  23487. *
  23488. * // Create a p5.Vector using the fromAngle function,
  23489. * // and extract its x and y components.
  23490. * var v = p5.Vector.fromAngle(radians(myDegrees));
  23491. * var vx = v.x;
  23492. * var vy = v.y;
  23493. *
  23494. * push();
  23495. * translate (width/2, height/2);
  23496. * noFill();
  23497. * stroke (150);
  23498. * line (0,0, 30,0);
  23499. * stroke (0);
  23500. * line (0,0, 30*vx, 30*vy);
  23501. * pop()
  23502. * }
  23503. * </code>
  23504. * </div>
  23505. */
  23506. p5.Vector.fromAngle = function(angle) {
  23507. if (this.p5) {
  23508. if (this.p5._angleMode === constants.DEGREES) {
  23509. angle = polarGeometry.degreesToRadians(angle);
  23510. }
  23511. }
  23512. if (this.p5) {
  23513. return new p5.Vector(this.p5,[Math.cos(angle),Math.sin(angle),0]);
  23514. } else {
  23515. return new p5.Vector(Math.cos(angle),Math.sin(angle),0);
  23516. }
  23517. };
  23518. /**
  23519. * Make a new 2D unit vector from a random angle
  23520. *
  23521. * @method random2D
  23522. * @static
  23523. * @return {p5.Vector} the new p5.Vector object
  23524. * @example
  23525. * <div class="norender">
  23526. * <code>
  23527. * var v = p5.Vector.random2D();
  23528. * // May make v's attributes something like:
  23529. * // [0.61554617, -0.51195765, 0.0] or
  23530. * // [-0.4695841, -0.14366731, 0.0] or
  23531. * // [0.6091097, -0.22805278, 0.0]
  23532. * </code>
  23533. * </div>
  23534. */
  23535. p5.Vector.random2D = function () {
  23536. var angle;
  23537. // A lot of nonsense to determine if we know about a
  23538. // p5 sketch and whether we should make a random angle in degrees or radians
  23539. if (this.p5) {
  23540. if (this.p5._angleMode === constants.DEGREES) {
  23541. angle = this.p5.random(360);
  23542. } else {
  23543. angle = this.p5.random(constants.TWO_PI);
  23544. }
  23545. } else {
  23546. angle = Math.random()*Math.PI*2;
  23547. }
  23548. return this.fromAngle(angle);
  23549. };
  23550. /**
  23551. * Make a new random 3D unit vector.
  23552. *
  23553. * @method random3D
  23554. * @static
  23555. * @return {p5.Vector} the new p5.Vector object
  23556. * @example
  23557. * <div class="norender">
  23558. * <code>
  23559. * var v = p5.Vector.random3D();
  23560. * // May make v's attributes something like:
  23561. * // [0.61554617, -0.51195765, 0.599168] or
  23562. * // [-0.4695841, -0.14366731, -0.8711202] or
  23563. * // [0.6091097, -0.22805278, -0.7595902]
  23564. * </code>
  23565. * </div>
  23566. */
  23567. p5.Vector.random3D = function () {
  23568. var angle,vz;
  23569. // If we know about p5
  23570. if (this.p5) {
  23571. angle = this.p5.random(0,constants.TWO_PI);
  23572. vz = this.p5.random(-1,1);
  23573. } else {
  23574. angle = Math.random()*Math.PI*2;
  23575. vz = Math.random()*2-1;
  23576. }
  23577. var vx = Math.sqrt(1-vz*vz)*Math.cos(angle);
  23578. var vy = Math.sqrt(1-vz*vz)*Math.sin(angle);
  23579. if (this.p5) {
  23580. return new p5.Vector(this.p5,[vx,vy,vz]);
  23581. } else {
  23582. return new p5.Vector(vx,vy,vz);
  23583. }
  23584. };
  23585. /**
  23586. * Adds two vectors together and returns a new one.
  23587. *
  23588. * @static
  23589. * @param {p5.Vector} v1 a p5.Vector to add
  23590. * @param {p5.Vector} v2 a p5.Vector to add
  23591. * @param {p5.Vector} target if undefined a new vector will be created
  23592. * @return {p5.Vector} the resulting p5.Vector
  23593. *
  23594. */
  23595. p5.Vector.add = function (v1, v2, target) {
  23596. if (!target) {
  23597. target = v1.copy();
  23598. } else {
  23599. target.set(v1);
  23600. }
  23601. target.add(v2);
  23602. return target;
  23603. };
  23604. /**
  23605. * Subtracts one p5.Vector from another and returns a new one. The second
  23606. * vector (v2) is subtracted from the first (v1), resulting in v1-v2.
  23607. *
  23608. * @static
  23609. * @param {p5.Vector} v1 a p5.Vector to subtract from
  23610. * @param {p5.Vector} v2 a p5.Vector to subtract
  23611. * @param {p5.Vector} target if undefined a new vector will be created
  23612. * @return {p5.Vector} the resulting p5.Vector
  23613. */
  23614. p5.Vector.sub = function (v1, v2, target) {
  23615. if (!target) {
  23616. target = v1.copy();
  23617. } else {
  23618. target.set(v1);
  23619. }
  23620. target.sub(v2);
  23621. return target;
  23622. };
  23623. /**
  23624. * Multiplies a vector by a scalar and returns a new vector.
  23625. *
  23626. * @static
  23627. * @param {p5.Vector} v the p5.Vector to multiply
  23628. * @param {Number} n the scalar
  23629. * @param {p5.Vector} target if undefined a new vector will be created
  23630. * @return {p5.Vector} the resulting new p5.Vector
  23631. */
  23632. p5.Vector.mult = function (v, n, target) {
  23633. if (!target) {
  23634. target = v.copy();
  23635. } else {
  23636. target.set(v);
  23637. }
  23638. target.mult(n);
  23639. return target;
  23640. };
  23641. /**
  23642. * Divides a vector by a scalar and returns a new vector.
  23643. *
  23644. * @static
  23645. * @param {p5.Vector} v the p5.Vector to divide
  23646. * @param {Number} n the scalar
  23647. * @param {p5.Vector} target if undefined a new vector will be created
  23648. * @return {p5.Vector} the resulting new p5.Vector
  23649. */
  23650. p5.Vector.div = function (v, n, target) {
  23651. if (!target) {
  23652. target = v.copy();
  23653. } else {
  23654. target.set(v);
  23655. }
  23656. target.div(n);
  23657. return target;
  23658. };
  23659. /**
  23660. * Calculates the dot product of two vectors.
  23661. *
  23662. * @static
  23663. * @param {p5.Vector} v1 the first p5.Vector
  23664. * @param {p5.Vector} v2 the second p5.Vector
  23665. * @return {Number} the dot product
  23666. */
  23667. p5.Vector.dot = function (v1, v2) {
  23668. return v1.dot(v2);
  23669. };
  23670. /**
  23671. * Calculates the cross product of two vectors.
  23672. *
  23673. * @static
  23674. * @param {p5.Vector} v1 the first p5.Vector
  23675. * @param {p5.Vector} v2 the second p5.Vector
  23676. * @return {Number} the cross product
  23677. */
  23678. p5.Vector.cross = function (v1, v2) {
  23679. return v1.cross(v2);
  23680. };
  23681. /**
  23682. * Calculates the Euclidean distance between two points (considering a
  23683. * point as a vector object).
  23684. *
  23685. * @static
  23686. * @param {p5.Vector} v1 the first p5.Vector
  23687. * @param {p5.Vector} v2 the second p5.Vector
  23688. * @return {Number} the distance
  23689. */
  23690. p5.Vector.dist = function (v1,v2) {
  23691. return v1.dist(v2);
  23692. };
  23693. /**
  23694. * Linear interpolate a vector to another vector and return the result as a
  23695. * new vector.
  23696. *
  23697. * @static
  23698. * @param {p5.Vector} v1 a starting p5.Vector
  23699. * @param {p5.Vector} v2 the p5.Vector to lerp to
  23700. * @param {Number} the amount of interpolation; some value between 0.0
  23701. * (old vector) and 1.0 (new vector). 0.1 is very near
  23702. * the new vector. 0.5 is halfway in between.
  23703. */
  23704. p5.Vector.lerp = function (v1, v2, amt, target) {
  23705. if (!target) {
  23706. target = v1.copy();
  23707. } else {
  23708. target.set(v1);
  23709. }
  23710. target.lerp(v2, amt);
  23711. return target;
  23712. };
  23713. /**
  23714. * Calculates and returns the angle (in radians) between two vectors.
  23715. * @method angleBetween
  23716. * @static
  23717. * @param {p5.Vector} v1 the x, y, and z components of a p5.Vector
  23718. * @param {p5.Vector} v2 the x, y, and z components of a p5.Vector
  23719. * @return {Number} the angle between (in radians)
  23720. * @example
  23721. * <div class="norender">
  23722. * <code>
  23723. * var v1 = createVector(1, 0, 0);
  23724. * var v2 = createVector(0, 1, 0);
  23725. *
  23726. * var angle = p5.Vector.angleBetween(v1, v2);
  23727. * // angle is PI/2
  23728. * </code>
  23729. * </div>
  23730. */
  23731. p5.Vector.angleBetween = function (v1, v2) {
  23732. var angle = Math.acos(v1.dot(v2) / (v1.mag() * v2.mag()));
  23733. if (this.p5) {
  23734. if (this.p5._angleMode === constants.DEGREES) {
  23735. angle = polarGeometry.radiansToDegrees(angle);
  23736. }
  23737. }
  23738. return angle;
  23739. };
  23740. /**
  23741. * @static
  23742. */
  23743. p5.Vector.mag = function (vecT){
  23744. var x = vecT.x,
  23745. y = vecT.y,
  23746. z = vecT.z;
  23747. var magSq = x * x + y * y + z * z;
  23748. return Math.sqrt(magSq);
  23749. };
  23750. module.exports = p5.Vector;
  23751. },{"../core/constants":36,"../core/core":37,"./polargeometry":67}],67:[function(_dereq_,module,exports){
  23752. module.exports = {
  23753. degreesToRadians: function(x) {
  23754. return 2 * Math.PI * x / 360;
  23755. },
  23756. radiansToDegrees: function(x) {
  23757. return 360 * x / (2 * Math.PI);
  23758. }
  23759. };
  23760. },{}],68:[function(_dereq_,module,exports){
  23761. /**
  23762. * @module Math
  23763. * @submodule Random
  23764. * @for p5
  23765. * @requires core
  23766. */
  23767. 'use strict';
  23768. var p5 = _dereq_('../core/core');
  23769. var seeded = false;
  23770. var previous = false;
  23771. var y2 = 0;
  23772. // Linear Congruential Generator
  23773. // Variant of a Lehman Generator
  23774. var lcg = (function() {
  23775. // Set to values from http://en.wikipedia.org/wiki/Numerical_Recipes
  23776. // m is basically chosen to be large (as it is the max period)
  23777. // and for its relationships to a and c
  23778. var m = 4294967296,
  23779. // a - 1 should be divisible by m's prime factors
  23780. a = 1664525,
  23781. // c and m should be co-prime
  23782. c = 1013904223,
  23783. seed, z;
  23784. return {
  23785. setSeed : function(val) {
  23786. // pick a random seed if val is undefined or null
  23787. // the >>> 0 casts the seed to an unsigned 32-bit integer
  23788. z = seed = (val == null ? Math.random() * m : val) >>> 0;
  23789. },
  23790. getSeed : function() {
  23791. return seed;
  23792. },
  23793. rand : function() {
  23794. // define the recurrence relationship
  23795. z = (a * z + c) % m;
  23796. // return a float in [0, 1)
  23797. // if z = m then z / m = 0 therefore (z % m) / m < 1 always
  23798. return z / m;
  23799. }
  23800. };
  23801. }());
  23802. /**
  23803. * Sets the seed value for random().
  23804. *
  23805. * By default, random() produces different results each time the program
  23806. * is run. Set the seed parameter to a constant to return the same
  23807. * pseudo-random numbers each time the software is run.
  23808. *
  23809. * @method randomSeed
  23810. * @param {Number} seed the seed value
  23811. * @example
  23812. * <div>
  23813. * <code>
  23814. * randomSeed(99);
  23815. * for (var i=0; i < 100; i++) {
  23816. * var r = random(0, 255);
  23817. * stroke(r);
  23818. * line(i, 0, i, 100);
  23819. * }
  23820. * </code>
  23821. * </div>
  23822. *
  23823. * @alt
  23824. * many vertical lines drawn in white, black or grey.
  23825. *
  23826. */
  23827. p5.prototype.randomSeed = function(seed) {
  23828. lcg.setSeed(seed);
  23829. seeded = true;
  23830. previous = false;
  23831. };
  23832. /**
  23833. * Return a random floating-point number.
  23834. *
  23835. * Takes either 0, 1 or 2 arguments.
  23836. *
  23837. * If no argument is given, returns a random number from 0
  23838. * up to (but not including) 1.
  23839. *
  23840. * If one argument is given and it is a number, returns a random number from 0
  23841. * up to (but not including) the number.
  23842. *
  23843. * If one argument is given and it is an array, returns a random element from
  23844. * that array.
  23845. *
  23846. * If two arguments are given, returns a random number from the
  23847. * first argument up to (but not including) the second argument.
  23848. *
  23849. * @method random
  23850. * @param {Number} [min] the lower bound (inclusive)
  23851. * @param {Number} [max] the upper bound (exclusive)
  23852. * @return {Number|mixed} the random number or a random element in choices
  23853. * @example
  23854. * <div>
  23855. * <code>
  23856. * for (var i = 0; i < 100; i++) {
  23857. * var r = random(50);
  23858. * stroke(r*5);
  23859. * line(50, i, 50+r, i);
  23860. * }
  23861. * </code>
  23862. * </div>
  23863. * <div>
  23864. * <code>
  23865. * for (var i = 0; i < 100; i++) {
  23866. * var r = random(-50, 50);
  23867. * line(50,i,50+r,i);
  23868. * }
  23869. * </code>
  23870. * </div>
  23871. * <div>
  23872. * <code>
  23873. * // Get a random element from an array using the random(Array) syntax
  23874. * var words = [ "apple", "bear", "cat", "dog" ];
  23875. * var word = random(words); // select random word
  23876. * text(word,10,50); // draw the word
  23877. * </code>
  23878. * </div>
  23879. *
  23880. * @alt
  23881. * 100 horizontal lines from center canvas to right. size+fill change each time
  23882. * 100 horizontal lines from center of canvas. height & side change each render
  23883. * word displayed at random. Either apple, bear, cat, or dog
  23884. *
  23885. */
  23886. /**
  23887. * @method random
  23888. * @param {Array} choices the array to choose from
  23889. * @return {mixed} the random element from the array
  23890. * @example
  23891. */
  23892. p5.prototype.random = function (min, max) {
  23893. var rand;
  23894. if (seeded) {
  23895. rand = lcg.rand();
  23896. } else {
  23897. rand = Math.random();
  23898. }
  23899. if (typeof min === 'undefined') {
  23900. return rand;
  23901. } else
  23902. if (typeof max === 'undefined') {
  23903. if (min instanceof Array) {
  23904. return min[Math.floor(rand * min.length)];
  23905. } else {
  23906. return rand * min;
  23907. }
  23908. } else {
  23909. if (min > max) {
  23910. var tmp = min;
  23911. min = max;
  23912. max = tmp;
  23913. }
  23914. return rand * (max-min) + min;
  23915. }
  23916. };
  23917. /**
  23918. *
  23919. * Returns a random number fitting a Gaussian, or
  23920. * normal, distribution. There is theoretically no minimum or maximum
  23921. * value that randomGaussian() might return. Rather, there is
  23922. * just a very low probability that values far from the mean will be
  23923. * returned; and a higher probability that numbers near the mean will
  23924. * be returned.
  23925. * <br><br>
  23926. * Takes either 0, 1 or 2 arguments.<br>
  23927. * If no args, returns a mean of 0 and standard deviation of 1.<br>
  23928. * If one arg, that arg is the mean (standard deviation is 1).<br>
  23929. * If two args, first is mean, second is standard deviation.
  23930. *
  23931. * @method randomGaussian
  23932. * @param {Number} mean the mean
  23933. * @param {Number} sd the standard deviation
  23934. * @return {Number} the random number
  23935. * @example
  23936. * <div>
  23937. * <code>for (var y = 0; y < 100; y++) {
  23938. * var x = randomGaussian(50,15);
  23939. * line(50, y, x, y);
  23940. *}
  23941. * </code>
  23942. * </div>
  23943. * <div>
  23944. * <code>
  23945. *var distribution = new Array(360);
  23946. *
  23947. *function setup() {
  23948. * createCanvas(100, 100);
  23949. * for (var i = 0; i < distribution.length; i++) {
  23950. * distribution[i] = floor(randomGaussian(0,15));
  23951. * }
  23952. *}
  23953. *
  23954. *function draw() {
  23955. * background(204);
  23956. *
  23957. * translate(width/2, width/2);
  23958. *
  23959. * for (var i = 0; i < distribution.length; i++) {
  23960. * rotate(TWO_PI/distribution.length);
  23961. * stroke(0);
  23962. * var dist = abs(distribution[i]);
  23963. * line(0, 0, dist, 0);
  23964. * }
  23965. *}
  23966. * </code>
  23967. * </div>
  23968. * @alt
  23969. * 100 horizontal lines from center of canvas. height & side change each render
  23970. * black lines radiate from center of canvas. size determined each render
  23971. */
  23972. p5.prototype.randomGaussian = function(mean, sd) {
  23973. var y1,x1,x2,w;
  23974. if (previous) {
  23975. y1 = y2;
  23976. previous = false;
  23977. } else {
  23978. do {
  23979. x1 = this.random(2) - 1;
  23980. x2 = this.random(2) - 1;
  23981. w = x1 * x1 + x2 * x2;
  23982. } while (w >= 1);
  23983. w = Math.sqrt((-2 * Math.log(w))/w);
  23984. y1 = x1 * w;
  23985. y2 = x2 * w;
  23986. previous = true;
  23987. }
  23988. var m = mean || 0;
  23989. var s = sd || 1;
  23990. return y1*s + m;
  23991. };
  23992. module.exports = p5;
  23993. },{"../core/core":37}],69:[function(_dereq_,module,exports){
  23994. /**
  23995. * @module Math
  23996. * @submodule Trigonometry
  23997. * @for p5
  23998. * @requires core
  23999. * @requires polargeometry
  24000. * @requires constants
  24001. */
  24002. 'use strict';
  24003. var p5 = _dereq_('../core/core');
  24004. var polarGeometry = _dereq_('./polargeometry');
  24005. var constants = _dereq_('../core/constants');
  24006. p5.prototype._angleMode = constants.RADIANS;
  24007. /**
  24008. * The inverse of cos(), returns the arc cosine of a value. This function
  24009. * expects the values in the range of -1 to 1 and values are returned in
  24010. * the range 0 to PI (3.1415927).
  24011. *
  24012. * @method acos
  24013. * @param {Number} value the value whose arc cosine is to be returned
  24014. * @return {Number} the arc cosine of the given value
  24015. *
  24016. * @example
  24017. * <div class= “norender">
  24018. * <code>
  24019. * var a = PI;
  24020. * var c = cos(a);
  24021. * var ac = acos(c);
  24022. * // Prints: "3.1415927 : -1.0 : 3.1415927"
  24023. * print(a + " : " + c + " : " + ac);
  24024. * </code>
  24025. * </div>
  24026. *
  24027. * <div class= “norender">
  24028. * <code>
  24029. * var a = PI + PI/4.0;
  24030. * var c = cos(a);
  24031. * var ac = acos(c);
  24032. * // Prints: "3.926991 : -0.70710665 : 2.3561943"
  24033. * print(a + " : " + c + " : " + ac);
  24034. * </code>
  24035. * </div>
  24036. */
  24037. p5.prototype.acos = function(ratio) {
  24038. if (this._angleMode === constants.RADIANS) {
  24039. return Math.acos(ratio);
  24040. } else {
  24041. return polarGeometry.radiansToDegrees(Math.acos(ratio));
  24042. }
  24043. };
  24044. /**
  24045. * The inverse of sin(), returns the arc sine of a value. This function
  24046. * expects the values in the range of -1 to 1 and values are returned
  24047. * in the range -PI/2 to PI/2.
  24048. *
  24049. * @method asin
  24050. * @param {Number} value the value whose arc sine is to be returned
  24051. * @return {Number} the arc sine of the given value
  24052. *
  24053. * @example
  24054. * <div class= “norender">
  24055. * <code>
  24056. * var a = PI + PI/3;
  24057. * var s = sin(a);
  24058. * var as = asin(s);
  24059. * // Prints: "1.0471976 : 0.86602545 : 1.0471976"
  24060. * print(a + " : " + s + " : " + as);
  24061. * </code>
  24062. * </div>
  24063. *
  24064. * <div class= “norender">
  24065. * <code>
  24066. * var a = PI + PI/3.0;
  24067. * var s = sin(a);
  24068. * var as = asin(s);
  24069. * // Prints: "4.1887903 : -0.86602545 : -1.0471976"
  24070. * print(a + " : " + s + " : " + as);
  24071. * </code>
  24072. * </div>
  24073. *
  24074. */
  24075. p5.prototype.asin = function(ratio) {
  24076. if (this._angleMode === constants.RADIANS) {
  24077. return Math.asin(ratio);
  24078. } else {
  24079. return polarGeometry.radiansToDegrees(Math.asin(ratio));
  24080. }
  24081. };
  24082. /**
  24083. * The inverse of tan(), returns the arc tangent of a value. This function
  24084. * expects the values in the range of -Infinity to Infinity (exclusive) and
  24085. * values are returned in the range -PI/2 to PI/2.
  24086. *
  24087. * @method atan
  24088. * @param {Number} value the value whose arc tangent is to be returned
  24089. * @return {Number} the arc tangent of the given value
  24090. *
  24091. * @example
  24092. * <div class= “norender">
  24093. * <code>
  24094. * var a = PI + PI/3;
  24095. * var t = tan(a);
  24096. * var at = atan(t);
  24097. * // Prints: "1.0471976 : 1.7320509 : 1.0471976"
  24098. * print(a + " : " + t + " : " + at);
  24099. * </code>
  24100. * </div>
  24101. *
  24102. * <div class= “norender">
  24103. * <code>
  24104. * var a = PI + PI/3.0;
  24105. * var t = tan(a);
  24106. * var at = atan(t);
  24107. * // Prints: "4.1887903 : 1.7320513 : 1.0471977"
  24108. * print(a + " : " + t + " : " + at);
  24109. * </code>
  24110. * </div>
  24111. *
  24112. */
  24113. p5.prototype.atan = function(ratio) {
  24114. if (this._angleMode === constants.RADIANS) {
  24115. return Math.atan(ratio);
  24116. } else {
  24117. return polarGeometry.radiansToDegrees(Math.atan(ratio));
  24118. }
  24119. };
  24120. /**
  24121. * Calculates the angle (in radians) from a specified point to the coordinate
  24122. * origin as measured from the positive x-axis. Values are returned as a
  24123. * float in the range from PI to -PI. The atan2() function is most often used
  24124. * for orienting geometry to the position of the cursor.
  24125. * <br><br>
  24126. * Note: The y-coordinate of the point is the first parameter, and the
  24127. * x-coordinate is the second parameter, due the the structure of calculating
  24128. * the tangent.
  24129. *
  24130. * @method atan2
  24131. * @param {Number} y y-coordinate of the point
  24132. * @param {Number} x x-coordinate of the point
  24133. * @return {Number} the arc tangent of the given point
  24134. *
  24135. * @example
  24136. * <div>
  24137. * <code>
  24138. * function draw() {
  24139. * background(204);
  24140. * translate(width/2, height/2);
  24141. * var a = atan2(mouseY-height/2, mouseX-width/2);
  24142. * rotate(a);
  24143. * rect(-30, -5, 60, 10);
  24144. * }
  24145. * </code>
  24146. * </div>
  24147. *
  24148. * @alt
  24149. * 60 by 10 rect at center of canvas rotates with mouse movements
  24150. *
  24151. */
  24152. p5.prototype.atan2 = function (y, x) {
  24153. if (this._angleMode === constants.RADIANS) {
  24154. return Math.atan2(y, x);
  24155. } else {
  24156. return polarGeometry.radiansToDegrees(Math.atan2(y, x));
  24157. }
  24158. };
  24159. /**
  24160. * Calculates the cosine of an angle. This function takes into account the
  24161. * current angleMode. Values are returned in the range -1 to 1.
  24162. *
  24163. * @method cos
  24164. * @param {Number} angle the angle
  24165. * @return {Number} the cosine of the angle
  24166. *
  24167. * @example
  24168. * <div>
  24169. * <code>
  24170. * var a = 0.0;
  24171. * var inc = TWO_PI/25.0;
  24172. * for (var i = 0; i < 25; i++) {
  24173. * line(i*4, 50, i*4, 50+cos(a)*40.0);
  24174. * a = a + inc;
  24175. * }
  24176. * </code>
  24177. * </div>
  24178. *
  24179. * @alt
  24180. * vertical black lines form wave patterns, extend-down on left and right side
  24181. *
  24182. */
  24183. p5.prototype.cos = function(angle) {
  24184. if (this._angleMode === constants.RADIANS) {
  24185. return Math.cos(angle);
  24186. } else {
  24187. return Math.cos(this.radians(angle));
  24188. }
  24189. };
  24190. /**
  24191. * Calculates the sine of an angle. This function takes into account the
  24192. * current angleMode. Values are returned in the range -1 to 1.
  24193. *
  24194. * @method sin
  24195. * @param {Number} angle the angle
  24196. * @return {Number} the sine of the angle
  24197. *
  24198. * @example
  24199. * <div>
  24200. * <code>
  24201. * var a = 0.0;
  24202. * var inc = TWO_PI/25.0;
  24203. * for (var i = 0; i < 25; i++) {
  24204. * line(i*4, 50, i*4, 50+sin(a)*40.0);
  24205. * a = a + inc;
  24206. * }
  24207. * </code>
  24208. * </div>
  24209. *
  24210. * @alt
  24211. * vertical black lines extend down and up from center to form wave pattern
  24212. *
  24213. */
  24214. p5.prototype.sin = function(angle) {
  24215. if (this._angleMode === constants.RADIANS) {
  24216. return Math.sin(angle);
  24217. } else {
  24218. return Math.sin(this.radians(angle));
  24219. }
  24220. };
  24221. /**
  24222. * Calculates the tangent of an angle. This function takes into account
  24223. * the current angleMode. Values are returned in the range -1 to 1.
  24224. *
  24225. * @method tan
  24226. * @param {Number} angle the angle
  24227. * @return {Number} the tangent of the angle
  24228. *
  24229. * @example
  24230. * <div>
  24231. * <code>
  24232. * var a = 0.0;
  24233. * var inc = TWO_PI/50.0;
  24234. * for (var i = 0; i < 100; i = i+2) {
  24235. * line(i, 50, i, 50+tan(a)*2.0);
  24236. * a = a + inc;
  24237. * }
  24238. * </code>
  24239. *
  24240. *
  24241. * @alt
  24242. * vertical black lines end down and up from center to form spike pattern
  24243. *
  24244. */
  24245. p5.prototype.tan = function(angle) {
  24246. if (this._angleMode === constants.RADIANS) {
  24247. return Math.tan(angle);
  24248. } else {
  24249. return Math.tan(this.radians(angle));
  24250. }
  24251. };
  24252. /**
  24253. * Converts a radian measurement to its corresponding value in degrees.
  24254. * Radians and degrees are two ways of measuring the same thing. There are
  24255. * 360 degrees in a circle and 2*PI radians in a circle. For example,
  24256. * 90° = PI/2 = 1.5707964.
  24257. *
  24258. * @method degrees
  24259. * @param {Number} radians the radians value to convert to degrees
  24260. * @return {Number} the converted angle
  24261. *
  24262. *
  24263. * @example
  24264. * <div class= “norender">
  24265. * <code>
  24266. * var rad = PI/4;
  24267. * var deg = degrees(rad);
  24268. * print(rad + " radians is " + deg + " degrees");
  24269. * // Prints: 0.7853981633974483 radians is 45 degrees
  24270. * </code>
  24271. * </div>
  24272. *
  24273. */
  24274. p5.prototype.degrees = function(angle) {
  24275. return polarGeometry.radiansToDegrees(angle);
  24276. };
  24277. /**
  24278. * Converts a degree measurement to its corresponding value in radians.
  24279. * Radians and degrees are two ways of measuring the same thing. There are
  24280. * 360 degrees in a circle and 2*PI radians in a circle. For example,
  24281. * 90° = PI/2 = 1.5707964.
  24282. *
  24283. * @method radians
  24284. * @param {Number} degrees the degree value to convert to radians
  24285. * @return {Number} the converted angle
  24286. *
  24287. * @example
  24288. * <div class= “norender">
  24289. * <code>
  24290. * var deg = 45.0;
  24291. * var rad = radians(deg);
  24292. * print(deg + " degrees is " + rad + " radians");
  24293. * // Prints: 45 degrees is 0.7853981633974483 radians
  24294. * </code>
  24295. * </div>
  24296. */
  24297. p5.prototype.radians = function(angle) {
  24298. return polarGeometry.degreesToRadians(angle);
  24299. };
  24300. /**
  24301. * Sets the current mode of p5 to given mode. Default mode is RADIANS.
  24302. *
  24303. * @method angleMode
  24304. * @param {Constant} mode either RADIANS or DEGREES
  24305. *
  24306. * @example
  24307. * <div>
  24308. * <code>
  24309. * function draw(){
  24310. * background(204);
  24311. * angleMode(DEGREES); // Change the mode to DEGREES
  24312. * var a = atan2(mouseY-height/2, mouseX-width/2);
  24313. * translate(width/2, height/2);
  24314. * push();
  24315. * rotate(a);
  24316. * rect(-20, -5, 40, 10); // Larger rectangle is rotating in degrees
  24317. * pop();
  24318. * angleMode(RADIANS); // Change the mode to RADIANS
  24319. * rotate(a); // var a stays the same
  24320. * rect(-40, -5, 20, 10); // Smaller rectangle is rotating in radians
  24321. * }
  24322. * </code>
  24323. * </div>
  24324. *
  24325. * @alt
  24326. * 40 by 10 rect in center rotates with mouse moves. 20 by 10 rect moves faster.
  24327. *
  24328. *
  24329. */
  24330. p5.prototype.angleMode = function(mode) {
  24331. if (mode === constants.DEGREES || mode === constants.RADIANS) {
  24332. this._angleMode = mode;
  24333. }
  24334. };
  24335. module.exports = p5;
  24336. },{"../core/constants":36,"../core/core":37,"./polargeometry":67}],70:[function(_dereq_,module,exports){
  24337. /**
  24338. * @module Typography
  24339. * @submodule Attributes
  24340. * @for p5
  24341. * @requires core
  24342. * @requires constants
  24343. */
  24344. 'use strict';
  24345. var p5 = _dereq_('../core/core');
  24346. /**
  24347. * Sets the current alignment for drawing text. Accepts two
  24348. * arguments: horizAlign (LEFT, CENTER, or RIGHT) and
  24349. * vertAlign (TOP, BOTTOM, CENTER, or BASELINE).
  24350. *
  24351. * The horizAlign parameter is in reference to the x value
  24352. * of the text() function, while the vertAlign parameter is
  24353. * in reference to the y value.
  24354. *
  24355. * So if you write textAlign(LEFT), you are aligning the left
  24356. * edge of your text to the x value you give in text(). If you
  24357. * write textAlign(RIGHT, TOP), you are aligning the right edge
  24358. * of your text to the x value and the top of edge of the text
  24359. * to the y value.
  24360. *
  24361. * @method textAlign
  24362. * @param {Constant} horizAlign horizontal alignment, either LEFT,
  24363. * CENTER, or RIGHT
  24364. * @param {Constant} vertAlign vertical alignment, either TOP,
  24365. * BOTTOM, CENTER, or BASELINE
  24366. * @return {Number}
  24367. * @example
  24368. * <div>
  24369. * <code>
  24370. * textSize(16);
  24371. * textAlign(RIGHT);
  24372. * text("ABCD", 50, 30);
  24373. * textAlign(CENTER);
  24374. * text("EFGH", 50, 50);
  24375. * textAlign(LEFT);
  24376. * text("IJKL", 50, 70);
  24377. * </code>
  24378. * </div>
  24379. *
  24380. * @alt
  24381. *Letters ABCD displayed at top right, EFGH at center and IJKL at bottom left.
  24382. *
  24383. */
  24384. p5.prototype.textAlign = function(horizAlign, vertAlign) {
  24385. return this._renderer.textAlign.apply(this._renderer, arguments);
  24386. };
  24387. /**
  24388. * Sets/gets the spacing, in pixels, between lines of text. This
  24389. * setting will be used in all subsequent calls to the text() function.
  24390. *
  24391. * @method textLeading
  24392. * @param {Number} leading the size in pixels for spacing between lines
  24393. * @return {Object|Number}
  24394. * @example
  24395. * <div>
  24396. * <code>
  24397. * // Text to display. The "\n" is a "new line" character
  24398. * lines = "L1\nL2\nL3";
  24399. * textSize(12);
  24400. *
  24401. * textLeading(10); // Set leading to 10
  24402. * text(lines, 10, 25);
  24403. *
  24404. * textLeading(20); // Set leading to 20
  24405. * text(lines, 40, 25);
  24406. *
  24407. * textLeading(30); // Set leading to 30
  24408. * text(lines, 70, 25);
  24409. * </code>
  24410. * </div>
  24411. *
  24412. * @alt
  24413. *set L1 L2 & L3 displayed vertically 3 times. spacing increases for each set
  24414. *
  24415. */
  24416. p5.prototype.textLeading = function(theLeading) {
  24417. return this._renderer.textLeading.apply(this._renderer, arguments);
  24418. };
  24419. /**
  24420. * Sets/gets the current font size. This size will be used in all subsequent
  24421. * calls to the text() function. Font size is measured in pixels.
  24422. *
  24423. * @method textSize
  24424. * @param {Number} theSize the size of the letters in units of pixels
  24425. * @return {Object|Number}
  24426. * @example
  24427. * <div>
  24428. * <code>
  24429. * textSize(12);
  24430. * text("Font Size 12", 10, 30);
  24431. * textSize(14);
  24432. * text("Font Size 14", 10, 60);
  24433. * textSize(16);
  24434. * text("Font Size 16", 10, 90);
  24435. * </code>
  24436. * </div>
  24437. *
  24438. * @alt
  24439. *Font Size 12 displayed small, Font Size 14 medium & Font Size 16 large
  24440. *
  24441. */
  24442. p5.prototype.textSize = function(theSize) {
  24443. return this._renderer.textSize.apply(this._renderer, arguments);
  24444. };
  24445. /**
  24446. * Sets/gets the style of the text for system fonts to NORMAL, ITALIC, or BOLD.
  24447. * Note: this may be is overridden by CSS styling. For non-system fonts
  24448. * (opentype, truetype, etc.) please load styled fonts instead.
  24449. *
  24450. * @method textStyle
  24451. * @param {Number/Constant} theStyle styling for text, either NORMAL,
  24452. * ITALIC, or BOLD
  24453. * @return {Object|String}
  24454. * @example
  24455. * <div>
  24456. * <code>
  24457. * strokeWeight(0);
  24458. * textSize(12);
  24459. * textStyle(NORMAL);
  24460. * text("Font Style Normal", 10, 30);
  24461. * textStyle(ITALIC);
  24462. * text("Font Style Italic", 10, 60);
  24463. * textStyle(BOLD);
  24464. * text("Font Style Bold", 10, 90);
  24465. * </code>
  24466. * </div>
  24467. *
  24468. * @alt
  24469. *words Font Style Normal displayed normally, Italic in italic and bold in bold
  24470. *
  24471. */
  24472. p5.prototype.textStyle = function(theStyle) {
  24473. return this._renderer.textStyle.apply(this._renderer, arguments);
  24474. };
  24475. /**
  24476. * Calculates and returns the width of any character or text string.
  24477. *
  24478. * @method textWidth
  24479. * @param {String} theText the String of characters to measure
  24480. * @return {Number}
  24481. * @example
  24482. * <div>
  24483. * <code>
  24484. * textSize(28);
  24485. *
  24486. * var aChar = 'P';
  24487. * var cWidth = textWidth(aChar);
  24488. * text(aChar, 0, 40);
  24489. * line(cWidth, 0, cWidth, 50);
  24490. *
  24491. * var aString = "p5.js";
  24492. * var sWidth = textWidth(aString);
  24493. * text(aString, 0, 85);
  24494. * line(sWidth, 50, sWidth, 100);
  24495. * </code>
  24496. * </div>
  24497. *
  24498. * @alt
  24499. *Letter P and p5.js are displayed with vertical lines at end. P is wide
  24500. *
  24501. */
  24502. p5.prototype.textWidth = function(theText) {
  24503. if (theText.length === 0) {
  24504. return 0;
  24505. }
  24506. return this._renderer.textWidth.apply(this._renderer, arguments);
  24507. };
  24508. /**
  24509. * Returns the ascent of the current font at its current size. The ascent
  24510. * represents the distance, in pixels, of the tallest character above
  24511. * the baseline.
  24512. *
  24513. * @return {Number}
  24514. * @example
  24515. * <div>
  24516. * <code>
  24517. * var base = height * 0.75;
  24518. * var scalar = 0.8; // Different for each font
  24519. *
  24520. * textSize(32); // Set initial text size
  24521. * var asc = textAscent() * scalar; // Calc ascent
  24522. * line(0, base - asc, width, base - asc);
  24523. * text("dp", 0, base); // Draw text on baseline
  24524. *
  24525. * textSize(64); // Increase text size
  24526. * asc = textAscent() * scalar; // Recalc ascent
  24527. * line(40, base - asc, width, base - asc);
  24528. * text("dp", 40, base); // Draw text on baseline
  24529. * </code>
  24530. * </div>
  24531. */
  24532. p5.prototype.textAscent = function() {
  24533. return this._renderer.textAscent();
  24534. };
  24535. /**
  24536. * Returns the descent of the current font at its current size. The descent
  24537. * represents the distance, in pixels, of the character with the longest
  24538. * descender below the baseline.
  24539. *
  24540. * @return {Number}
  24541. * @example
  24542. * <div>
  24543. * <code>
  24544. * var base = height * 0.75;
  24545. * var scalar = 0.8; // Different for each font
  24546. *
  24547. * textSize(32); // Set initial text size
  24548. * var desc = textDescent() * scalar; // Calc ascent
  24549. * line(0, base+desc, width, base+desc);
  24550. * text("dp", 0, base); // Draw text on baseline
  24551. *
  24552. * textSize(64); // Increase text size
  24553. * desc = textDescent() * scalar; // Recalc ascent
  24554. * line(40, base + desc, width, base + desc);
  24555. * text("dp", 40, base); // Draw text on baseline
  24556. * </code>
  24557. * </div>
  24558. */
  24559. p5.prototype.textDescent = function() {
  24560. return this._renderer.textDescent();
  24561. };
  24562. /**
  24563. * Helper function to measure ascent and descent.
  24564. */
  24565. p5.prototype._updateTextMetrics = function() {
  24566. return this._renderer._updateTextMetrics();
  24567. };
  24568. module.exports = p5;
  24569. },{"../core/core":37}],71:[function(_dereq_,module,exports){
  24570. /**
  24571. * @module Typography
  24572. * @submodule Loading & Displaying
  24573. * @for p5
  24574. * @requires core
  24575. */
  24576. 'use strict';
  24577. var p5 = _dereq_('../core/core');
  24578. var constants = _dereq_('../core/constants');
  24579. _dereq_('../core/error_helpers');
  24580. /**
  24581. * Draws text to the screen. Displays the information specified in the first
  24582. * parameter on the screen in the position specified by the additional
  24583. * parameters. A default font will be used unless a font is set with the
  24584. * textFont() function and a default size will be used unless a font is set
  24585. * with textSize(). Change the color of the text with the fill() function.
  24586. * Change the outline of the text with the stroke() and strokeWeight()
  24587. * functions.
  24588. * <br><br>
  24589. * The text displays in relation to the textAlign() function, which gives the
  24590. * option to draw to the left, right, and center of the coordinates.
  24591. * <br><br>
  24592. * The x2 and y2 parameters define a rectangular area to display within and
  24593. * may only be used with string data. When these parameters are specified,
  24594. * they are interpreted based on the current rectMode() setting. Text that
  24595. * does not fit completely within the rectangle specified will not be drawn
  24596. * to the screen.
  24597. *
  24598. * @method text
  24599. * @param {String} str the alphanumeric symbols to be displayed
  24600. * @param {Number} x x-coordinate of text
  24601. * @param {Number} y y-coordinate of text
  24602. * @param {Number} x2 by default, the width of the text box,
  24603. * see rectMode() for more info
  24604. * @param {Number} y2 by default, the height of the text box,
  24605. * see rectMode() for more info
  24606. * @return {Object} this
  24607. * @example
  24608. * <div>
  24609. * <code>
  24610. * textSize(32);
  24611. * text("word", 10, 30);
  24612. * fill(0, 102, 153);
  24613. * text("word", 10, 60);
  24614. * fill(0, 102, 153, 51);
  24615. * text("word", 10, 90);
  24616. * </code>
  24617. * </div>
  24618. * <div>
  24619. * <code>
  24620. * s = "The quick brown fox jumped over the lazy dog.";
  24621. * fill(50);
  24622. * text(s, 10, 10, 70, 80); // Text wraps within text box
  24623. * </code>
  24624. * </div>
  24625. *
  24626. * @alt
  24627. *'word' displayed 3 times going from black, blue to translucent blue
  24628. * The quick brown fox jumped over the lazy dog.
  24629. *
  24630. */
  24631. p5.prototype.text = function(str, x, y, maxWidth, maxHeight) {
  24632. return (!(this._renderer._doFill || this._renderer._doStroke)) ? this :
  24633. this._renderer.text.apply(this._renderer, arguments);
  24634. };
  24635. /**
  24636. * Sets the current font that will be drawn with the text() function.
  24637. *
  24638. * @method textFont
  24639. * @param {Object|String} f a font loaded via loadFont(), or a String
  24640. * representing a <a href="https://mzl.la/2dOw8WD">web safe font</a> (a font
  24641. * that is generally available across all systems).
  24642. * @return {Object} this
  24643. * @example
  24644. * <div>
  24645. * <code>
  24646. * fill(0);
  24647. * textSize(12);
  24648. * textFont("Georgia");
  24649. * text("Georgia", 12, 30);
  24650. * textFont("Helvetica");
  24651. * text("Helvetica", 12, 60);
  24652. * </code>
  24653. * </div>
  24654. * <div>
  24655. * <code>
  24656. * var fontRegular, fontItalic, fontBold;
  24657. * function preload() {
  24658. * fontRegular = loadFont("assets/Regular.otf");
  24659. * fontItalic = loadFont("assets/Italic.ttf");
  24660. * fontBold = loadFont("assets/Bold.ttf");
  24661. * }
  24662. * function setup() {
  24663. * background(210);
  24664. * fill(0).strokeWeight(0).textSize(10);
  24665. * textFont(fontRegular);
  24666. * text("Font Style Normal", 10, 30);
  24667. * textFont(fontItalic);
  24668. * text("Font Style Italic", 10, 50);
  24669. * textFont(fontBold);
  24670. * text("Font Style Bold", 10, 70);
  24671. * }
  24672. * </code>
  24673. * </div>
  24674. *
  24675. * @alt
  24676. *words Font Style Normal displayed normally, Italic in italic and bold in bold
  24677. *
  24678. */
  24679. p5.prototype.textFont = function(theFont, theSize) {
  24680. if (arguments.length) {
  24681. if (!theFont) {
  24682. throw Error('null font passed to textFont');
  24683. }
  24684. this._renderer._setProperty('_textFont', theFont);
  24685. if (theSize) {
  24686. this._renderer._setProperty('_textSize', theSize);
  24687. this._renderer._setProperty('_textLeading',
  24688. theSize * constants._DEFAULT_LEADMULT);
  24689. }
  24690. return this._renderer._applyTextProperties();
  24691. }
  24692. return this;
  24693. };
  24694. module.exports = p5;
  24695. },{"../core/constants":36,"../core/core":37,"../core/error_helpers":40}],72:[function(_dereq_,module,exports){
  24696. /**
  24697. * This module defines the p5.Font class and functions for
  24698. * drawing text to the display canvas.
  24699. * @module Typography
  24700. * @submodule Font
  24701. * @requires core
  24702. * @requires constants
  24703. */
  24704. 'use strict';
  24705. var p5 = _dereq_('../core/core');
  24706. var constants = _dereq_('../core/constants');
  24707. /*
  24708. * TODO:
  24709. *
  24710. * API:
  24711. * -- textBounds()
  24712. * -- getPath()
  24713. * -- getPoints()
  24714. *
  24715. * ===========================================
  24716. * -- PFont functions:
  24717. * PFont.list()
  24718. *
  24719. * -- kerning
  24720. * -- alignment: justified?
  24721. * -- integrate p5.dom? (later)
  24722. */
  24723. /**
  24724. * Base class for font handling
  24725. * @class p5.Font
  24726. * @constructor
  24727. * @param {Object} [pInst] pointer to p5 instance
  24728. */
  24729. p5.Font = function(p) {
  24730. this.parent = p;
  24731. this.cache = {};
  24732. /**
  24733. * Underlying opentype font implementation
  24734. * @property font
  24735. */
  24736. this.font = undefined;
  24737. };
  24738. p5.Font.prototype.list = function() {
  24739. // TODO
  24740. throw 'not yet implemented';
  24741. };
  24742. /**
  24743. * Returns a tight bounding box for the given text string using this
  24744. * font (currently only supports single lines)
  24745. *
  24746. * @method textBounds
  24747. * @param {String} line a line of text
  24748. * @param {Number} x x-position
  24749. * @param {Number} y y-position
  24750. * @param {Number} fontSize font size to use (optional)
  24751. * @param {Object} options opentype options (optional)
  24752. *
  24753. * @return {Object} a rectangle object with properties: x, y, w, h
  24754. *
  24755. * @example
  24756. * <div>
  24757. * <code>
  24758. * var font;
  24759. * var textString = 'Lorem ipsum dolor sit amet.';
  24760. * function preload() {
  24761. * font = loadFont('./assets/Regular.otf');
  24762. * };
  24763. * function setup() {
  24764. * background(210);
  24765. *
  24766. * var bbox = font.textBounds(textString, 10, 30, 12);
  24767. * fill(255);
  24768. * stroke(0);
  24769. * rect(bbox.x, bbox.y, bbox.w, bbox.h);
  24770. * fill(0);
  24771. * noStroke();
  24772. *
  24773. * textFont(font);
  24774. * textSize(12);
  24775. * text(textString, 10, 30);
  24776. * };
  24777. * </code>
  24778. * </div>
  24779. *
  24780. * @alt
  24781. *words Lorem ipsum dol go off canvas and contained by white bounding box
  24782. *
  24783. */
  24784. p5.Font.prototype.textBounds = function(str, x, y, fontSize, options) {
  24785. x = x !== undefined ? x : 0;
  24786. y = y !== undefined ? y : 0;
  24787. fontSize = fontSize || this.parent._renderer._textSize;
  24788. // Check cache for existing bounds. Take into consideration the text alignment
  24789. // settings. Default alignment should match opentype's origin: left-aligned &
  24790. // alphabetic baseline.
  24791. var p = (options && options.renderer && options.renderer._pInst) ||
  24792. this.parent,
  24793. ctx = p._renderer.drawingContext,
  24794. alignment = ctx.textAlign || constants.LEFT,
  24795. baseline = ctx.textBaseline || constants.BASELINE;
  24796. var result = this.cache[cacheKey('textBounds', str, x, y, fontSize, alignment,
  24797. baseline)];
  24798. if (!result) {
  24799. var xCoords = [], yCoords = [], self = this,
  24800. scale = this._scale(fontSize), minX, minY, maxX, maxY;
  24801. this.font.forEachGlyph(str, x, y, fontSize, options,
  24802. function(glyph, gX, gY, gFontSize) {
  24803. xCoords.push(gX);
  24804. yCoords.push(gY);
  24805. var gm = glyph.getMetrics();
  24806. if (glyph.name !== 'space' && glyph.unicode !== 32) {
  24807. xCoords.push(gX + (gm.xMax * scale));
  24808. yCoords.push(gY + (-gm.yMin * scale));
  24809. yCoords.push(gY + (-gm.yMax * scale));
  24810. } else { // NOTE: deals with broken metrics for spaces in opentype.js
  24811. xCoords.push(gX + self.font.charToGlyph(' ').advanceWidth *
  24812. self._scale(fontSize));
  24813. }
  24814. });
  24815. // fix to #1409 (not sure why these max() functions were here)
  24816. /*minX = Math.max(0, Math.min.apply(null, xCoords));
  24817. minY = Math.max(0, Math.min.apply(null, yCoords));
  24818. maxX = Math.max(0, Math.max.apply(null, xCoords));
  24819. maxY = Math.max(0, Math.max.apply(null, yCoords));*/
  24820. minX = Math.min.apply(null, xCoords);
  24821. minY = Math.min.apply(null, yCoords);
  24822. maxX = Math.max.apply(null, xCoords);
  24823. maxY = Math.max.apply(null, yCoords);
  24824. result = {
  24825. x: minX,
  24826. y: minY,
  24827. h: maxY - minY,
  24828. w: maxX - minX,
  24829. advance: minX - x
  24830. };
  24831. // Bounds are now calculated, so shift the x & y to match alignment settings
  24832. var textWidth = result.w + result.advance;
  24833. var pos = this._handleAlignment(p, ctx, str, result.x, result.y, textWidth);
  24834. result.x = pos.x;
  24835. result.y = pos.y;
  24836. this.cache[cacheKey('textBounds', str, x, y, fontSize, alignment,
  24837. baseline)] = result;
  24838. }
  24839. //else console.log('cache-hit');
  24840. return result;
  24841. };
  24842. /**
  24843. * Computes an array of points following the path for specified text
  24844. *
  24845. * @param {String} txt a line of text
  24846. * @param {Number} x x-position
  24847. * @param {Number} y y-position
  24848. * @param {Number} fontSize font size to use (optional)
  24849. * @param {Object} options an (optional) object that can contain:
  24850. *
  24851. * <br>sampleFactor - the ratio of path-length to number of samples
  24852. * (default=.25); higher values yield more points and are therefore
  24853. * more precise
  24854. *
  24855. * <br>simplifyThreshold - if set to a non-zero value, collinear points will be
  24856. * be removed from the polygon; the value represents the threshold angle to use
  24857. * when determining whether two edges are collinear
  24858. *
  24859. * @return {Array} an array of points, each with x, y, alpha (the path angle)
  24860. */
  24861. p5.Font.prototype.textToPoints = function(txt, x, y, fontSize, options) {
  24862. var xoff = 0, result = [], glyphs = this._getGlyphs(txt);
  24863. fontSize = fontSize || this.parent._renderer._textSize;
  24864. for (var i = 0; i < glyphs.length; i++) {
  24865. var gpath = glyphs[i].getPath(x, y, fontSize),
  24866. paths = splitPaths(gpath.commands);
  24867. for (var j = 0; j < paths.length; j++) {
  24868. var pts = pathToPoints(paths[j], options);
  24869. for (var k = 0; k < pts.length; k++) {
  24870. pts[k].x += xoff;
  24871. result.push(pts[k]);
  24872. }
  24873. }
  24874. xoff += glyphs[i].advanceWidth * this._scale(fontSize);
  24875. }
  24876. return result;
  24877. };
  24878. // ----------------------------- End API ------------------------------
  24879. /**
  24880. * Returns the set of opentype glyphs for the supplied string.
  24881. *
  24882. * Note that there is not a strict one-to-one mapping between characters
  24883. * and glyphs, so the list of returned glyphs can be larger or smaller
  24884. * than the length of the given string.
  24885. *
  24886. * @param {String} str the string to be converted
  24887. * @return {array} the opentype glyphs
  24888. */
  24889. p5.Font.prototype._getGlyphs = function(str) {
  24890. return this.font.stringToGlyphs(str);
  24891. };
  24892. /**
  24893. * Returns an opentype path for the supplied string and position.
  24894. *
  24895. * @param {String} line a line of text
  24896. * @param {Number} x x-position
  24897. * @param {Number} y y-position
  24898. * @param {Object} options opentype options (optional)
  24899. * @return {Object} the opentype path
  24900. */
  24901. p5.Font.prototype._getPath = function(line, x, y, options) {
  24902. var p = (options && options.renderer && options.renderer._pInst) ||
  24903. this.parent,
  24904. ctx = p._renderer.drawingContext,
  24905. pos = this._handleAlignment(p, ctx, line, x, y);
  24906. return this.font.getPath(line, pos.x, pos.y, p._renderer._textSize, options);
  24907. };
  24908. /*
  24909. * Creates an SVG-formatted path-data string
  24910. * (See http://www.w3.org/TR/SVG/paths.html#PathData)
  24911. * from the given opentype path or string/position
  24912. *
  24913. * @param {Object} path an opentype path, OR the following:
  24914. *
  24915. * @param {String} line a line of text
  24916. * @param {Number} x x-position
  24917. * @param {Number} y y-position
  24918. * @param {Object} options opentype options (optional), set options.decimals
  24919. * to set the decimal precision of the path-data
  24920. *
  24921. * @return {Object} this p5.Font object
  24922. */
  24923. p5.Font.prototype._getPathData = function(line, x, y, options) {
  24924. var decimals = 3;
  24925. // create path from string/position
  24926. if (typeof line === 'string' && arguments.length > 2) {
  24927. line = this._getPath(line, x, y, options);
  24928. }
  24929. // handle options specified in 2nd arg
  24930. else if (typeof x === 'object') {
  24931. options = x;
  24932. }
  24933. // handle svg arguments
  24934. if (options && typeof options.decimals === 'number') {
  24935. decimals = options.decimals;
  24936. }
  24937. return line.toPathData(decimals);
  24938. };
  24939. /*
  24940. * Creates an SVG <path> element, as a string,
  24941. * from the given opentype path or string/position
  24942. *
  24943. * @param {Object} path an opentype path, OR the following:
  24944. *
  24945. * @param {String} line a line of text
  24946. * @param {Number} x x-position
  24947. * @param {Number} y y-position
  24948. * @param {Object} options opentype options (optional), set options.decimals
  24949. * to set the decimal precision of the path-data in the <path> element,
  24950. * options.fill to set the fill color for the <path> element,
  24951. * options.stroke to set the stroke color for the <path> element,
  24952. * options.strokeWidth to set the strokeWidth for the <path> element.
  24953. *
  24954. * @return {Object} this p5.Font object
  24955. */
  24956. p5.Font.prototype._getSVG = function(line, x, y, options) {
  24957. var decimals = 3;
  24958. // create path from string/position
  24959. if (typeof line === 'string' && arguments.length > 2) {
  24960. line = this._getPath(line, x, y, options);
  24961. }
  24962. // handle options specified in 2nd arg
  24963. else if (typeof x === 'object') {
  24964. options = x;
  24965. }
  24966. // handle svg arguments
  24967. if (options) {
  24968. if (typeof options.decimals === 'number') {
  24969. decimals = options.decimals;
  24970. }
  24971. if (typeof options.strokeWidth === 'number') {
  24972. line.strokeWidth = options.strokeWidth;
  24973. }
  24974. if (typeof options.fill !== 'undefined') {
  24975. line.fill = options.fill;
  24976. }
  24977. if (typeof options.stroke !== 'undefined') {
  24978. line.stroke = options.stroke;
  24979. }
  24980. }
  24981. return line.toSVG(decimals);
  24982. };
  24983. /*
  24984. * Renders an opentype path or string/position
  24985. * to the current graphics context
  24986. *
  24987. * @param {Object} path an opentype path, OR the following:
  24988. *
  24989. * @param {String} line a line of text
  24990. * @param {Number} x x-position
  24991. * @param {Number} y y-position
  24992. * @param {Object} options opentype options (optional)
  24993. *
  24994. * @return {Object} this p5.Font object
  24995. */
  24996. p5.Font.prototype._renderPath = function(line, x, y, options) {
  24997. var pdata, pg = (options && options.renderer) || this.parent._renderer,
  24998. ctx = pg.drawingContext;
  24999. if (typeof line === 'object' && line.commands) {
  25000. pdata = line.commands;
  25001. } else {
  25002. //pos = handleAlignment(p, ctx, line, x, y);
  25003. pdata = this._getPath(line, x, y, options).commands;
  25004. }
  25005. ctx.beginPath();
  25006. for (var i = 0; i < pdata.length; i += 1) {
  25007. var cmd = pdata[i];
  25008. if (cmd.type === 'M') {
  25009. ctx.moveTo(cmd.x, cmd.y);
  25010. } else if (cmd.type === 'L') {
  25011. ctx.lineTo(cmd.x, cmd.y);
  25012. } else if (cmd.type === 'C') {
  25013. ctx.bezierCurveTo(cmd.x1, cmd.y1, cmd.x2, cmd.y2, cmd.x, cmd.y);
  25014. } else if (cmd.type === 'Q') {
  25015. ctx.quadraticCurveTo(cmd.x1, cmd.y1, cmd.x, cmd.y);
  25016. } else if (cmd.type === 'Z') {
  25017. ctx.closePath();
  25018. }
  25019. }
  25020. // only draw stroke if manually set by user
  25021. if (pg._doStroke && pg._strokeSet) {
  25022. ctx.stroke();
  25023. }
  25024. if (pg._doFill) {
  25025. // if fill hasn't been set by user, use default-text-fill
  25026. ctx.fillStyle = pg._fillSet ? ctx.fillStyle : constants._DEFAULT_TEXT_FILL;
  25027. ctx.fill();
  25028. }
  25029. return this;
  25030. };
  25031. p5.Font.prototype._textWidth = function(str, fontSize) {
  25032. if (str === ' ') { // special case for now
  25033. return this.font.charToGlyph(' ').advanceWidth * this._scale(fontSize);
  25034. }
  25035. var bounds = this.textBounds(str, 0, 0, fontSize);
  25036. return bounds.w + bounds.advance;
  25037. };
  25038. p5.Font.prototype._textAscent = function(fontSize) {
  25039. return this.font.ascender * this._scale(fontSize);
  25040. };
  25041. p5.Font.prototype._textDescent = function(fontSize) {
  25042. return -this.font.descender * this._scale(fontSize);
  25043. };
  25044. p5.Font.prototype._scale = function(fontSize) {
  25045. return (1 / this.font.unitsPerEm) * (fontSize ||
  25046. this.parent._renderer._textSize);
  25047. };
  25048. p5.Font.prototype._handleAlignment = function(p, ctx, line, x, y, textWidth) {
  25049. var fontSize = p._renderer._textSize,
  25050. textAscent = this._textAscent(fontSize),
  25051. textDescent = this._textDescent(fontSize);
  25052. textWidth = textWidth !== undefined ? textWidth :
  25053. this._textWidth(line, fontSize);
  25054. if (ctx.textAlign === constants.CENTER) {
  25055. x -= textWidth / 2;
  25056. } else if (ctx.textAlign === constants.RIGHT) {
  25057. x -= textWidth;
  25058. }
  25059. if (ctx.textBaseline === constants.TOP) {
  25060. y += textAscent;
  25061. } else if (ctx.textBaseline === constants._CTX_MIDDLE) {
  25062. y += textAscent / 2;
  25063. } else if (ctx.textBaseline === constants.BOTTOM) {
  25064. y -= textDescent;
  25065. }
  25066. return { x: x, y: y };
  25067. };
  25068. // path-utils
  25069. function pathToPoints(cmds, options) {
  25070. var opts = parseOpts(options, {
  25071. sampleFactor: 0.1,
  25072. simplifyThreshold: 0,
  25073. });
  25074. var len = pointAtLength(cmds,0,1), // total-length
  25075. t = len / (len * opts.sampleFactor),
  25076. pts = [];
  25077. for (var i = 0; i < len; i += t) {
  25078. pts.push(pointAtLength(cmds, i));
  25079. }
  25080. if (opts.simplifyThreshold) {
  25081. /*var count = */simplify(pts, opts.simplifyThreshold);
  25082. //console.log('Simplify: removed ' + count + ' pts');
  25083. }
  25084. return pts;
  25085. }
  25086. function simplify(pts, angle) {
  25087. angle = (typeof angle === 'undefined') ? 0 : angle;
  25088. var num = 0;
  25089. for (var i = pts.length - 1; pts.length > 3 && i >= 0; --i) {
  25090. if (collinear(at(pts, i - 1), at(pts, i), at(pts, i + 1), angle)) {
  25091. // Remove the middle point
  25092. pts.splice(i % pts.length, 1);
  25093. num++;
  25094. }
  25095. }
  25096. return num;
  25097. }
  25098. function splitPaths(cmds) {
  25099. var paths = [], current;
  25100. for (var i = 0; i < cmds.length; i++) {
  25101. if (cmds[i].type === 'M') {
  25102. if (current) {
  25103. paths.push(current);
  25104. }
  25105. current = [];
  25106. }
  25107. current.push(cmdToArr(cmds[i]));
  25108. }
  25109. paths.push(current);
  25110. return paths;
  25111. }
  25112. function cmdToArr(cmd) {
  25113. var arr = [ cmd.type ];
  25114. if (cmd.type === 'M' || cmd.type === 'L') { // moveto or lineto
  25115. arr.push(cmd.x, cmd.y);
  25116. } else if (cmd.type === 'C') {
  25117. arr.push(cmd.x1, cmd.y1, cmd.x2, cmd.y2, cmd.x, cmd.y);
  25118. } else if (cmd.type === 'Q') {
  25119. arr.push(cmd.x1, cmd.y1, cmd.x, cmd.y);
  25120. }
  25121. // else if (cmd.type === 'Z') { /* no-op */ }
  25122. return arr;
  25123. }
  25124. function parseOpts(options, defaults) {
  25125. if (typeof options !== 'object') {
  25126. options = defaults;
  25127. }
  25128. else {
  25129. for (var key in defaults) {
  25130. if (typeof options[key] === 'undefined') {
  25131. options[key] = defaults[key];
  25132. }
  25133. }
  25134. }
  25135. return options;
  25136. }
  25137. //////////////////////// Helpers ////////////////////////////
  25138. function at(v, i) {
  25139. var s = v.length;
  25140. return v[i < 0 ? i % s + s : i % s];
  25141. }
  25142. function collinear(a, b, c, thresholdAngle) {
  25143. if (!thresholdAngle) {
  25144. return areaTriangle(a, b, c) === 0;
  25145. }
  25146. if (typeof collinear.tmpPoint1 === 'undefined') {
  25147. collinear.tmpPoint1 = [];
  25148. collinear.tmpPoint2 = [];
  25149. }
  25150. var ab = collinear.tmpPoint1, bc = collinear.tmpPoint2;
  25151. ab.x = b.x - a.x;
  25152. ab.y = b.y - a.y;
  25153. bc.x = c.x - b.x;
  25154. bc.y = c.y - b.y;
  25155. var dot = ab.x * bc.x + ab.y * bc.y,
  25156. magA = Math.sqrt(ab.x * ab.x + ab.y * ab.y),
  25157. magB = Math.sqrt(bc.x * bc.x + bc.y * bc.y),
  25158. angle = Math.acos(dot / (magA * magB));
  25159. return angle < thresholdAngle;
  25160. }
  25161. function areaTriangle(a, b, c) {
  25162. return (((b[0] - a[0]) * (c[1] - a[1])) - ((c[0] - a[0]) * (b[1] - a[1])));
  25163. }
  25164. // Portions of below code copyright 2008 Dmitry Baranovskiy (via MIT license)
  25165. function findDotsAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) {
  25166. var t1 = 1 - t, t13 = Math.pow(t1, 3), t12 = Math.pow(t1, 2), t2 = t * t,
  25167. t3 = t2 * t, x = t13 * p1x + t12 * 3 * t * c1x + t1 * 3 * t * t * c2x +
  25168. t3 * p2x, y = t13 * p1y + t12 * 3 * t * c1y + t1 * 3 * t * t * c2y +
  25169. t3 * p2y, mx = p1x + 2 * t * (c1x - p1x) + t2 * (c2x - 2 * c1x + p1x),
  25170. my = p1y + 2 * t * (c1y - p1y) + t2 * (c2y - 2 * c1y + p1y),
  25171. nx = c1x + 2 * t * (c2x - c1x) + t2 * (p2x - 2 * c2x + c1x),
  25172. ny = c1y + 2 * t * (c2y - c1y) + t2 * (p2y - 2 * c2y + c1y),
  25173. ax = t1 * p1x + t * c1x, ay = t1 * p1y + t * c1y,
  25174. cx = t1 * c2x + t * p2x, cy = t1 * c2y + t * p2y,
  25175. alpha = (90 - Math.atan2(mx - nx, my - ny) * 180 / Math.PI);
  25176. if (mx > nx || my < ny) { alpha += 180; }
  25177. return { x: x, y: y, m: { x: mx, y: my }, n: { x: nx, y: ny },
  25178. start: { x: ax, y: ay }, end: { x: cx, y: cy }, alpha: alpha
  25179. };
  25180. }
  25181. function getPointAtSegmentLength(p1x,p1y,c1x,c1y,c2x,c2y,p2x,p2y,length) {
  25182. return (length == null) ? bezlen(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) :
  25183. findDotsAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y,
  25184. getTatLen(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, length));
  25185. }
  25186. function pointAtLength(path, length, istotal) {
  25187. path = path2curve(path);
  25188. var x, y, p, l, sp = '', subpaths = {}, point, len = 0;
  25189. for (var i = 0, ii = path.length; i < ii; i++) {
  25190. p = path[i];
  25191. if (p[0] === 'M') {
  25192. x = +p[1];
  25193. y = +p[2];
  25194. } else {
  25195. l = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6]);
  25196. if (len + l > length) {
  25197. if (!istotal) {
  25198. point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5],
  25199. p[6], length - len);
  25200. return { x: point.x, y: point.y, alpha: point.alpha };
  25201. }
  25202. }
  25203. len += l;
  25204. x = +p[5];
  25205. y = +p[6];
  25206. }
  25207. sp += p.shift() + p;
  25208. }
  25209. subpaths.end = sp;
  25210. point = istotal ? len : findDotsAtSegment
  25211. (x, y, p[0], p[1], p[2], p[3], p[4], p[5], 1);
  25212. if (point.alpha) {
  25213. point = { x: point.x, y: point.y, alpha: point.alpha };
  25214. }
  25215. return point;
  25216. }
  25217. function pathToAbsolute(pathArray) {
  25218. var res = [], x = 0, y = 0, mx = 0, my = 0, start = 0;
  25219. if (pathArray[0][0] === 'M') {
  25220. x = +pathArray[0][1];
  25221. y = +pathArray[0][2];
  25222. mx = x;
  25223. my = y;
  25224. start++;
  25225. res[0] = ['M', x, y];
  25226. }
  25227. var dots,crz = pathArray.length===3 && pathArray[0][0]==='M' &&
  25228. pathArray[1][0].toUpperCase()==='R' && pathArray[2][0].toUpperCase()==='Z';
  25229. for (var r, pa, i = start, ii = pathArray.length; i < ii; i++) {
  25230. res.push(r = []);
  25231. pa = pathArray[i];
  25232. if (pa[0] !== String.prototype.toUpperCase.call(pa[0])) {
  25233. r[0] = String.prototype.toUpperCase.call(pa[0]);
  25234. switch (r[0]) {
  25235. case 'A':
  25236. r[1] = pa[1];
  25237. r[2] = pa[2];
  25238. r[3] = pa[3];
  25239. r[4] = pa[4];
  25240. r[5] = pa[5];
  25241. r[6] = +(pa[6] + x);
  25242. r[7] = +(pa[7] + y);
  25243. break;
  25244. case 'V':
  25245. r[1] = +pa[1] + y;
  25246. break;
  25247. case 'H':
  25248. r[1] = +pa[1] + x;
  25249. break;
  25250. case 'R':
  25251. dots = [x, y].concat(pa.slice(1));
  25252. for (var j = 2, jj = dots.length; j < jj; j++) {
  25253. dots[j] = +dots[j] + x;
  25254. dots[++j] = +dots[j] + y;
  25255. }
  25256. res.pop();
  25257. res = res.concat(catmullRom2bezier(dots, crz));
  25258. break;
  25259. case 'M':
  25260. mx = +pa[1] + x;
  25261. my = +pa[2] + y;
  25262. break;
  25263. default:
  25264. for (j = 1, jj = pa.length; j < jj; j++) {
  25265. r[j] = +pa[j] + ((j % 2) ? x : y);
  25266. }
  25267. }
  25268. } else if (pa[0] === 'R') {
  25269. dots = [x, y].concat(pa.slice(1));
  25270. res.pop();
  25271. res = res.concat(catmullRom2bezier(dots, crz));
  25272. r = ['R'].concat(pa.slice(-2));
  25273. } else {
  25274. for (var k = 0, kk = pa.length; k < kk; k++) {
  25275. r[k] = pa[k];
  25276. }
  25277. }
  25278. switch (r[0]) {
  25279. case 'Z':
  25280. x = mx;
  25281. y = my;
  25282. break;
  25283. case 'H':
  25284. x = r[1];
  25285. break;
  25286. case 'V':
  25287. y = r[1];
  25288. break;
  25289. case 'M':
  25290. mx = r[r.length - 2];
  25291. my = r[r.length - 1];
  25292. break;
  25293. default:
  25294. x = r[r.length - 2];
  25295. y = r[r.length - 1];
  25296. }
  25297. }
  25298. return res;
  25299. }
  25300. function path2curve(path, path2) {
  25301. var p = pathToAbsolute(path), p2 = path2 && pathToAbsolute(path2),
  25302. attrs = { x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null },
  25303. attrs2 = { x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null },
  25304. processPath = function(path, d, pcom) {
  25305. var nx, ny, tq = { T: 1, Q: 1 };
  25306. if (!path) { return ['C', d.x, d.y, d.x, d.y, d.x, d.y]; }
  25307. if (!(path[0] in tq)) { d.qx = d.qy = null; }
  25308. switch (path[0]) {
  25309. case 'M':
  25310. d.X = path[1];
  25311. d.Y = path[2];
  25312. break;
  25313. case 'A':
  25314. path = ['C'].concat(a2c.apply(0, [d.x, d.y].concat(path.slice(1))));
  25315. break;
  25316. case 'S':
  25317. if (pcom === 'C' || pcom === 'S') {
  25318. nx = d.x * 2 - d.bx;
  25319. ny = d.y * 2 - d.by;
  25320. } else {
  25321. nx = d.x;
  25322. ny = d.y;
  25323. }
  25324. path = ['C', nx, ny].concat(path.slice(1));
  25325. break;
  25326. case 'T':
  25327. if (pcom === 'Q' || pcom === 'T') {
  25328. d.qx = d.x * 2 - d.qx;
  25329. d.qy = d.y * 2 - d.qy;
  25330. } else {
  25331. d.qx = d.x;
  25332. d.qy = d.y;
  25333. }
  25334. path = ['C'].concat(q2c(d.x, d.y, d.qx, d.qy, path[1], path[2]));
  25335. break;
  25336. case 'Q':
  25337. d.qx = path[1];
  25338. d.qy = path[2];
  25339. path = ['C'].concat(q2c(d.x,d.y,path[1],path[2],path[3],path[4]));
  25340. break;
  25341. case 'L':
  25342. path = ['C'].concat(l2c(d.x, d.y, path[1], path[2]));
  25343. break;
  25344. case 'H':
  25345. path = ['C'].concat(l2c(d.x, d.y, path[1], d.y));
  25346. break;
  25347. case 'V':
  25348. path = ['C'].concat(l2c(d.x, d.y, d.x, path[1]));
  25349. break;
  25350. case 'Z':
  25351. path = ['C'].concat(l2c(d.x, d.y, d.X, d.Y));
  25352. break;
  25353. }
  25354. return path;
  25355. },
  25356. fixArc = function(pp, i) {
  25357. if (pp[i].length > 7) {
  25358. pp[i].shift();
  25359. var pi = pp[i];
  25360. while (pi.length) {
  25361. pcoms1[i] = 'A';
  25362. if (p2) { pcoms2[i] = 'A'; }
  25363. pp.splice(i++, 0, ['C'].concat(pi.splice(0, 6)));
  25364. }
  25365. pp.splice(i, 1);
  25366. ii = Math.max(p.length, p2 && p2.length || 0);
  25367. }
  25368. },
  25369. fixM = function(path1, path2, a1, a2, i) {
  25370. if (path1 && path2 && path1[i][0] === 'M' && path2[i][0] !== 'M') {
  25371. path2.splice(i, 0, ['M', a2.x, a2.y]);
  25372. a1.bx = 0;
  25373. a1.by = 0;
  25374. a1.x = path1[i][1];
  25375. a1.y = path1[i][2];
  25376. ii = Math.max(p.length, p2 && p2.length || 0);
  25377. }
  25378. },
  25379. pcoms1 = [], // path commands of original path p
  25380. pcoms2 = [], // path commands of original path p2
  25381. pfirst = '', // temporary holder for original path command
  25382. pcom = ''; // holder for previous path command of original path
  25383. for (var i = 0, ii = Math.max(p.length, p2 && p2.length || 0); i < ii; i++) {
  25384. if (p[i]) { pfirst = p[i][0]; } // save current path command
  25385. if (pfirst !== 'C') {
  25386. pcoms1[i] = pfirst; // Save current path command
  25387. if (i) { pcom = pcoms1[i - 1]; } // Get previous path command pcom
  25388. }
  25389. p[i] = processPath(p[i], attrs, pcom);
  25390. if (pcoms1[i] !== 'A' && pfirst === 'C') { pcoms1[i] = 'C'; }
  25391. fixArc(p, i); // fixArc adds also the right amount of A:s to pcoms1
  25392. if (p2) { // the same procedures is done to p2
  25393. if (p2[i]) { pfirst = p2[i][0]; }
  25394. if (pfirst !== 'C') {
  25395. pcoms2[i] = pfirst;
  25396. if (i) { pcom = pcoms2[i - 1]; }
  25397. }
  25398. p2[i] = processPath(p2[i], attrs2, pcom);
  25399. if (pcoms2[i] !== 'A' && pfirst === 'C') { pcoms2[i] = 'C'; }
  25400. fixArc(p2, i);
  25401. }
  25402. fixM(p, p2, attrs, attrs2, i);
  25403. fixM(p2, p, attrs2, attrs, i);
  25404. var seg = p[i], seg2 = p2 && p2[i], seglen = seg.length,
  25405. seg2len = p2 && seg2.length;
  25406. attrs.x = seg[seglen - 2];
  25407. attrs.y = seg[seglen - 1];
  25408. attrs.bx = parseFloat(seg[seglen - 4]) || attrs.x;
  25409. attrs.by = parseFloat(seg[seglen - 3]) || attrs.y;
  25410. attrs2.bx = p2 && (parseFloat(seg2[seg2len - 4]) || attrs2.x);
  25411. attrs2.by = p2 && (parseFloat(seg2[seg2len - 3]) || attrs2.y);
  25412. attrs2.x = p2 && seg2[seg2len - 2];
  25413. attrs2.y = p2 && seg2[seg2len - 1];
  25414. }
  25415. return p2 ? [p, p2] : p;
  25416. }
  25417. function a2c(x1, y1, rx, ry, angle, lac, sweep_flag, x2, y2, recursive) {
  25418. // for more information of where this Math came from visit:
  25419. // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
  25420. var PI = Math.PI, _120 = PI * 120 / 180, f1, f2, cx, cy,
  25421. rad = PI / 180 * (+angle || 0), res = [], xy,
  25422. rotate = function (x, y, rad) {
  25423. var X = x * Math.cos(rad) - y * Math.sin(rad),
  25424. Y = x * Math.sin(rad) + y * Math.cos(rad);
  25425. return { x: X, y: Y };
  25426. };
  25427. if (!recursive) {
  25428. xy = rotate(x1, y1, -rad);
  25429. x1 = xy.x;
  25430. y1 = xy.y;
  25431. xy = rotate(x2, y2, -rad);
  25432. x2 = xy.x;
  25433. y2 = xy.y;
  25434. var x = (x1 - x2) / 2, y = (y1 - y2) / 2,
  25435. h = (x * x) / (rx * rx) + (y * y) / (ry * ry);
  25436. if (h > 1) {
  25437. h = Math.sqrt(h);
  25438. rx = h * rx;
  25439. ry = h * ry;
  25440. }
  25441. var rx2 = rx * rx, ry2 = ry * ry,
  25442. k = (lac === sweep_flag ? -1 : 1) * Math.sqrt(Math.abs
  25443. ((rx2 * ry2 - rx2 * y * y - ry2 * x * x)/(rx2 * y * y + ry2 * x * x)));
  25444. cx = k * rx * y / ry + (x1 + x2) / 2;
  25445. cy = k * -ry * x / rx + (y1 + y2) / 2;
  25446. f1 = Math.asin(((y1 - cy) / ry).toFixed(9));
  25447. f2 = Math.asin(((y2 - cy) / ry).toFixed(9));
  25448. f1 = x1 < cx ? PI - f1 : f1;
  25449. f2 = x2 < cx ? PI - f2 : f2;
  25450. if (f1 < 0) { f1 = PI * 2 + f1; }
  25451. if (f2 < 0) { f2 = PI * 2 + f2; }
  25452. if (sweep_flag && f1 > f2) {
  25453. f1 = f1 - PI * 2;
  25454. }
  25455. if (!sweep_flag && f2 > f1) {
  25456. f2 = f2 - PI * 2;
  25457. }
  25458. } else {
  25459. f1 = recursive[0];
  25460. f2 = recursive[1];
  25461. cx = recursive[2];
  25462. cy = recursive[3];
  25463. }
  25464. var df = f2 - f1;
  25465. if (Math.abs(df) > _120) {
  25466. var f2old = f2, x2old = x2, y2old = y2;
  25467. f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1);
  25468. x2 = cx + rx * Math.cos(f2);
  25469. y2 = cy + ry * Math.sin(f2);
  25470. res = a2c(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old,
  25471. [f2, f2old, cx, cy]);
  25472. }
  25473. df = f2 - f1;
  25474. var c1 = Math.cos(f1),
  25475. s1 = Math.sin(f1),
  25476. c2 = Math.cos(f2),
  25477. s2 = Math.sin(f2),
  25478. t = Math.tan(df / 4),
  25479. hx = 4 / 3 * rx * t,
  25480. hy = 4 / 3 * ry * t,
  25481. m1 = [x1, y1],
  25482. m2 = [x1 + hx * s1, y1 - hy * c1],
  25483. m3 = [x2 + hx * s2, y2 - hy * c2],
  25484. m4 = [x2, y2];
  25485. m2[0] = 2 * m1[0] - m2[0];
  25486. m2[1] = 2 * m1[1] - m2[1];
  25487. if (recursive) {
  25488. return [m2, m3, m4].concat(res);
  25489. } else {
  25490. res = [m2, m3, m4].concat(res).join().split(',');
  25491. var newres = [];
  25492. for (var i = 0, ii = res.length; i < ii; i++) {
  25493. newres[i] = i % 2 ? rotate(res[i - 1], res[i], rad).y : rotate(res[i],
  25494. res[i + 1], rad).x;
  25495. }
  25496. return newres;
  25497. }
  25498. }
  25499. // http://schepers.cc/getting-to-the-point
  25500. function catmullRom2bezier(crp, z) {
  25501. var d = [];
  25502. for (var i = 0, iLen = crp.length; iLen - 2 * !z > i; i += 2) {
  25503. var p = [{
  25504. x: +crp[i - 2],
  25505. y: +crp[i - 1]
  25506. }, {
  25507. x: +crp[i],
  25508. y: +crp[i + 1]
  25509. }, {
  25510. x: +crp[i + 2],
  25511. y: +crp[i + 3]
  25512. }, {
  25513. x: +crp[i + 4],
  25514. y: +crp[i + 5]
  25515. }];
  25516. if (z) {
  25517. if (!i) {
  25518. p[0] = {
  25519. x: +crp[iLen - 2],
  25520. y: +crp[iLen - 1]
  25521. };
  25522. } else if (iLen - 4 === i) {
  25523. p[3] = {
  25524. x: +crp[0],
  25525. y: +crp[1]
  25526. };
  25527. } else if (iLen - 2 === i) {
  25528. p[2] = {
  25529. x: +crp[0],
  25530. y: +crp[1]
  25531. };
  25532. p[3] = {
  25533. x: +crp[2],
  25534. y: +crp[3]
  25535. };
  25536. }
  25537. } else {
  25538. if (iLen - 4 === i) {
  25539. p[3] = p[2];
  25540. } else if (!i) {
  25541. p[0] = {
  25542. x: +crp[i],
  25543. y: +crp[i + 1]
  25544. };
  25545. }
  25546. }
  25547. d.push(['C', (-p[0].x + 6 * p[1].x + p[2].x) / 6, (-p[0].y + 6 * p[1].y +
  25548. p[2].y) / 6, (p[1].x + 6 * p[2].x - p[3].x) / 6, (p[1].y + 6 * p[2].y -
  25549. p[3].y) / 6, p[2].x, p[2].y ]);
  25550. }
  25551. return d;
  25552. }
  25553. function l2c(x1, y1, x2, y2) { return [x1, y1, x2, y2, x2, y2]; }
  25554. function q2c(x1, y1, ax, ay, x2, y2) {
  25555. var _13 = 1 / 3, _23 = 2 / 3;
  25556. return [
  25557. _13 * x1 + _23 * ax, _13 * y1 + _23 * ay,
  25558. _13 * x2 + _23 * ax, _13 * y2 + _23 * ay, x2, y2
  25559. ];
  25560. }
  25561. function bezlen(x1, y1, x2, y2, x3, y3, x4, y4, z) {
  25562. if (z == null) { z = 1; }
  25563. z = z > 1 ? 1 : z < 0 ? 0 : z;
  25564. var z2 = z / 2,
  25565. n = 12, Tvalues = [-0.1252, 0.1252, -0.3678, 0.3678, -0.5873, 0.5873,
  25566. -0.7699, 0.7699, -0.9041, 0.9041, -0.9816, 0.9816],
  25567. sum = 0, Cvalues = [0.2491, 0.2491, 0.2335, 0.2335, 0.2032, 0.2032,
  25568. 0.1601, 0.1601, 0.1069, 0.1069, 0.0472, 0.0472 ];
  25569. for (var i = 0; i < n; i++) {
  25570. var ct = z2 * Tvalues[i] + z2,
  25571. xbase = base3(ct, x1, x2, x3, x4),
  25572. ybase = base3(ct, y1, y2, y3, y4),
  25573. comb = xbase * xbase + ybase * ybase;
  25574. sum += Cvalues[i] * Math.sqrt(comb);
  25575. }
  25576. return z2 * sum;
  25577. }
  25578. function getTatLen(x1, y1, x2, y2, x3, y3, x4, y4, ll) {
  25579. if (ll < 0 || bezlen(x1, y1, x2, y2, x3, y3, x4, y4) < ll) {
  25580. return;
  25581. }
  25582. var t = 1, step = t / 2, t2 = t - step, l, e = 0.01;
  25583. l = bezlen(x1, y1, x2, y2, x3, y3, x4, y4, t2);
  25584. while (Math.abs(l - ll) > e) {
  25585. step /= 2;
  25586. t2 += (l < ll ? 1 : -1) * step;
  25587. l = bezlen(x1, y1, x2, y2, x3, y3, x4, y4, t2);
  25588. }
  25589. return t2;
  25590. }
  25591. function base3(t, p1, p2, p3, p4) {
  25592. var t1 = -3 * p1 + 9 * p2 - 9 * p3 + 3 * p4,
  25593. t2 = t * t1 + 6 * p1 - 12 * p2 + 6 * p3;
  25594. return t * t2 - 3 * p1 + 3 * p2;
  25595. }
  25596. function cacheKey() {
  25597. var args = new Array(arguments.length);
  25598. for (var i = 0; i < args.length; ++i) {
  25599. args[i] = arguments[i];
  25600. }
  25601. i = args.length;
  25602. var hash = '';
  25603. while (i--) {
  25604. hash += (args[i] === Object(args[i])) ?
  25605. JSON.stringify(args[i]) : args[i];
  25606. }
  25607. return hash;
  25608. }
  25609. module.exports = p5.Font;
  25610. },{"../core/constants":36,"../core/core":37}],73:[function(_dereq_,module,exports){
  25611. /**
  25612. * @module Data
  25613. * @submodule Array Functions
  25614. * @for p5
  25615. * @requires core
  25616. */
  25617. 'use strict';
  25618. var p5 = _dereq_('../core/core');
  25619. /**
  25620. * Adds a value to the end of an array. Extends the length of
  25621. * the array by one. Maps to Array.push().
  25622. *
  25623. * @method append
  25624. * @param {Array} array Array to append
  25625. * @param {any} value to be added to the Array
  25626. * @example
  25627. * <div class = "norender"><code>
  25628. * function setup() {
  25629. *
  25630. * var myArray = new Array("Mango", "Apple", "Papaya")
  25631. * print(myArray) // ["Mango", "Apple", "Papaya"]
  25632. *
  25633. * append(myArray, "Peach")
  25634. * print(myArray) // ["Mango", "Apple", "Papaya", "Peach"]
  25635. *
  25636. * }
  25637. * </div></code>
  25638. */
  25639. p5.prototype.append = function(array, value) {
  25640. array.push(value);
  25641. return array;
  25642. };
  25643. /**
  25644. * Copies an array (or part of an array) to another array. The src array is
  25645. * copied to the dst array, beginning at the position specified by
  25646. * srcPosition and into the position specified by dstPosition. The number of
  25647. * elements to copy is determined by length. Note that copying values
  25648. * overwrites existing values in the destination array. To append values
  25649. * instead of overwriting them, use concat().
  25650. * <br><br>
  25651. * The simplified version with only two arguments, arrayCopy(src, dst),
  25652. * copies an entire array to another of the same size. It is equivalent to
  25653. * arrayCopy(src, 0, dst, 0, src.length).
  25654. * <br><br>
  25655. * Using this function is far more efficient for copying array data than
  25656. * iterating through a for() loop and copying each element individually.
  25657. *
  25658. * @method arrayCopy
  25659. * @param {Array} src the source Array
  25660. * @param {Number} [srcPosition] starting position in the source Array
  25661. * @param {Array} dst the destination Array
  25662. * @param {Number} [dstPosition] starting position in the destination Array
  25663. * @param {Number} [length] number of Array elements to be copied
  25664. *
  25665. * @example
  25666. * <div class="norender"><code>
  25667. * function setup() {
  25668. *
  25669. * var src = new Array("A", "B", "C");
  25670. * var dst = new Array( 1 , 2 , 3 );
  25671. * var srcPosition = 1;
  25672. * var dstPosition = 0;
  25673. * var length = 2;
  25674. *
  25675. * print(src); // ["A", "B", "C"]
  25676. * print(dst); // [ 1 , 2 , 3 ]
  25677. *
  25678. * arrayCopy(src, srcPosition, dst, dstPosition, length);
  25679. * print(dst); // ["B", "C", 3]
  25680. *
  25681. * }
  25682. * </div></code>
  25683. */
  25684. p5.prototype.arrayCopy = function(
  25685. src,
  25686. srcPosition,
  25687. dst,
  25688. dstPosition,
  25689. length) {
  25690. // the index to begin splicing from dst array
  25691. var start,
  25692. end;
  25693. if (typeof length !== 'undefined') {
  25694. end = Math.min(length, src.length);
  25695. start = dstPosition;
  25696. src = src.slice(srcPosition, end + srcPosition);
  25697. } else {
  25698. if (typeof dst !== 'undefined') { // src, dst, length
  25699. // rename so we don't get confused
  25700. end = dst;
  25701. end = Math.min(end, src.length);
  25702. } else { // src, dst
  25703. end = src.length;
  25704. }
  25705. start = 0;
  25706. // rename so we don't get confused
  25707. dst = srcPosition;
  25708. src = src.slice(0, end);
  25709. }
  25710. // Since we are not returning the array and JavaScript is pass by reference
  25711. // we must modify the actual values of the array
  25712. // instead of reassigning arrays
  25713. Array.prototype.splice.apply(dst, [start, end].concat(src));
  25714. };
  25715. /**
  25716. * Concatenates two arrays, maps to Array.concat(). Does not modify the
  25717. * input arrays.
  25718. *
  25719. * @method concat
  25720. * @param {Array} a first Array to concatenate
  25721. * @param {Array} b second Array to concatenate
  25722. * @return {Array} concatenated array
  25723. *
  25724. * @example
  25725. * <div class = "norender"><code>
  25726. * function setup() {
  25727. * var arr1 = new Array("A", "B", "C");
  25728. * var arr2 = new Array( 1 , 2 , 3 );
  25729. *
  25730. * print(arr1); // ["A","B","C"]
  25731. * print(arr2); // [1,2,3]
  25732. *
  25733. * var arr3 = concat(arr1, arr2);
  25734. *
  25735. * print(arr1); // ["A","B","C"]
  25736. * print(arr2); // [1,2,3]
  25737. * print(arr3); // ["A","B","C",1,2,3]
  25738. *
  25739. * }
  25740. * </div></code>
  25741. */
  25742. p5.prototype.concat = function(list0, list1) {
  25743. return list0.concat(list1);
  25744. };
  25745. /**
  25746. * Reverses the order of an array, maps to Array.reverse()
  25747. *
  25748. * @method reverse
  25749. * @param {Array} list Array to reverse
  25750. * @example
  25751. * <div class="norender"><code>
  25752. * function setup() {
  25753. * var myArray = new Array("A", "B", "C");
  25754. * print(myArray); // ["A","B","C"]
  25755. *
  25756. * reverse(myArray);
  25757. * print(myArray); // ["C","B","A"]
  25758. * }
  25759. * </div></code>
  25760. */
  25761. p5.prototype.reverse = function(list) {
  25762. return list.reverse();
  25763. };
  25764. /**
  25765. * Decreases an array by one element and returns the shortened array,
  25766. * maps to Array.pop().
  25767. *
  25768. * @method shorten
  25769. * @param {Array} list Array to shorten
  25770. * @return {Array} shortened Array
  25771. * @example
  25772. * <div class = "norender"><code>
  25773. * function setup() {
  25774. * var myArray = new Array("A", "B", "C");
  25775. * print(myArray); // ["A","B","C"]
  25776. *
  25777. * var newArray = shorten(myArray);
  25778. * print(myArray); // ["A","B","C"]
  25779. * print(newArray); // ["A","B"]
  25780. * }
  25781. * </div></code>
  25782. */
  25783. p5.prototype.shorten = function(list) {
  25784. list.pop();
  25785. return list;
  25786. };
  25787. /**
  25788. * Randomizes the order of the elements of an array. Implements
  25789. * <a href="http://Bost.Ocks.org/mike/shuffle/" target=_blank>
  25790. * Fisher-Yates Shuffle Algorithm</a>.
  25791. *
  25792. * @method shuffle
  25793. * @param {Array} array Array to shuffle
  25794. * @param {Boolean} [bool] modify passed array
  25795. * @return {Array} shuffled Array
  25796. * @example
  25797. * <div><code>
  25798. * function setup() {
  25799. * var regularArr = ['ABC', 'def', createVector(), TAU, Math.E];
  25800. * print(regularArr);
  25801. * shuffle(regularArr, true); // force modifications to passed array
  25802. * print(regularArr);
  25803. *
  25804. * // By default shuffle() returns a shuffled cloned array:
  25805. * var newArr = shuffle(regularArr);
  25806. * print(regularArr);
  25807. * print(newArr);
  25808. * }
  25809. * </code></div>
  25810. */
  25811. p5.prototype.shuffle = function(arr, bool) {
  25812. var isView = ArrayBuffer && ArrayBuffer.isView && ArrayBuffer.isView(arr);
  25813. arr = bool || isView ? arr : arr.slice();
  25814. var rnd, tmp, idx = arr.length;
  25815. while (idx > 1) {
  25816. rnd = Math.random()*idx | 0;
  25817. tmp = arr[--idx];
  25818. arr[idx] = arr[rnd];
  25819. arr[rnd] = tmp;
  25820. }
  25821. return arr;
  25822. };
  25823. /**
  25824. * Sorts an array of numbers from smallest to largest, or puts an array of
  25825. * words in alphabetical order. The original array is not modified; a
  25826. * re-ordered array is returned. The count parameter states the number of
  25827. * elements to sort. For example, if there are 12 elements in an array and
  25828. * count is set to 5, only the first 5 elements in the array will be sorted.
  25829. *
  25830. * @method sort
  25831. * @param {Array} list Array to sort
  25832. * @param {Number} [count] number of elements to sort, starting from 0
  25833. *
  25834. * @example
  25835. * <div class = "norender"><code>
  25836. * function setup() {
  25837. * var words = new Array("banana", "apple", "pear","lime");
  25838. * print(words); // ["banana", "apple", "pear", "lime"]
  25839. * var count = 4; // length of array
  25840. *
  25841. * words = sort(words, count);
  25842. * print(words); // ["apple", "banana", "lime", "pear"]
  25843. * }
  25844. * </div></code>
  25845. * <div class = "norender"><code>
  25846. * function setup() {
  25847. * var numbers = new Array(2,6,1,5,14,9,8,12);
  25848. * print(numbers); // [2,6,1,5,14,9,8,12]
  25849. * var count = 5; // Less than the length of the array
  25850. *
  25851. * numbers = sort(numbers, count);
  25852. * print(numbers); // [1,2,5,6,14,9,8,12]
  25853. * }
  25854. * </div></code>
  25855. */
  25856. p5.prototype.sort = function(list, count) {
  25857. var arr = count ? list.slice(0, Math.min(count, list.length)) : list;
  25858. var rest = count ? list.slice(Math.min(count, list.length)) : [];
  25859. if (typeof arr[0] === 'string') {
  25860. arr = arr.sort();
  25861. } else {
  25862. arr = arr.sort(function(a,b){return a-b;});
  25863. }
  25864. return arr.concat(rest);
  25865. };
  25866. /**
  25867. * Inserts a value or an array of values into an existing array. The first
  25868. * parameter specifies the initial array to be modified, and the second
  25869. * parameter defines the data to be inserted. The third parameter is an index
  25870. * value which specifies the array position from which to insert data.
  25871. * (Remember that array index numbering starts at zero, so the first position
  25872. * is 0, the second position is 1, and so on.)
  25873. *
  25874. * @method splice
  25875. * @param {Array} list Array to splice into
  25876. * @param {any} value value to be spliced in
  25877. * @param {Number} position in the array from which to insert data
  25878. *
  25879. * @example
  25880. * <div class = "norender"><code>
  25881. * function setup() {
  25882. * var myArray = new Array(0,1,2,3,4);
  25883. * var insArray = new Array("A","B","C");
  25884. * print(myArray); // [0,1,2,3,4]
  25885. * print(insArray); // ["A","B","C"]
  25886. *
  25887. * splice(myArray, insArray, 3);
  25888. * print(myArray); // [0,1,2,"A","B","C",3,4]
  25889. * }
  25890. * </div></code>
  25891. */
  25892. p5.prototype.splice = function(list, value, index) {
  25893. // note that splice returns spliced elements and not an array
  25894. Array.prototype.splice.apply(list, [index, 0].concat(value));
  25895. return list;
  25896. };
  25897. /**
  25898. * Extracts an array of elements from an existing array. The list parameter
  25899. * defines the array from which the elements will be copied, and the start
  25900. * and count parameters specify which elements to extract. If no count is
  25901. * given, elements will be extracted from the start to the end of the array.
  25902. * When specifying the start, remember that the first array element is 0.
  25903. * This function does not change the source array.
  25904. *
  25905. * @method subset
  25906. * @param {Array} list Array to extract from
  25907. * @param {Number} start position to begin
  25908. * @param {Number} [count] number of values to extract
  25909. * @return {Array} Array of extracted elements
  25910. *
  25911. * @example
  25912. * <div class = "norender"><code>
  25913. * function setup() {
  25914. * var myArray = new Array(1,2,3,4,5);
  25915. * print(myArray); // [1,2,3,4,5]
  25916. *
  25917. * var sub1 = subset(myArray, 0, 3);
  25918. * var sub2 = subset(myArray, 2, 2);
  25919. * print(sub1); // [1,2,3]
  25920. * print(sub2); // [3,4]
  25921. * }
  25922. * </div></code>
  25923. */
  25924. p5.prototype.subset = function(list, start, count) {
  25925. if (typeof count !== 'undefined') {
  25926. return list.slice(start, start + count);
  25927. } else {
  25928. return list.slice(start, list.length);
  25929. }
  25930. };
  25931. module.exports = p5;
  25932. },{"../core/core":37}],74:[function(_dereq_,module,exports){
  25933. /**
  25934. * @module Data
  25935. * @submodule Conversion
  25936. * @for p5
  25937. * @requires core
  25938. */
  25939. 'use strict';
  25940. var p5 = _dereq_('../core/core');
  25941. /**
  25942. * Converts a string to its floating point representation. The contents of a
  25943. * string must resemble a number, or NaN (not a number) will be returned.
  25944. * For example, float("1234.56") evaluates to 1234.56, but float("giraffe")
  25945. * will return NaN.
  25946. *
  25947. * When an array of values is passed in, then an array of floats of the same
  25948. * length is returned.
  25949. *
  25950. * @method float
  25951. * @param {String} str float string to parse
  25952. * @return {Number} floating point representation of string
  25953. * @example
  25954. * <div><code>
  25955. * var str = '20';
  25956. * var diameter = float(str);
  25957. * ellipse(width/2, height/2, diameter, diameter);
  25958. * </code></div>
  25959. *
  25960. * @alt
  25961. * 20 by 20 white ellipse in the center of the canvas
  25962. *
  25963. */
  25964. p5.prototype.float = function(str) {
  25965. if (str instanceof Array) {
  25966. return str.map(parseFloat);
  25967. }
  25968. return parseFloat(str);
  25969. };
  25970. /**
  25971. * Converts a boolean, string, or float to its integer representation.
  25972. * When an array of values is passed in, then an int array of the same length
  25973. * is returned.
  25974. *
  25975. * @method int
  25976. * @param {String|Boolean|Number|Array} n value to parse
  25977. * @return {Number} integer representation of value
  25978. * @example
  25979. * <div class='norender'><code>
  25980. * print(int("10")); // 10
  25981. * print(int(10.31)); // 10
  25982. * print(int(-10)); // -10
  25983. * print(int(true)); // 1
  25984. * print(int(false)); // 0
  25985. * print(int([false, true, "10.3", 9.8])); // [0, 1, 10, 9]
  25986. * </code></div>
  25987. */
  25988. p5.prototype.int = function(n, radix) {
  25989. radix = radix || 10;
  25990. if (typeof n === 'string') {
  25991. return parseInt(n, radix);
  25992. } else if (typeof n === 'number') {
  25993. return n | 0;
  25994. } else if (typeof n === 'boolean') {
  25995. return n ? 1 : 0;
  25996. } else if (n instanceof Array) {
  25997. return n.map(function(n) { return p5.prototype.int(n, radix); });
  25998. }
  25999. };
  26000. /**
  26001. * Converts a boolean, string or number to its string representation.
  26002. * When an array of values is passed in, then an array of strings of the same
  26003. * length is returned.
  26004. *
  26005. * @method str
  26006. * @param {String|Boolean|Number|Array} n value to parse
  26007. * @return {String} string representation of value
  26008. * @example
  26009. * <div class='norender'><code>
  26010. * print(str("10")); // "10"
  26011. * print(str(10.31)); // "10.31"
  26012. * print(str(-10)); // "-10"
  26013. * print(str(true)); // "true"
  26014. * print(str(false)); // "false"
  26015. * print(str([true, "10.3", 9.8])); // [ "true", "10.3", "9.8" ]
  26016. * </code></div>
  26017. */
  26018. p5.prototype.str = function(n) {
  26019. if (n instanceof Array) {
  26020. return n.map(p5.prototype.str);
  26021. } else {
  26022. return String(n);
  26023. }
  26024. };
  26025. /**
  26026. * Converts a number or string to its boolean representation.
  26027. * For a number, any non-zero value (positive or negative) evaluates to true,
  26028. * while zero evaluates to false. For a string, the value "true" evaluates to
  26029. * true, while any other value evaluates to false. When an array of number or
  26030. * string values is passed in, then a array of booleans of the same length is
  26031. * returned.
  26032. *
  26033. * @method boolean
  26034. * @param {String|Boolean|Number|Array} n value to parse
  26035. * @return {Boolean} boolean representation of value
  26036. * @example
  26037. * <div class='norender'><code>
  26038. * print(boolean(0)); // false
  26039. * print(boolean(1)); // true
  26040. * print(boolean("true")); // true
  26041. * print(boolean("abcd")); // false
  26042. * print(boolean([0, 12, "true"])); // [false, true, false]
  26043. * </code></div>
  26044. */
  26045. p5.prototype.boolean = function(n) {
  26046. if (typeof n === 'number') {
  26047. return n !== 0;
  26048. } else if (typeof n === 'string') {
  26049. return n.toLowerCase() === 'true';
  26050. } else if (typeof n === 'boolean') {
  26051. return n;
  26052. } else if (n instanceof Array) {
  26053. return n.map(p5.prototype.boolean);
  26054. }
  26055. };
  26056. /**
  26057. * Converts a number, string or boolean to its byte representation.
  26058. * A byte can be only a whole number between -128 and 127, so when a value
  26059. * outside of this range is converted, it wraps around to the corresponding
  26060. * byte representation. When an array of number, string or boolean values is
  26061. * passed in, then an array of bytes the same length is returned.
  26062. *
  26063. * @method byte
  26064. * @param {String|Boolean|Number|Array} n value to parse
  26065. * @return {Number} byte representation of value
  26066. * @example
  26067. * <div class='norender'><code>
  26068. * print(byte(127)); // 127
  26069. * print(byte(128)); // -128
  26070. * print(byte(23.4)); // 23
  26071. * print(byte("23.4")); // 23
  26072. * print(byte(true)); // 1
  26073. * print(byte([0, 255, "100"])); // [0, -1, 100]
  26074. * </code></div>
  26075. */
  26076. p5.prototype.byte = function(n) {
  26077. var nn = p5.prototype.int(n, 10);
  26078. if (typeof nn === 'number') {
  26079. return ((nn + 128) % 256) - 128;
  26080. } else if (nn instanceof Array) {
  26081. return nn.map(p5.prototype.byte);
  26082. }
  26083. };
  26084. /**
  26085. * Converts a number or string to its corresponding single-character
  26086. * string representation. If a string parameter is provided, it is first
  26087. * parsed as an integer and then translated into a single-character string.
  26088. * When an array of number or string values is passed in, then an array of
  26089. * single-character strings of the same length is returned.
  26090. *
  26091. * @method char
  26092. * @param {String|Number|Array} n value to parse
  26093. * @return {String} string representation of value
  26094. * @example
  26095. * <div class='norender'><code>
  26096. * print(char(65)); // "A"
  26097. * print(char("65")); // "A"
  26098. * print(char([65, 66, 67])); // [ "A", "B", "C" ]
  26099. * print(join(char([65, 66, 67]), '')); // "ABC"
  26100. * </code></div>
  26101. */
  26102. p5.prototype.char = function(n) {
  26103. if (typeof n === 'number' && !isNaN(n)) {
  26104. return String.fromCharCode(n);
  26105. } else if (n instanceof Array) {
  26106. return n.map(p5.prototype.char);
  26107. } else if (typeof n === 'string') {
  26108. return p5.prototype.char(parseInt(n, 10));
  26109. }
  26110. };
  26111. /**
  26112. * Converts a single-character string to its corresponding integer
  26113. * representation. When an array of single-character string values is passed
  26114. * in, then an array of integers of the same length is returned.
  26115. *
  26116. * @method unchar
  26117. * @param {String|Array} n value to parse
  26118. * @return {Number} integer representation of value
  26119. * @example
  26120. * <div class='norender'><code>
  26121. * print(unchar("A")); // 65
  26122. * print(unchar(["A", "B", "C"])); // [ 65, 66, 67 ]
  26123. * print(unchar(split("ABC", ""))); // [ 65, 66, 67 ]
  26124. * </code></div>
  26125. */
  26126. p5.prototype.unchar = function(n) {
  26127. if (typeof n === 'string' && n.length === 1) {
  26128. return n.charCodeAt(0);
  26129. } else if (n instanceof Array) {
  26130. return n.map(p5.prototype.unchar);
  26131. }
  26132. };
  26133. /**
  26134. * Converts a number to a string in its equivalent hexadecimal notation. If a
  26135. * second parameter is passed, it is used to set the number of characters to
  26136. * generate in the hexadecimal notation. When an array is passed in, an
  26137. * array of strings in hexadecimal notation of the same length is returned.
  26138. *
  26139. * @method hex
  26140. * @param {Number|Array} n value to parse
  26141. * @return {String} hexadecimal string representation of value
  26142. * @example
  26143. * <div class='norender'><code>
  26144. * print(hex(255)); // "000000FF"
  26145. * print(hex(255, 6)); // "0000FF"
  26146. * print(hex([0, 127, 255], 6)); // [ "000000", "00007F", "0000FF" ]
  26147. * </code></div>
  26148. */
  26149. p5.prototype.hex = function(n, digits) {
  26150. digits = (digits === undefined || digits === null) ? digits = 8 : digits;
  26151. if (n instanceof Array) {
  26152. return n.map(function(n) { return p5.prototype.hex(n, digits); });
  26153. } else if (typeof n === 'number') {
  26154. if (n < 0) {
  26155. n = 0xFFFFFFFF + n + 1;
  26156. }
  26157. var hex = Number(n).toString(16).toUpperCase();
  26158. while (hex.length < digits) {
  26159. hex = '0' + hex;
  26160. }
  26161. if (hex.length >= digits) {
  26162. hex = hex.substring(hex.length - digits, hex.length);
  26163. }
  26164. return hex;
  26165. }
  26166. };
  26167. /**
  26168. * Converts a string representation of a hexadecimal number to its equivalent
  26169. * integer value. When an array of strings in hexadecimal notation is passed
  26170. * in, an array of integers of the same length is returned.
  26171. *
  26172. * @method unhex
  26173. * @param {String|Array} n value to parse
  26174. * @return {Number} integer representation of hexadecimal value
  26175. * @example
  26176. * <div class='norender'><code>
  26177. * print(unhex("A")); // 10
  26178. * print(unhex("FF")); // 255
  26179. * print(unhex(["FF", "AA", "00"])); // [ 255, 170, 0 ]
  26180. * </code></div>
  26181. */
  26182. p5.prototype.unhex = function(n) {
  26183. if (n instanceof Array) {
  26184. return n.map(p5.prototype.unhex);
  26185. } else {
  26186. return parseInt('0x' + n, 16);
  26187. }
  26188. };
  26189. module.exports = p5;
  26190. },{"../core/core":37}],75:[function(_dereq_,module,exports){
  26191. /**
  26192. * @module Data
  26193. * @submodule String Functions
  26194. * @for p5
  26195. * @requires core
  26196. */
  26197. 'use strict';
  26198. var p5 = _dereq_('../core/core');
  26199. //return p5; //LM is this a mistake?
  26200. /**
  26201. * Combines an array of Strings into one String, each separated by the
  26202. * character(s) used for the separator parameter. To join arrays of ints or
  26203. * floats, it's necessary to first convert them to Strings using nf() or
  26204. * nfs().
  26205. *
  26206. * @method join
  26207. * @param {Array} list array of Strings to be joined
  26208. * @param {String} separator String to be placed between each item
  26209. * @return {String} joined String
  26210. * @example
  26211. * <div>
  26212. * <code>
  26213. * var array = ["Hello", "world!"]
  26214. * var separator = " "
  26215. * var message = join(array, separator);
  26216. * text(message, 5, 50);
  26217. * </code>
  26218. * </div>
  26219. *
  26220. * @alt
  26221. * "hello world!" displayed middle left of canvas.
  26222. *
  26223. */
  26224. p5.prototype.join = function(list, separator) {
  26225. return list.join(separator);
  26226. };
  26227. /**
  26228. * This function is used to apply a regular expression to a piece of text,
  26229. * and return matching groups (elements found inside parentheses) as a
  26230. * String array. If there are no matches, a null value will be returned.
  26231. * If no groups are specified in the regular expression, but the sequence
  26232. * matches, an array of length 1 (with the matched text as the first element
  26233. * of the array) will be returned.
  26234. * <br><br>
  26235. * To use the function, first check to see if the result is null. If the
  26236. * result is null, then the sequence did not match at all. If the sequence
  26237. * did match, an array is returned.
  26238. * <br><br>
  26239. * If there are groups (specified by sets of parentheses) in the regular
  26240. * expression, then the contents of each will be returned in the array.
  26241. * Element [0] of a regular expression match returns the entire matching
  26242. * string, and the match groups start at element [1] (the first group is [1],
  26243. * the second [2], and so on).
  26244. *
  26245. * @method match
  26246. * @param {String} str the String to be searched
  26247. * @param {String} regexp the regexp to be used for matching
  26248. * @return {Array} Array of Strings found
  26249. * @example
  26250. * <div>
  26251. * <code>
  26252. * var string = "Hello p5js*!"
  26253. * var regexp = "p5js\\*"
  26254. * var match = match(string, regexp);
  26255. * text(match, 5, 50);
  26256. * </code>
  26257. * </div>
  26258. *
  26259. * @alt
  26260. * "p5js*" displayed middle left of canvas.
  26261. *
  26262. */
  26263. p5.prototype.match = function(str, reg) {
  26264. return str.match(reg);
  26265. };
  26266. /**
  26267. * This function is used to apply a regular expression to a piece of text,
  26268. * and return a list of matching groups (elements found inside parentheses)
  26269. * as a two-dimensional String array. If there are no matches, a null value
  26270. * will be returned. If no groups are specified in the regular expression,
  26271. * but the sequence matches, a two dimensional array is still returned, but
  26272. * the second dimension is only of length one.
  26273. * <br><br>
  26274. * To use the function, first check to see if the result is null. If the
  26275. * result is null, then the sequence did not match at all. If the sequence
  26276. * did match, a 2D array is returned.
  26277. * <br><br>
  26278. * If there are groups (specified by sets of parentheses) in the regular
  26279. * expression, then the contents of each will be returned in the array.
  26280. * Assuming a loop with counter variable i, element [i][0] of a regular
  26281. * expression match returns the entire matching string, and the match groups
  26282. * start at element [i][1] (the first group is [i][1], the second [i][2],
  26283. * and so on).
  26284. *
  26285. * @method matchAll
  26286. * @param {String} str the String to be searched
  26287. * @param {String} regexp the regexp to be used for matching
  26288. * @return {Array} 2d Array of Strings found
  26289. * @example
  26290. * <div class="norender">
  26291. * <code>
  26292. * var string = "Hello p5js*! Hello world!"
  26293. * var regexp = "Hello"
  26294. * matchAll(string, regexp);
  26295. * </code>
  26296. * </div>
  26297. */
  26298. p5.prototype.matchAll = function(str, reg) {
  26299. var re = new RegExp(reg, 'g');
  26300. var match = re.exec(str);
  26301. var matches = [];
  26302. while (match !== null) {
  26303. matches.push(match);
  26304. // matched text: match[0]
  26305. // match start: match.index
  26306. // capturing group n: match[n]
  26307. match = re.exec(str);
  26308. }
  26309. return matches;
  26310. };
  26311. /**
  26312. * Utility function for formatting numbers into strings. There are two
  26313. * versions: one for formatting floats, and one for formatting ints.
  26314. * The values for the digits, left, and right parameters should always
  26315. * be positive integers.
  26316. *
  26317. * @method nf
  26318. * @param {Number|Array} num the Number to format
  26319. * @param {Number} [left] number of digits to the left of the
  26320. * decimal point
  26321. * @param {Number} [right] number of digits to the right of the
  26322. * decimal point
  26323. * @return {String|Array} formatted String
  26324. * @example
  26325. * <div>
  26326. * <code>
  26327. * function setup() {
  26328. * background(200);
  26329. * var num = 112.53106115;
  26330. *
  26331. * noStroke();
  26332. * fill(0);
  26333. * textSize(14);
  26334. * // Draw formatted numbers
  26335. * text(nf(num, 5, 2), 10, 20);
  26336. *
  26337. * text(nf(num, 4, 3), 10, 55);
  26338. *
  26339. * text(nf(num, 3, 6), 10, 85);
  26340. *
  26341. * // Draw dividing lines
  26342. * stroke(120);
  26343. * line(0, 30, width, 30);
  26344. * line(0, 65, width, 65);
  26345. * }
  26346. * </code>
  26347. * </div>
  26348. *
  26349. * @alt
  26350. * "0011253" top left, "0112.531" mid left, "112.531061" bottom left canvas
  26351. *
  26352. */
  26353. p5.prototype.nf = function () {
  26354. if (arguments[0] instanceof Array) {
  26355. var a = arguments[1];
  26356. var b = arguments[2];
  26357. return arguments[0].map(function (x) {
  26358. return doNf(x, a, b);
  26359. });
  26360. }
  26361. else{
  26362. var typeOfFirst = Object.prototype.toString.call(arguments[0]);
  26363. if(typeOfFirst === '[object Arguments]'){
  26364. if(arguments[0].length===3){
  26365. return this.nf(arguments[0][0],arguments[0][1],arguments[0][2]);
  26366. }
  26367. else if(arguments[0].length===2){
  26368. return this.nf(arguments[0][0],arguments[0][1]);
  26369. }
  26370. else{
  26371. return this.nf(arguments[0][0]);
  26372. }
  26373. }
  26374. else {
  26375. return doNf.apply(this, arguments);
  26376. }
  26377. }
  26378. };
  26379. function doNf() {
  26380. var num = arguments[0];
  26381. var neg = num < 0;
  26382. var n = neg ? num.toString().substring(1) : num.toString();
  26383. var decimalInd = n.indexOf('.');
  26384. var intPart = decimalInd !== -1 ? n.substring(0, decimalInd) : n;
  26385. var decPart = decimalInd !== -1 ? n.substring(decimalInd + 1) : '';
  26386. var str = neg ? '-' : '';
  26387. if (arguments.length === 3) {
  26388. var decimal = '';
  26389. if(decimalInd !== -1 || arguments[2] - decPart.length > 0){
  26390. decimal = '.';
  26391. }
  26392. if (decPart.length > arguments[2]) {
  26393. decPart = decPart.substring(0, arguments[2]);
  26394. }
  26395. for (var i = 0; i < arguments[1] - intPart.length; i++) {
  26396. str += '0';
  26397. }
  26398. str += intPart;
  26399. str += decimal;
  26400. str += decPart;
  26401. for (var j = 0; j < arguments[2] - decPart.length; j++) {
  26402. str += '0';
  26403. }
  26404. return str;
  26405. }
  26406. else {
  26407. for (var k = 0; k < Math.max(arguments[1] - intPart.length, 0); k++) {
  26408. str += '0';
  26409. }
  26410. str += n;
  26411. return str;
  26412. }
  26413. }
  26414. /**
  26415. * Utility function for formatting numbers into strings and placing
  26416. * appropriate commas to mark units of 1000. There are two versions: one
  26417. * for formatting ints, and one for formatting an array of ints. The value
  26418. * for the right parameter should always be a positive integer.
  26419. *
  26420. * @method nfc
  26421. * @param {Number|Array} num the Number to format
  26422. * @param {Number} [right] number of digits to the right of the
  26423. * decimal point
  26424. * @return {String|Array} formatted String
  26425. * @example
  26426. * <div>
  26427. * <code>
  26428. * function setup() {
  26429. * background(200);
  26430. * var num = 11253106.115;
  26431. * var numArr = new Array(1,1,2);
  26432. *
  26433. * noStroke();
  26434. * fill(0);
  26435. * textSize(12);
  26436. *
  26437. * // Draw formatted numbers
  26438. * text(nfc(num, 4, 2), 10, 30);
  26439. * text(nfc(numArr, 2, 1), 10, 80);
  26440. *
  26441. * // Draw dividing line
  26442. * stroke(120);
  26443. * line(0, 50, width, 50);
  26444. * }
  26445. * </code>
  26446. * </div>
  26447. *
  26448. * @alt
  26449. * "11,253,106.115" top middle and "1.00,1.00,2.00" displayed bottom mid
  26450. *
  26451. */
  26452. p5.prototype.nfc = function () {
  26453. if (arguments[0] instanceof Array) {
  26454. var a = arguments[1];
  26455. return arguments[0].map(function (x) {
  26456. return doNfc(x, a);
  26457. });
  26458. } else {
  26459. return doNfc.apply(this, arguments);
  26460. }
  26461. };
  26462. function doNfc() {
  26463. var num = arguments[0].toString();
  26464. var dec = num.indexOf('.');
  26465. var rem = dec !== -1 ? num.substring(dec) : '';
  26466. var n = dec !== -1 ? num.substring(0, dec) : num;
  26467. n = n.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
  26468. if (arguments[1] === 0) {
  26469. rem = '';
  26470. }
  26471. else if(arguments[1] !== undefined){
  26472. if(arguments[1] > rem.length){
  26473. rem+= dec === -1 ? '.' : '';
  26474. var len = arguments[1] - rem.length + 1;
  26475. for(var i =0; i< len; i++){
  26476. rem += '0';
  26477. }
  26478. }
  26479. else{
  26480. rem = rem.substring(0, arguments[1] + 1);
  26481. }
  26482. }
  26483. return n + rem;
  26484. }
  26485. /**
  26486. * Utility function for formatting numbers into strings. Similar to nf() but
  26487. * puts a "+" in front of positive numbers and a "-" in front of negative
  26488. * numbers. There are two versions: one for formatting floats, and one for
  26489. * formatting ints. The values for left, and right parameters
  26490. * should always be positive integers.
  26491. *
  26492. * @method nfp
  26493. * @param {Number|Array} num the Number to format
  26494. * @param {Number} [left] number of digits to the left of the decimal
  26495. * point
  26496. * @param {Number} [right] number of digits to the right of the
  26497. * decimal point
  26498. * @return {String|Array} formatted String
  26499. * @example
  26500. * <div>
  26501. * <code>
  26502. * function setup() {
  26503. * background(200);
  26504. * var num1 = 11253106.115;
  26505. * var num2 = -11253106.115;
  26506. *
  26507. * noStroke();
  26508. * fill(0);
  26509. * textSize(12);
  26510. *
  26511. * // Draw formatted numbers
  26512. * text(nfp(num1, 4, 2), 10, 30);
  26513. * text(nfp(num2, 4, 2), 10, 80);
  26514. *
  26515. * // Draw dividing line
  26516. * stroke(120);
  26517. * line(0, 50, width, 50);
  26518. * }
  26519. * </code>
  26520. * </div>
  26521. *
  26522. * @alt
  26523. * "+11253106.11" top middle and "-11253106.11" displayed bottom middle
  26524. *
  26525. */
  26526. p5.prototype.nfp = function() {
  26527. var nfRes = this.nf.apply(this, arguments);
  26528. if (nfRes instanceof Array) {
  26529. return nfRes.map(addNfp);
  26530. } else {
  26531. return addNfp(nfRes);
  26532. }
  26533. };
  26534. function addNfp() {
  26535. return (
  26536. parseFloat(arguments[0]) > 0) ?
  26537. '+'+arguments[0].toString() :
  26538. arguments[0].toString();
  26539. }
  26540. /**
  26541. * Utility function for formatting numbers into strings. Similar to nf() but
  26542. * puts a " " (space) in front of positive numbers and a "-" in front of
  26543. * negative numbers. There are two versions: one for formatting floats, and
  26544. * one for formatting ints. The values for the digits, left, and right
  26545. * parameters should always be positive integers.
  26546. *
  26547. * @method nfs
  26548. * @param {Number|Array} num the Number to format
  26549. * @param {Number} [left] number of digits to the left of the decimal
  26550. * point
  26551. * @param {Number} [right] number of digits to the right of the
  26552. * decimal point
  26553. * @return {String|Array} formatted String
  26554. * @example
  26555. * <div>
  26556. * <code>
  26557. * function setup() {
  26558. * background(200);
  26559. * var num1 = 11253106.115;
  26560. * var num2 = -11253106.115;
  26561. *
  26562. * noStroke();
  26563. * fill(0);
  26564. * textSize(12);
  26565. * // Draw formatted numbers
  26566. * text(nfs(num1, 4, 2), 10, 30);
  26567. *
  26568. * text(nfs(num2, 4, 2), 10, 80);
  26569. *
  26570. * // Draw dividing line
  26571. * stroke(120);
  26572. * line(0, 50, width, 50);
  26573. * }
  26574. * </code>
  26575. * </div>
  26576. *
  26577. * @alt
  26578. * "11253106.11" top middle and "-11253106.11" displayed bottom middle
  26579. *
  26580. */
  26581. p5.prototype.nfs = function() {
  26582. var nfRes = this.nf.apply(this, arguments);
  26583. if (nfRes instanceof Array) {
  26584. return nfRes.map(addNfs);
  26585. } else {
  26586. return addNfs(nfRes);
  26587. }
  26588. };
  26589. function addNfs() {
  26590. return (
  26591. parseFloat(arguments[0]) > 0) ?
  26592. ' '+arguments[0].toString() :
  26593. arguments[0].toString();
  26594. }
  26595. /**
  26596. * The split() function maps to String.split(), it breaks a String into
  26597. * pieces using a character or string as the delimiter. The delim parameter
  26598. * specifies the character or characters that mark the boundaries between
  26599. * each piece. A String[] array is returned that contains each of the pieces.
  26600. *
  26601. * The splitTokens() function works in a similar fashion, except that it
  26602. * splits using a range of characters instead of a specific character or
  26603. * sequence.
  26604. *
  26605. * @method split
  26606. * @param {String} value the String to be split
  26607. * @param {String} delim the String used to separate the data
  26608. * @return {Array} Array of Strings
  26609. * @example
  26610. * <div>
  26611. * <code>
  26612. * var names = "Pat,Xio,Alex"
  26613. * var splitString = split(names, ",");
  26614. * text(splitString[0], 5, 30);
  26615. * text(splitString[1], 5, 50);
  26616. * text(splitString[2], 5, 70);
  26617. * </code>
  26618. * </div>
  26619. *
  26620. * @alt
  26621. * "pat" top left, "Xio" mid left and "Alex" displayed bottom left
  26622. *
  26623. */
  26624. p5.prototype.split = function(str, delim) {
  26625. return str.split(delim);
  26626. };
  26627. /**
  26628. * The splitTokens() function splits a String at one or many character
  26629. * delimiters or "tokens." The delim parameter specifies the character or
  26630. * characters to be used as a boundary.
  26631. * <br><br>
  26632. * If no delim characters are specified, any whitespace character is used to
  26633. * split. Whitespace characters include tab (\t), line feed (\n), carriage
  26634. * return (\r), form feed (\f), and space.
  26635. *
  26636. * @method splitTokens
  26637. * @param {String} value the String to be split
  26638. * @param {String} [delim] list of individual Strings that will be used as
  26639. * separators
  26640. * @return {Array} Array of Strings
  26641. * @example
  26642. * <div class = "norender">
  26643. * <code>
  26644. * function setup() {
  26645. * var myStr = "Mango, Banana, Lime";
  26646. * var myStrArr = splitTokens(myStr, ",");
  26647. *
  26648. * print(myStrArr); // prints : ["Mango"," Banana"," Lime"]
  26649. * }
  26650. * </code>
  26651. * </div>
  26652. */
  26653. p5.prototype.splitTokens = function() {
  26654. var d,sqo,sqc,str;
  26655. str = arguments[1];
  26656. if (arguments.length > 1) {
  26657. sqc = /\]/g.exec(str);
  26658. sqo = /\[/g.exec(str);
  26659. if ( sqo && sqc ) {
  26660. str = str.slice(0, sqc.index) + str.slice(sqc.index+1);
  26661. sqo = /\[/g.exec(str);
  26662. str = str.slice(0, sqo.index) + str.slice(sqo.index+1);
  26663. d = new RegExp('[\\['+str+'\\]]','g');
  26664. } else if ( sqc ) {
  26665. str = str.slice(0, sqc.index) + str.slice(sqc.index+1);
  26666. d = new RegExp('[' + str + '\\]]', 'g');
  26667. } else if(sqo) {
  26668. str = str.slice(0, sqo.index) + str.slice(sqo.index+1);
  26669. d = new RegExp('[' + str + '\\[]', 'g');
  26670. } else {
  26671. d = new RegExp('[' + str + ']', 'g');
  26672. }
  26673. } else {
  26674. d = /\s/g;
  26675. }
  26676. return arguments[0].split(d).filter(function(n){return n;});
  26677. };
  26678. /**
  26679. * Removes whitespace characters from the beginning and end of a String. In
  26680. * addition to standard whitespace characters such as space, carriage return,
  26681. * and tab, this function also removes the Unicode "nbsp" character.
  26682. *
  26683. * @method trim
  26684. * @param {String|Array} str a String or Array of Strings to be trimmed
  26685. * @return {String|Array} a trimmed String or Array of Strings
  26686. * @example
  26687. * <div>
  26688. * <code>
  26689. * var string = trim(" No new lines\n ");
  26690. * text(string +" here", 2, 50);
  26691. * </code>
  26692. * </div>
  26693. *
  26694. * @alt
  26695. * "No new lines here" displayed center canvas
  26696. *
  26697. */
  26698. p5.prototype.trim = function(str) {
  26699. if (str instanceof Array) {
  26700. return str.map(this.trim);
  26701. } else {
  26702. return str.trim();
  26703. }
  26704. };
  26705. module.exports = p5;
  26706. },{"../core/core":37}],76:[function(_dereq_,module,exports){
  26707. /**
  26708. * @module IO
  26709. * @submodule Time & Date
  26710. * @for p5
  26711. * @requires core
  26712. */
  26713. 'use strict';
  26714. var p5 = _dereq_('../core/core');
  26715. /**
  26716. * p5.js communicates with the clock on your computer. The day() function
  26717. * returns the current day as a value from 1 - 31.
  26718. *
  26719. * @method day
  26720. * @return {Number} the current day
  26721. * @example
  26722. * <div>
  26723. * <code>
  26724. * var d = day();
  26725. * text("Current day: \n" + d, 5, 50);
  26726. * </code>
  26727. * </div>
  26728. *
  26729. * @alt
  26730. * Current day is displayed
  26731. *
  26732. */
  26733. p5.prototype.day = function() {
  26734. return new Date().getDate();
  26735. };
  26736. /**
  26737. * p5.js communicates with the clock on your computer. The hour() function
  26738. * returns the current hour as a value from 0 - 23.
  26739. *
  26740. * @method hour
  26741. * @return {Number} the current hour
  26742. * @example
  26743. * <div>
  26744. * <code>
  26745. * var h = hour();
  26746. * text("Current hour:\n" + h, 5, 50);
  26747. * </code>
  26748. * </div>
  26749. *
  26750. * @alt
  26751. * Current hour is displayed
  26752. *
  26753. */
  26754. p5.prototype.hour = function() {
  26755. return new Date().getHours();
  26756. };
  26757. /**
  26758. * p5.js communicates with the clock on your computer. The minute() function
  26759. * returns the current minute as a value from 0 - 59.
  26760. *
  26761. * @method minute
  26762. * @return {Number} the current minute
  26763. * @example
  26764. * <div>
  26765. * <code>
  26766. * var m = minute();
  26767. * text("Current minute: \n" + m, 5, 50);
  26768. * </code>
  26769. * </div>
  26770. *
  26771. * @alt
  26772. * Current minute is displayed
  26773. *
  26774. */
  26775. p5.prototype.minute = function() {
  26776. return new Date().getMinutes();
  26777. };
  26778. /**
  26779. * Returns the number of milliseconds (thousandths of a second) since
  26780. * starting the program. This information is often used for timing events and
  26781. * animation sequences.
  26782. *
  26783. * @method millis
  26784. * @return {Number} the number of milliseconds since starting the program
  26785. * @example
  26786. * <div>
  26787. * <code>
  26788. * var millisecond = millis();
  26789. * text("Milliseconds \nrunning: \n" + millisecond, 5, 40);
  26790. * </code>
  26791. * </div>
  26792. *
  26793. * @alt
  26794. * number of milliseconds since program has started displayed
  26795. *
  26796. */
  26797. p5.prototype.millis = function() {
  26798. return window.performance.now();
  26799. };
  26800. /**
  26801. * p5.js communicates with the clock on your computer. The month() function
  26802. * returns the current month as a value from 1 - 12.
  26803. *
  26804. * @method month
  26805. * @return {Number} the current month
  26806. * @example
  26807. * <div>
  26808. * <code>
  26809. * var m = month();
  26810. * text("Current month: \n" + m, 5, 50);
  26811. * </code>
  26812. * </div>
  26813. *
  26814. * @alt
  26815. * Current month is displayed
  26816. *
  26817. */
  26818. p5.prototype.month = function() {
  26819. return new Date().getMonth() + 1; //January is 0!
  26820. };
  26821. /**
  26822. * p5.js communicates with the clock on your computer. The second() function
  26823. * returns the current second as a value from 0 - 59.
  26824. *
  26825. * @method second
  26826. * @return {Number} the current second
  26827. * @example
  26828. * <div>
  26829. * <code>
  26830. * var s = second();
  26831. * text("Current second: \n" + s, 5, 50);
  26832. * </code>
  26833. * </div>
  26834. *
  26835. * @alt
  26836. * Current second is displayed
  26837. *
  26838. */
  26839. p5.prototype.second = function() {
  26840. return new Date().getSeconds();
  26841. };
  26842. /**
  26843. * p5.js communicates with the clock on your computer. The year() function
  26844. * returns the current year as an integer (2014, 2015, 2016, etc).
  26845. *
  26846. * @method year
  26847. * @return {Number} the current year
  26848. * @example
  26849. * <div>
  26850. * <code>
  26851. * var y = year();
  26852. * text("Current year: \n" + y, 5, 50);
  26853. * </code>
  26854. * </div>
  26855. *
  26856. * @alt
  26857. * Current year is displayed
  26858. *
  26859. */
  26860. p5.prototype.year = function() {
  26861. return new Date().getFullYear();
  26862. };
  26863. module.exports = p5;
  26864. },{"../core/core":37}],77:[function(_dereq_,module,exports){
  26865. /**
  26866. * @module Lights, Camera
  26867. * @submodule Camera
  26868. * @for p5
  26869. * @requires core
  26870. */
  26871. 'use strict';
  26872. var p5 = _dereq_('../core/core');
  26873. /**
  26874. * Sets camera position
  26875. * @method camera
  26876. * @param {Number} x camera position value on x axis
  26877. * @param {Number} y camera position value on y axis
  26878. * @param {Number} z camera position value on z axis
  26879. * @return {p5} the p5 object
  26880. * @example
  26881. * <div>
  26882. * <code>
  26883. * function setup(){
  26884. * createCanvas(100, 100, WEBGL);
  26885. * }
  26886. * function draw(){
  26887. * //move the camera away from the plane by a sin wave
  26888. * camera(0, 0, sin(frameCount * 0.01) * 100);
  26889. * plane(120, 120);
  26890. * }
  26891. * </code>
  26892. * </div>
  26893. *
  26894. * @alt
  26895. * blue square shrinks in size grows to fill canvas. disappears then loops.
  26896. *
  26897. */
  26898. p5.prototype.camera = function(x, y, z){
  26899. //what it manipulates is the model view matrix
  26900. this._renderer.translate(-x, -y, -z);
  26901. };
  26902. /**
  26903. * Sets perspective camera
  26904. * @method perspective
  26905. * @param {Number} fovy camera frustum vertical field of view,
  26906. * from bottom to top of view, in degrees
  26907. * @param {Number} aspect camera frustum aspect ratio
  26908. * @param {Number} near frustum near plane length
  26909. * @param {Number} far frustum far plane length
  26910. * @return {p5} the p5 object
  26911. * @example
  26912. * <div>
  26913. * <code>
  26914. * //drag mouse to toggle the world!
  26915. * //you will see there's a vanish point
  26916. * function setup(){
  26917. * createCanvas(100, 100, WEBGL);
  26918. * var fov = 60 / 180 * PI;
  26919. * var cameraZ = (height/2.0) / tan(fov/2.0);
  26920. * perspective(60 / 180 * PI, width/height, cameraZ * 0.1, cameraZ * 10);
  26921. * }
  26922. * function draw(){
  26923. * background(200);
  26924. * orbitControl();
  26925. * for(var i = -1; i < 2; i++){
  26926. * for(var j = -2; j < 3; j++){
  26927. * push();
  26928. * translate(i*160, 0, j*160);
  26929. * box(40, 40, 40);
  26930. * pop();
  26931. * }
  26932. * }
  26933. * }
  26934. * </code>
  26935. * </div>
  26936. *
  26937. * @alt
  26938. * colored 3d boxes toggleable with mouse position
  26939. *
  26940. */
  26941. p5.prototype.perspective = function(fovy,aspect,near,far) {
  26942. fovy = fovy || (60 / 180 * this.PI);
  26943. aspect = aspect || (this.width/this.height);
  26944. near = near || ((this.height/2.0) / this.tan(fovy/2.0) * 0.1);
  26945. far = far || ((this.height/2.0) / this.tan(fovy/2.0) * 10);
  26946. this._renderer.uPMatrix = p5.Matrix.identity();
  26947. this._renderer.uPMatrix.perspective(fovy,aspect,near,far);
  26948. this._renderer._curCamera = 'custom';
  26949. };
  26950. /**
  26951. * Setup ortho camera
  26952. * @method ortho
  26953. * @param {Number} left camera frustum left plane
  26954. * @param {Number} right camera frustum right plane
  26955. * @param {Number} bottom camera frustum bottom plane
  26956. * @param {Number} top camera frustum top plane
  26957. * @param {Number} near camera frustum near plane
  26958. * @param {Number} far camera frustum far plane
  26959. * @return {p5} the p5 object
  26960. * @example
  26961. * <div>
  26962. * <code>
  26963. * //drag mouse to toggle the world!
  26964. * //there's no vanish point
  26965. * function setup(){
  26966. * createCanvas(100, 100, WEBGL);
  26967. * ortho(-width/2, width/2, height/2, -height/2, 0, 500);
  26968. * }
  26969. * function draw(){
  26970. * background(200);
  26971. * orbitControl();
  26972. * for(var i = -1; i < 2; i++){
  26973. * for(var j = -2; j < 3; j++){
  26974. * push();
  26975. * translate(i*160, 0, j*160);
  26976. * box(40, 40, 40);
  26977. * pop();
  26978. * }
  26979. * }
  26980. * }
  26981. * </code>
  26982. * </div>
  26983. *
  26984. * @alt
  26985. * 3 3d boxes, reveal several more boxes on 3d plane when mouse used to toggle
  26986. *
  26987. */
  26988. p5.prototype.ortho = function(left,right,bottom,top,near,far) {
  26989. left = left || (-this.width/2);
  26990. right = right || (this.width/2);
  26991. bottom = bottom || (-this.height/2);
  26992. top = top || (this.height/2);
  26993. near = near || 0;
  26994. far = far || Math.max(this.width, this.height);
  26995. this._renderer.uPMatrix = p5.Matrix.identity();
  26996. this._renderer.uPMatrix.ortho(left,right,bottom,top,near,far);
  26997. this._renderer._curCamera = 'custom';
  26998. };
  26999. module.exports = p5;
  27000. },{"../core/core":37}],78:[function(_dereq_,module,exports){
  27001. 'use strict';
  27002. var p5 = _dereq_('../core/core');
  27003. //@TODO: implement full orbit controls including
  27004. //pan, zoom, quaternion rotation, etc.
  27005. p5.prototype.orbitControl = function(){
  27006. if(this.mouseIsPressed){
  27007. this.rotateY((this.mouseX - this.width / 2) / (this.width / 2));
  27008. this.rotateX((this.mouseY - this.height / 2) / (this.width / 2));
  27009. }
  27010. return this;
  27011. };
  27012. module.exports = p5;
  27013. },{"../core/core":37}],79:[function(_dereq_,module,exports){
  27014. /**
  27015. * @module Lights, Camera
  27016. * @submodule Lights
  27017. * @for p5
  27018. * @requires core
  27019. */
  27020. 'use strict';
  27021. var p5 = _dereq_('../core/core');
  27022. /**
  27023. * Creates an ambient light with a color
  27024. * @method ambientLight
  27025. * @param {Number|Array|String|p5.Color} v1 gray value,
  27026. * red or hue value (depending on the current color mode),
  27027. * or color Array, or CSS color string
  27028. * @param {Number} [v2] optional: green or saturation value
  27029. * @param {Number} [v3] optional: blue or brightness value
  27030. * @param {Number} [a] optional: opacity
  27031. * @return {p5} the p5 object
  27032. * @example
  27033. * <div>
  27034. * <code>
  27035. * function setup(){
  27036. * createCanvas(100, 100, WEBGL);
  27037. * }
  27038. * function draw(){
  27039. * background(0);
  27040. * ambientLight(150);
  27041. * ambientMaterial(250);
  27042. * sphere(50);
  27043. * }
  27044. * </code>
  27045. * </div>
  27046. *
  27047. * @alt
  27048. * nothing displayed
  27049. *
  27050. */
  27051. p5.prototype.ambientLight = function(v1, v2, v3, a){
  27052. var gl = this._renderer.GL;
  27053. var shaderProgram = this._renderer._getShader(
  27054. 'lightVert', 'lightTextureFrag');
  27055. gl.useProgram(shaderProgram);
  27056. shaderProgram.uAmbientColor = gl.getUniformLocation(
  27057. shaderProgram,
  27058. 'uAmbientColor[' + this._renderer.ambientLightCount + ']');
  27059. var color = this._renderer._pInst.color.apply(
  27060. this._renderer._pInst, arguments);
  27061. var colors = color._array;
  27062. gl.uniform3f( shaderProgram.uAmbientColor,
  27063. colors[0], colors[1], colors[2]);
  27064. //in case there's no material color for the geometry
  27065. shaderProgram.uMaterialColor = gl.getUniformLocation(
  27066. shaderProgram, 'uMaterialColor' );
  27067. gl.uniform4f( shaderProgram.uMaterialColor, 1, 1, 1, 1);
  27068. this._renderer.ambientLightCount ++;
  27069. shaderProgram.uAmbientLightCount =
  27070. gl.getUniformLocation(shaderProgram, 'uAmbientLightCount');
  27071. gl.uniform1i(shaderProgram.uAmbientLightCount,
  27072. this._renderer.ambientLightCount);
  27073. return this;
  27074. };
  27075. /**
  27076. * Creates a directional light with a color and a direction
  27077. * @method directionalLight
  27078. * @param {Number|Array|String|p5.Color} v1 gray value,
  27079. * red or hue value (depending on the current color mode),
  27080. * or color Array, or CSS color string
  27081. * @param {Number} [v2] optional: green or saturation value
  27082. * @param {Number} [v3] optional: blue or brightness value
  27083. * @param {Number} [a] optional: opacity
  27084. * @param {Number|p5.Vector} x x axis direction or a p5.Vector
  27085. * @param {Number} [y] optional: y axis direction
  27086. * @param {Number} [z] optional: z axis direction
  27087. * @return {p5} the p5 object
  27088. * @example
  27089. * <div>
  27090. * <code>
  27091. * function setup(){
  27092. * createCanvas(100, 100, WEBGL);
  27093. * }
  27094. * function draw(){
  27095. * background(0);
  27096. * //move your mouse to change light direction
  27097. * var dirX = (mouseX / width - 0.5) *2;
  27098. * var dirY = (mouseY / height - 0.5) *(-2);
  27099. * directionalLight(250, 250, 250, dirX, dirY, 0.25);
  27100. * ambientMaterial(250);
  27101. * sphere(50);
  27102. * }
  27103. * </code>
  27104. * </div>
  27105. *
  27106. * @alt
  27107. * light source on canvas changeable with mouse position
  27108. *
  27109. */
  27110. p5.prototype.directionalLight = function(v1, v2, v3, a, x, y, z) {
  27111. var gl = this._renderer.GL;
  27112. var shaderProgram = this._renderer._getShader(
  27113. 'lightVert', 'lightTextureFrag');
  27114. gl.useProgram(shaderProgram);
  27115. shaderProgram.uDirectionalColor = gl.getUniformLocation(
  27116. shaderProgram,
  27117. 'uDirectionalColor[' + this._renderer.directionalLightCount + ']');
  27118. //@TODO: check parameters number
  27119. var color = this._renderer._pInst.color.apply(
  27120. this._renderer._pInst, [v1, v2, v3]);
  27121. var colors = color._array;
  27122. gl.uniform3f( shaderProgram.uDirectionalColor,
  27123. colors[0], colors[1], colors[2]);
  27124. var _x, _y, _z;
  27125. var args = new Array(arguments.length);
  27126. for (var i = 0; i < args.length; ++i) {
  27127. args[i] = arguments[i];
  27128. }
  27129. if(typeof args[args.length-1] === 'number'){
  27130. _x = args[args.length-3];
  27131. _y = args[args.length-2];
  27132. _z = args[args.length-1];
  27133. }else{
  27134. try{
  27135. _x = args[args.length-1].x;
  27136. _y = args[args.length-1].y;
  27137. _z = args[args.length-1].z;
  27138. }
  27139. catch(error){
  27140. throw error;
  27141. }
  27142. }
  27143. shaderProgram.uLightingDirection = gl.getUniformLocation(
  27144. shaderProgram,
  27145. 'uLightingDirection[' + this._renderer.directionalLightCount + ']');
  27146. gl.uniform3f( shaderProgram.uLightingDirection, _x, _y, _z);
  27147. //in case there's no material color for the geometry
  27148. shaderProgram.uMaterialColor = gl.getUniformLocation(
  27149. shaderProgram, 'uMaterialColor' );
  27150. gl.uniform4f( shaderProgram.uMaterialColor, 1, 1, 1, 1);
  27151. this._renderer.directionalLightCount ++;
  27152. shaderProgram.uDirectionalLightCount =
  27153. gl.getUniformLocation(shaderProgram, 'uDirectionalLightCount');
  27154. gl.uniform1i(shaderProgram.uDirectionalLightCount,
  27155. this._renderer.directionalLightCount);
  27156. return this;
  27157. };
  27158. /**
  27159. * Creates a point light with a color and a light position
  27160. * @method pointLight
  27161. * @param {Number|Array|String|p5.Color} v1 gray value,
  27162. * red or hue value (depending on the current color mode),
  27163. * or color Array, or CSS color string
  27164. * @param {Number} [v2] optional: green or saturation value
  27165. * @param {Number} [v3] optional: blue or brightness value
  27166. * @param {Number} [a] optional: opacity
  27167. * @param {Number|p5.Vector} x x axis position or a p5.Vector
  27168. * @param {Number} [y] optional: y axis position
  27169. * @param {Number} [z] optional: z axis position
  27170. * @return {p5} the p5 object
  27171. * @example
  27172. * <div>
  27173. * <code>
  27174. * function setup(){
  27175. * createCanvas(100, 100, WEBGL);
  27176. * }
  27177. * function draw(){
  27178. * background(0);
  27179. * //move your mouse to change light position
  27180. * var locY = (mouseY / height - 0.5) *(-2);
  27181. * var locX = (mouseX / width - 0.5) *2;
  27182. * //to set the light position,
  27183. * //think of the world's coordinate as:
  27184. * // -1,1 -------- 1,1
  27185. * // | |
  27186. * // | |
  27187. * // | |
  27188. * // -1,-1---------1,-1
  27189. * pointLight(250, 250, 250, locX, locY, 0);
  27190. * ambientMaterial(250);
  27191. * sphere(50);
  27192. * }
  27193. * </code>
  27194. * </div>
  27195. *
  27196. * @alt
  27197. * spot light on canvas changes position with mouse
  27198. *
  27199. */
  27200. p5.prototype.pointLight = function(v1, v2, v3, a, x, y, z) {
  27201. var gl = this._renderer.GL;
  27202. var shaderProgram = this._renderer._getShader(
  27203. 'lightVert', 'lightTextureFrag');
  27204. gl.useProgram(shaderProgram);
  27205. shaderProgram.uPointLightColor = gl.getUniformLocation(
  27206. shaderProgram,
  27207. 'uPointLightColor[' + this._renderer.pointLightCount + ']');
  27208. //@TODO: check parameters number
  27209. var color = this._renderer._pInst.color.apply(
  27210. this._renderer._pInst, [v1, v2, v3]);
  27211. var colors = color._array;
  27212. gl.uniform3f( shaderProgram.uPointLightColor,
  27213. colors[0], colors[1], colors[2]);
  27214. var _x, _y, _z;
  27215. var args = new Array(arguments.length);
  27216. for (var i = 0; i < args.length; ++i) {
  27217. args[i] = arguments[i];
  27218. }
  27219. if(typeof args[args.length-1] === 'number'){
  27220. _x = args[args.length-3];
  27221. _y = args[args.length-2];
  27222. _z = args[args.length-1];
  27223. }else{
  27224. try{
  27225. _x = args[args.length-1].x;
  27226. _y = args[args.length-1].y;
  27227. _z = args[args.length-1].z;
  27228. }
  27229. catch(error){
  27230. throw error;
  27231. }
  27232. }
  27233. shaderProgram.uPointLightLocation = gl.getUniformLocation(
  27234. shaderProgram,
  27235. 'uPointLightLocation[' + this._renderer.pointLightCount + ']');
  27236. gl.uniform3f( shaderProgram.uPointLightLocation, _x, _y, _z);
  27237. //in case there's no material color for the geometry
  27238. shaderProgram.uMaterialColor = gl.getUniformLocation(
  27239. shaderProgram, 'uMaterialColor' );
  27240. gl.uniform4f( shaderProgram.uMaterialColor, 1, 1, 1, 1);
  27241. this._renderer.pointLightCount ++;
  27242. shaderProgram.uPointLightCount =
  27243. gl.getUniformLocation(shaderProgram, 'uPointLightCount');
  27244. gl.uniform1i(shaderProgram.uPointLightCount,
  27245. this._renderer.pointLightCount);
  27246. return this;
  27247. };
  27248. module.exports = p5;
  27249. },{"../core/core":37}],80:[function(_dereq_,module,exports){
  27250. /**
  27251. * @module Shape
  27252. * @submodule 3D Models
  27253. * @for p5
  27254. * @requires core
  27255. * @requires p5.Geometry3D
  27256. */
  27257. 'use strict';
  27258. var p5 = _dereq_('../core/core');
  27259. _dereq_('./p5.Geometry');
  27260. /**
  27261. * Load a 3d model from an OBJ file.
  27262. * <br><br>
  27263. * One of the limitations of the OBJ format is that it doesn't have a built-in
  27264. * sense of scale. This means that models exported from different programs might
  27265. * be very different sizes. If your model isn't displaying, try calling
  27266. * loadModel() with the normalized parameter set to true. This will resize the
  27267. * model to a scale appropriate for p5. You can also make additional changes to
  27268. * the final size of your model with the scale() function.
  27269. *
  27270. * @method loadModel
  27271. * @param {String} path Path of the model to be loaded
  27272. * @param {Boolean} [normalize] If true, scale the model to a
  27273. * standardized size when loading
  27274. * @param {Function(p5.Geometry3D)} [successCallback] Function to be called
  27275. * once the model is loaded. Will be passed
  27276. * the 3D model object.
  27277. * @param {Function(Event)} [failureCallback] called with event error if
  27278. * the image fails to load.
  27279. * @return {p5.Geometry} the p5.Geometry3D object
  27280. * @example
  27281. * <div>
  27282. * <code>
  27283. * //draw a spinning teapot
  27284. * var teapot;
  27285. *
  27286. * function setup(){
  27287. * createCanvas(100, 100, WEBGL);
  27288. *
  27289. * teapot = loadModel('assets/teapot.obj');
  27290. * }
  27291. *
  27292. * function draw(){
  27293. * background(200);
  27294. * rotateX(frameCount * 0.01);
  27295. * rotateY(frameCount * 0.01);
  27296. * model(teapot);
  27297. * }
  27298. * </code>
  27299. * </div>
  27300. *
  27301. * @alt
  27302. * Vertically rotating 3-d teapot with red, green and blue gradient.
  27303. *
  27304. */
  27305. p5.prototype.loadModel = function () {
  27306. var path = arguments[0];
  27307. var normalize;
  27308. var successCallback;
  27309. var failureCallback;
  27310. if(typeof arguments[1] === 'boolean') {
  27311. normalize = arguments[1];
  27312. successCallback = arguments[2];
  27313. failureCallback = arguments[3];
  27314. } else {
  27315. normalize = false;
  27316. successCallback = arguments[1];
  27317. failureCallback = arguments[2];
  27318. }
  27319. var model = new p5.Geometry();
  27320. model.gid = path + '|' + normalize;
  27321. this.loadStrings(path, function(strings) {
  27322. parseObj(model, strings);
  27323. if (normalize) {
  27324. model.normalize();
  27325. }
  27326. if (typeof successCallback === 'function') {
  27327. successCallback(model);
  27328. }
  27329. }.bind(this), failureCallback);
  27330. return model;
  27331. };
  27332. /**
  27333. * Parse OBJ lines into model. For reference, this is what a simple model of a
  27334. * square might look like:
  27335. *
  27336. * v -0.5 -0.5 0.5
  27337. * v -0.5 -0.5 -0.5
  27338. * v -0.5 0.5 -0.5
  27339. * v -0.5 0.5 0.5
  27340. *
  27341. * f 4 3 2 1
  27342. */
  27343. function parseObj( model, lines ) {
  27344. // OBJ allows a face to specify an index for a vertex (in the above example),
  27345. // but it also allows you to specify a custom combination of vertex, UV
  27346. // coordinate, and vertex normal. So, "3/4/3" would mean, "use vertex 3 with
  27347. // UV coordinate 4 and vertex normal 3". In WebGL, every vertex with different
  27348. // parameters must be a different vertex, so loadedVerts is used to
  27349. // temporarily store the parsed vertices, normals, etc., and indexedVerts is
  27350. // used to map a specific combination (keyed on, for example, the string
  27351. // "3/4/3"), to the actual index of the newly created vertex in the final
  27352. // object.
  27353. var loadedVerts = {'v' : [],
  27354. 'vt' : [],
  27355. 'vn' : []};
  27356. var indexedVerts = {};
  27357. for (var line = 0; line < lines.length; ++line) {
  27358. // Each line is a separate object (vertex, face, vertex normal, etc)
  27359. // For each line, split it into tokens on whitespace. The first token
  27360. // describes the type.
  27361. var tokens = lines[line].trim().split(/\b\s+/);
  27362. if (tokens.length > 0) {
  27363. if (tokens[0] === 'v' || tokens[0] === 'vn') {
  27364. // Check if this line describes a vertex or vertex normal.
  27365. // It will have three numeric parameters.
  27366. var vertex = new p5.Vector(parseFloat(tokens[1]),
  27367. parseFloat(tokens[2]),
  27368. parseFloat(tokens[3]));
  27369. loadedVerts[tokens[0]].push(vertex);
  27370. } else if (tokens[0] === 'vt') {
  27371. // Check if this line describes a texture coordinate.
  27372. // It will have two numeric parameters.
  27373. var texVertex = [parseFloat(tokens[1]), parseFloat(tokens[2])];
  27374. loadedVerts[tokens[0]].push(texVertex);
  27375. } else if (tokens[0] === 'f') {
  27376. // Check if this line describes a face.
  27377. // OBJ faces can have more than three points. Triangulate points.
  27378. for (var tri = 3; tri < tokens.length; ++tri) {
  27379. var face = [];
  27380. var vertexTokens = [1, tri - 1, tri];
  27381. for (var tokenInd = 0; tokenInd < vertexTokens.length; ++tokenInd) {
  27382. // Now, convert the given token into an index
  27383. var vertString = tokens[vertexTokens[tokenInd]];
  27384. var vertIndex = 0;
  27385. // TODO: Faces can technically use negative numbers to refer to the
  27386. // previous nth vertex. I haven't seen this used in practice, but
  27387. // it might be good to implement this in the future.
  27388. if (indexedVerts[vertString] !== undefined) {
  27389. vertIndex = indexedVerts[vertString];
  27390. } else {
  27391. var vertParts = vertString.split('/');
  27392. for (var i = 0; i < vertParts.length; i++) {
  27393. vertParts[i] = parseInt(vertParts[i]) - 1;
  27394. }
  27395. vertIndex = indexedVerts[vertString] = model.vertices.length;
  27396. model.vertices.push(loadedVerts.v[vertParts[0]].copy());
  27397. if (loadedVerts.vt[vertParts[1]]) {
  27398. model.uvs.push(loadedVerts.vt[vertParts[1]].slice());
  27399. } else {
  27400. model.uvs.push([0, 0]);
  27401. }
  27402. if (loadedVerts.vn[vertParts[2]]) {
  27403. model.vertexNormals.push(loadedVerts.vn[vertParts[2]].copy());
  27404. }
  27405. }
  27406. face.push(vertIndex);
  27407. }
  27408. model.faces.push(face);
  27409. }
  27410. }
  27411. }
  27412. }
  27413. // If the model doesn't have normals, compute the normals
  27414. if(model.vertexNormals.length === 0) {
  27415. model.computeNormals();
  27416. }
  27417. return model;
  27418. }
  27419. /**
  27420. * Render a 3d model to the screen.
  27421. *
  27422. * @method model
  27423. * @param {p5.Geometry} model Loaded 3d model to be rendered
  27424. * @example
  27425. * <div>
  27426. * <code>
  27427. * //draw a spinning teapot
  27428. * var teapot;
  27429. *
  27430. * function setup(){
  27431. * createCanvas(100, 100, WEBGL);
  27432. *
  27433. * teapot = loadModel('assets/teapot.obj');
  27434. * }
  27435. *
  27436. * function draw(){
  27437. * background(200);
  27438. * rotateX(frameCount * 0.01);
  27439. * rotateY(frameCount * 0.01);
  27440. * model(teapot);
  27441. * }
  27442. * </code>
  27443. * </div>
  27444. *
  27445. * @alt
  27446. * Vertically rotating 3-d teapot with red, green and blue gradient.
  27447. *
  27448. */
  27449. p5.prototype.model = function ( model ) {
  27450. if (model.vertices.length > 0) {
  27451. if (!this._renderer.geometryInHash(model.gid)) {
  27452. this._renderer.createBuffers(model.gid, model);
  27453. }
  27454. this._renderer.drawBuffers(model.gid);
  27455. }
  27456. };
  27457. module.exports = p5;
  27458. },{"../core/core":37,"./p5.Geometry":82}],81:[function(_dereq_,module,exports){
  27459. /**
  27460. * @module Lights, Camera
  27461. * @submodule Material
  27462. * @for p5
  27463. * @requires core
  27464. */
  27465. 'use strict';
  27466. var p5 = _dereq_('../core/core');
  27467. //require('./p5.Texture');
  27468. /**
  27469. * Normal material for geometry. You can view all
  27470. * possible materials in this
  27471. * <a href="https://http://p5js.org/examples/3d-materials.html">example</a>.
  27472. * @method normalMaterial
  27473. * @return {p5} the p5 object
  27474. * @example
  27475. * <div>
  27476. * <code>
  27477. * function setup(){
  27478. * createCanvas(100, 100, WEBGL);
  27479. * }
  27480. *
  27481. * function draw(){
  27482. * background(200);
  27483. * normalMaterial();
  27484. * sphere(50);
  27485. * }
  27486. * </code>
  27487. * </div>
  27488. *
  27489. * @alt
  27490. * Red, green and blue gradient.
  27491. *
  27492. */
  27493. p5.prototype.normalMaterial = function(){
  27494. this._renderer._getShader('normalVert', 'normalFrag');
  27495. return this;
  27496. };
  27497. /**
  27498. * Texture for geometry. You can view other possible materials in this
  27499. * <a href="https://http://p5js.org/examples/3d-materials.html">example</a>.
  27500. * @method texture
  27501. * @param {p5.Image | p5.MediaElement | p5.Graphics} tex 2-dimensional graphics
  27502. * to render as texture
  27503. * @return {p5} the p5 object
  27504. * @example
  27505. * <div>
  27506. * <code>
  27507. * var img;
  27508. * function setup(){
  27509. * createCanvas(100, 100, WEBGL);
  27510. * img = loadImage("assets/laDefense.jpg");
  27511. * }
  27512. *
  27513. * function draw(){
  27514. * background(0);
  27515. * rotateZ(frameCount * 0.01);
  27516. * rotateX(frameCount * 0.01);
  27517. * rotateY(frameCount * 0.01);
  27518. * //pass image as texture
  27519. * texture(img);
  27520. * box(200, 200, 200);
  27521. * }
  27522. * </code>
  27523. * </div>
  27524. *
  27525. * <div>
  27526. * <code>
  27527. * var pg;
  27528. * function setup(){
  27529. * createCanvas(100, 100, WEBGL);
  27530. * pg = createGraphics(200, 200);
  27531. * pg.textSize(100);
  27532. * }
  27533. *
  27534. * function draw(){
  27535. * background(0);
  27536. * pg.background(255);
  27537. * pg.text('hello!', 0, 100);
  27538. * //pass image as texture
  27539. * texture(pg);
  27540. * plane(200);
  27541. * }
  27542. * </code>
  27543. * </div>
  27544. *
  27545. * <div>
  27546. * <code>
  27547. * var vid;
  27548. * function preload(){
  27549. * vid = createVideo("assets/fingers.mov");
  27550. * vid.hide();
  27551. * vid.loop();
  27552. * }
  27553. * function setup(){
  27554. * createCanvas(100, 100, WEBGL);
  27555. * }
  27556. *
  27557. * function draw(){
  27558. * background(0);
  27559. * //pass video frame as texture
  27560. * texture(vid);
  27561. * plane(200);
  27562. * }
  27563. * </code>
  27564. * </div>
  27565. *
  27566. * @alt
  27567. * Rotating view of many images umbrella and grid roof on a 3d plane
  27568. * black canvas
  27569. * black canvas
  27570. *
  27571. */
  27572. p5.prototype.texture = function(){
  27573. var args = new Array(arguments.length);
  27574. for (var i = 0; i < args.length; ++i) {
  27575. args[i] = arguments[i];
  27576. }
  27577. var gl = this._renderer.GL;
  27578. var shaderProgram = this._renderer._getShader('lightVert',
  27579. 'lightTextureFrag');
  27580. gl.useProgram(shaderProgram);
  27581. var textureData;
  27582. //if argument is not already a texture
  27583. //create a new one
  27584. if(!args[0].isTexture){
  27585. if (args[0] instanceof p5.Image) {
  27586. textureData = args[0].canvas;
  27587. }
  27588. //if param is a video
  27589. else if (typeof p5.MediaElement !== 'undefined' &&
  27590. args[0] instanceof p5.MediaElement){
  27591. if(!args[0].loadedmetadata) {return;}
  27592. textureData = args[0].elt;
  27593. }
  27594. //used with offscreen 2d graphics renderer
  27595. else if(args[0] instanceof p5.Graphics){
  27596. textureData = args[0].elt;
  27597. }
  27598. var tex = gl.createTexture();
  27599. args[0]._setProperty('tex', tex);
  27600. args[0]._setProperty('isTexture', true);
  27601. this._renderer._bind.call(this, tex, textureData);
  27602. }
  27603. else {
  27604. if(args[0] instanceof p5.Graphics ||
  27605. (typeof p5.MediaElement !== 'undefined' &&
  27606. args[0] instanceof p5.MediaElement)){
  27607. textureData = args[0].elt;
  27608. }
  27609. else if(args[0] instanceof p5.Image){
  27610. textureData = args[0].canvas;
  27611. }
  27612. this._renderer._bind.call(this, args[0].tex, textureData);
  27613. }
  27614. //this is where we'd activate multi textures
  27615. //eg. gl.activeTexture(gl.TEXTURE0 + (unit || 0));
  27616. //but for now we just have a single texture.
  27617. //@TODO need to extend this functionality
  27618. gl.activeTexture(gl.TEXTURE0);
  27619. gl.bindTexture(gl.TEXTURE_2D, args[0].tex);
  27620. gl.uniform1i(gl.getUniformLocation(shaderProgram, 'isTexture'), true);
  27621. gl.uniform1i(gl.getUniformLocation(shaderProgram, 'uSampler'), 0);
  27622. return this;
  27623. };
  27624. /**
  27625. * Texture Util functions
  27626. */
  27627. p5.RendererGL.prototype._bind = function(tex, data){
  27628. var gl = this._renderer.GL;
  27629. gl.bindTexture(gl.TEXTURE_2D, tex);
  27630. gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
  27631. gl.texImage2D(gl.TEXTURE_2D, 0,
  27632. gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, data);
  27633. gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
  27634. gl.texParameteri(gl.TEXTURE_2D,
  27635. gl.TEXTURE_MAG_FILTER, gl.LINEAR);
  27636. gl.texParameteri(gl.TEXTURE_2D,
  27637. gl.TEXTURE_MIN_FILTER, gl.LINEAR);
  27638. gl.texParameteri(gl.TEXTURE_2D,
  27639. gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  27640. gl.texParameteri(gl.TEXTURE_2D,
  27641. gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
  27642. gl.bindTexture(gl.TEXTURE_2D, null);
  27643. };
  27644. /**
  27645. * Checks whether val is a pot
  27646. * more info on power of 2 here:
  27647. * https://www.opengl.org/wiki/NPOT_Texture
  27648. * @param {Number} value
  27649. * @return {Boolean}
  27650. */
  27651. // function _isPowerOf2 (value){
  27652. // return (value & (value - 1)) === 0;
  27653. // }
  27654. /**
  27655. * returns the next highest power of 2 value
  27656. * @param {Number} value [description]
  27657. * @return {Number} [description]
  27658. */
  27659. // function _nextHighestPOT (value){
  27660. // --value;
  27661. // for (var i = 1; i < 32; i <<= 1) {
  27662. // value = value | value >> i;
  27663. // }
  27664. // return value + 1;
  27665. /**
  27666. * Ambient material for geometry with a given color. You can view all
  27667. * possible materials in this
  27668. * <a href="https://http://p5js.org/examples/3d-materials.html">example</a>.
  27669. * @method ambientMaterial
  27670. * @param {Number|Array|String|p5.Color} v1 gray value,
  27671. * red or hue value (depending on the current color mode),
  27672. * or color Array, or CSS color string
  27673. * @param {Number} [v2] optional: green or saturation value
  27674. * @param {Number} [v3] optional: blue or brightness value
  27675. * @param {Number} [a] optional: opacity
  27676. * @return {p5} the p5 object
  27677. * @example
  27678. * <div>
  27679. * <code>
  27680. * function setup(){
  27681. * createCanvas(100, 100, WEBGL);
  27682. * }
  27683. * function draw(){
  27684. * background(0);
  27685. * ambientLight(100);
  27686. * pointLight(250, 250, 250, 100, 100, 0);
  27687. * ambientMaterial(250);
  27688. * sphere(50);
  27689. * }
  27690. * </code>
  27691. * </div>
  27692. *
  27693. * @alt
  27694. * radiating light source from top right of canvas
  27695. *
  27696. */
  27697. p5.prototype.ambientMaterial = function(v1, v2, v3, a) {
  27698. var gl = this._renderer.GL;
  27699. var shaderProgram =
  27700. this._renderer._getShader('lightVert', 'lightTextureFrag');
  27701. gl.useProgram(shaderProgram);
  27702. shaderProgram.uMaterialColor = gl.getUniformLocation(
  27703. shaderProgram, 'uMaterialColor' );
  27704. var colors = this._renderer._applyColorBlend.apply(this._renderer, arguments);
  27705. gl.uniform4f(shaderProgram.uMaterialColor,
  27706. colors[0], colors[1], colors[2], colors[3]);
  27707. shaderProgram.uSpecular = gl.getUniformLocation(
  27708. shaderProgram, 'uSpecular' );
  27709. gl.uniform1i(shaderProgram.uSpecular, false);
  27710. gl.uniform1i(gl.getUniformLocation(shaderProgram, 'isTexture'), false);
  27711. return this;
  27712. };
  27713. /**
  27714. * Specular material for geometry with a given color. You can view all
  27715. * possible materials in this
  27716. * <a href="https://http://p5js.org/examples/3d-materials.html">example</a>.
  27717. * @method specularMaterial
  27718. * @param {Number|Array|String|p5.Color} v1 gray value,
  27719. * red or hue value (depending on the current color mode),
  27720. * or color Array, or CSS color string
  27721. * @param {Number} [v2] optional: green or saturation value
  27722. * @param {Number} [v3] optional: blue or brightness value
  27723. * @param {Number} [a] optional: opacity
  27724. * @return {p5} the p5 object
  27725. * @example
  27726. * <div>
  27727. * <code>
  27728. * function setup(){
  27729. * createCanvas(100, 100, WEBGL);
  27730. * }
  27731. * function draw(){
  27732. * background(0);
  27733. * ambientLight(100);
  27734. * pointLight(250, 250, 250, 100, 100, 0);
  27735. * specularMaterial(250);
  27736. * sphere(50);
  27737. * }
  27738. * </code>
  27739. * </div>
  27740. *
  27741. * @alt
  27742. * diffused radiating light source from top right of canvas
  27743. *
  27744. */
  27745. p5.prototype.specularMaterial = function(v1, v2, v3, a) {
  27746. var gl = this._renderer.GL;
  27747. var shaderProgram =
  27748. this._renderer._getShader('lightVert', 'lightTextureFrag');
  27749. gl.useProgram(shaderProgram);
  27750. gl.uniform1i(gl.getUniformLocation(shaderProgram, 'isTexture'), false);
  27751. shaderProgram.uMaterialColor = gl.getUniformLocation(
  27752. shaderProgram, 'uMaterialColor' );
  27753. var colors = this._renderer._applyColorBlend.apply(this._renderer, arguments);
  27754. gl.uniform4f(shaderProgram.uMaterialColor,
  27755. colors[0], colors[1], colors[2], colors[3]);
  27756. shaderProgram.uSpecular = gl.getUniformLocation(
  27757. shaderProgram, 'uSpecular' );
  27758. gl.uniform1i(shaderProgram.uSpecular, true);
  27759. return this;
  27760. };
  27761. /**
  27762. * @private blends colors according to color components.
  27763. * If alpha value is less than 1, we need to enable blending
  27764. * on our gl context. Otherwise opaque objects need to a depthMask.
  27765. * @param {Number} v1 [description]
  27766. * @param {Number} v2 [description]
  27767. * @param {Number} v3 [description]
  27768. * @param {Number} a [description]
  27769. * @return {[Number]} Normalized numbers array
  27770. */
  27771. p5.RendererGL.prototype._applyColorBlend = function(v1,v2,v3,a){
  27772. var gl = this.GL;
  27773. var color = this._pInst.color.apply(
  27774. this._pInst, arguments);
  27775. var colors = color._array;
  27776. if(colors[colors.length-1] < 1.0){
  27777. gl.depthMask(false);
  27778. gl.enable(gl.BLEND);
  27779. gl.blendEquation( gl.FUNC_ADD );
  27780. gl.blendFunc( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA );
  27781. } else {
  27782. gl.depthMask(true);
  27783. gl.disable(gl.BLEND);
  27784. }
  27785. return colors;
  27786. };
  27787. module.exports = p5;
  27788. },{"../core/core":37}],82:[function(_dereq_,module,exports){
  27789. //some of the functions are adjusted from Three.js(http://threejs.org)
  27790. 'use strict';
  27791. var p5 = _dereq_('../core/core');
  27792. /**
  27793. * p5 Geometry class
  27794. * @constructor
  27795. * @param {Function | Object} vertData callback function or Object
  27796. * containing routine(s) for vertex data generation
  27797. * @param {Number} [detailX] number of vertices on horizontal surface
  27798. * @param {Number} [detailY] number of vertices on horizontal surface
  27799. * @param {Function} [callback] function to call upon object instantiation.
  27800. *
  27801. */
  27802. p5.Geometry = function
  27803. (detailX, detailY, callback){
  27804. //an array containing every vertex
  27805. //@type [p5.Vector]
  27806. this.vertices = [];
  27807. //an array containing 1 normal per vertex
  27808. //@type [p5.Vector]
  27809. //[p5.Vector, p5.Vector, p5.Vector,p5.Vector, p5.Vector, p5.Vector,...]
  27810. this.vertexNormals = [];
  27811. //an array containing each three vertex indices that form a face
  27812. //[[0, 1, 2], [2, 1, 3], ...]
  27813. this.faces = [];
  27814. //a 2D array containing uvs for every vertex
  27815. //[[0.0,0.0],[1.0,0.0], ...]
  27816. this.uvs = [];
  27817. this.detailX = (detailX !== undefined) ? detailX: 1;
  27818. this.detailY = (detailY !== undefined) ? detailY: 1;
  27819. if(callback instanceof Function){
  27820. callback.call(this);
  27821. }
  27822. return this;
  27823. };
  27824. p5.Geometry.prototype.computeFaces = function(){
  27825. var sliceCount = this.detailX + 1;
  27826. var a, b, c, d;
  27827. for (var i = 0; i < this.detailY; i++){
  27828. for (var j = 0; j < this.detailX; j++){
  27829. a = i * sliceCount + j;// + offset;
  27830. b = i * sliceCount + j + 1;// + offset;
  27831. c = (i + 1)* sliceCount + j + 1;// + offset;
  27832. d = (i + 1)* sliceCount + j;// + offset;
  27833. this.faces.push([a, b, d]);
  27834. this.faces.push([d, b, c]);
  27835. }
  27836. }
  27837. return this;
  27838. };
  27839. p5.Geometry.prototype._getFaceNormal = function(faceId,vertId){
  27840. //This assumes that vA->vB->vC is a counter-clockwise ordering
  27841. var face = this.faces[faceId];
  27842. var vA = this.vertices[face[vertId%3]];
  27843. var vB = this.vertices[face[(vertId+1)%3]];
  27844. var vC = this.vertices[face[(vertId+2)%3]];
  27845. var n = p5.Vector.cross(
  27846. p5.Vector.sub(vB,vA),
  27847. p5.Vector.sub(vC,vA));
  27848. var sinAlpha = p5.Vector.mag(n) /
  27849. (p5.Vector.mag(p5.Vector.sub(vB,vA))*
  27850. p5.Vector.mag(p5.Vector.sub(vC,vA)));
  27851. n = n.normalize();
  27852. return n.mult(Math.asin(sinAlpha));
  27853. };
  27854. /**
  27855. * computes smooth normals per vertex as an average of each
  27856. * face.
  27857. */
  27858. p5.Geometry.prototype.computeNormals = function (){
  27859. for(var v=0; v < this.vertices.length; v++){
  27860. var normal = new p5.Vector();
  27861. for(var i=0; i < this.faces.length; i++){
  27862. //if our face contains a given vertex
  27863. //calculate an average of the normals
  27864. //of the triangles adjacent to that vertex
  27865. if(this.faces[i][0] === v ||
  27866. this.faces[i][1] === v ||
  27867. this.faces[i][2] === v)
  27868. {
  27869. normal = normal.add(this._getFaceNormal(i, v));
  27870. }
  27871. }
  27872. normal = normal.normalize();
  27873. this.vertexNormals.push(normal);
  27874. }
  27875. return this;
  27876. };
  27877. /**
  27878. * Averages the vertex normals. Used in curved
  27879. * surfaces
  27880. * @return {p5.Geometry}
  27881. */
  27882. p5.Geometry.prototype.averageNormals = function() {
  27883. for(var i = 0; i <= this.detailY; i++){
  27884. var offset = this.detailX + 1;
  27885. var temp = p5.Vector
  27886. .add(this.vertexNormals[i*offset],
  27887. this.vertexNormals[i*offset + this.detailX]);
  27888. temp = p5.Vector.div(temp, 2);
  27889. this.vertexNormals[i*offset] = temp;
  27890. this.vertexNormals[i*offset + this.detailX] = temp;
  27891. }
  27892. return this;
  27893. };
  27894. /**
  27895. * Averages pole normals. Used in spherical primitives
  27896. * @return {p5.Geometry}
  27897. */
  27898. p5.Geometry.prototype.averagePoleNormals = function() {
  27899. //average the north pole
  27900. var sum = new p5.Vector(0, 0, 0);
  27901. for(var i = 0; i < this.detailX; i++){
  27902. sum.add(this.vertexNormals[i]);
  27903. }
  27904. sum = p5.Vector.div(sum, this.detailX);
  27905. for(i = 0; i < this.detailX; i++){
  27906. this.vertexNormals[i] = sum;
  27907. }
  27908. //average the south pole
  27909. sum = new p5.Vector(0, 0, 0);
  27910. for(i = this.vertices.length - 1;
  27911. i > this.vertices.length - 1 - this.detailX; i--){
  27912. sum.add(this.vertexNormals[i]);
  27913. }
  27914. sum = p5.Vector.div(sum, this.detailX);
  27915. for(i = this.vertices.length - 1;
  27916. i > this.vertices.length - 1 - this.detailX; i--){
  27917. this.vertexNormals[i] = sum;
  27918. }
  27919. return this;
  27920. };
  27921. /**
  27922. * Modifies all vertices to be centered within the range -100 to 100.
  27923. * @return {p5.Geometry}
  27924. */
  27925. p5.Geometry.prototype.normalize = function() {
  27926. if(this.vertices.length > 0) {
  27927. // Find the corners of our bounding box
  27928. var maxPosition = this.vertices[0].copy();
  27929. var minPosition = this.vertices[0].copy();
  27930. for(var i = 0; i < this.vertices.length; i++) {
  27931. maxPosition.x = Math.max(maxPosition.x, this.vertices[i].x);
  27932. minPosition.x = Math.min(minPosition.x, this.vertices[i].x);
  27933. maxPosition.y = Math.max(maxPosition.y, this.vertices[i].y);
  27934. minPosition.y = Math.min(minPosition.y, this.vertices[i].y);
  27935. maxPosition.z = Math.max(maxPosition.z, this.vertices[i].z);
  27936. minPosition.z = Math.min(minPosition.z, this.vertices[i].z);
  27937. }
  27938. var center = p5.Vector.lerp(maxPosition, minPosition, 0.5);
  27939. var dist = p5.Vector.sub(maxPosition, minPosition);
  27940. var longestDist = Math.max(Math.max(dist.x, dist.y), dist.z);
  27941. var scale = 200 / longestDist;
  27942. for(i = 0; i < this.vertices.length; i++) {
  27943. this.vertices[i].sub(center);
  27944. this.vertices[i].mult(scale);
  27945. }
  27946. }
  27947. return this;
  27948. };
  27949. module.exports = p5.Geometry;
  27950. },{"../core/core":37}],83:[function(_dereq_,module,exports){
  27951. /**
  27952. * @requires constants
  27953. * @todo see methods below needing further implementation.
  27954. * future consideration: implement SIMD optimizations
  27955. * when browser compatibility becomes available
  27956. * https://developer.mozilla.org/en-US/docs/Web/JavaScript/
  27957. * Reference/Global_Objects/SIMD
  27958. */
  27959. 'use strict';
  27960. var p5 = _dereq_('../core/core');
  27961. var polarGeometry = _dereq_('../math/polargeometry');
  27962. var constants = _dereq_('../core/constants');
  27963. var GLMAT_ARRAY_TYPE = (
  27964. typeof Float32Array !== 'undefined') ?
  27965. Float32Array : Array;
  27966. /**
  27967. * A class to describe a 4x4 matrix
  27968. * for model and view matrix manipulation in the p5js webgl renderer.
  27969. * class p5.Matrix
  27970. * @constructor
  27971. * @param {Array} [mat4] array literal of our 4x4 matrix
  27972. */
  27973. p5.Matrix = function() {
  27974. var args = new Array(arguments.length);
  27975. for (var i = 0; i < args.length; ++i) {
  27976. args[i] = arguments[i];
  27977. }
  27978. // This is default behavior when object
  27979. // instantiated using createMatrix()
  27980. // @todo implement createMatrix() in core/math.js
  27981. if(args[0] instanceof p5) {
  27982. // save reference to p5 if passed in
  27983. this.p5 = args[0];
  27984. if(args[1] === 'mat3'){
  27985. this.mat3 = args[2] || new GLMAT_ARRAY_TYPE([
  27986. 1, 0, 0,
  27987. 0, 1, 0,
  27988. 0, 0, 1
  27989. ]);
  27990. }
  27991. else {
  27992. this.mat4 = args[1] || new GLMAT_ARRAY_TYPE([
  27993. 1, 0, 0, 0,
  27994. 0, 1, 0, 0,
  27995. 0, 0, 1, 0,
  27996. 0, 0, 0, 1
  27997. ]);
  27998. }
  27999. // default behavior when object
  28000. // instantiated using new p5.Matrix()
  28001. } else {
  28002. if(args[0] === 'mat3'){
  28003. this.mat3 = args[1] || new GLMAT_ARRAY_TYPE([
  28004. 1, 0, 0,
  28005. 0, 1, 0,
  28006. 0, 0, 1
  28007. ]);
  28008. }
  28009. else {
  28010. this.mat4 = args[0] || new GLMAT_ARRAY_TYPE([
  28011. 1, 0, 0, 0,
  28012. 0, 1, 0, 0,
  28013. 0, 0, 1, 0,
  28014. 0, 0, 0, 1
  28015. ]);
  28016. }
  28017. }
  28018. return this;
  28019. };
  28020. /**
  28021. * Sets the x, y, and z component of the vector using two or three separate
  28022. * variables, the data from a p5.Matrix, or the values from a float array.
  28023. *
  28024. * @param {p5.Matrix|Array} [inMatrix] the input p5.Matrix or
  28025. * an Array of length 16
  28026. */
  28027. p5.Matrix.prototype.set = function (inMatrix) {
  28028. if (inMatrix instanceof p5.Matrix) {
  28029. this.mat4 = inMatrix.mat4;
  28030. return this;
  28031. }
  28032. else if (inMatrix instanceof GLMAT_ARRAY_TYPE) {
  28033. this.mat4 = inMatrix;
  28034. return this;
  28035. }
  28036. return this;
  28037. };
  28038. /**
  28039. * Gets a copy of the vector, returns a p5.Matrix object.
  28040. *
  28041. * @return {p5.Matrix} the copy of the p5.Matrix object
  28042. */
  28043. p5.Matrix.prototype.get = function () {
  28044. return new p5.Matrix(this.mat4);
  28045. };
  28046. /**
  28047. * return a copy of a matrix
  28048. * @return {p5.Matrix} the result matrix
  28049. */
  28050. p5.Matrix.prototype.copy = function(){
  28051. var copied = new p5.Matrix();
  28052. copied.mat4[0] = this.mat4[0];
  28053. copied.mat4[1] = this.mat4[1];
  28054. copied.mat4[2] = this.mat4[2];
  28055. copied.mat4[3] = this.mat4[3];
  28056. copied.mat4[4] = this.mat4[4];
  28057. copied.mat4[5] = this.mat4[5];
  28058. copied.mat4[6] = this.mat4[6];
  28059. copied.mat4[7] = this.mat4[7];
  28060. copied.mat4[8] = this.mat4[8];
  28061. copied.mat4[9] = this.mat4[9];
  28062. copied.mat4[10] = this.mat4[10];
  28063. copied.mat4[11] = this.mat4[11];
  28064. copied.mat4[12] = this.mat4[12];
  28065. copied.mat4[13] = this.mat4[13];
  28066. copied.mat4[14] = this.mat4[14];
  28067. copied.mat4[15] = this.mat4[15];
  28068. return copied;
  28069. };
  28070. /**
  28071. * return an identity matrix
  28072. * @return {p5.Matrix} the result matrix
  28073. */
  28074. p5.Matrix.identity = function(){
  28075. return new p5.Matrix();
  28076. };
  28077. /**
  28078. * transpose according to a given matrix
  28079. * @param {p5.Matrix | Typed Array} a the matrix to be based on to transpose
  28080. * @return {p5.Matrix} this
  28081. */
  28082. p5.Matrix.prototype.transpose = function(a){
  28083. var a01, a02, a03, a12, a13, a23;
  28084. if(a instanceof p5.Matrix){
  28085. a01 = a.mat4[1];
  28086. a02 = a.mat4[2];
  28087. a03 = a.mat4[3];
  28088. a12 = a.mat4[6];
  28089. a13 = a.mat4[7];
  28090. a23 = a.mat4[11];
  28091. this.mat4[0] = a.mat4[0];
  28092. this.mat4[1] = a.mat4[4];
  28093. this.mat4[2] = a.mat4[8];
  28094. this.mat4[3] = a.mat4[12];
  28095. this.mat4[4] = a01;
  28096. this.mat4[5] = a.mat4[5];
  28097. this.mat4[6] = a.mat4[9];
  28098. this.mat4[7] = a.mat4[13];
  28099. this.mat4[8] = a02;
  28100. this.mat4[9] = a12;
  28101. this.mat4[10] = a.mat4[10];
  28102. this.mat4[11] = a.mat4[14];
  28103. this.mat4[12] = a03;
  28104. this.mat4[13] = a13;
  28105. this.mat4[14] = a23;
  28106. this.mat4[15] = a.mat4[15];
  28107. }else if(a instanceof GLMAT_ARRAY_TYPE){
  28108. a01 = a[1];
  28109. a02 = a[2];
  28110. a03 = a[3];
  28111. a12 = a[6];
  28112. a13 = a[7];
  28113. a23 = a[11];
  28114. this.mat4[0] = a[0];
  28115. this.mat4[1] = a[4];
  28116. this.mat4[2] = a[8];
  28117. this.mat4[3] = a[12];
  28118. this.mat4[4] = a01;
  28119. this.mat4[5] = a[5];
  28120. this.mat4[6] = a[9];
  28121. this.mat4[7] = a[13];
  28122. this.mat4[8] = a02;
  28123. this.mat4[9] = a12;
  28124. this.mat4[10] = a[10];
  28125. this.mat4[11] = a[14];
  28126. this.mat4[12] = a03;
  28127. this.mat4[13] = a13;
  28128. this.mat4[14] = a23;
  28129. this.mat4[15] = a[15];
  28130. }
  28131. return this;
  28132. };
  28133. /**
  28134. * invert matrix according to a give matrix
  28135. * @param {p5.Matrix or Typed Array} a the matrix to be based on to invert
  28136. * @return {p5.Matrix} this
  28137. */
  28138. p5.Matrix.prototype.invert = function(a){
  28139. var a00, a01, a02, a03, a10, a11, a12, a13,
  28140. a20, a21, a22, a23, a30, a31, a32, a33;
  28141. if(a instanceof p5.Matrix){
  28142. a00 = a.mat4[0];
  28143. a01 = a.mat4[1];
  28144. a02 = a.mat4[2];
  28145. a03 = a.mat4[3];
  28146. a10 = a.mat4[4];
  28147. a11 = a.mat4[5];
  28148. a12 = a.mat4[6];
  28149. a13 = a.mat4[7];
  28150. a20 = a.mat4[8];
  28151. a21 = a.mat4[9];
  28152. a22 = a.mat4[10];
  28153. a23 = a.mat4[11];
  28154. a30 = a.mat4[12];
  28155. a31 = a.mat4[13];
  28156. a32 = a.mat4[14];
  28157. a33 = a.mat4[15];
  28158. }else if(a instanceof GLMAT_ARRAY_TYPE){
  28159. a00 = a[0];
  28160. a01 = a[1];
  28161. a02 = a[2];
  28162. a03 = a[3];
  28163. a10 = a[4];
  28164. a11 = a[5];
  28165. a12 = a[6];
  28166. a13 = a[7];
  28167. a20 = a[8];
  28168. a21 = a[9];
  28169. a22 = a[10];
  28170. a23 = a[11];
  28171. a30 = a[12];
  28172. a31 = a[13];
  28173. a32 = a[14];
  28174. a33 = a[15];
  28175. }
  28176. var b00 = a00 * a11 - a01 * a10,
  28177. b01 = a00 * a12 - a02 * a10,
  28178. b02 = a00 * a13 - a03 * a10,
  28179. b03 = a01 * a12 - a02 * a11,
  28180. b04 = a01 * a13 - a03 * a11,
  28181. b05 = a02 * a13 - a03 * a12,
  28182. b06 = a20 * a31 - a21 * a30,
  28183. b07 = a20 * a32 - a22 * a30,
  28184. b08 = a20 * a33 - a23 * a30,
  28185. b09 = a21 * a32 - a22 * a31,
  28186. b10 = a21 * a33 - a23 * a31,
  28187. b11 = a22 * a33 - a23 * a32,
  28188. // Calculate the determinant
  28189. det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 -
  28190. b04 * b07 + b05 * b06;
  28191. if (!det) {
  28192. return null;
  28193. }
  28194. det = 1.0 / det;
  28195. this.mat4[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
  28196. this.mat4[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
  28197. this.mat4[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
  28198. this.mat4[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;
  28199. this.mat4[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
  28200. this.mat4[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
  28201. this.mat4[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
  28202. this.mat4[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;
  28203. this.mat4[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
  28204. this.mat4[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
  28205. this.mat4[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
  28206. this.mat4[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;
  28207. this.mat4[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;
  28208. this.mat4[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;
  28209. this.mat4[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;
  28210. this.mat4[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;
  28211. return this;
  28212. };
  28213. /**
  28214. * Inverts a 3x3 matrix
  28215. * @return {[type]} [description]
  28216. */
  28217. p5.Matrix.prototype.invert3x3 = function (){
  28218. var a00 = this.mat3[0],
  28219. a01 = this.mat3[1],
  28220. a02 = this.mat3[2],
  28221. a10 = this.mat3[3],
  28222. a11 = this.mat3[4],
  28223. a12 = this.mat3[5],
  28224. a20 = this.mat3[6],
  28225. a21 = this.mat3[7],
  28226. a22 = this.mat3[8],
  28227. b01 = a22 * a11 - a12 * a21,
  28228. b11 = -a22 * a10 + a12 * a20,
  28229. b21 = a21 * a10 - a11 * a20,
  28230. // Calculate the determinant
  28231. det = a00 * b01 + a01 * b11 + a02 * b21;
  28232. if (!det) {
  28233. return null;
  28234. }
  28235. det = 1.0 / det;
  28236. this.mat3[0] = b01 * det;
  28237. this.mat3[1] = (-a22 * a01 + a02 * a21) * det;
  28238. this.mat3[2] = (a12 * a01 - a02 * a11) * det;
  28239. this.mat3[3] = b11 * det;
  28240. this.mat3[4] = (a22 * a00 - a02 * a20) * det;
  28241. this.mat3[5] = (-a12 * a00 + a02 * a10) * det;
  28242. this.mat3[6] = b21 * det;
  28243. this.mat3[7] = (-a21 * a00 + a01 * a20) * det;
  28244. this.mat3[8] = (a11 * a00 - a01 * a10) * det;
  28245. return this;
  28246. };
  28247. /**
  28248. * transposes a 3x3 p5.Matrix by a mat3
  28249. * @param {[Number]} mat3 1-dimensional array
  28250. * @return {p5.Matrix} this
  28251. */
  28252. p5.Matrix.prototype.transpose3x3 = function (mat3){
  28253. var a01 = mat3[1], a02 = mat3[2], a12 = mat3[5];
  28254. this.mat3[1] = mat3[3];
  28255. this.mat3[2] = mat3[6];
  28256. this.mat3[3] = a01;
  28257. this.mat3[5] = mat3[7];
  28258. this.mat3[6] = a02;
  28259. this.mat3[7] = a12;
  28260. return this;
  28261. };
  28262. /**
  28263. * converts a 4x4 matrix to its 3x3 inverse tranform
  28264. * commonly used in MVMatrix to NMatrix conversions.
  28265. * @param {p5.Matrix} mat4 the matrix to be based on to invert
  28266. * @return {p5.Matrix} this with mat3
  28267. * @todo finish implementation
  28268. */
  28269. p5.Matrix.prototype.inverseTranspose = function (matrix){
  28270. if(this.mat3 === undefined){
  28271. console.error('sorry, this function only works with mat3');
  28272. }
  28273. else {
  28274. //convert mat4 -> mat3
  28275. this.mat3[0] = matrix.mat4[0];
  28276. this.mat3[1] = matrix.mat4[1];
  28277. this.mat3[2] = matrix.mat4[2];
  28278. this.mat3[3] = matrix.mat4[4];
  28279. this.mat3[4] = matrix.mat4[5];
  28280. this.mat3[5] = matrix.mat4[6];
  28281. this.mat3[6] = matrix.mat4[8];
  28282. this.mat3[7] = matrix.mat4[9];
  28283. this.mat3[8] = matrix.mat4[10];
  28284. }
  28285. this.invert3x3().transpose3x3(this.mat3);
  28286. return this;
  28287. };
  28288. /**
  28289. * inspired by Toji's mat4 determinant
  28290. * @return {Number} Determinant of our 4x4 matrix
  28291. */
  28292. p5.Matrix.prototype.determinant = function(){
  28293. var d00 = (this.mat4[0] * this.mat4[5]) - (this.mat4[1] * this.mat4[4]),
  28294. d01 = (this.mat4[0] * this.mat4[6]) - (this.mat4[2] * this.mat4[4]),
  28295. d02 = (this.mat4[0] * this.mat4[7]) - (this.mat4[3] * this.mat4[4]),
  28296. d03 = (this.mat4[1] * this.mat4[6]) - (this.mat4[2] * this.mat4[5]),
  28297. d04 = (this.mat4[1] * this.mat4[7]) - (this.mat4[3] * this.mat4[5]),
  28298. d05 = (this.mat4[2] * this.mat4[7]) - (this.mat4[3] * this.mat4[6]),
  28299. d06 = (this.mat4[8] * this.mat4[13]) - (this.mat4[9] * this.mat4[12]),
  28300. d07 = (this.mat4[8] * this.mat4[14]) - (this.mat4[10] * this.mat4[12]),
  28301. d08 = (this.mat4[8] * this.mat4[15]) - (this.mat4[11] * this.mat4[12]),
  28302. d09 = (this.mat4[9] * this.mat4[14]) - (this.mat4[10] * this.mat4[13]),
  28303. d10 = (this.mat4[9] * this.mat4[15]) - (this.mat4[11] * this.mat4[13]),
  28304. d11 = (this.mat4[10] * this.mat4[15]) - (this.mat4[11] * this.mat4[14]);
  28305. // Calculate the determinant
  28306. return d00 * d11 - d01 * d10 + d02 * d09 +
  28307. d03 * d08 - d04 * d07 + d05 * d06;
  28308. };
  28309. /**
  28310. * multiply two mat4s
  28311. * @param {p5.Matrix | Array} multMatrix The matrix we want to multiply by
  28312. * @return {p5.Matrix} this
  28313. */
  28314. p5.Matrix.prototype.mult = function(multMatrix){
  28315. var _dest = new GLMAT_ARRAY_TYPE(16);
  28316. var _src = new GLMAT_ARRAY_TYPE(16);
  28317. if(multMatrix instanceof p5.Matrix) {
  28318. _src = multMatrix.mat4;
  28319. }
  28320. else if(multMatrix instanceof GLMAT_ARRAY_TYPE){
  28321. _src = multMatrix;
  28322. }
  28323. // each row is used for the multiplier
  28324. var b0 = this.mat4[0], b1 = this.mat4[1],
  28325. b2 = this.mat4[2], b3 = this.mat4[3];
  28326. _dest[0] = b0*_src[0] + b1*_src[4] + b2*_src[8] + b3*_src[12];
  28327. _dest[1] = b0*_src[1] + b1*_src[5] + b2*_src[9] + b3*_src[13];
  28328. _dest[2] = b0*_src[2] + b1*_src[6] + b2*_src[10] + b3*_src[14];
  28329. _dest[3] = b0*_src[3] + b1*_src[7] + b2*_src[11] + b3*_src[15];
  28330. b0 = this.mat4[4];
  28331. b1 = this.mat4[5];
  28332. b2 = this.mat4[6];
  28333. b3 = this.mat4[7];
  28334. _dest[4] = b0*_src[0] + b1*_src[4] + b2*_src[8] + b3*_src[12];
  28335. _dest[5] = b0*_src[1] + b1*_src[5] + b2*_src[9] + b3*_src[13];
  28336. _dest[6] = b0*_src[2] + b1*_src[6] + b2*_src[10] + b3*_src[14];
  28337. _dest[7] = b0*_src[3] + b1*_src[7] + b2*_src[11] + b3*_src[15];
  28338. b0 = this.mat4[8];
  28339. b1 = this.mat4[9];
  28340. b2 = this.mat4[10];
  28341. b3 = this.mat4[11];
  28342. _dest[8] = b0*_src[0] + b1*_src[4] + b2*_src[8] + b3*_src[12];
  28343. _dest[9] = b0*_src[1] + b1*_src[5] + b2*_src[9] + b3*_src[13];
  28344. _dest[10] = b0*_src[2] + b1*_src[6] + b2*_src[10] + b3*_src[14];
  28345. _dest[11] = b0*_src[3] + b1*_src[7] + b2*_src[11] + b3*_src[15];
  28346. b0 = this.mat4[12];
  28347. b1 = this.mat4[13];
  28348. b2 = this.mat4[14];
  28349. b3 = this.mat4[15];
  28350. _dest[12] = b0*_src[0] + b1*_src[4] + b2*_src[8] + b3*_src[12];
  28351. _dest[13] = b0*_src[1] + b1*_src[5] + b2*_src[9] + b3*_src[13];
  28352. _dest[14] = b0*_src[2] + b1*_src[6] + b2*_src[10] + b3*_src[14];
  28353. _dest[15] = b0*_src[3] + b1*_src[7] + b2*_src[11] + b3*_src[15];
  28354. this.mat4 = _dest;
  28355. return this;
  28356. };
  28357. /**
  28358. * scales a p5.Matrix by scalars or a vector
  28359. * @param {p5.Vector | Array }
  28360. * vector to scale by
  28361. * @return {p5.Matrix} this
  28362. */
  28363. p5.Matrix.prototype.scale = function() {
  28364. var x,y,z;
  28365. var args = new Array(arguments.length);
  28366. for (var i = 0; i < args.length; ++i) {
  28367. args[i] = arguments[i];
  28368. }
  28369. //if our 1st arg is a type p5.Vector
  28370. if (args[0] instanceof p5.Vector){
  28371. x = args[0].x;
  28372. y = args[0].y;
  28373. z = args[0].z;
  28374. }
  28375. //otherwise if it's an array
  28376. else if (args[0] instanceof Array){
  28377. x = args[0][0];
  28378. y = args[0][1];
  28379. z = args[0][2];
  28380. }
  28381. var _dest = new GLMAT_ARRAY_TYPE(16);
  28382. _dest[0] = this.mat4[0] * x;
  28383. _dest[1] = this.mat4[1] * x;
  28384. _dest[2] = this.mat4[2] * x;
  28385. _dest[3] = this.mat4[3] * x;
  28386. _dest[4] = this.mat4[4] * y;
  28387. _dest[5] = this.mat4[5] * y;
  28388. _dest[6] = this.mat4[6] * y;
  28389. _dest[7] = this.mat4[7] * y;
  28390. _dest[8] = this.mat4[8] * z;
  28391. _dest[9] = this.mat4[9] * z;
  28392. _dest[10] = this.mat4[10] * z;
  28393. _dest[11] = this.mat4[11] * z;
  28394. _dest[12] = this.mat4[12];
  28395. _dest[13] = this.mat4[13];
  28396. _dest[14] = this.mat4[14];
  28397. _dest[15] = this.mat4[15];
  28398. this.mat4 = _dest;
  28399. return this;
  28400. };
  28401. /**
  28402. * rotate our Matrix around an axis by the given angle.
  28403. * @param {Number} a The angle of rotation in radians
  28404. * @param {p5.Vector | Array} axis the axis(es) to rotate around
  28405. * @return {p5.Matrix} this
  28406. * inspired by Toji's gl-matrix lib, mat4 rotation
  28407. */
  28408. p5.Matrix.prototype.rotate = function(a, axis){
  28409. var x, y, z, _a, len;
  28410. if (this.p5) {
  28411. if (this.p5._angleMode === constants.DEGREES) {
  28412. _a = polarGeometry.degreesToRadians(a);
  28413. }
  28414. }
  28415. else {
  28416. _a = a;
  28417. }
  28418. if (axis instanceof p5.Vector) {
  28419. x = axis.x;
  28420. y = axis.y;
  28421. z = axis.z;
  28422. }
  28423. else if (axis instanceof Array) {
  28424. x = axis[0];
  28425. y = axis[1];
  28426. z = axis[2];
  28427. }
  28428. len = Math.sqrt(x * x + y * y + z * z);
  28429. x *= (1/len);
  28430. y *= (1/len);
  28431. z *= (1/len);
  28432. var a00 = this.mat4[0];
  28433. var a01 = this.mat4[1];
  28434. var a02 = this.mat4[2];
  28435. var a03 = this.mat4[3];
  28436. var a10 = this.mat4[4];
  28437. var a11 = this.mat4[5];
  28438. var a12 = this.mat4[6];
  28439. var a13 = this.mat4[7];
  28440. var a20 = this.mat4[8];
  28441. var a21 = this.mat4[9];
  28442. var a22 = this.mat4[10];
  28443. var a23 = this.mat4[11];
  28444. //sin,cos, and tan of respective angle
  28445. var sA = Math.sin(_a);
  28446. var cA = Math.cos(_a);
  28447. var tA = 1 - cA;
  28448. // Construct the elements of the rotation matrix
  28449. var b00 = x * x * tA + cA;
  28450. var b01 = y * x * tA + z * sA;
  28451. var b02 = z * x * tA - y * sA;
  28452. var b10 = x * y * tA - z * sA;
  28453. var b11 = y * y * tA + cA;
  28454. var b12 = z * y * tA + x * sA;
  28455. var b20 = x * z * tA + y * sA;
  28456. var b21 = y * z * tA - x * sA;
  28457. var b22 = z * z * tA + cA;
  28458. // rotation-specific matrix multiplication
  28459. this.mat4[0] = a00 * b00 + a10 * b01 + a20 * b02;
  28460. this.mat4[1] = a01 * b00 + a11 * b01 + a21 * b02;
  28461. this.mat4[2] = a02 * b00 + a12 * b01 + a22 * b02;
  28462. this.mat4[3] = a03 * b00 + a13 * b01 + a23 * b02;
  28463. this.mat4[4] = a00 * b10 + a10 * b11 + a20 * b12;
  28464. this.mat4[5] = a01 * b10 + a11 * b11 + a21 * b12;
  28465. this.mat4[6] = a02 * b10 + a12 * b11 + a22 * b12;
  28466. this.mat4[7] = a03 * b10 + a13 * b11 + a23 * b12;
  28467. this.mat4[8] = a00 * b20 + a10 * b21 + a20 * b22;
  28468. this.mat4[9] = a01 * b20 + a11 * b21 + a21 * b22;
  28469. this.mat4[10] = a02 * b20 + a12 * b21 + a22 * b22;
  28470. this.mat4[11] = a03 * b20 + a13 * b21 + a23 * b22;
  28471. return this;
  28472. };
  28473. /**
  28474. * @todo finish implementing this method!
  28475. * translates
  28476. * @param {Array} v vector to translate by
  28477. * @return {p5.Matrix} this
  28478. */
  28479. p5.Matrix.prototype.translate = function(v){
  28480. var x = v[0],
  28481. y = v[1],
  28482. z = v[2] || 0;
  28483. this.mat4[12] =
  28484. this.mat4[0] * x +this.mat4[4] * y +this.mat4[8] * z +this.mat4[12];
  28485. this.mat4[13] =
  28486. this.mat4[1] * x +this.mat4[5] * y +this.mat4[9] * z +this.mat4[13];
  28487. this.mat4[14] =
  28488. this.mat4[2] * x +this.mat4[6] * y +this.mat4[10] * z +this.mat4[14];
  28489. this.mat4[15] =
  28490. this.mat4[3] * x +this.mat4[7] * y +this.mat4[11] * z +this.mat4[15];
  28491. };
  28492. p5.Matrix.prototype.rotateX = function(a){
  28493. this.rotate(a, [1,0,0]);
  28494. };
  28495. p5.Matrix.prototype.rotateY = function(a){
  28496. this.rotate(a, [0,1,0]);
  28497. };
  28498. p5.Matrix.prototype.rotateZ = function(a){
  28499. this.rotate(a, [0,0,1]);
  28500. };
  28501. /**
  28502. * sets the perspective matrix
  28503. * @param {Number} fovy [description]
  28504. * @param {Number} aspect [description]
  28505. * @param {Number} near near clipping plane
  28506. * @param {Number} far far clipping plane
  28507. * @return {void}
  28508. */
  28509. p5.Matrix.prototype.perspective = function(fovy,aspect,near,far){
  28510. var f = 1.0 / Math.tan(fovy / 2),
  28511. nf = 1 / (near - far);
  28512. this.mat4[0] = f / aspect;
  28513. this.mat4[1] = 0;
  28514. this.mat4[2] = 0;
  28515. this.mat4[3] = 0;
  28516. this.mat4[4] = 0;
  28517. this.mat4[5] = f;
  28518. this.mat4[6] = 0;
  28519. this.mat4[7] = 0;
  28520. this.mat4[8] = 0;
  28521. this.mat4[9] = 0;
  28522. this.mat4[10] = (far + near) * nf;
  28523. this.mat4[11] = -1;
  28524. this.mat4[12] = 0;
  28525. this.mat4[13] = 0;
  28526. this.mat4[14] = (2 * far * near) * nf;
  28527. this.mat4[15] = 0;
  28528. return this;
  28529. };
  28530. /**
  28531. * sets the ortho matrix
  28532. * @param {Number} left [description]
  28533. * @param {Number} right [description]
  28534. * @param {Number} bottom [description]
  28535. * @param {Number} top [description]
  28536. * @param {Number} near near clipping plane
  28537. * @param {Number} far far clipping plane
  28538. * @return {void}
  28539. */
  28540. p5.Matrix.prototype.ortho = function(left,right,bottom,top,near,far){
  28541. var lr = 1 / (left - right),
  28542. bt = 1 / (bottom - top),
  28543. nf = 1 / (near - far);
  28544. this.mat4[0] = -2 * lr;
  28545. this.mat4[1] = 0;
  28546. this.mat4[2] = 0;
  28547. this.mat4[3] = 0;
  28548. this.mat4[4] = 0;
  28549. this.mat4[5] = -2 * bt;
  28550. this.mat4[6] = 0;
  28551. this.mat4[7] = 0;
  28552. this.mat4[8] = 0;
  28553. this.mat4[9] = 0;
  28554. this.mat4[10] = 2 * nf;
  28555. this.mat4[11] = 0;
  28556. this.mat4[12] = (left + right) * lr;
  28557. this.mat4[13] = (top + bottom) * bt;
  28558. this.mat4[14] = (far + near) * nf;
  28559. this.mat4[15] = 1;
  28560. return this;
  28561. };
  28562. /**
  28563. * PRIVATE
  28564. */
  28565. // matrix methods adapted from:
  28566. // https://developer.mozilla.org/en-US/docs/Web/WebGL/
  28567. // gluPerspective
  28568. //
  28569. // function _makePerspective(fovy, aspect, znear, zfar){
  28570. // var ymax = znear * Math.tan(fovy * Math.PI / 360.0);
  28571. // var ymin = -ymax;
  28572. // var xmin = ymin * aspect;
  28573. // var xmax = ymax * aspect;
  28574. // return _makeFrustum(xmin, xmax, ymin, ymax, znear, zfar);
  28575. // }
  28576. ////
  28577. //// glFrustum
  28578. ////
  28579. //function _makeFrustum(left, right, bottom, top, znear, zfar){
  28580. // var X = 2*znear/(right-left);
  28581. // var Y = 2*znear/(top-bottom);
  28582. // var A = (right+left)/(right-left);
  28583. // var B = (top+bottom)/(top-bottom);
  28584. // var C = -(zfar+znear)/(zfar-znear);
  28585. // var D = -2*zfar*znear/(zfar-znear);
  28586. // var frustrumMatrix =[
  28587. // X, 0, A, 0,
  28588. // 0, Y, B, 0,
  28589. // 0, 0, C, D,
  28590. // 0, 0, -1, 0
  28591. //];
  28592. //return frustrumMatrix;
  28593. // }
  28594. // function _setMVPMatrices(){
  28595. ////an identity matrix
  28596. ////@TODO use the p5.Matrix class to abstract away our MV matrices and
  28597. ///other math
  28598. //var _mvMatrix =
  28599. //[
  28600. // 1.0,0.0,0.0,0.0,
  28601. // 0.0,1.0,0.0,0.0,
  28602. // 0.0,0.0,1.0,0.0,
  28603. // 0.0,0.0,0.0,1.0
  28604. //];
  28605. module.exports = p5.Matrix;
  28606. },{"../core/constants":36,"../core/core":37,"../math/polargeometry":67}],84:[function(_dereq_,module,exports){
  28607. /**
  28608. * Welcome to RendererGL Immediate Mode.
  28609. * Immediate mode is used for drawing custom shapes
  28610. * from a set of vertices. Immediate Mode is activated
  28611. * when you call beginShape() & de-activated when you call endShape().
  28612. * Immediate mode is a style of programming borrowed
  28613. * from OpenGL's (now-deprecated) immediate mode.
  28614. * It differs from p5.js' default, Retained Mode, which caches
  28615. * geometries and buffers on the CPU to reduce the number of webgl
  28616. * draw calls. Retained mode is more efficient & performative,
  28617. * however, Immediate Mode is useful for sketching quick
  28618. * geometric ideas.
  28619. */
  28620. 'use strict';
  28621. var p5 = _dereq_('../core/core');
  28622. var constants = _dereq_('../core/constants');
  28623. /**
  28624. * Begin shape drawing. This is a helpful way of generating
  28625. * custom shapes quickly. However in WEBGL mode, application
  28626. * performance will likely drop as a result of too many calls to
  28627. * beginShape() / endShape(). As a high performance alternative,
  28628. * please use p5.js geometry primitives.
  28629. * @param {Number} mode webgl primitives mode. beginShape supports the
  28630. * following modes:
  28631. * POINTS,LINES,LINE_STRIP,LINE_LOOP,TRIANGLES,
  28632. * TRIANGLE_STRIP,and TRIANGLE_FAN.
  28633. * @return {[type]} [description]
  28634. */
  28635. p5.RendererGL.prototype.beginShape = function(mode){
  28636. //default shape mode is line_strip
  28637. this.immediateMode.shapeMode = (mode !== undefined ) ?
  28638. mode : constants.LINE_STRIP;
  28639. //if we haven't yet initialized our
  28640. //immediateMode vertices & buffers, create them now!
  28641. if(this.immediateMode.vertexPositions === undefined){
  28642. this.immediateMode.vertexPositions = [];
  28643. this.immediateMode.vertexColors = [];
  28644. this.immediateMode.vertexBuffer = this.GL.createBuffer();
  28645. this.immediateMode.colorBuffer = this.GL.createBuffer();
  28646. } else {
  28647. this.immediateMode.vertexPositions.length = 0;
  28648. this.immediateMode.vertexColors.length = 0;
  28649. }
  28650. this.isImmediateDrawing = true;
  28651. return this;
  28652. };
  28653. /**
  28654. * adds a vertex to be drawn in a custom Shape.
  28655. * @param {Number} x x-coordinate of vertex
  28656. * @param {Number} y y-coordinate of vertex
  28657. * @param {Number} z z-coordinate of vertex
  28658. * @return {p5.RendererGL} [description]
  28659. * @TODO implement handling of p5.Vector args
  28660. */
  28661. p5.RendererGL.prototype.vertex = function(x, y, z){
  28662. this.immediateMode.vertexPositions.push(x, y, z);
  28663. var vertexColor = this.curFillColor || [0.5, 0.5, 0.5, 1.0];
  28664. this.immediateMode.vertexColors.push(
  28665. vertexColor[0],
  28666. vertexColor[1],
  28667. vertexColor[2],
  28668. vertexColor[3]);
  28669. return this;
  28670. };
  28671. /**
  28672. * End shape drawing and render vertices to screen.
  28673. * @return {p5.RendererGL} [description]
  28674. */
  28675. p5.RendererGL.prototype.endShape =
  28676. function(mode, isCurve, isBezier,isQuadratic, isContour, shapeKind){
  28677. var gl = this.GL;
  28678. this._bindImmediateBuffers(
  28679. this.immediateMode.vertexPositions,
  28680. this.immediateMode.vertexColors);
  28681. if(mode){
  28682. if(this.drawMode === 'fill'){
  28683. switch(this.immediateMode.shapeMode){
  28684. case constants.LINE_STRIP:
  28685. this.immediateMode.shapeMode = constants.TRIANGLE_FAN;
  28686. break;
  28687. case constants.LINES:
  28688. this.immediateMode.shapeMode = constants.TRIANGLE_FAN;
  28689. break;
  28690. case constants.TRIANGLES:
  28691. this.immediateMode.shapeMode = constants.TRIANGLE_FAN;
  28692. break;
  28693. }
  28694. } else {
  28695. switch(this.immediateMode.shapeMode){
  28696. case constants.LINE_STRIP:
  28697. this.immediateMode.shapeMode = constants.LINE_LOOP;
  28698. break;
  28699. case constants.LINES:
  28700. this.immediateMode.shapeMode = constants.LINE_LOOP;
  28701. break;
  28702. }
  28703. }
  28704. }
  28705. //QUADS & QUAD_STRIP are not supported primitives modes
  28706. //in webgl.
  28707. if(this.immediateMode.shapeMode === constants.QUADS ||
  28708. this.immediateMode.shapeMode === constants.QUAD_STRIP){
  28709. throw new Error('sorry, ' + this.immediateMode.shapeMode+
  28710. ' not yet implemented in webgl mode.');
  28711. }
  28712. else {
  28713. gl.enable(gl.BLEND);
  28714. gl.drawArrays(this.immediateMode.shapeMode, 0,
  28715. this.immediateMode.vertexPositions.length / 3);
  28716. }
  28717. //clear out our vertexPositions & colors arrays
  28718. //after rendering
  28719. this.immediateMode.vertexPositions.length = 0;
  28720. this.immediateMode.vertexColors.length = 0;
  28721. this.isImmediateDrawing = false;
  28722. return this;
  28723. };
  28724. /**
  28725. * Bind immediateMode buffers to data,
  28726. * then draw gl arrays
  28727. * @param {Array} vertices Numbers array representing
  28728. * vertex positions
  28729. * @return {p5.RendererGL}
  28730. */
  28731. p5.RendererGL.prototype._bindImmediateBuffers = function(vertices, colors){
  28732. this._setDefaultCamera();
  28733. var gl = this.GL;
  28734. var shaderKey = this._getCurShaderId();
  28735. var shaderProgram = this.mHash[shaderKey];
  28736. //vertex position Attribute
  28737. shaderProgram.vertexPositionAttribute =
  28738. gl.getAttribLocation(shaderProgram, 'aPosition');
  28739. gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
  28740. gl.bindBuffer(gl.ARRAY_BUFFER, this.immediateMode.vertexBuffer);
  28741. gl.bufferData(
  28742. gl.ARRAY_BUFFER, new Float32Array(vertices), gl.DYNAMIC_DRAW);
  28743. gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute,
  28744. 3, gl.FLOAT, false, 0, 0);
  28745. shaderProgram.vertexColorAttribute =
  28746. gl.getAttribLocation(shaderProgram, 'aVertexColor');
  28747. gl.enableVertexAttribArray(shaderProgram.vertexColorAttribute);
  28748. gl.bindBuffer(gl.ARRAY_BUFFER, this.immediateMode.colorBuffer);
  28749. gl.bufferData(gl.ARRAY_BUFFER,
  28750. new Float32Array(colors),gl.DYNAMIC_DRAW);
  28751. gl.vertexAttribPointer(shaderProgram.vertexColorAttribute,
  28752. 4, gl.FLOAT, false, 0, 0);
  28753. //matrix
  28754. this._setMatrixUniforms(shaderKey);
  28755. //@todo implement in all shaders (not just immediateVert)
  28756. //set our default point size
  28757. // this._setUniform1f(shaderKey,
  28758. // 'uPointSize',
  28759. // this.pointSize);
  28760. return this;
  28761. };
  28762. //////////////////////////////////////////////
  28763. // COLOR
  28764. //////////////////////////////////////////////
  28765. p5.RendererGL.prototype._getColorVertexShader = function(){
  28766. var gl = this.GL;
  28767. var mId = 'immediateVert|vertexColorFrag';
  28768. var shaderProgram;
  28769. if(!this.materialInHash(mId)){
  28770. shaderProgram =
  28771. this._initShaders('immediateVert', 'vertexColorFrag', true);
  28772. this.mHash[mId] = shaderProgram;
  28773. shaderProgram.vertexColorAttribute =
  28774. gl.getAttribLocation(shaderProgram, 'aVertexColor');
  28775. gl.enableVertexAttribArray(shaderProgram.vertexColorAttribute);
  28776. }else{
  28777. shaderProgram = this.mHash[mId];
  28778. }
  28779. return shaderProgram;
  28780. };
  28781. module.exports = p5.RendererGL;
  28782. },{"../core/constants":36,"../core/core":37}],85:[function(_dereq_,module,exports){
  28783. //Retained Mode. The default mode for rendering 3D primitives
  28784. //in WEBGL.
  28785. 'use strict';
  28786. var p5 = _dereq_('../core/core');
  28787. var hashCount = 0;
  28788. /**
  28789. * _initBufferDefaults
  28790. * @description initializes buffer defaults. runs each time a new geometry is
  28791. * registered
  28792. * @param {String} gId key of the geometry object
  28793. */
  28794. p5.RendererGL.prototype._initBufferDefaults = function(gId) {
  28795. //@TODO remove this limit on hashes in gHash
  28796. hashCount ++;
  28797. if(hashCount > 1000){
  28798. var key = Object.keys(this.gHash)[0];
  28799. delete this.gHash[key];
  28800. hashCount --;
  28801. }
  28802. var gl = this.GL;
  28803. //create a new entry in our gHash
  28804. this.gHash[gId] = {};
  28805. this.gHash[gId].vertexBuffer = gl.createBuffer();
  28806. this.gHash[gId].normalBuffer = gl.createBuffer();
  28807. this.gHash[gId].uvBuffer = gl.createBuffer();
  28808. this.gHash[gId].indexBuffer = gl.createBuffer();
  28809. };
  28810. /**
  28811. * createBuffers description
  28812. * @param {String} gId key of the geometry object
  28813. * @param {p5.Geometry} obj contains geometry data
  28814. */
  28815. p5.RendererGL.prototype.createBuffers = function(gId, obj) {
  28816. var gl = this.GL;
  28817. this._setDefaultCamera();
  28818. //initialize the gl buffers for our geom groups
  28819. this._initBufferDefaults(gId);
  28820. //return the current shaderProgram from our material hash
  28821. var shaderProgram = this.mHash[this._getCurShaderId()];
  28822. //@todo rename "numberOfItems" property to something more descriptive
  28823. //we mult the num geom faces by 3
  28824. this.gHash[gId].numberOfItems = obj.faces.length * 3;
  28825. gl.bindBuffer(gl.ARRAY_BUFFER, this.gHash[gId].vertexBuffer);
  28826. gl.bufferData(
  28827. gl.ARRAY_BUFFER,
  28828. new Float32Array( vToNArray(obj.vertices) ),
  28829. gl.STATIC_DRAW);
  28830. //vertex position
  28831. shaderProgram.vertexPositionAttribute =
  28832. gl.getAttribLocation(shaderProgram, 'aPosition');
  28833. gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
  28834. gl.vertexAttribPointer(
  28835. shaderProgram.vertexPositionAttribute,
  28836. 3, gl.FLOAT, false, 0, 0);
  28837. gl.bindBuffer(gl.ARRAY_BUFFER, this.gHash[gId].normalBuffer);
  28838. gl.bufferData(
  28839. gl.ARRAY_BUFFER,
  28840. new Float32Array( vToNArray(obj.vertexNormals) ),
  28841. gl.STATIC_DRAW);
  28842. //vertex normal
  28843. shaderProgram.vertexNormalAttribute =
  28844. gl.getAttribLocation(shaderProgram, 'aNormal');
  28845. gl.enableVertexAttribArray(shaderProgram.vertexNormalAttribute);
  28846. gl.vertexAttribPointer(
  28847. shaderProgram.vertexNormalAttribute,
  28848. 3, gl.FLOAT, false, 0, 0);
  28849. gl.bindBuffer(gl.ARRAY_BUFFER, this.gHash[gId].uvBuffer);
  28850. gl.bufferData(
  28851. gl.ARRAY_BUFFER,
  28852. new Float32Array( flatten(obj.uvs) ),
  28853. gl.STATIC_DRAW);
  28854. //texture coordinate Attribute
  28855. shaderProgram.textureCoordAttribute =
  28856. gl.getAttribLocation(shaderProgram, 'aTexCoord');
  28857. gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute);
  28858. gl.vertexAttribPointer(
  28859. shaderProgram.textureCoordAttribute,
  28860. 2, gl.FLOAT, false, 0, 0);
  28861. gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.gHash[gId].indexBuffer);
  28862. gl.bufferData(
  28863. gl.ELEMENT_ARRAY_BUFFER,
  28864. new Uint16Array( flatten(obj.faces) ),
  28865. gl.STATIC_DRAW);
  28866. };
  28867. /**
  28868. * Draws buffers given a geometry key ID
  28869. * @param {String} gId ID in our geom hash
  28870. * @return {p5.RendererGL} this
  28871. */
  28872. p5.RendererGL.prototype.drawBuffers = function(gId) {
  28873. this._setDefaultCamera();
  28874. var gl = this.GL;
  28875. var shaderKey = this._getCurShaderId();
  28876. var shaderProgram = this.mHash[shaderKey];
  28877. //vertex position buffer
  28878. gl.bindBuffer(gl.ARRAY_BUFFER, this.gHash[gId].vertexBuffer);
  28879. gl.vertexAttribPointer(
  28880. shaderProgram.vertexPositionAttribute,
  28881. 3, gl.FLOAT, false, 0, 0);
  28882. //normal buffer
  28883. gl.bindBuffer(gl.ARRAY_BUFFER, this.gHash[gId].normalBuffer);
  28884. gl.vertexAttribPointer(
  28885. shaderProgram.vertexNormalAttribute,
  28886. 3, gl.FLOAT, false, 0, 0);
  28887. // uv buffer
  28888. gl.bindBuffer(gl.ARRAY_BUFFER, this.gHash[gId].uvBuffer);
  28889. gl.vertexAttribPointer(
  28890. shaderProgram.textureCoordAttribute,
  28891. 2, gl.FLOAT, false, 0, 0);
  28892. //vertex index buffer
  28893. gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.gHash[gId].indexBuffer);
  28894. this._setMatrixUniforms(shaderKey);
  28895. gl.drawElements(
  28896. gl.TRIANGLES, this.gHash[gId].numberOfItems,
  28897. gl.UNSIGNED_SHORT, 0);
  28898. return this;
  28899. };
  28900. ///////////////////////////////
  28901. //// UTILITY FUNCTIONS
  28902. //////////////////////////////
  28903. /**
  28904. * turn a two dimensional array into one dimensional array
  28905. * @param {Array} arr 2-dimensional array
  28906. * @return {Array} 1-dimensional array
  28907. * [[1, 2, 3],[4, 5, 6]] -> [1, 2, 3, 4, 5, 6]
  28908. */
  28909. function flatten(arr){
  28910. if (arr.length>0){
  28911. return arr.reduce(function(a, b){
  28912. return a.concat(b);
  28913. });
  28914. } else {
  28915. return [];
  28916. }
  28917. }
  28918. /**
  28919. * turn a p5.Vector Array into a one dimensional number array
  28920. * @param {Array} arr an array of p5.Vector
  28921. * @return {Array]} a one dimensional array of numbers
  28922. * [p5.Vector(1, 2, 3), p5.Vector(4, 5, 6)] ->
  28923. * [1, 2, 3, 4, 5, 6]
  28924. */
  28925. function vToNArray(arr){
  28926. return flatten(arr.map(function(item){
  28927. return [item.x, item.y, item.z];
  28928. }));
  28929. }
  28930. module.exports = p5.RendererGL;
  28931. },{"../core/core":37}],86:[function(_dereq_,module,exports){
  28932. 'use strict';
  28933. var p5 = _dereq_('../core/core');
  28934. var shader = _dereq_('./shader');
  28935. _dereq_('../core/p5.Renderer');
  28936. _dereq_('./p5.Matrix');
  28937. var uMVMatrixStack = [];
  28938. //@TODO should implement public method
  28939. //to override these attributes
  28940. var attributes = {
  28941. alpha: true,
  28942. depth: true,
  28943. stencil: true,
  28944. antialias: false,
  28945. premultipliedAlpha: false,
  28946. preserveDrawingBuffer: false
  28947. };
  28948. /**
  28949. * @class p5.RendererGL
  28950. * @constructor
  28951. * @extends p5.Renderer
  28952. * 3D graphics class.
  28953. * @todo extend class to include public method for offscreen
  28954. * rendering (FBO).
  28955. *
  28956. */
  28957. p5.RendererGL = function(elt, pInst, isMainCanvas) {
  28958. p5.Renderer.call(this, elt, pInst, isMainCanvas);
  28959. this._initContext();
  28960. this.isP3D = true; //lets us know we're in 3d mode
  28961. this.GL = this.drawingContext;
  28962. //lights
  28963. this.ambientLightCount = 0;
  28964. this.directionalLightCount = 0;
  28965. this.pointLightCount = 0;
  28966. //camera
  28967. this._curCamera = null;
  28968. /**
  28969. * model view, projection, & normal
  28970. * matrices
  28971. */
  28972. this.uMVMatrix = new p5.Matrix();
  28973. this.uPMatrix = new p5.Matrix();
  28974. this.uNMatrix = new p5.Matrix('mat3');
  28975. //Geometry & Material hashes
  28976. this.gHash = {};
  28977. this.mHash = {};
  28978. //Imediate Mode
  28979. //default drawing is done in Retained Mode
  28980. this.isImmediateDrawing = false;
  28981. this.immediateMode = {};
  28982. this.curFillColor = [0.5,0.5,0.5,1.0];
  28983. this.curStrokeColor = [0.5,0.5,0.5,1.0];
  28984. this.pointSize = 5.0;//default point/stroke
  28985. return this;
  28986. };
  28987. p5.RendererGL.prototype = Object.create(p5.Renderer.prototype);
  28988. //////////////////////////////////////////////
  28989. // Setting
  28990. //////////////////////////////////////////////
  28991. p5.RendererGL.prototype._initContext = function() {
  28992. try {
  28993. this.drawingContext = this.canvas.getContext('webgl', attributes) ||
  28994. this.canvas.getContext('experimental-webgl', attributes);
  28995. if (this.drawingContext === null) {
  28996. throw new Error('Error creating webgl context');
  28997. } else {
  28998. console.log('p5.RendererGL: enabled webgl context');
  28999. var gl = this.drawingContext;
  29000. gl.enable(gl.DEPTH_TEST);
  29001. gl.depthFunc(gl.LEQUAL);
  29002. gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
  29003. }
  29004. } catch (er) {
  29005. throw new Error(er);
  29006. }
  29007. };
  29008. //detect if user didn't set the camera
  29009. //then call this function below
  29010. p5.RendererGL.prototype._setDefaultCamera = function(){
  29011. if(this._curCamera === null){
  29012. var _w = this.width;
  29013. var _h = this.height;
  29014. this.uPMatrix = p5.Matrix.identity();
  29015. var cameraZ = (this.height / 2) / Math.tan(Math.PI * 30 / 180);
  29016. this.uPMatrix.perspective(60 / 180 * Math.PI, _w / _h,
  29017. cameraZ * 0.1, cameraZ * 10);
  29018. this._curCamera = 'default';
  29019. }
  29020. };
  29021. p5.RendererGL.prototype._update = function() {
  29022. this.uMVMatrix = p5.Matrix.identity();
  29023. this.translate(0, 0, -(this.height / 2) / Math.tan(Math.PI * 30 / 180));
  29024. this.ambientLightCount = 0;
  29025. this.directionalLightCount = 0;
  29026. this.pointLightCount = 0;
  29027. };
  29028. /**
  29029. * [background description]
  29030. * @return {[type]} [description]
  29031. */
  29032. p5.RendererGL.prototype.background = function() {
  29033. var gl = this.GL;
  29034. var _col = this._pInst.color.apply(this._pInst, arguments);
  29035. var _r = (_col.levels[0]) / 255;
  29036. var _g = (_col.levels[1]) / 255;
  29037. var _b = (_col.levels[2]) / 255;
  29038. var _a = (_col.levels[3]) / 255;
  29039. gl.clearColor(_r, _g, _b, _a);
  29040. gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
  29041. };
  29042. //@TODO implement this
  29043. // p5.RendererGL.prototype.clear = function() {
  29044. //@TODO
  29045. // };
  29046. //////////////////////////////////////////////
  29047. // SHADER
  29048. //////////////////////////////////////////////
  29049. /**
  29050. * [_initShaders description]
  29051. * @param {string} vertId [description]
  29052. * @param {string} fragId [description]
  29053. * @return {[type]} [description]
  29054. */
  29055. p5.RendererGL.prototype._initShaders =
  29056. function(vertId, fragId, isImmediateMode) {
  29057. var gl = this.GL;
  29058. //set up our default shaders by:
  29059. // 1. create the shader,
  29060. // 2. load the shader source,
  29061. // 3. compile the shader
  29062. var _vertShader = gl.createShader(gl.VERTEX_SHADER);
  29063. //load in our default vertex shader
  29064. gl.shaderSource(_vertShader, shader[vertId]);
  29065. gl.compileShader(_vertShader);
  29066. // if our vertex shader failed compilation?
  29067. if (!gl.getShaderParameter(_vertShader, gl.COMPILE_STATUS)) {
  29068. alert('Yikes! An error occurred compiling the shaders:' +
  29069. gl.getShaderInfoLog(_vertShader));
  29070. return null;
  29071. }
  29072. var _fragShader = gl.createShader(gl.FRAGMENT_SHADER);
  29073. //load in our material frag shader
  29074. gl.shaderSource(_fragShader, shader[fragId]);
  29075. gl.compileShader(_fragShader);
  29076. // if our frag shader failed compilation?
  29077. if (!gl.getShaderParameter(_fragShader, gl.COMPILE_STATUS)) {
  29078. alert('Darn! An error occurred compiling the shaders:' +
  29079. gl.getShaderInfoLog(_fragShader));
  29080. return null;
  29081. }
  29082. var shaderProgram = gl.createProgram();
  29083. gl.attachShader(shaderProgram, _vertShader);
  29084. gl.attachShader(shaderProgram, _fragShader);
  29085. gl.linkProgram(shaderProgram);
  29086. if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
  29087. alert('Snap! Error linking shader program');
  29088. }
  29089. //END SHADERS SETUP
  29090. this._getLocation(shaderProgram, isImmediateMode);
  29091. return shaderProgram;
  29092. };
  29093. p5.RendererGL.prototype._getLocation =
  29094. function(shaderProgram, isImmediateMode) {
  29095. var gl = this.GL;
  29096. gl.useProgram(shaderProgram);
  29097. //projection Matrix uniform
  29098. shaderProgram.uPMatrixUniform =
  29099. gl.getUniformLocation(shaderProgram, 'uProjectionMatrix');
  29100. //model view Matrix uniform
  29101. shaderProgram.uMVMatrixUniform =
  29102. gl.getUniformLocation(shaderProgram, 'uModelViewMatrix');
  29103. //@TODO: figure out a better way instead of if statement
  29104. if(isImmediateMode === undefined){
  29105. //normal Matrix uniform
  29106. shaderProgram.uNMatrixUniform =
  29107. gl.getUniformLocation(shaderProgram, 'uNormalMatrix');
  29108. shaderProgram.samplerUniform =
  29109. gl.getUniformLocation(shaderProgram, 'uSampler');
  29110. }
  29111. };
  29112. /**
  29113. * Sets a shader uniform given a shaderProgram and uniform string
  29114. * @param {String} shaderKey key to material Hash.
  29115. * @param {String} uniform location in shader.
  29116. * @param { Number} data data to bind uniform. Float data type.
  29117. * @todo currently this function sets uniform1f data.
  29118. * Should generalize function to accept any uniform
  29119. * data type.
  29120. */
  29121. p5.RendererGL.prototype._setUniform1f = function(shaderKey,uniform,data)
  29122. {
  29123. var gl = this.GL;
  29124. var shaderProgram = this.mHash[shaderKey];
  29125. gl.useProgram(shaderProgram);
  29126. shaderProgram[uniform] = gl.getUniformLocation(shaderProgram, uniform);
  29127. gl.uniform1f(shaderProgram[uniform], data);
  29128. return this;
  29129. };
  29130. p5.RendererGL.prototype._setMatrixUniforms = function(shaderKey) {
  29131. var gl = this.GL;
  29132. var shaderProgram = this.mHash[shaderKey];
  29133. gl.useProgram(shaderProgram);
  29134. gl.uniformMatrix4fv(
  29135. shaderProgram.uPMatrixUniform,
  29136. false, this.uPMatrix.mat4);
  29137. gl.uniformMatrix4fv(
  29138. shaderProgram.uMVMatrixUniform,
  29139. false, this.uMVMatrix.mat4);
  29140. this.uNMatrix.inverseTranspose(this.uMVMatrix);
  29141. gl.uniformMatrix3fv(
  29142. shaderProgram.uNMatrixUniform,
  29143. false, this.uNMatrix.mat3);
  29144. };
  29145. //////////////////////////////////////////////
  29146. // GET CURRENT | for shader and color
  29147. //////////////////////////////////////////////
  29148. p5.RendererGL.prototype._getShader = function(vertId, fragId, isImmediateMode) {
  29149. var mId = vertId + '|' + fragId;
  29150. //create it and put it into hashTable
  29151. if(!this.materialInHash(mId)){
  29152. var shaderProgram = this._initShaders(vertId, fragId, isImmediateMode);
  29153. this.mHash[mId] = shaderProgram;
  29154. }
  29155. this.curShaderId = mId;
  29156. return this.mHash[this.curShaderId];
  29157. };
  29158. p5.RendererGL.prototype._getCurShaderId = function(){
  29159. //if the shader ID is not yet defined
  29160. var mId, shaderProgram;
  29161. if(this.drawMode !== 'fill' && this.curShaderId === undefined){
  29162. //default shader: normalMaterial()
  29163. mId = 'normalVert|normalFrag';
  29164. shaderProgram = this._initShaders('normalVert', 'normalFrag');
  29165. this.mHash[mId] = shaderProgram;
  29166. this.curShaderId = mId;
  29167. } else if(this.isImmediateDrawing && this.drawMode === 'fill'){
  29168. mId = 'immediateVert|vertexColorFrag';
  29169. shaderProgram = this._initShaders('immediateVert', 'vertexColorFrag');
  29170. this.mHash[mId] = shaderProgram;
  29171. this.curShaderId = mId;
  29172. }
  29173. return this.curShaderId;
  29174. };
  29175. //////////////////////////////////////////////
  29176. // COLOR
  29177. //////////////////////////////////////////////
  29178. /**
  29179. * Basic fill material for geometry with a given color
  29180. * @method fill
  29181. * @param {Number|Array|String|p5.Color} v1 gray value,
  29182. * red or hue value (depending on the current color mode),
  29183. * or color Array, or CSS color string
  29184. * @param {Number} [v2] optional: green or saturation value
  29185. * @param {Number} [v3] optional: blue or brightness value
  29186. * @param {Number} [a] optional: opacity
  29187. * @return {p5} the p5 object
  29188. * @example
  29189. * <div>
  29190. * <code>
  29191. * function setup(){
  29192. * createCanvas(100, 100, WEBGL);
  29193. * }
  29194. *
  29195. * function draw(){
  29196. * background(0);
  29197. * fill(250, 0, 0);
  29198. * rotateX(frameCount * 0.01);
  29199. * rotateY(frameCount * 0.01);
  29200. * rotateZ(frameCount * 0.01);
  29201. * box(200, 200, 200);
  29202. * }
  29203. * </code>
  29204. * </div>
  29205. *
  29206. * @alt
  29207. * red canvas
  29208. *
  29209. */
  29210. p5.RendererGL.prototype.fill = function(v1, v2, v3, a) {
  29211. var gl = this.GL;
  29212. var shaderProgram;
  29213. //see material.js for more info on color blending in webgl
  29214. var colors = this._applyColorBlend.apply(this, arguments);
  29215. this.curFillColor = colors;
  29216. this.drawMode = 'fill';
  29217. if(this.isImmediateDrawing){
  29218. shaderProgram =
  29219. this._getShader('immediateVert','vertexColorFrag');
  29220. gl.useProgram(shaderProgram);
  29221. } else {
  29222. shaderProgram =
  29223. this._getShader('normalVert', 'basicFrag');
  29224. gl.useProgram(shaderProgram);
  29225. //RetainedMode uses a webgl uniform to pass color vals
  29226. //in ImmediateMode, we want access to each vertex so therefore
  29227. //we cannot use a uniform.
  29228. shaderProgram.uMaterialColor = gl.getUniformLocation(
  29229. shaderProgram, 'uMaterialColor' );
  29230. gl.uniform4f( shaderProgram.uMaterialColor,
  29231. colors[0],
  29232. colors[1],
  29233. colors[2],
  29234. colors[3]);
  29235. }
  29236. return this;
  29237. };
  29238. p5.RendererGL.prototype.stroke = function(r, g, b, a) {
  29239. var color = this._pInst.color.apply(this._pInst, arguments);
  29240. var colorNormalized = color._array;
  29241. this.curStrokeColor = colorNormalized;
  29242. this.drawMode = 'stroke';
  29243. return this;
  29244. };
  29245. //@TODO
  29246. p5.RendererGL.prototype._strokeCheck = function(){
  29247. if(this.drawMode === 'stroke'){
  29248. throw new Error(
  29249. 'stroke for shapes in 3D not yet implemented, use fill for now :('
  29250. );
  29251. }
  29252. };
  29253. /**
  29254. * [strokeWeight description]
  29255. * @param {Number} pointSize stroke point size
  29256. * @return {[type]} [description]
  29257. * @todo strokeWeight currently works on points only.
  29258. * implement on all wireframes and strokes.
  29259. */
  29260. p5.RendererGL.prototype.strokeWeight = function(pointSize) {
  29261. this.pointSize = pointSize;
  29262. return this;
  29263. };
  29264. //////////////////////////////////////////////
  29265. // HASH | for material and geometry
  29266. //////////////////////////////////////////////
  29267. p5.RendererGL.prototype.geometryInHash = function(gId){
  29268. return this.gHash[gId] !== undefined;
  29269. };
  29270. p5.RendererGL.prototype.materialInHash = function(mId){
  29271. return this.mHash[mId] !== undefined;
  29272. };
  29273. /**
  29274. * [resize description]
  29275. * @param {[type]} w [description]
  29276. * @param {[tyoe]} h [description]
  29277. * @return {[type]} [description]
  29278. */
  29279. p5.RendererGL.prototype.resize = function(w,h) {
  29280. var gl = this.GL;
  29281. p5.Renderer.prototype.resize.call(this, w, h);
  29282. gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
  29283. // If we're using the default camera, update the aspect ratio
  29284. if(this._curCamera === 'default') {
  29285. this._curCamera = null;
  29286. this._setDefaultCamera();
  29287. }
  29288. };
  29289. /**
  29290. * clears color and depth buffers
  29291. * with r,g,b,a
  29292. * @param {Number} r normalized red val.
  29293. * @param {Number} g normalized green val.
  29294. * @param {Number} b normalized blue val.
  29295. * @param {Number} a normalized alpha val.
  29296. */
  29297. p5.RendererGL.prototype.clear = function() {
  29298. var gl = this.GL;
  29299. gl.clearColor(arguments[0],
  29300. arguments[1],
  29301. arguments[2],
  29302. arguments[3]);
  29303. gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
  29304. };
  29305. /**
  29306. * [translate description]
  29307. * @param {[type]} x [description]
  29308. * @param {[type]} y [description]
  29309. * @param {[type]} z [description]
  29310. * @return {[type]} [description]
  29311. * @todo implement handle for components or vector as args
  29312. */
  29313. p5.RendererGL.prototype.translate = function(x, y, z) {
  29314. this.uMVMatrix.translate([x,-y,z]);
  29315. return this;
  29316. };
  29317. /**
  29318. * Scales the Model View Matrix by a vector
  29319. * @param {Number | p5.Vector | Array} x [description]
  29320. * @param {Number} [y] y-axis scalar
  29321. * @param {Number} [z] z-axis scalar
  29322. * @return {this} [description]
  29323. */
  29324. p5.RendererGL.prototype.scale = function(x,y,z) {
  29325. this.uMVMatrix.scale([x,y,z]);
  29326. return this;
  29327. };
  29328. p5.RendererGL.prototype.rotate = function(rad, axis){
  29329. this.uMVMatrix.rotate(rad, axis);
  29330. return this;
  29331. };
  29332. p5.RendererGL.prototype.rotateX = function(rad) {
  29333. this.rotate(rad, [1,0,0]);
  29334. return this;
  29335. };
  29336. p5.RendererGL.prototype.rotateY = function(rad) {
  29337. this.rotate(rad, [0,1,0]);
  29338. return this;
  29339. };
  29340. p5.RendererGL.prototype.rotateZ = function(rad) {
  29341. this.rotate(rad, [0,0,1]);
  29342. return this;
  29343. };
  29344. /**
  29345. * pushes a copy of the model view matrix onto the
  29346. * MV Matrix stack.
  29347. */
  29348. p5.RendererGL.prototype.push = function() {
  29349. uMVMatrixStack.push(this.uMVMatrix.copy());
  29350. };
  29351. /**
  29352. * [pop description]
  29353. * @return {[type]} [description]
  29354. */
  29355. p5.RendererGL.prototype.pop = function() {
  29356. if (uMVMatrixStack.length === 0) {
  29357. throw new Error('Invalid popMatrix!');
  29358. }
  29359. this.uMVMatrix = uMVMatrixStack.pop();
  29360. };
  29361. p5.RendererGL.prototype.resetMatrix = function() {
  29362. this.uMVMatrix = p5.Matrix.identity();
  29363. this.translate(0, 0, -800);
  29364. return this;
  29365. };
  29366. // Text/Typography
  29367. // @TODO:
  29368. p5.RendererGL.prototype._applyTextProperties = function() {
  29369. //@TODO finish implementation
  29370. console.error('text commands not yet implemented in webgl');
  29371. };
  29372. module.exports = p5.RendererGL;
  29373. },{"../core/core":37,"../core/p5.Renderer":43,"./p5.Matrix":83,"./shader":88}],87:[function(_dereq_,module,exports){
  29374. /**
  29375. * @module Shape
  29376. * @submodule 3D Primitives
  29377. * @for p5
  29378. * @requires core
  29379. * @requires p5.Geometry
  29380. */
  29381. 'use strict';
  29382. var p5 = _dereq_('../core/core');
  29383. _dereq_('./p5.Geometry');
  29384. /**
  29385. * Draw a plane with given a width and height
  29386. * @method plane
  29387. * @param {Number} width width of the plane
  29388. * @param {Number} height height of the plane
  29389. * @param {Number} [detailX] Optional number of triangle
  29390. * subdivisions in x-dimension
  29391. * @param {Number} [detailY] Optional number of triangle
  29392. * subdivisions in y-dimension
  29393. * @return {p5} the p5 object
  29394. * @example
  29395. * <div>
  29396. * <code>
  29397. * //draw a plane with width 200 and height 200
  29398. * function setup(){
  29399. * createCanvas(100, 100, WEBGL);
  29400. * }
  29401. *
  29402. * function draw(){
  29403. * background(200);
  29404. * plane(50, 50);
  29405. * }
  29406. * </code>
  29407. * </div>
  29408. *
  29409. * @alt
  29410. * Nothing displayed on canvas
  29411. * Rotating interior view of a box with sides that change color.
  29412. * 3d red and green gradient.
  29413. * Rotating interior view of a cylinder with sides that change color.
  29414. * Rotating view of a cylinder with sides that change color.
  29415. * 3d red and green gradient.
  29416. * rotating view of a multi-colored cylinder with concave sides.
  29417. */
  29418. p5.prototype.plane = function(){
  29419. var args = new Array(arguments.length);
  29420. for (var i = 0; i < args.length; ++i) {
  29421. args[i] = arguments[i];
  29422. }
  29423. var width = args[0] || 50;
  29424. var height = args[1] || width;
  29425. var detailX = typeof args[2] === 'number' ? args[2] : 1;
  29426. var detailY = typeof args[3] === 'number' ? args[3] : 1;
  29427. var gId = 'plane|'+width+'|'+height+'|'+detailX+'|'+detailY;
  29428. if(!this._renderer.geometryInHash(gId)){
  29429. var _plane = function(){
  29430. var u,v,p;
  29431. for (var i = 0; i <= this.detailY; i++){
  29432. v = i / this.detailY;
  29433. for (var j = 0; j <= this.detailX; j++){
  29434. u = j / this.detailX;
  29435. p = new p5.Vector(width * u - width/2,
  29436. height * v - height/2,
  29437. 0);
  29438. this.vertices.push(p);
  29439. this.uvs.push([u,v]);
  29440. }
  29441. }
  29442. };
  29443. var planeGeom =
  29444. new p5.Geometry(detailX, detailY, _plane);
  29445. planeGeom
  29446. .computeFaces()
  29447. .computeNormals();
  29448. this._renderer.createBuffers(gId, planeGeom);
  29449. }
  29450. this._renderer.drawBuffers(gId);
  29451. };
  29452. /**
  29453. * Draw a box with given width, height and depth
  29454. * @method box
  29455. * @param {Number} width width of the box
  29456. * @param {Number} Height height of the box
  29457. * @param {Number} depth depth of the box
  29458. * @param {Number} [detailX] Optional number of triangle
  29459. * subdivisions in x-dimension
  29460. * @param {Number} [detailY] Optional number of triangle
  29461. * subdivisions in y-dimension
  29462. * @return {p5} the p5 object
  29463. * @example
  29464. * <div>
  29465. * <code>
  29466. * //draw a spinning box with width, height and depth 200
  29467. * function setup(){
  29468. * createCanvas(100, 100, WEBGL);
  29469. * }
  29470. *
  29471. * function draw(){
  29472. * background(200);
  29473. * rotateX(frameCount * 0.01);
  29474. * rotateY(frameCount * 0.01);
  29475. * box(200, 200, 200);
  29476. * }
  29477. * </code>
  29478. * </div>
  29479. */
  29480. p5.prototype.box = function(){
  29481. var args = new Array(arguments.length);
  29482. for (var i = 0; i < args.length; ++i) {
  29483. args[i] = arguments[i];
  29484. }
  29485. var width = args[0] || 50;
  29486. var height = args[1] || width;
  29487. var depth = args[2] || width;
  29488. var detailX = typeof args[3] === 'number' ? args[3] : 4;
  29489. var detailY = typeof args[4] === 'number' ? args[4] : 4;
  29490. var gId = 'box|'+width+'|'+height+'|'+depth+'|'+detailX+'|'+detailY;
  29491. if(!this._renderer.geometryInHash(gId)){
  29492. var _box = function(){
  29493. var cubeIndices = [
  29494. [0, 4, 2, 6],// -1, 0, 0],// -x
  29495. [1, 3, 5, 7],// +1, 0, 0],// +x
  29496. [0, 1, 4, 5],// 0, -1, 0],// -y
  29497. [2, 6, 3, 7],// 0, +1, 0],// +y
  29498. [0, 2, 1, 3],// 0, 0, -1],// -z
  29499. [4, 5, 6, 7]// 0, 0, +1] // +z
  29500. ];
  29501. var id=0;
  29502. for (var i = 0; i < cubeIndices.length; i++) {
  29503. var cubeIndex = cubeIndices[i];
  29504. var v = i * 4;
  29505. for (var j = 0; j < 4; j++) {
  29506. var d = cubeIndex[j];
  29507. //inspired by lightgl:
  29508. //https://github.com/evanw/lightgl.js
  29509. //octants:https://en.wikipedia.org/wiki/Octant_(solid_geometry)
  29510. var octant = new p5.Vector(
  29511. ((d & 1) * 2 - 1)*width/2,
  29512. ((d & 2) - 1) *height/2,
  29513. ((d & 4) / 2 - 1) * depth/2);
  29514. this.vertices.push( octant );
  29515. this.uvs.push([j & 1, (j & 2) / 2]);
  29516. id++;
  29517. }
  29518. this.faces.push([v, v + 1, v + 2]);
  29519. this.faces.push([v + 2, v + 1, v + 3]);
  29520. }
  29521. };
  29522. var boxGeom = new p5.Geometry(detailX,detailY, _box);
  29523. boxGeom.computeNormals();
  29524. //initialize our geometry buffer with
  29525. //the key val pair:
  29526. //geometry Id, Geom object
  29527. this._renderer.createBuffers(gId, boxGeom);
  29528. }
  29529. this._renderer.drawBuffers(gId);
  29530. return this;
  29531. };
  29532. /**
  29533. * Draw a sphere with given radius
  29534. * @method sphere
  29535. * @param {Number} radius radius of circle
  29536. * @param {Number} [detailX] optional: number of segments,
  29537. * the more segments the smoother geometry
  29538. * default is 24
  29539. * @param {Number} [detailY] optional: number of segments,
  29540. * the more segments the smoother geometry
  29541. * default is 16
  29542. * @return {p5} the p5 object
  29543. * @example
  29544. * <div>
  29545. * <code>
  29546. * // draw a sphere with radius 200
  29547. * function setup(){
  29548. * createCanvas(100, 100, WEBGL);
  29549. * }
  29550. *
  29551. * function draw(){
  29552. * background(200);
  29553. * sphere(50);
  29554. * }
  29555. * </code>
  29556. * </div>
  29557. */
  29558. p5.prototype.sphere = function(){
  29559. var args = new Array(arguments.length);
  29560. for (var i = 0; i < args.length; ++i) {
  29561. args[i] = arguments[i];
  29562. }
  29563. var radius = args[0] || 50;
  29564. var detailX = typeof args[1] === 'number' ? args[1] : 24;
  29565. var detailY = typeof args[2] === 'number' ? args[2] : 16;
  29566. var gId = 'sphere|'+radius+'|'+detailX+'|'+detailY;
  29567. if(!this._renderer.geometryInHash(gId)){
  29568. var _sphere = function(){
  29569. var u,v,p;
  29570. for (var i = 0; i <= this.detailY; i++){
  29571. v = i / this.detailY;
  29572. for (var j = 0; j <= this.detailX; j++){
  29573. u = j / this.detailX;
  29574. var theta = 2 * Math.PI * u;
  29575. var phi = Math.PI * v - Math.PI / 2;
  29576. p = new p5.Vector(radius * Math.cos(phi) * Math.sin(theta),
  29577. radius * Math.sin(phi),
  29578. radius * Math.cos(phi) * Math.cos(theta));
  29579. this.vertices.push(p);
  29580. this.uvs.push([u,v]);
  29581. }
  29582. }
  29583. };
  29584. var sphereGeom = new p5.Geometry(detailX, detailY, _sphere);
  29585. sphereGeom
  29586. .computeFaces()
  29587. .computeNormals()
  29588. .averageNormals()
  29589. .averagePoleNormals();
  29590. this._renderer.createBuffers(gId, sphereGeom);
  29591. }
  29592. this._renderer.drawBuffers(gId);
  29593. return this;
  29594. };
  29595. /**
  29596. * @private
  29597. * helper function for creating both cones and cyllinders
  29598. */
  29599. var _truncatedCone = function(
  29600. bottomRadius,
  29601. topRadius,
  29602. height,
  29603. detailX,
  29604. detailY,
  29605. topCap,
  29606. bottomCap) {
  29607. detailX = (detailX < 3) ? 3 : detailX;
  29608. detailY = (detailY < 1) ? 1 : detailY;
  29609. topCap = (topCap === undefined) ? true : topCap;
  29610. bottomCap = (bottomCap === undefined) ? true : bottomCap;
  29611. var extra = (topCap ? 2 : 0) + (bottomCap ? 2 : 0);
  29612. var vertsAroundEdge = detailX + 1;
  29613. // ensure constant slant
  29614. var slant = Math.atan2(bottomRadius - topRadius, height);
  29615. var start = topCap ? -2 : 0;
  29616. var end = detailY + (bottomCap ? 2 : 0);
  29617. var yy, ii;
  29618. for (yy = start; yy <= end; ++yy) {
  29619. var v = yy / detailY;
  29620. var y = height * v;
  29621. var ringRadius;
  29622. if (yy < 0) {
  29623. y = 0;
  29624. v = 1;
  29625. ringRadius = bottomRadius;
  29626. } else if (yy > detailY) {
  29627. y = height;
  29628. v = 1;
  29629. ringRadius = topRadius;
  29630. } else {
  29631. ringRadius = bottomRadius +
  29632. (topRadius - bottomRadius) * (yy / detailY);
  29633. }
  29634. if (yy === -2 || yy === detailY + 2) {
  29635. ringRadius = 0;
  29636. v = 0;
  29637. }
  29638. y -= height / 2;
  29639. for (ii = 0; ii < vertsAroundEdge; ++ii) {
  29640. //VERTICES
  29641. this.vertices.push(
  29642. new p5.Vector(
  29643. Math.sin(ii*Math.PI * 2 /detailX) * ringRadius,
  29644. y,
  29645. Math.cos(ii*Math.PI * 2 /detailX) * ringRadius)
  29646. );
  29647. //VERTEX NORMALS
  29648. this.vertexNormals.push(
  29649. new p5.Vector(
  29650. (yy < 0 || yy > detailY) ? 0 :
  29651. (Math.sin(ii * Math.PI * 2 / detailX) * Math.cos(slant)),
  29652. (yy < 0) ? -1 : (yy > detailY ? 1 : Math.sin(slant)),
  29653. (yy < 0 || yy > detailY) ? 0 :
  29654. (Math.cos(ii * Math.PI * 2 / detailX) * Math.cos(slant)))
  29655. );
  29656. //UVs
  29657. this.uvs.push([(ii / detailX), v]);
  29658. }
  29659. }
  29660. for (yy = 0; yy < detailY + extra; ++yy) {
  29661. for (ii = 0; ii < detailX; ++ii) {
  29662. this.faces.push([vertsAroundEdge * (yy + 0) + 0 + ii,
  29663. vertsAroundEdge * (yy + 0) + 1 + ii,
  29664. vertsAroundEdge * (yy + 1) + 1 + ii]);
  29665. this.faces.push([vertsAroundEdge * (yy + 0) + 0 + ii,
  29666. vertsAroundEdge * (yy + 1) + 1 + ii,
  29667. vertsAroundEdge * (yy + 1) + 0 + ii]);
  29668. }
  29669. }
  29670. };
  29671. /**
  29672. * Draw a cylinder with given radius and height
  29673. * @method cylinder
  29674. * @param {Number} radius radius of the surface
  29675. * @param {Number} height height of the cylinder
  29676. * @param {Number} [detailX] optional: number of segments,
  29677. * the more segments the smoother geometry
  29678. * default is 24
  29679. * @param {Number} [detailY] optional: number of segments in y-dimension,
  29680. * the more segments the smoother geometry
  29681. * default is 16
  29682. * @return {p5} the p5 object
  29683. * @example
  29684. * <div>
  29685. * <code>
  29686. * //draw a spinning cylinder with radius 200 and height 200
  29687. * function setup(){
  29688. * createCanvas(100, 100, WEBGL);
  29689. * }
  29690. *
  29691. * function draw(){
  29692. * background(200);
  29693. * rotateX(frameCount * 0.01);
  29694. * rotateZ(frameCount * 0.01);
  29695. * cylinder(200, 200);
  29696. * }
  29697. * </code>
  29698. * </div>
  29699. */
  29700. p5.prototype.cylinder = function(){
  29701. var args = new Array(arguments.length);
  29702. for (var i = 0; i < args.length; ++i) {
  29703. args[i] = arguments[i];
  29704. }
  29705. var radius = args[0] || 50;
  29706. var height = args[1] || radius;
  29707. var detailX = typeof args[2] === 'number' ? args[2] : 24;
  29708. var detailY = typeof args[3] === 'number' ? args[3] : 16;
  29709. var gId = 'cylinder|'+radius+'|'+height+'|'+detailX+'|'+detailY;
  29710. if(!this._renderer.geometryInHash(gId)){
  29711. var cylinderGeom = new p5.Geometry(detailX, detailY);
  29712. _truncatedCone.call(
  29713. cylinderGeom,
  29714. radius,
  29715. radius,
  29716. height,
  29717. detailX,
  29718. detailY,
  29719. true,true);
  29720. cylinderGeom.computeNormals();
  29721. this._renderer.createBuffers(gId, cylinderGeom);
  29722. }
  29723. this._renderer.drawBuffers(gId);
  29724. return this;
  29725. };
  29726. /**
  29727. * Draw a cone with given radius and height
  29728. * @method cone
  29729. * @param {Number} radius radius of the bottom surface
  29730. * @param {Number} height height of the cone
  29731. * @param {Number} [detailX] optional: number of segments,
  29732. * the more segments the smoother geometry
  29733. * default is 24
  29734. * @param {Number} [detailY] optional: number of segments,
  29735. * the more segments the smoother geometry
  29736. * default is 16
  29737. * @return {p5} the p5 object
  29738. * @example
  29739. * <div>
  29740. * <code>
  29741. * //draw a spinning cone with radius 200 and height 200
  29742. * function setup(){
  29743. * createCanvas(100, 100, WEBGL);
  29744. * }
  29745. *
  29746. * function draw(){
  29747. * background(200);
  29748. * rotateX(frameCount * 0.01);
  29749. * rotateZ(frameCount * 0.01);
  29750. * cone(200, 200);
  29751. * }
  29752. * </code>
  29753. * </div>
  29754. */
  29755. p5.prototype.cone = function(){
  29756. var args = new Array(arguments.length);
  29757. for (var i = 0; i < args.length; ++i) {
  29758. args[i] = arguments[i];
  29759. }
  29760. var baseRadius = args[0] || 50;
  29761. var height = args[1] || baseRadius;
  29762. var detailX = typeof args[2] === 'number' ? args[2] : 24;
  29763. var detailY = typeof args[3] === 'number' ? args[3] : 16;
  29764. var gId = 'cone|'+baseRadius+'|'+height+'|'+detailX+'|'+detailY;
  29765. if(!this._renderer.geometryInHash(gId)){
  29766. var coneGeom = new p5.Geometry(detailX, detailY);
  29767. _truncatedCone.call(coneGeom,
  29768. baseRadius,
  29769. 0,//top radius 0
  29770. height,
  29771. detailX,
  29772. detailY,
  29773. true,
  29774. true);
  29775. //for cones we need to average Normals
  29776. coneGeom
  29777. .computeNormals();
  29778. this._renderer.createBuffers(gId, coneGeom);
  29779. }
  29780. this._renderer.drawBuffers(gId);
  29781. return this;
  29782. };
  29783. /**
  29784. * Draw an ellipsoid with given radius
  29785. * @method ellipsoid
  29786. * @param {Number} radiusx xradius of circle
  29787. * @param {Number} radiusy yradius of circle
  29788. * @param {Number} radiusz zradius of circle
  29789. * @param {Number} [detailX] optional: number of segments,
  29790. * the more segments the smoother geometry
  29791. * default is 24. Avoid detail number above
  29792. * 150, it may crash the browser.
  29793. * @param {Number} [detailY] optional: number of segments,
  29794. * the more segments the smoother geometry
  29795. * default is 16. Avoid detail number above
  29796. * 150, it may crash the browser.
  29797. * @return {p5} the p5 object
  29798. * @example
  29799. * <div>
  29800. * <code>
  29801. * // draw an ellipsoid with radius 20, 30 and 40.
  29802. * function setup(){
  29803. * createCanvas(100, 100, WEBGL);
  29804. * }
  29805. *
  29806. * function draw(){
  29807. * background(200);
  29808. * ellipsoid(20, 30, 40);
  29809. * }
  29810. * </code>
  29811. * </div>
  29812. */
  29813. p5.prototype.ellipsoid = function(){
  29814. var args = new Array(arguments.length);
  29815. for (var i = 0; i < args.length; ++i) {
  29816. args[i] = arguments[i];
  29817. }
  29818. var detailX = typeof args[3] === 'number' ? args[3] : 24;
  29819. var detailY = typeof args[4] === 'number' ? args[4] : 24;
  29820. var radiusX = args[0] || 50;
  29821. var radiusY = args[1] || radiusX;
  29822. var radiusZ = args[2] || radiusX;
  29823. var gId = 'ellipsoid|'+radiusX+'|'+radiusY+
  29824. '|'+radiusZ+'|'+detailX+'|'+detailY;
  29825. if(!this._renderer.geometryInHash(gId)){
  29826. var _ellipsoid = function(){
  29827. var u,v,p;
  29828. for (var i = 0; i <= this.detailY; i++){
  29829. v = i / this.detailY;
  29830. for (var j = 0; j <= this.detailX; j++){
  29831. u = j / this.detailX;
  29832. var theta = 2 * Math.PI * u;
  29833. var phi = Math.PI * v - Math.PI / 2;
  29834. p = new p5.Vector(radiusX * Math.cos(phi) * Math.sin(theta),
  29835. radiusY * Math.sin(phi),
  29836. radiusZ * Math.cos(phi) * Math.cos(theta));
  29837. this.vertices.push(p);
  29838. this.uvs.push([u,v]);
  29839. }
  29840. }
  29841. };
  29842. var ellipsoidGeom = new p5.Geometry(detailX, detailY,_ellipsoid);
  29843. ellipsoidGeom
  29844. .computeFaces()
  29845. .computeNormals();
  29846. this._renderer.createBuffers(gId, ellipsoidGeom);
  29847. }
  29848. this._renderer.drawBuffers(gId);
  29849. return this;
  29850. };
  29851. /**
  29852. * Draw a torus with given radius and tube radius
  29853. * @method torus
  29854. * @param {Number} radius radius of the whole ring
  29855. * @param {Number} tubeRadius radius of the tube
  29856. * @param {Number} [detailX] optional: number of segments in x-dimension,
  29857. * the more segments the smoother geometry
  29858. * default is 24
  29859. * @param {Number} [detailY] optional: number of segments in y-dimension,
  29860. * the more segments the smoother geometry
  29861. * default is 16
  29862. * @return {p5} the p5 object
  29863. * @example
  29864. * <div>
  29865. * <code>
  29866. * //draw a spinning torus with radius 200 and tube radius 60
  29867. * function setup(){
  29868. * createCanvas(100, 100, WEBGL);
  29869. * }
  29870. *
  29871. * function draw(){
  29872. * background(200);
  29873. * rotateX(frameCount * 0.01);
  29874. * rotateY(frameCount * 0.01);
  29875. * torus(200, 60);
  29876. * }
  29877. * </code>
  29878. * </div>
  29879. */
  29880. p5.prototype.torus = function(){
  29881. var args = new Array(arguments.length);
  29882. for (var i = 0; i < args.length; ++i) {
  29883. args[i] = arguments[i];
  29884. }
  29885. var detailX = typeof args[2] === 'number' ? args[2] : 24;
  29886. var detailY = typeof args[3] === 'number' ? args[3] : 16;
  29887. var radius = args[0] || 50;
  29888. var tubeRadius = args[1] || 10;
  29889. var gId = 'torus|'+radius+'|'+tubeRadius+'|'+detailX+'|'+detailY;
  29890. if(!this._renderer.geometryInHash(gId)){
  29891. var _torus = function(){
  29892. var u,v,p;
  29893. for (var i = 0; i <= this.detailY; i++){
  29894. v = i / this.detailY;
  29895. for (var j = 0; j <= this.detailX; j++){
  29896. u = j / this.detailX;
  29897. var theta = 2 * Math.PI * u;
  29898. var phi = 2 * Math.PI * v;
  29899. p = new p5.Vector(
  29900. (radius + tubeRadius * Math.cos(phi)) * Math.cos(theta),
  29901. (radius + tubeRadius * Math.cos(phi)) * Math.sin(theta),
  29902. tubeRadius * Math.sin(phi));
  29903. this.vertices.push(p);
  29904. this.uvs.push([u,v]);
  29905. }
  29906. }
  29907. };
  29908. var torusGeom = new p5.Geometry(detailX, detailY, _torus);
  29909. torusGeom
  29910. .computeFaces()
  29911. .computeNormals()
  29912. .averageNormals();
  29913. this._renderer.createBuffers(gId, torusGeom);
  29914. }
  29915. this._renderer.drawBuffers(gId);
  29916. return this;
  29917. };
  29918. ///////////////////////
  29919. /// 2D primitives
  29920. /////////////////////////
  29921. //@TODO
  29922. p5.RendererGL.prototype.point = function(x, y, z){
  29923. console.log('point not yet implemented in webgl');
  29924. return this;
  29925. };
  29926. p5.RendererGL.prototype.triangle = function
  29927. (args){
  29928. var x1=args[0], y1=args[1];
  29929. var x2=args[2], y2=args[3];
  29930. var x3=args[4], y3=args[5];
  29931. var gId = 'tri|'+x1+'|'+y1+'|'+
  29932. x2+'|'+y2+'|'+
  29933. x3+'|'+y3;
  29934. if(!this.geometryInHash(gId)){
  29935. var _triangle = function(){
  29936. var vertices = [];
  29937. vertices.push(new p5.Vector(x1,y1,0));
  29938. vertices.push(new p5.Vector(x2,y2,0));
  29939. vertices.push(new p5.Vector(x3,y3,0));
  29940. this.vertices = vertices;
  29941. this.faces = [[0,1,2]];
  29942. this.uvs = [[0,0],[0,1],[1,1]];
  29943. };
  29944. var triGeom = new p5.Geometry(1,1,_triangle);
  29945. triGeom.computeNormals();
  29946. this.createBuffers(gId, triGeom);
  29947. }
  29948. this.drawBuffers(gId);
  29949. return this;
  29950. };
  29951. p5.RendererGL.prototype.ellipse = function
  29952. (args){
  29953. var x = args[0];
  29954. var y = args[1];
  29955. var width = args[2];
  29956. var height = args[3];
  29957. //detailX and Y are optional 6th & 7th
  29958. //arguments
  29959. var detailX = args[4] || 24;
  29960. var detailY = args[5] || 16;
  29961. var gId = 'ellipse|'+args[0]+'|'+args[1]+'|'+args[2]+'|'+
  29962. args[3];
  29963. if(!this.geometryInHash(gId)){
  29964. var _ellipse = function(){
  29965. var u,v,p;
  29966. var centerX = x+width*0.5;
  29967. var centerY = y+height*0.5;
  29968. for (var i = 0; i <= this.detailY; i++){
  29969. v = i / this.detailY;
  29970. for (var j = 0; j <= this.detailX; j++){
  29971. u = j / this.detailX;
  29972. var theta = 2 * Math.PI * u;
  29973. if(v === 0){
  29974. p = new p5.Vector(centerX, centerY, 0);
  29975. }
  29976. else{
  29977. var _x = centerX + width*0.5 * Math.cos(theta);
  29978. var _y = centerY + height*0.5 * Math.sin(theta);
  29979. p = new p5.Vector(_x, _y, 0);
  29980. }
  29981. this.vertices.push(p);
  29982. this.uvs.push([u,v]);
  29983. }
  29984. }
  29985. };
  29986. var ellipseGeom = new p5.Geometry(detailX,detailY,_ellipse);
  29987. ellipseGeom
  29988. .computeFaces()
  29989. .computeNormals();
  29990. this.createBuffers(gId, ellipseGeom);
  29991. }
  29992. this.drawBuffers(gId);
  29993. return this;
  29994. };
  29995. p5.RendererGL.prototype.rect = function
  29996. (args){
  29997. var gId = 'rect|'+args[0]+'|'+args[1]+'|'+args[2]+'|'+
  29998. args[3];
  29999. var x = args[0];
  30000. var y = args[1];
  30001. var width = args[2];
  30002. var height = args[3];
  30003. var detailX = args[4] || 24;
  30004. var detailY = args[5] || 16;
  30005. if(!this.geometryInHash(gId)){
  30006. var _rect = function(){
  30007. var u,v,p;
  30008. for (var i = 0; i <= this.detailY; i++){
  30009. v = i / this.detailY;
  30010. for (var j = 0; j <= this.detailX; j++){
  30011. u = j / this.detailX;
  30012. // var _x = x-width/2;
  30013. // var _y = y-height/2;
  30014. p = new p5.Vector(
  30015. x + (width*u),
  30016. y + (height*v),
  30017. 0
  30018. );
  30019. this.vertices.push(p);
  30020. this.uvs.push([u,v]);
  30021. }
  30022. }
  30023. };
  30024. var rectGeom = new p5.Geometry(detailX,detailY,_rect);
  30025. rectGeom
  30026. .computeFaces()
  30027. .computeNormals();
  30028. this.createBuffers(gId, rectGeom);
  30029. }
  30030. this.drawBuffers(gId);
  30031. return this;
  30032. };
  30033. p5.RendererGL.prototype.quad = function(){
  30034. var args = new Array(arguments.length);
  30035. for (var i = 0; i < args.length; ++i) {
  30036. args[i] = arguments[i];
  30037. }
  30038. var x1 = args[0],
  30039. y1 = args[1],
  30040. x2 = args[2],
  30041. y2 = args[3],
  30042. x3 = args[4],
  30043. y3 = args[5],
  30044. x4 = args[6],
  30045. y4 = args[7];
  30046. var gId = 'quad|'+x1+'|'+y1+'|'+
  30047. x2+'|'+y2+'|'+
  30048. x3+'|'+y3+'|'+
  30049. x4+'|'+y4;
  30050. if(!this.geometryInHash(gId)){
  30051. var _quad = function(){
  30052. this.vertices.push(new p5.Vector(x1,y1,0));
  30053. this.vertices.push(new p5.Vector(x2,y2,0));
  30054. this.vertices.push(new p5.Vector(x3,y3,0));
  30055. this.vertices.push(new p5.Vector(x4,y4,0));
  30056. this.uvs.push([0, 0], [1, 0], [1, 1], [0, 1]);
  30057. };
  30058. var quadGeom = new p5.Geometry(2,2,_quad);
  30059. quadGeom.computeNormals();
  30060. quadGeom.faces = [[0,1,2],[2,3,0]];
  30061. this.createBuffers(gId, quadGeom);
  30062. }
  30063. this.drawBuffers(gId);
  30064. return this;
  30065. };
  30066. //this implementation of bezier curve
  30067. //is based on Bernstein polynomial
  30068. p5.RendererGL.prototype.bezier = function
  30069. (args){
  30070. var bezierDetail=args[12] || 20;//value of Bezier detail
  30071. this.beginShape();
  30072. var coeff=[0,0,0,0];// Bernstein polynomial coeffecients
  30073. var vertex=[0,0,0]; //(x,y,z) coordinates of points in bezier curve
  30074. for(var i=0; i<=bezierDetail; i++){
  30075. coeff[0]=Math.pow(1-(i/bezierDetail),3);
  30076. coeff[1]=(3*(i/bezierDetail)) * (Math.pow(1-(i/bezierDetail),2));
  30077. coeff[2]=(3*Math.pow(i/bezierDetail,2)) * (1-(i/bezierDetail));
  30078. coeff[3]=Math.pow(i/bezierDetail,3);
  30079. vertex[0]=args[0]*coeff[0] + args[3]*coeff[1] +
  30080. args[6]*coeff[2] + args[9]*coeff[3];
  30081. vertex[1]=args[1]*coeff[0] + args[4]*coeff[1] +
  30082. args[7]*coeff[2] + args[10]*coeff[3];
  30083. vertex[2]=args[2]*coeff[0] + args[5]*coeff[1] +
  30084. args[8]*coeff[2] + args[11]*coeff[3];
  30085. this.vertex(vertex[0],vertex[1],vertex[2]);
  30086. }
  30087. this.endShape();
  30088. return this;
  30089. };
  30090. p5.RendererGL.prototype.curve=function
  30091. (args){
  30092. var curveDetail=args[12];
  30093. this.beginShape();
  30094. var coeff=[0,0,0,0];//coeffecients of the equation
  30095. var vertex=[0,0,0]; //(x,y,z) coordinates of points in bezier curve
  30096. for(var i=0; i<=curveDetail; i++){
  30097. coeff[0]=Math.pow((i/curveDetail),3) * 0.5;
  30098. coeff[1]=Math.pow((i/curveDetail),2) * 0.5;
  30099. coeff[2]=(i/curveDetail) * 0.5;
  30100. coeff[3]=0.5;
  30101. vertex[0]=coeff[0]*(-args[0] + (3*args[3]) - (3*args[6]) +args[9]) +
  30102. coeff[1]*((2*args[0]) - (5*args[3]) + (4*args[6]) - args[9]) +
  30103. coeff[2]*(-args[0] + args[6]) +
  30104. coeff[3]*(2*args[3]);
  30105. vertex[1]=coeff[0]*(-args[1] + (3*args[4]) - (3*args[7]) +args[10]) +
  30106. coeff[1]*((2*args[1]) - (5*args[4]) + (4*args[7]) - args[10]) +
  30107. coeff[2]*(-args[1] + args[7]) +
  30108. coeff[3]*(2*args[4]);
  30109. vertex[2]=coeff[0]*(-args[2] + (3*args[5]) - (3*args[8]) +args[11]) +
  30110. coeff[1]*((2*args[2]) - (5*args[5]) + (4*args[8]) - args[11]) +
  30111. coeff[2]*(-args[2] + args[8]) +
  30112. coeff[3]*(2*args[5]);
  30113. this.vertex(vertex[0],vertex[1],vertex[2]);
  30114. }
  30115. this.endShape();
  30116. return this;
  30117. };
  30118. module.exports = p5;
  30119. },{"../core/core":37,"./p5.Geometry":82}],88:[function(_dereq_,module,exports){
  30120. module.exports = {
  30121. immediateVert:
  30122. "attribute vec3 aPosition;\nattribute vec4 aVertexColor;\n\nuniform mat4 uModelViewMatrix;\nuniform mat4 uProjectionMatrix;\nuniform float uResolution;\nuniform float uPointSize;\n\nvarying vec4 vColor;\nvoid main(void) {\n vec4 positionVec4 = vec4(aPosition * vec3(1.0, -1.0, 1.0), 1.0);\n gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;\n vColor = aVertexColor;\n gl_PointSize = uPointSize;\n}\n",
  30123. vertexColorVert:
  30124. "attribute vec3 aPosition;\nattribute vec4 aVertexColor;\n\nuniform mat4 uModelViewMatrix;\nuniform mat4 uProjectionMatrix;\n\nvarying vec4 vColor;\n\nvoid main(void) {\n vec4 positionVec4 = vec4(aPosition * vec3(1.0, -1.0, 1.0), 1.0);\n gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;\n vColor = aVertexColor;\n}\n",
  30125. vertexColorFrag:
  30126. "precision mediump float;\nvarying vec4 vColor;\nvoid main(void) {\n gl_FragColor = vColor;\n}",
  30127. normalVert:
  30128. "attribute vec3 aPosition;\nattribute vec3 aNormal;\nattribute vec2 aTexCoord;\n\nuniform mat4 uModelViewMatrix;\nuniform mat4 uProjectionMatrix;\nuniform mat3 uNormalMatrix;\n\nvarying vec3 vVertexNormal;\nvarying highp vec2 vVertTexCoord;\n\nvoid main(void) {\n vec4 positionVec4 = vec4(aPosition * vec3(1.0, -1.0, 1.0), 1.0);\n gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;\n vVertexNormal = vec3( uNormalMatrix * aNormal );\n vVertTexCoord = aTexCoord;\n}\n",
  30129. normalFrag:
  30130. "precision mediump float;\nvarying vec3 vVertexNormal;\nvoid main(void) {\n gl_FragColor = vec4(vVertexNormal, 1.0);\n}",
  30131. basicFrag:
  30132. "precision mediump float;\nvarying vec3 vVertexNormal;\nuniform vec4 uMaterialColor;\nvoid main(void) {\n gl_FragColor = uMaterialColor;\n}",
  30133. lightVert:
  30134. "attribute vec3 aPosition;\nattribute vec3 aNormal;\nattribute vec2 aTexCoord;\n\nuniform mat4 uModelViewMatrix;\nuniform mat4 uProjectionMatrix;\nuniform mat3 uNormalMatrix;\nuniform int uAmbientLightCount;\nuniform int uDirectionalLightCount;\nuniform int uPointLightCount;\n\nuniform vec3 uAmbientColor[8];\nuniform vec3 uLightingDirection[8];\nuniform vec3 uDirectionalColor[8];\nuniform vec3 uPointLightLocation[8];\nuniform vec3 uPointLightColor[8];\nuniform bool uSpecular;\n\nvarying vec3 vVertexNormal;\nvarying vec2 vVertTexCoord;\nvarying vec3 vLightWeighting;\n\nvec3 ambientLightFactor = vec3(0.0, 0.0, 0.0);\nvec3 directionalLightFactor = vec3(0.0, 0.0, 0.0);\nvec3 pointLightFactor = vec3(0.0, 0.0, 0.0);\nvec3 pointLightFactor2 = vec3(0.0, 0.0, 0.0);\n\nvoid main(void){\n\n vec4 positionVec4 = vec4(aPosition, 1.0);\n gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;\n\n vec3 vertexNormal = vec3( uNormalMatrix * aNormal );\n vVertexNormal = vertexNormal;\n vVertTexCoord = aTexCoord;\n\n vec4 mvPosition = uModelViewMatrix * vec4(aPosition, 1.0);\n vec3 eyeDirection = normalize(-mvPosition.xyz);\n\n float shininess = 32.0;\n float specularFactor = 2.0;\n float diffuseFactor = 0.3;\n\n for(int i = 0; i < 8; i++){\n if(uAmbientLightCount == i) break;\n ambientLightFactor += uAmbientColor[i];\n }\n\n for(int j = 0; j < 8; j++){\n if(uDirectionalLightCount == j) break;\n vec3 dir = uLightingDirection[j];\n float directionalLightWeighting = max(dot(vertexNormal, dir), 0.0);\n directionalLightFactor += uDirectionalColor[j] * directionalLightWeighting;\n }\n\n for(int k = 0; k < 8; k++){\n if(uPointLightCount == k) break;\n vec3 loc = uPointLightLocation[k];\n vec3 lightDirection = normalize(loc - mvPosition.xyz);\n\n float directionalLightWeighting = max(dot(vertexNormal, lightDirection), 0.0);\n pointLightFactor += uPointLightColor[k] * directionalLightWeighting;\n\n //factor2 for specular\n vec3 reflectionDirection = reflect(-lightDirection, vertexNormal);\n float specularLightWeighting = pow(max(dot(reflectionDirection, eyeDirection), 0.0), shininess);\n\n pointLightFactor2 += uPointLightColor[k] * (specularFactor * specularLightWeighting\n + directionalLightWeighting * diffuseFactor);\n }\n\n if(!uSpecular){\n vLightWeighting = ambientLightFactor + directionalLightFactor + pointLightFactor;\n }else{\n vLightWeighting = ambientLightFactor + directionalLightFactor + pointLightFactor2;\n }\n\n}\n",
  30135. lightTextureFrag:
  30136. "precision mediump float;\n\nuniform vec4 uMaterialColor;\nuniform sampler2D uSampler;\nuniform bool isTexture;\n\nvarying vec3 vLightWeighting;\nvarying highp vec2 vVertTexCoord;\n\nvoid main(void) {\n if(!isTexture){\n gl_FragColor = vec4(vec3(uMaterialColor.rgb * vLightWeighting), uMaterialColor.a);\n }else{\n vec4 textureColor = texture2D(uSampler, vVertTexCoord);\n if(vLightWeighting == vec3(0., 0., 0.)){\n gl_FragColor = textureColor;\n }else{\n gl_FragColor = vec4(vec3(textureColor.rgb * vLightWeighting), textureColor.a);\n }\n }\n}"
  30137. };
  30138. },{}]},{},[28])(28)
  30139. });