123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757 |
- /*!
- * ====================================================
- * Kity Formula Render - v1.0.0 - 2014-07-30
- * https://github.com/kitygraph/formula
- * GitHub: https://github.com/kitygraph/formula.git
- * Copyright (c) 2014 Baidu Kity Group; Licensed MIT
- * ====================================================
- */
- (function () {
- var _p = {
- r: function(index) {
- if (_p[index].inited) {
- return _p[index].value;
- }
- if (typeof _p[index].value === "function") {
- var module = {
- exports: {}
- }, returnValue = _p[index].value(null, module.exports, module);
- _p[index].inited = true;
- _p[index].value = returnValue;
- if (returnValue !== undefined) {
- return returnValue;
- } else {
- for (var key in module.exports) {
- if (module.exports.hasOwnProperty(key)) {
- _p[index].inited = true;
- _p[index].value = module.exports;
- return module.exports;
- }
- }
- }
- } else {
- _p[index].inited = true;
- return _p[index].value;
- }
- }
- };
- /*!
- * canvg库封装
- * canvg官网: https://code.google.com/p/canvg/
- */
- _p[0] = {
- value: function(require) {
- /**
- * A class to parse color values
- * @author Stoyan Stefanov <sstoo@gmail.com>
- * @link http://www.phpied.com/rgb-color-parser-in-javascript/
- * @license Use it if you like it
- */
- function RGBColor(color_string) {
- this.ok = false;
- // strip any leading #
- if (color_string.charAt(0) == "#") {
- // remove # if any
- color_string = color_string.substr(1, 6);
- }
- color_string = color_string.replace(/ /g, "");
- color_string = color_string.toLowerCase();
- // before getting into regexps, try simple matches
- // and overwrite the input
- var simple_colors = {
- aliceblue: "f0f8ff",
- antiquewhite: "faebd7",
- aqua: "00ffff",
- aquamarine: "7fffd4",
- azure: "f0ffff",
- beige: "f5f5dc",
- bisque: "ffe4c4",
- black: "000000",
- blanchedalmond: "ffebcd",
- blue: "0000ff",
- blueviolet: "8a2be2",
- brown: "a52a2a",
- burlywood: "deb887",
- cadetblue: "5f9ea0",
- chartreuse: "7fff00",
- chocolate: "d2691e",
- coral: "ff7f50",
- cornflowerblue: "6495ed",
- cornsilk: "fff8dc",
- crimson: "dc143c",
- cyan: "00ffff",
- darkblue: "00008b",
- darkcyan: "008b8b",
- darkgoldenrod: "b8860b",
- darkgray: "a9a9a9",
- darkgreen: "006400",
- darkkhaki: "bdb76b",
- darkmagenta: "8b008b",
- darkolivegreen: "556b2f",
- darkorange: "ff8c00",
- darkorchid: "9932cc",
- darkred: "8b0000",
- darksalmon: "e9967a",
- darkseagreen: "8fbc8f",
- darkslateblue: "483d8b",
- darkslategray: "2f4f4f",
- darkturquoise: "00ced1",
- darkviolet: "9400d3",
- deeppink: "ff1493",
- deepskyblue: "00bfff",
- dimgray: "696969",
- dodgerblue: "1e90ff",
- feldspar: "d19275",
- firebrick: "b22222",
- floralwhite: "fffaf0",
- forestgreen: "228b22",
- fuchsia: "ff00ff",
- gainsboro: "dcdcdc",
- ghostwhite: "f8f8ff",
- gold: "ffd700",
- goldenrod: "daa520",
- gray: "808080",
- green: "008000",
- greenyellow: "adff2f",
- honeydew: "f0fff0",
- hotpink: "ff69b4",
- indianred: "cd5c5c",
- indigo: "4b0082",
- ivory: "fffff0",
- khaki: "f0e68c",
- lavender: "e6e6fa",
- lavenderblush: "fff0f5",
- lawngreen: "7cfc00",
- lemonchiffon: "fffacd",
- lightblue: "add8e6",
- lightcoral: "f08080",
- lightcyan: "e0ffff",
- lightgoldenrodyellow: "fafad2",
- lightgrey: "d3d3d3",
- lightgreen: "90ee90",
- lightpink: "ffb6c1",
- lightsalmon: "ffa07a",
- lightseagreen: "20b2aa",
- lightskyblue: "87cefa",
- lightslateblue: "8470ff",
- lightslategray: "778899",
- lightsteelblue: "b0c4de",
- lightyellow: "ffffe0",
- lime: "00ff00",
- limegreen: "32cd32",
- linen: "faf0e6",
- magenta: "ff00ff",
- maroon: "800000",
- mediumaquamarine: "66cdaa",
- mediumblue: "0000cd",
- mediumorchid: "ba55d3",
- mediumpurple: "9370d8",
- mediumseagreen: "3cb371",
- mediumslateblue: "7b68ee",
- mediumspringgreen: "00fa9a",
- mediumturquoise: "48d1cc",
- mediumvioletred: "c71585",
- midnightblue: "191970",
- mintcream: "f5fffa",
- mistyrose: "ffe4e1",
- moccasin: "ffe4b5",
- navajowhite: "ffdead",
- navy: "000080",
- oldlace: "fdf5e6",
- olive: "808000",
- olivedrab: "6b8e23",
- orange: "ffa500",
- orangered: "ff4500",
- orchid: "da70d6",
- palegoldenrod: "eee8aa",
- palegreen: "98fb98",
- paleturquoise: "afeeee",
- palevioletred: "d87093",
- papayawhip: "ffefd5",
- peachpuff: "ffdab9",
- peru: "cd853f",
- pink: "ffc0cb",
- plum: "dda0dd",
- powderblue: "b0e0e6",
- purple: "800080",
- red: "ff0000",
- rosybrown: "bc8f8f",
- royalblue: "4169e1",
- saddlebrown: "8b4513",
- salmon: "fa8072",
- sandybrown: "f4a460",
- seagreen: "2e8b57",
- seashell: "fff5ee",
- sienna: "a0522d",
- silver: "c0c0c0",
- skyblue: "87ceeb",
- slateblue: "6a5acd",
- slategray: "708090",
- snow: "fffafa",
- springgreen: "00ff7f",
- steelblue: "4682b4",
- tan: "d2b48c",
- teal: "008080",
- thistle: "d8bfd8",
- tomato: "ff6347",
- turquoise: "40e0d0",
- violet: "ee82ee",
- violetred: "d02090",
- wheat: "f5deb3",
- white: "ffffff",
- whitesmoke: "f5f5f5",
- yellow: "ffff00",
- yellowgreen: "9acd32"
- };
- for (var key in simple_colors) {
- if (color_string == key) {
- color_string = simple_colors[key];
- }
- }
- // emd of simple type-in colors
- // array of color definition objects
- var color_defs = [ {
- re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,
- example: [ "rgb(123, 234, 45)", "rgb(255,234,245)" ],
- process: function(bits) {
- return [ parseInt(bits[1]), parseInt(bits[2]), parseInt(bits[3]) ];
- }
- }, {
- re: /^(\w{2})(\w{2})(\w{2})$/,
- example: [ "#00ff00", "336699" ],
- process: function(bits) {
- return [ parseInt(bits[1], 16), parseInt(bits[2], 16), parseInt(bits[3], 16) ];
- }
- }, {
- re: /^(\w{1})(\w{1})(\w{1})$/,
- example: [ "#fb0", "f0f" ],
- process: function(bits) {
- return [ parseInt(bits[1] + bits[1], 16), parseInt(bits[2] + bits[2], 16), parseInt(bits[3] + bits[3], 16) ];
- }
- } ];
- // search through the definitions to find a match
- for (var i = 0; i < color_defs.length; i++) {
- var re = color_defs[i].re;
- var processor = color_defs[i].process;
- var bits = re.exec(color_string);
- if (bits) {
- channels = processor(bits);
- this.r = channels[0];
- this.g = channels[1];
- this.b = channels[2];
- this.ok = true;
- }
- }
- // validate/cleanup values
- this.r = this.r < 0 || isNaN(this.r) ? 0 : this.r > 255 ? 255 : this.r;
- this.g = this.g < 0 || isNaN(this.g) ? 0 : this.g > 255 ? 255 : this.g;
- this.b = this.b < 0 || isNaN(this.b) ? 0 : this.b > 255 ? 255 : this.b;
- // some getters
- this.toRGB = function() {
- return "rgb(" + this.r + ", " + this.g + ", " + this.b + ")";
- };
- this.toHex = function() {
- var r = this.r.toString(16);
- var g = this.g.toString(16);
- var b = this.b.toString(16);
- if (r.length == 1) r = "0" + r;
- if (g.length == 1) g = "0" + g;
- if (b.length == 1) b = "0" + b;
- return "#" + r + g + b;
- };
- // help
- this.getHelpXML = function() {
- var examples = new Array();
- // add regexps
- for (var i = 0; i < color_defs.length; i++) {
- var example = color_defs[i].example;
- for (var j = 0; j < example.length; j++) {
- examples[examples.length] = example[j];
- }
- }
- // add type-in colors
- for (var sc in simple_colors) {
- examples[examples.length] = sc;
- }
- var xml = document.createElement("ul");
- xml.setAttribute("id", "rgbcolor-examples");
- for (var i = 0; i < examples.length; i++) {
- try {
- var list_item = document.createElement("li");
- var list_color = new RGBColor(examples[i]);
- var example_div = document.createElement("div");
- example_div.style.cssText = "margin: 3px; " + "border: 1px solid black; " + "background:" + list_color.toHex() + "; " + "color:" + list_color.toHex();
- example_div.appendChild(document.createTextNode("test"));
- var list_item_value = document.createTextNode(" " + examples[i] + " -> " + list_color.toRGB() + " -> " + list_color.toHex());
- list_item.appendChild(example_div);
- list_item.appendChild(list_item_value);
- xml.appendChild(list_item);
- } catch (e) {}
- }
- return xml;
- };
- }
- /*
- StackBlur - a fast almost Gaussian Blur For Canvas
- Version: 0.5
- Author: Mario Klingemann
- Contact: mario@quasimondo.com
- Website: http://www.quasimondo.com/StackBlurForCanvas
- Twitter: @quasimondo
- In case you find this class useful - especially in commercial projects -
- I am not totally unhappy for a small donation to my PayPal account
- mario@quasimondo.de
- Or support me on flattr:
- https://flattr.com/thing/72791/StackBlur-a-fast-almost-Gaussian-Blur-Effect-for-CanvasJavascript
- Copyright (c) 2010 Mario Klingemann
- Permission is hereby granted, free of charge, to any person
- obtaining a copy of this software and associated documentation
- files (the "Software"), to deal in the Software without
- restriction, including without limitation the rights to use,
- copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the
- Software is furnished to do so, subject to the following
- conditions:
- The above copyright notice and this permission notice shall be
- included in all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- OTHER DEALINGS IN THE SOFTWARE.
- */
- var mul_table = [ 512, 512, 456, 512, 328, 456, 335, 512, 405, 328, 271, 456, 388, 335, 292, 512, 454, 405, 364, 328, 298, 271, 496, 456, 420, 388, 360, 335, 312, 292, 273, 512, 482, 454, 428, 405, 383, 364, 345, 328, 312, 298, 284, 271, 259, 496, 475, 456, 437, 420, 404, 388, 374, 360, 347, 335, 323, 312, 302, 292, 282, 273, 265, 512, 497, 482, 468, 454, 441, 428, 417, 405, 394, 383, 373, 364, 354, 345, 337, 328, 320, 312, 305, 298, 291, 284, 278, 271, 265, 259, 507, 496, 485, 475, 465, 456, 446, 437, 428, 420, 412, 404, 396, 388, 381, 374, 367, 360, 354, 347, 341, 335, 329, 323, 318, 312, 307, 302, 297, 292, 287, 282, 278, 273, 269, 265, 261, 512, 505, 497, 489, 482, 475, 468, 461, 454, 447, 441, 435, 428, 422, 417, 411, 405, 399, 394, 389, 383, 378, 373, 368, 364, 359, 354, 350, 345, 341, 337, 332, 328, 324, 320, 316, 312, 309, 305, 301, 298, 294, 291, 287, 284, 281, 278, 274, 271, 268, 265, 262, 259, 257, 507, 501, 496, 491, 485, 480, 475, 470, 465, 460, 456, 451, 446, 442, 437, 433, 428, 424, 420, 416, 412, 408, 404, 400, 396, 392, 388, 385, 381, 377, 374, 370, 367, 363, 360, 357, 354, 350, 347, 344, 341, 338, 335, 332, 329, 326, 323, 320, 318, 315, 312, 310, 307, 304, 302, 299, 297, 294, 292, 289, 287, 285, 282, 280, 278, 275, 273, 271, 269, 267, 265, 263, 261, 259 ];
- var shg_table = [ 9, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24 ];
- function stackBlurImage(imageID, canvasID, radius, blurAlphaChannel) {
- var img = document.getElementById(imageID);
- var w = img.naturalWidth;
- var h = img.naturalHeight;
- var canvas = document.getElementById(canvasID);
- canvas.style.width = w + "px";
- canvas.style.height = h + "px";
- canvas.width = w;
- canvas.height = h;
- var context = canvas.getContext("2d");
- context.clearRect(0, 0, w, h);
- context.drawImage(img, 0, 0);
- if (isNaN(radius) || radius < 1) return;
- if (blurAlphaChannel) stackBlurCanvasRGBA(canvasID, 0, 0, w, h, radius); else stackBlurCanvasRGB(canvasID, 0, 0, w, h, radius);
- }
- function stackBlurCanvasRGBA(id, top_x, top_y, width, height, radius) {
- if (isNaN(radius) || radius < 1) return;
- radius |= 0;
- var canvas = document.getElementById(id);
- var context = canvas.getContext("2d");
- var imageData;
- try {
- try {
- imageData = context.getImageData(top_x, top_y, width, height);
- } catch (e) {
- // NOTE: this part is supposedly only needed if you want to work with local files
- // so it might be okay to remove the whole try/catch block and just use
- // imageData = context.getImageData( top_x, top_y, width, height );
- try {
- netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
- imageData = context.getImageData(top_x, top_y, width, height);
- } catch (e) {
- alert("Cannot access local image");
- throw new Error("unable to access local image data: " + e);
- return;
- }
- }
- } catch (e) {
- alert("Cannot access image");
- throw new Error("unable to access image data: " + e);
- }
- var pixels = imageData.data;
- var x, y, i, p, yp, yi, yw, r_sum, g_sum, b_sum, a_sum, r_out_sum, g_out_sum, b_out_sum, a_out_sum, r_in_sum, g_in_sum, b_in_sum, a_in_sum, pr, pg, pb, pa, rbs;
- var div = radius + radius + 1;
- var w4 = width << 2;
- var widthMinus1 = width - 1;
- var heightMinus1 = height - 1;
- var radiusPlus1 = radius + 1;
- var sumFactor = radiusPlus1 * (radiusPlus1 + 1) / 2;
- var stackStart = new BlurStack();
- var stack = stackStart;
- for (i = 1; i < div; i++) {
- stack = stack.next = new BlurStack();
- if (i == radiusPlus1) var stackEnd = stack;
- }
- stack.next = stackStart;
- var stackIn = null;
- var stackOut = null;
- yw = yi = 0;
- var mul_sum = mul_table[radius];
- var shg_sum = shg_table[radius];
- for (y = 0; y < height; y++) {
- r_in_sum = g_in_sum = b_in_sum = a_in_sum = r_sum = g_sum = b_sum = a_sum = 0;
- r_out_sum = radiusPlus1 * (pr = pixels[yi]);
- g_out_sum = radiusPlus1 * (pg = pixels[yi + 1]);
- b_out_sum = radiusPlus1 * (pb = pixels[yi + 2]);
- a_out_sum = radiusPlus1 * (pa = pixels[yi + 3]);
- r_sum += sumFactor * pr;
- g_sum += sumFactor * pg;
- b_sum += sumFactor * pb;
- a_sum += sumFactor * pa;
- stack = stackStart;
- for (i = 0; i < radiusPlus1; i++) {
- stack.r = pr;
- stack.g = pg;
- stack.b = pb;
- stack.a = pa;
- stack = stack.next;
- }
- for (i = 1; i < radiusPlus1; i++) {
- p = yi + ((widthMinus1 < i ? widthMinus1 : i) << 2);
- r_sum += (stack.r = pr = pixels[p]) * (rbs = radiusPlus1 - i);
- g_sum += (stack.g = pg = pixels[p + 1]) * rbs;
- b_sum += (stack.b = pb = pixels[p + 2]) * rbs;
- a_sum += (stack.a = pa = pixels[p + 3]) * rbs;
- r_in_sum += pr;
- g_in_sum += pg;
- b_in_sum += pb;
- a_in_sum += pa;
- stack = stack.next;
- }
- stackIn = stackStart;
- stackOut = stackEnd;
- for (x = 0; x < width; x++) {
- pixels[yi + 3] = pa = a_sum * mul_sum >> shg_sum;
- if (pa != 0) {
- pa = 255 / pa;
- pixels[yi] = (r_sum * mul_sum >> shg_sum) * pa;
- pixels[yi + 1] = (g_sum * mul_sum >> shg_sum) * pa;
- pixels[yi + 2] = (b_sum * mul_sum >> shg_sum) * pa;
- } else {
- pixels[yi] = pixels[yi + 1] = pixels[yi + 2] = 0;
- }
- r_sum -= r_out_sum;
- g_sum -= g_out_sum;
- b_sum -= b_out_sum;
- a_sum -= a_out_sum;
- r_out_sum -= stackIn.r;
- g_out_sum -= stackIn.g;
- b_out_sum -= stackIn.b;
- a_out_sum -= stackIn.a;
- p = yw + ((p = x + radius + 1) < widthMinus1 ? p : widthMinus1) << 2;
- r_in_sum += stackIn.r = pixels[p];
- g_in_sum += stackIn.g = pixels[p + 1];
- b_in_sum += stackIn.b = pixels[p + 2];
- a_in_sum += stackIn.a = pixels[p + 3];
- r_sum += r_in_sum;
- g_sum += g_in_sum;
- b_sum += b_in_sum;
- a_sum += a_in_sum;
- stackIn = stackIn.next;
- r_out_sum += pr = stackOut.r;
- g_out_sum += pg = stackOut.g;
- b_out_sum += pb = stackOut.b;
- a_out_sum += pa = stackOut.a;
- r_in_sum -= pr;
- g_in_sum -= pg;
- b_in_sum -= pb;
- a_in_sum -= pa;
- stackOut = stackOut.next;
- yi += 4;
- }
- yw += width;
- }
- for (x = 0; x < width; x++) {
- g_in_sum = b_in_sum = a_in_sum = r_in_sum = g_sum = b_sum = a_sum = r_sum = 0;
- yi = x << 2;
- r_out_sum = radiusPlus1 * (pr = pixels[yi]);
- g_out_sum = radiusPlus1 * (pg = pixels[yi + 1]);
- b_out_sum = radiusPlus1 * (pb = pixels[yi + 2]);
- a_out_sum = radiusPlus1 * (pa = pixels[yi + 3]);
- r_sum += sumFactor * pr;
- g_sum += sumFactor * pg;
- b_sum += sumFactor * pb;
- a_sum += sumFactor * pa;
- stack = stackStart;
- for (i = 0; i < radiusPlus1; i++) {
- stack.r = pr;
- stack.g = pg;
- stack.b = pb;
- stack.a = pa;
- stack = stack.next;
- }
- yp = width;
- for (i = 1; i <= radius; i++) {
- yi = yp + x << 2;
- r_sum += (stack.r = pr = pixels[yi]) * (rbs = radiusPlus1 - i);
- g_sum += (stack.g = pg = pixels[yi + 1]) * rbs;
- b_sum += (stack.b = pb = pixels[yi + 2]) * rbs;
- a_sum += (stack.a = pa = pixels[yi + 3]) * rbs;
- r_in_sum += pr;
- g_in_sum += pg;
- b_in_sum += pb;
- a_in_sum += pa;
- stack = stack.next;
- if (i < heightMinus1) {
- yp += width;
- }
- }
- yi = x;
- stackIn = stackStart;
- stackOut = stackEnd;
- for (y = 0; y < height; y++) {
- p = yi << 2;
- pixels[p + 3] = pa = a_sum * mul_sum >> shg_sum;
- if (pa > 0) {
- pa = 255 / pa;
- pixels[p] = (r_sum * mul_sum >> shg_sum) * pa;
- pixels[p + 1] = (g_sum * mul_sum >> shg_sum) * pa;
- pixels[p + 2] = (b_sum * mul_sum >> shg_sum) * pa;
- } else {
- pixels[p] = pixels[p + 1] = pixels[p + 2] = 0;
- }
- r_sum -= r_out_sum;
- g_sum -= g_out_sum;
- b_sum -= b_out_sum;
- a_sum -= a_out_sum;
- r_out_sum -= stackIn.r;
- g_out_sum -= stackIn.g;
- b_out_sum -= stackIn.b;
- a_out_sum -= stackIn.a;
- p = x + ((p = y + radiusPlus1) < heightMinus1 ? p : heightMinus1) * width << 2;
- r_sum += r_in_sum += stackIn.r = pixels[p];
- g_sum += g_in_sum += stackIn.g = pixels[p + 1];
- b_sum += b_in_sum += stackIn.b = pixels[p + 2];
- a_sum += a_in_sum += stackIn.a = pixels[p + 3];
- stackIn = stackIn.next;
- r_out_sum += pr = stackOut.r;
- g_out_sum += pg = stackOut.g;
- b_out_sum += pb = stackOut.b;
- a_out_sum += pa = stackOut.a;
- r_in_sum -= pr;
- g_in_sum -= pg;
- b_in_sum -= pb;
- a_in_sum -= pa;
- stackOut = stackOut.next;
- yi += width;
- }
- }
- context.putImageData(imageData, top_x, top_y);
- }
- function stackBlurCanvasRGB(id, top_x, top_y, width, height, radius) {
- if (isNaN(radius) || radius < 1) return;
- radius |= 0;
- var canvas = document.getElementById(id);
- var context = canvas.getContext("2d");
- var imageData;
- try {
- try {
- imageData = context.getImageData(top_x, top_y, width, height);
- } catch (e) {
- // NOTE: this part is supposedly only needed if you want to work with local files
- // so it might be okay to remove the whole try/catch block and just use
- // imageData = context.getImageData( top_x, top_y, width, height );
- try {
- netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
- imageData = context.getImageData(top_x, top_y, width, height);
- } catch (e) {
- alert("Cannot access local image");
- throw new Error("unable to access local image data: " + e);
- return;
- }
- }
- } catch (e) {
- alert("Cannot access image");
- throw new Error("unable to access image data: " + e);
- }
- var pixels = imageData.data;
- var x, y, i, p, yp, yi, yw, r_sum, g_sum, b_sum, r_out_sum, g_out_sum, b_out_sum, r_in_sum, g_in_sum, b_in_sum, pr, pg, pb, rbs;
- var div = radius + radius + 1;
- var w4 = width << 2;
- var widthMinus1 = width - 1;
- var heightMinus1 = height - 1;
- var radiusPlus1 = radius + 1;
- var sumFactor = radiusPlus1 * (radiusPlus1 + 1) / 2;
- var stackStart = new BlurStack();
- var stack = stackStart;
- for (i = 1; i < div; i++) {
- stack = stack.next = new BlurStack();
- if (i == radiusPlus1) var stackEnd = stack;
- }
- stack.next = stackStart;
- var stackIn = null;
- var stackOut = null;
- yw = yi = 0;
- var mul_sum = mul_table[radius];
- var shg_sum = shg_table[radius];
- for (y = 0; y < height; y++) {
- r_in_sum = g_in_sum = b_in_sum = r_sum = g_sum = b_sum = 0;
- r_out_sum = radiusPlus1 * (pr = pixels[yi]);
- g_out_sum = radiusPlus1 * (pg = pixels[yi + 1]);
- b_out_sum = radiusPlus1 * (pb = pixels[yi + 2]);
- r_sum += sumFactor * pr;
- g_sum += sumFactor * pg;
- b_sum += sumFactor * pb;
- stack = stackStart;
- for (i = 0; i < radiusPlus1; i++) {
- stack.r = pr;
- stack.g = pg;
- stack.b = pb;
- stack = stack.next;
- }
- for (i = 1; i < radiusPlus1; i++) {
- p = yi + ((widthMinus1 < i ? widthMinus1 : i) << 2);
- r_sum += (stack.r = pr = pixels[p]) * (rbs = radiusPlus1 - i);
- g_sum += (stack.g = pg = pixels[p + 1]) * rbs;
- b_sum += (stack.b = pb = pixels[p + 2]) * rbs;
- r_in_sum += pr;
- g_in_sum += pg;
- b_in_sum += pb;
- stack = stack.next;
- }
- stackIn = stackStart;
- stackOut = stackEnd;
- for (x = 0; x < width; x++) {
- pixels[yi] = r_sum * mul_sum >> shg_sum;
- pixels[yi + 1] = g_sum * mul_sum >> shg_sum;
- pixels[yi + 2] = b_sum * mul_sum >> shg_sum;
- r_sum -= r_out_sum;
- g_sum -= g_out_sum;
- b_sum -= b_out_sum;
- r_out_sum -= stackIn.r;
- g_out_sum -= stackIn.g;
- b_out_sum -= stackIn.b;
- p = yw + ((p = x + radius + 1) < widthMinus1 ? p : widthMinus1) << 2;
- r_in_sum += stackIn.r = pixels[p];
- g_in_sum += stackIn.g = pixels[p + 1];
- b_in_sum += stackIn.b = pixels[p + 2];
- r_sum += r_in_sum;
- g_sum += g_in_sum;
- b_sum += b_in_sum;
- stackIn = stackIn.next;
- r_out_sum += pr = stackOut.r;
- g_out_sum += pg = stackOut.g;
- b_out_sum += pb = stackOut.b;
- r_in_sum -= pr;
- g_in_sum -= pg;
- b_in_sum -= pb;
- stackOut = stackOut.next;
- yi += 4;
- }
- yw += width;
- }
- for (x = 0; x < width; x++) {
- g_in_sum = b_in_sum = r_in_sum = g_sum = b_sum = r_sum = 0;
- yi = x << 2;
- r_out_sum = radiusPlus1 * (pr = pixels[yi]);
- g_out_sum = radiusPlus1 * (pg = pixels[yi + 1]);
- b_out_sum = radiusPlus1 * (pb = pixels[yi + 2]);
- r_sum += sumFactor * pr;
- g_sum += sumFactor * pg;
- b_sum += sumFactor * pb;
- stack = stackStart;
- for (i = 0; i < radiusPlus1; i++) {
- stack.r = pr;
- stack.g = pg;
- stack.b = pb;
- stack = stack.next;
- }
- yp = width;
- for (i = 1; i <= radius; i++) {
- yi = yp + x << 2;
- r_sum += (stack.r = pr = pixels[yi]) * (rbs = radiusPlus1 - i);
- g_sum += (stack.g = pg = pixels[yi + 1]) * rbs;
- b_sum += (stack.b = pb = pixels[yi + 2]) * rbs;
- r_in_sum += pr;
- g_in_sum += pg;
- b_in_sum += pb;
- stack = stack.next;
- if (i < heightMinus1) {
- yp += width;
- }
- }
- yi = x;
- stackIn = stackStart;
- stackOut = stackEnd;
- for (y = 0; y < height; y++) {
- p = yi << 2;
- pixels[p] = r_sum * mul_sum >> shg_sum;
- pixels[p + 1] = g_sum * mul_sum >> shg_sum;
- pixels[p + 2] = b_sum * mul_sum >> shg_sum;
- r_sum -= r_out_sum;
- g_sum -= g_out_sum;
- b_sum -= b_out_sum;
- r_out_sum -= stackIn.r;
- g_out_sum -= stackIn.g;
- b_out_sum -= stackIn.b;
- p = x + ((p = y + radiusPlus1) < heightMinus1 ? p : heightMinus1) * width << 2;
- r_sum += r_in_sum += stackIn.r = pixels[p];
- g_sum += g_in_sum += stackIn.g = pixels[p + 1];
- b_sum += b_in_sum += stackIn.b = pixels[p + 2];
- stackIn = stackIn.next;
- r_out_sum += pr = stackOut.r;
- g_out_sum += pg = stackOut.g;
- b_out_sum += pb = stackOut.b;
- r_in_sum -= pr;
- g_in_sum -= pg;
- b_in_sum -= pb;
- stackOut = stackOut.next;
- yi += width;
- }
- }
- context.putImageData(imageData, top_x, top_y);
- }
- function BlurStack() {
- this.r = 0;
- this.g = 0;
- this.b = 0;
- this.a = 0;
- this.next = null;
- }
- /*
- * canvg.js - Javascript SVG parser and renderer on Canvas
- * MIT Licensed
- * Gabe Lerner (gabelerner@gmail.com)
- * http://code.google.com/p/canvg/
- *
- * Requires: rgbcolor.js - http://www.phpied.com/rgb-color-parser-in-javascript/
- */
- (function() {
- // canvg(target, s)
- // empty parameters: replace all 'svg' elements on page with 'canvas' elements
- // target: canvas element or the id of a canvas element
- // s: svg string, url to svg file, or xml document
- // opts: optional hash of options
- // ignoreMouse: true => ignore mouse events
- // ignoreAnimation: true => ignore animations
- // ignoreDimensions: true => does not try to resize canvas
- // ignoreClear: true => does not clear canvas
- // offsetX: int => draws at a x offset
- // offsetY: int => draws at a y offset
- // scaleWidth: int => scales horizontally to width
- // scaleHeight: int => scales vertically to height
- // renderCallback: function => will call the function after the first render is completed
- // forceRedraw: function => will call the function on every frame, if it returns true, will redraw
- this.canvg = function(target, s, opts) {
- // no parameters
- if (target == null && s == null && opts == null) {
- var svgTags = document.getElementsByTagName("svg");
- for (var i = 0; i < svgTags.length; i++) {
- var svgTag = svgTags[i];
- var c = document.createElement("canvas");
- c.width = svgTag.clientWidth;
- c.height = svgTag.clientHeight;
- svgTag.parentNode.insertBefore(c, svgTag);
- svgTag.parentNode.removeChild(svgTag);
- var div = document.createElement("div");
- div.appendChild(svgTag);
- canvg(c, div.innerHTML);
- }
- return;
- }
- opts = opts || {};
- if (typeof target == "string") {
- target = document.getElementById(target);
- }
- // store class on canvas
- if (target.svg != null) target.svg.stop();
- var svg = build();
- // on i.e. 8 for flash canvas, we can't assign the property so check for it
- if (!(target.childNodes.length == 1 && target.childNodes[0].nodeName == "OBJECT")) target.svg = svg;
- svg.opts = opts;
- var ctx = target.getContext("2d");
- if (typeof s.documentElement != "undefined") {
- // load from xml doc
- svg.loadXmlDoc(ctx, s);
- } else if (s.substr(0, 1) == "<") {
- // load from xml string
- svg.loadXml(ctx, s);
- } else {
- // load from url
- svg.load(ctx, s);
- }
- };
- function build() {
- var svg = {};
- svg.FRAMERATE = 30;
- svg.MAX_VIRTUAL_PIXELS = 3e4;
- // globals
- svg.init = function(ctx) {
- var uniqueId = 0;
- svg.UniqueId = function() {
- uniqueId++;
- return "canvg" + uniqueId;
- };
- svg.Definitions = {};
- svg.Styles = {};
- svg.Animations = [];
- svg.Images = [];
- svg.ctx = ctx;
- svg.ViewPort = new function() {
- this.viewPorts = [];
- this.Clear = function() {
- this.viewPorts = [];
- };
- this.SetCurrent = function(width, height) {
- this.viewPorts.push({
- width: width,
- height: height
- });
- };
- this.RemoveCurrent = function() {
- this.viewPorts.pop();
- };
- this.Current = function() {
- return this.viewPorts[this.viewPorts.length - 1];
- };
- this.width = function() {
- return this.Current().width;
- };
- this.height = function() {
- return this.Current().height;
- };
- this.ComputeSize = function(d) {
- if (d != null && typeof d == "number") return d;
- if (d == "x") return this.width();
- if (d == "y") return this.height();
- return Math.sqrt(Math.pow(this.width(), 2) + Math.pow(this.height(), 2)) / Math.sqrt(2);
- };
- }();
- };
- svg.init();
- // images loaded
- svg.ImagesLoaded = function() {
- for (var i = 0; i < svg.Images.length; i++) {
- if (!svg.Images[i].loaded) return false;
- }
- return true;
- };
- // trim
- svg.trim = function(s) {
- return s.replace(/^\s+|\s+$/g, "");
- };
- // compress spaces
- svg.compressSpaces = function(s) {
- return s.replace(/[\s\r\t\n]+/gm, " ");
- };
- // ajax
- svg.ajax = function(url) {
- var AJAX;
- if (window.XMLHttpRequest) {
- AJAX = new XMLHttpRequest();
- } else {
- AJAX = new ActiveXObject("Microsoft.XMLHTTP");
- }
- if (AJAX) {
- AJAX.open("GET", url, false);
- AJAX.send(null);
- return AJAX.responseText;
- }
- return null;
- };
- // parse xml
- svg.parseXml = function(xml) {
- if (window.DOMParser) {
- var parser = new DOMParser();
- return parser.parseFromString(xml, "text/xml");
- } else {
- xml = xml.replace(/<!DOCTYPE svg[^>]*>/, "");
- var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
- xmlDoc.async = "false";
- xmlDoc.loadXML(xml);
- return xmlDoc;
- }
- };
- svg.Property = function(name, value) {
- this.name = name;
- this.value = value;
- };
- svg.Property.prototype.getValue = function() {
- return this.value;
- };
- svg.Property.prototype.hasValue = function() {
- return this.value != null && this.value !== "";
- };
- // return the numerical value of the property
- svg.Property.prototype.numValue = function() {
- if (!this.hasValue()) return 0;
- var n = parseFloat(this.value);
- if ((this.value + "").match(/%$/)) {
- n = n / 100;
- }
- return n;
- };
- svg.Property.prototype.valueOrDefault = function(def) {
- if (this.hasValue()) return this.value;
- return def;
- };
- svg.Property.prototype.numValueOrDefault = function(def) {
- if (this.hasValue()) return this.numValue();
- return def;
- };
- // color extensions
- // augment the current color value with the opacity
- svg.Property.prototype.addOpacity = function(opacity) {
- var newValue = this.value;
- if (opacity != null && opacity != "" && typeof this.value == "string") {
- // can only add opacity to colors, not patterns
- var color = new RGBColor(this.value);
- if (color.ok) {
- newValue = "rgba(" + color.r + ", " + color.g + ", " + color.b + ", " + opacity + ")";
- }
- }
- return new svg.Property(this.name, newValue);
- };
- // definition extensions
- // get the definition from the definitions table
- svg.Property.prototype.getDefinition = function() {
- var name = this.value.match(/#([^\)'"]+)/);
- if (name) {
- name = name[1];
- }
- if (!name) {
- name = this.value;
- }
- return svg.Definitions[name];
- };
- svg.Property.prototype.isUrlDefinition = function() {
- return this.value.indexOf("url(") == 0;
- };
- svg.Property.prototype.getFillStyleDefinition = function(e, opacityProp) {
- var def = this.getDefinition();
- // gradient
- if (def != null && def.createGradient) {
- return def.createGradient(svg.ctx, e, opacityProp);
- }
- // pattern
- if (def != null && def.createPattern) {
- if (def.getHrefAttribute().hasValue()) {
- var pt = def.attribute("patternTransform");
- def = def.getHrefAttribute().getDefinition();
- if (pt.hasValue()) {
- def.attribute("patternTransform", true).value = pt.value;
- }
- }
- return def.createPattern(svg.ctx, e);
- }
- return null;
- };
- // length extensions
- svg.Property.prototype.getDPI = function(viewPort) {
- return 96;
- };
- svg.Property.prototype.getEM = function(viewPort) {
- var em = 12;
- var fontSize = new svg.Property("fontSize", svg.Font.Parse(svg.ctx.font).fontSize);
- if (fontSize.hasValue()) em = fontSize.toPixels(viewPort);
- return em;
- };
- svg.Property.prototype.getUnits = function() {
- var s = this.value + "";
- return s.replace(/[0-9\.\-]/g, "");
- };
- // get the length as pixels
- svg.Property.prototype.toPixels = function(viewPort, processPercent) {
- if (!this.hasValue()) return 0;
- var s = this.value + "";
- if (s.match(/em$/)) return this.numValue() * this.getEM(viewPort);
- if (s.match(/ex$/)) return this.numValue() * this.getEM(viewPort) / 2;
- if (s.match(/px$/)) return this.numValue();
- if (s.match(/pt$/)) return this.numValue() * this.getDPI(viewPort) * (1 / 72);
- if (s.match(/pc$/)) return this.numValue() * 15;
- if (s.match(/cm$/)) return this.numValue() * this.getDPI(viewPort) / 2.54;
- if (s.match(/mm$/)) return this.numValue() * this.getDPI(viewPort) / 25.4;
- if (s.match(/in$/)) return this.numValue() * this.getDPI(viewPort);
- if (s.match(/%$/)) return this.numValue() * svg.ViewPort.ComputeSize(viewPort);
- var n = this.numValue();
- if (processPercent && n < 1) return n * svg.ViewPort.ComputeSize(viewPort);
- return n;
- };
- // time extensions
- // get the time as milliseconds
- svg.Property.prototype.toMilliseconds = function() {
- if (!this.hasValue()) return 0;
- var s = this.value + "";
- if (s.match(/s$/)) return this.numValue() * 1e3;
- if (s.match(/ms$/)) return this.numValue();
- return this.numValue();
- };
- // angle extensions
- // get the angle as radians
- svg.Property.prototype.toRadians = function() {
- if (!this.hasValue()) return 0;
- var s = this.value + "";
- if (s.match(/deg$/)) return this.numValue() * (Math.PI / 180);
- if (s.match(/grad$/)) return this.numValue() * (Math.PI / 200);
- if (s.match(/rad$/)) return this.numValue();
- return this.numValue() * (Math.PI / 180);
- };
- // fonts
- svg.Font = new function() {
- this.Styles = "normal|italic|oblique|inherit";
- this.Variants = "normal|small-caps|inherit";
- this.Weights = "normal|bold|bolder|lighter|100|200|300|400|500|600|700|800|900|inherit";
- this.CreateFont = function(fontStyle, fontVariant, fontWeight, fontSize, fontFamily, inherit) {
- var f = inherit != null ? this.Parse(inherit) : this.CreateFont("", "", "", "", "", svg.ctx.font);
- return {
- fontFamily: fontFamily || f.fontFamily,
- fontSize: fontSize || f.fontSize,
- fontStyle: fontStyle || f.fontStyle,
- fontWeight: fontWeight || f.fontWeight,
- fontVariant: fontVariant || f.fontVariant,
- toString: function() {
- return [ this.fontStyle, this.fontVariant, this.fontWeight, this.fontSize, this.fontFamily ].join(" ");
- }
- };
- };
- var that = this;
- this.Parse = function(s) {
- var f = {};
- var d = svg.trim(svg.compressSpaces(s || "")).split(" ");
- var set = {
- fontSize: false,
- fontStyle: false,
- fontWeight: false,
- fontVariant: false
- };
- var ff = "";
- for (var i = 0; i < d.length; i++) {
- if (!set.fontStyle && that.Styles.indexOf(d[i]) != -1) {
- if (d[i] != "inherit") f.fontStyle = d[i];
- set.fontStyle = true;
- } else if (!set.fontVariant && that.Variants.indexOf(d[i]) != -1) {
- if (d[i] != "inherit") f.fontVariant = d[i];
- set.fontStyle = set.fontVariant = true;
- } else if (!set.fontWeight && that.Weights.indexOf(d[i]) != -1) {
- if (d[i] != "inherit") f.fontWeight = d[i];
- set.fontStyle = set.fontVariant = set.fontWeight = true;
- } else if (!set.fontSize) {
- if (d[i] != "inherit") f.fontSize = d[i].split("/")[0];
- set.fontStyle = set.fontVariant = set.fontWeight = set.fontSize = true;
- } else {
- if (d[i] != "inherit") ff += d[i];
- }
- }
- if (ff != "") f.fontFamily = ff;
- return f;
- };
- }();
- // points and paths
- svg.ToNumberArray = function(s) {
- var a = svg.trim(svg.compressSpaces((s || "").replace(/,/g, " "))).split(" ");
- for (var i = 0; i < a.length; i++) {
- a[i] = parseFloat(a[i]);
- }
- return a;
- };
- svg.Point = function(x, y) {
- this.x = x;
- this.y = y;
- };
- svg.Point.prototype.angleTo = function(p) {
- return Math.atan2(p.y - this.y, p.x - this.x);
- };
- svg.Point.prototype.applyTransform = function(v) {
- var xp = this.x * v[0] + this.y * v[2] + v[4];
- var yp = this.x * v[1] + this.y * v[3] + v[5];
- this.x = xp;
- this.y = yp;
- };
- svg.CreatePoint = function(s) {
- var a = svg.ToNumberArray(s);
- return new svg.Point(a[0], a[1]);
- };
- svg.CreatePath = function(s) {
- var a = svg.ToNumberArray(s);
- var path = [];
- for (var i = 0; i < a.length; i += 2) {
- path.push(new svg.Point(a[i], a[i + 1]));
- }
- return path;
- };
- // bounding box
- svg.BoundingBox = function(x1, y1, x2, y2) {
- // pass in initial points if you want
- this.x1 = Number.NaN;
- this.y1 = Number.NaN;
- this.x2 = Number.NaN;
- this.y2 = Number.NaN;
- this.x = function() {
- return this.x1;
- };
- this.y = function() {
- return this.y1;
- };
- this.width = function() {
- return this.x2 - this.x1;
- };
- this.height = function() {
- return this.y2 - this.y1;
- };
- this.addPoint = function(x, y) {
- if (x != null) {
- if (isNaN(this.x1) || isNaN(this.x2)) {
- this.x1 = x;
- this.x2 = x;
- }
- if (x < this.x1) this.x1 = x;
- if (x > this.x2) this.x2 = x;
- }
- if (y != null) {
- if (isNaN(this.y1) || isNaN(this.y2)) {
- this.y1 = y;
- this.y2 = y;
- }
- if (y < this.y1) this.y1 = y;
- if (y > this.y2) this.y2 = y;
- }
- };
- this.addX = function(x) {
- this.addPoint(x, null);
- };
- this.addY = function(y) {
- this.addPoint(null, y);
- };
- this.addBoundingBox = function(bb) {
- this.addPoint(bb.x1, bb.y1);
- this.addPoint(bb.x2, bb.y2);
- };
- this.addQuadraticCurve = function(p0x, p0y, p1x, p1y, p2x, p2y) {
- var cp1x = p0x + 2 / 3 * (p1x - p0x);
- // CP1 = QP0 + 2/3 *(QP1-QP0)
- var cp1y = p0y + 2 / 3 * (p1y - p0y);
- // CP1 = QP0 + 2/3 *(QP1-QP0)
- var cp2x = cp1x + 1 / 3 * (p2x - p0x);
- // CP2 = CP1 + 1/3 *(QP2-QP0)
- var cp2y = cp1y + 1 / 3 * (p2y - p0y);
- // CP2 = CP1 + 1/3 *(QP2-QP0)
- this.addBezierCurve(p0x, p0y, cp1x, cp2x, cp1y, cp2y, p2x, p2y);
- };
- this.addBezierCurve = function(p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y) {
- // from http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html
- var p0 = [ p0x, p0y ], p1 = [ p1x, p1y ], p2 = [ p2x, p2y ], p3 = [ p3x, p3y ];
- this.addPoint(p0[0], p0[1]);
- this.addPoint(p3[0], p3[1]);
- for (i = 0; i <= 1; i++) {
- var f = function(t) {
- return Math.pow(1 - t, 3) * p0[i] + 3 * Math.pow(1 - t, 2) * t * p1[i] + 3 * (1 - t) * Math.pow(t, 2) * p2[i] + Math.pow(t, 3) * p3[i];
- };
- var b = 6 * p0[i] - 12 * p1[i] + 6 * p2[i];
- var a = -3 * p0[i] + 9 * p1[i] - 9 * p2[i] + 3 * p3[i];
- var c = 3 * p1[i] - 3 * p0[i];
- if (a == 0) {
- if (b == 0) continue;
- var t = -c / b;
- if (0 < t && t < 1) {
- if (i == 0) this.addX(f(t));
- if (i == 1) this.addY(f(t));
- }
- continue;
- }
- var b2ac = Math.pow(b, 2) - 4 * c * a;
- if (b2ac < 0) continue;
- var t1 = (-b + Math.sqrt(b2ac)) / (2 * a);
- if (0 < t1 && t1 < 1) {
- if (i == 0) this.addX(f(t1));
- if (i == 1) this.addY(f(t1));
- }
- var t2 = (-b - Math.sqrt(b2ac)) / (2 * a);
- if (0 < t2 && t2 < 1) {
- if (i == 0) this.addX(f(t2));
- if (i == 1) this.addY(f(t2));
- }
- }
- };
- this.isPointInBox = function(x, y) {
- return this.x1 <= x && x <= this.x2 && this.y1 <= y && y <= this.y2;
- };
- this.addPoint(x1, y1);
- this.addPoint(x2, y2);
- };
- // transforms
- svg.Transform = function(v) {
- var that = this;
- this.Type = {};
- // translate
- this.Type.translate = function(s) {
- this.p = svg.CreatePoint(s);
- this.apply = function(ctx) {
- ctx.translate(this.p.x || 0, this.p.y || 0);
- };
- this.unapply = function(ctx) {
- ctx.translate(-1 * this.p.x || 0, -1 * this.p.y || 0);
- };
- this.applyToPoint = function(p) {
- p.applyTransform([ 1, 0, 0, 1, this.p.x || 0, this.p.y || 0 ]);
- };
- };
- // rotate
- this.Type.rotate = function(s) {
- var a = svg.ToNumberArray(s);
- this.angle = new svg.Property("angle", a[0]);
- this.cx = a[1] || 0;
- this.cy = a[2] || 0;
- this.apply = function(ctx) {
- ctx.translate(this.cx, this.cy);
- ctx.rotate(this.angle.toRadians());
- ctx.translate(-this.cx, -this.cy);
- };
- this.unapply = function(ctx) {
- ctx.translate(this.cx, this.cy);
- ctx.rotate(-1 * this.angle.toRadians());
- ctx.translate(-this.cx, -this.cy);
- };
- this.applyToPoint = function(p) {
- var a = this.angle.toRadians();
- p.applyTransform([ 1, 0, 0, 1, this.p.x || 0, this.p.y || 0 ]);
- p.applyTransform([ Math.cos(a), Math.sin(a), -Math.sin(a), Math.cos(a), 0, 0 ]);
- p.applyTransform([ 1, 0, 0, 1, -this.p.x || 0, -this.p.y || 0 ]);
- };
- };
- this.Type.scale = function(s) {
- this.p = svg.CreatePoint(s);
- this.apply = function(ctx) {
- ctx.scale(this.p.x || 1, this.p.y || this.p.x || 1);
- };
- this.unapply = function(ctx) {
- ctx.scale(1 / this.p.x || 1, 1 / this.p.y || this.p.x || 1);
- };
- this.applyToPoint = function(p) {
- p.applyTransform([ this.p.x || 0, 0, 0, this.p.y || 0, 0, 0 ]);
- };
- };
- this.Type.matrix = function(s) {
- this.m = svg.ToNumberArray(s);
- this.apply = function(ctx) {
- ctx.transform(this.m[0], this.m[1], this.m[2], this.m[3], this.m[4], this.m[5]);
- };
- this.applyToPoint = function(p) {
- p.applyTransform(this.m);
- };
- };
- this.Type.SkewBase = function(s) {
- this.base = that.Type.matrix;
- this.base(s);
- this.angle = new svg.Property("angle", s);
- };
- this.Type.SkewBase.prototype = new this.Type.matrix();
- this.Type.skewX = function(s) {
- this.base = that.Type.SkewBase;
- this.base(s);
- this.m = [ 1, 0, Math.tan(this.angle.toRadians()), 1, 0, 0 ];
- };
- this.Type.skewX.prototype = new this.Type.SkewBase();
- this.Type.skewY = function(s) {
- this.base = that.Type.SkewBase;
- this.base(s);
- this.m = [ 1, Math.tan(this.angle.toRadians()), 0, 1, 0, 0 ];
- };
- this.Type.skewY.prototype = new this.Type.SkewBase();
- this.transforms = [];
- this.apply = function(ctx) {
- for (var i = 0; i < this.transforms.length; i++) {
- this.transforms[i].apply(ctx);
- }
- };
- this.unapply = function(ctx) {
- for (var i = this.transforms.length - 1; i >= 0; i--) {
- this.transforms[i].unapply(ctx);
- }
- };
- this.applyToPoint = function(p) {
- for (var i = 0; i < this.transforms.length; i++) {
- this.transforms[i].applyToPoint(p);
- }
- };
- var data = svg.trim(svg.compressSpaces(v)).replace(/\)(\s?,\s?)/g, ") ").split(/\s(?=[a-z])/);
- for (var i = 0; i < data.length; i++) {
- var type = svg.trim(data[i].split("(")[0]);
- var s = data[i].split("(")[1].replace(")", "");
- var transform = new this.Type[type](s);
- transform.type = type;
- this.transforms.push(transform);
- }
- };
- // aspect ratio
- svg.AspectRatio = function(ctx, aspectRatio, width, desiredWidth, height, desiredHeight, minX, minY, refX, refY) {
- // aspect ratio - http://www.w3.org/TR/SVG/coords.html#PreserveAspectRatioAttribute
- aspectRatio = svg.compressSpaces(aspectRatio);
- aspectRatio = aspectRatio.replace(/^defer\s/, "");
- // ignore defer
- var align = aspectRatio.split(" ")[0] || "xMidYMid";
- var meetOrSlice = aspectRatio.split(" ")[1] || "meet";
- // calculate scale
- var scaleX = width / desiredWidth;
- var scaleY = height / desiredHeight;
- var scaleMin = Math.min(scaleX, scaleY);
- var scaleMax = Math.max(scaleX, scaleY);
- if (meetOrSlice == "meet") {
- desiredWidth *= scaleMin;
- desiredHeight *= scaleMin;
- }
- if (meetOrSlice == "slice") {
- desiredWidth *= scaleMax;
- desiredHeight *= scaleMax;
- }
- refX = new svg.Property("refX", refX);
- refY = new svg.Property("refY", refY);
- if (refX.hasValue() && refY.hasValue()) {
- ctx.translate(-scaleMin * refX.toPixels("x"), -scaleMin * refY.toPixels("y"));
- } else {
- // align
- if (align.match(/^xMid/) && (meetOrSlice == "meet" && scaleMin == scaleY || meetOrSlice == "slice" && scaleMax == scaleY)) ctx.translate(width / 2 - desiredWidth / 2, 0);
- if (align.match(/YMid$/) && (meetOrSlice == "meet" && scaleMin == scaleX || meetOrSlice == "slice" && scaleMax == scaleX)) ctx.translate(0, height / 2 - desiredHeight / 2);
- if (align.match(/^xMax/) && (meetOrSlice == "meet" && scaleMin == scaleY || meetOrSlice == "slice" && scaleMax == scaleY)) ctx.translate(width - desiredWidth, 0);
- if (align.match(/YMax$/) && (meetOrSlice == "meet" && scaleMin == scaleX || meetOrSlice == "slice" && scaleMax == scaleX)) ctx.translate(0, height - desiredHeight);
- }
- // scale
- if (align == "none") ctx.scale(scaleX, scaleY); else if (meetOrSlice == "meet") ctx.scale(scaleMin, scaleMin); else if (meetOrSlice == "slice") ctx.scale(scaleMax, scaleMax);
- // translate
- ctx.translate(minX == null ? 0 : -minX, minY == null ? 0 : -minY);
- };
- // elements
- svg.Element = {};
- svg.EmptyProperty = new svg.Property("EMPTY", "");
- svg.Element.ElementBase = function(node) {
- this.attributes = {};
- this.styles = {};
- this.children = [];
- // get or create attribute
- this.attribute = function(name, createIfNotExists) {
- var a = this.attributes[name];
- if (a != null) return a;
- if (createIfNotExists == true) {
- a = new svg.Property(name, "");
- this.attributes[name] = a;
- }
- return a || svg.EmptyProperty;
- };
- this.getHrefAttribute = function() {
- for (var a in this.attributes) {
- if (a.match(/:href$/)) {
- return this.attributes[a];
- }
- }
- return svg.EmptyProperty;
- };
- // get or create style, crawls up node tree
- this.style = function(name, createIfNotExists) {
- var s = this.styles[name];
- if (s != null) return s;
- var a = this.attribute(name);
- if (a != null && a.hasValue()) {
- this.styles[name] = a;
- // move up to me to cache
- return a;
- }
- var p = this.parent;
- if (p != null) {
- var ps = p.style(name);
- if (ps != null && ps.hasValue()) {
- return ps;
- }
- }
- if (createIfNotExists == true) {
- s = new svg.Property(name, "");
- this.styles[name] = s;
- }
- return s || svg.EmptyProperty;
- };
- // base render
- this.render = function(ctx) {
- // don't render display=none
- if (this.style("display").value == "none") return;
- // don't render visibility=hidden
- if (this.attribute("visibility").value == "hidden") return;
- ctx.save();
- if (this.attribute("mask").hasValue()) {
- // mask
- var mask = this.attribute("mask").getDefinition();
- if (mask != null) mask.apply(ctx, this);
- } else if (this.style("filter").hasValue()) {
- // filter
- var filter = this.style("filter").getDefinition();
- if (filter != null) filter.apply(ctx, this);
- } else {
- this.setContext(ctx);
- this.renderChildren(ctx);
- this.clearContext(ctx);
- }
- ctx.restore();
- };
- // base set context
- this.setContext = function(ctx) {};
- // base clear context
- this.clearContext = function(ctx) {};
- // base render children
- this.renderChildren = function(ctx) {
- for (var i = 0; i < this.children.length; i++) {
- this.children[i].render(ctx);
- }
- };
- this.addChild = function(childNode, create) {
- var child = childNode;
- if (create) child = svg.CreateElement(childNode);
- child.parent = this;
- this.children.push(child);
- };
- if (node != null && node.nodeType == 1) {
- //ELEMENT_NODE
- // add children
- for (var i = 0; i < node.childNodes.length; i++) {
- var childNode = node.childNodes[i];
- if (childNode.nodeType == 1) this.addChild(childNode, true);
- //ELEMENT_NODE
- if (this.captureTextNodes && childNode.nodeType == 3) {
- var text = childNode.nodeValue || childNode.text || "";
- if (svg.trim(svg.compressSpaces(text)) != "") {
- this.addChild(new svg.Element.tspan(childNode), false);
- }
- }
- }
- // add attributes
- for (var i = 0; i < node.attributes.length; i++) {
- var attribute = node.attributes[i];
- this.attributes[attribute.nodeName] = new svg.Property(attribute.nodeName, attribute.nodeValue);
- }
- // add tag styles
- var styles = svg.Styles[node.nodeName];
- if (styles != null) {
- for (var name in styles) {
- this.styles[name] = styles[name];
- }
- }
- // add class styles
- if (this.attribute("class").hasValue()) {
- var classes = svg.compressSpaces(this.attribute("class").value).split(" ");
- for (var j = 0; j < classes.length; j++) {
- styles = svg.Styles["." + classes[j]];
- if (styles != null) {
- for (var name in styles) {
- this.styles[name] = styles[name];
- }
- }
- styles = svg.Styles[node.nodeName + "." + classes[j]];
- if (styles != null) {
- for (var name in styles) {
- this.styles[name] = styles[name];
- }
- }
- }
- }
- // add id styles
- if (this.attribute("id").hasValue()) {
- var styles = svg.Styles["#" + this.attribute("id").value];
- if (styles != null) {
- for (var name in styles) {
- this.styles[name] = styles[name];
- }
- }
- }
- // add inline styles
- if (this.attribute("style").hasValue()) {
- var styles = this.attribute("style").value.split(";");
- for (var i = 0; i < styles.length; i++) {
- if (svg.trim(styles[i]) != "") {
- var style = styles[i].split(":");
- var name = svg.trim(style[0]);
- var value = svg.trim(style[1]);
- this.styles[name] = new svg.Property(name, value);
- }
- }
- }
- // add id
- if (this.attribute("id").hasValue()) {
- if (svg.Definitions[this.attribute("id").value] == null) {
- svg.Definitions[this.attribute("id").value] = this;
- }
- }
- }
- };
- svg.Element.RenderedElementBase = function(node) {
- this.base = svg.Element.ElementBase;
- this.base(node);
- this.setContext = function(ctx) {
- // fill
- if (this.style("fill").isUrlDefinition()) {
- var fs = this.style("fill").getFillStyleDefinition(this, this.style("fill-opacity"));
- if (fs != null) ctx.fillStyle = fs;
- } else if (this.style("fill").hasValue()) {
- var fillStyle = this.style("fill");
- if (fillStyle.value == "currentColor") fillStyle.value = this.style("color").value;
- ctx.fillStyle = fillStyle.value == "none" ? "rgba(0,0,0,0)" : fillStyle.value;
- }
- if (this.style("fill-opacity").hasValue()) {
- var fillStyle = new svg.Property("fill", ctx.fillStyle);
- fillStyle = fillStyle.addOpacity(this.style("fill-opacity").value);
- ctx.fillStyle = fillStyle.value;
- }
- // stroke
- if (this.style("stroke").isUrlDefinition()) {
- var fs = this.style("stroke").getFillStyleDefinition(this, this.style("stroke-opacity"));
- if (fs != null) ctx.strokeStyle = fs;
- } else if (this.style("stroke").hasValue()) {
- var strokeStyle = this.style("stroke");
- if (strokeStyle.value == "currentColor") strokeStyle.value = this.style("color").value;
- ctx.strokeStyle = strokeStyle.value == "none" ? "rgba(0,0,0,0)" : strokeStyle.value;
- }
- if (this.style("stroke-opacity").hasValue()) {
- var strokeStyle = new svg.Property("stroke", ctx.strokeStyle);
- strokeStyle = strokeStyle.addOpacity(this.style("stroke-opacity").value);
- ctx.strokeStyle = strokeStyle.value;
- }
- if (this.style("stroke-width").hasValue()) {
- var newLineWidth = this.style("stroke-width").toPixels();
- ctx.lineWidth = newLineWidth == 0 ? .001 : newLineWidth;
- }
- if (this.style("stroke-linecap").hasValue()) ctx.lineCap = this.style("stroke-linecap").value;
- if (this.style("stroke-linejoin").hasValue()) ctx.lineJoin = this.style("stroke-linejoin").value;
- if (this.style("stroke-miterlimit").hasValue()) ctx.miterLimit = this.style("stroke-miterlimit").value;
- if (this.style("stroke-dasharray").hasValue()) {
- var gaps = svg.ToNumberArray(this.style("stroke-dasharray").value);
- if (typeof ctx.setLineDash != "undefined") {
- ctx.setLineDash(gaps);
- } else if (typeof ctx.webkitLineDash != "undefined") {
- ctx.webkitLineDash = gaps;
- } else if (typeof ctx.mozDash != "undefined") {
- ctx.mozDash = gaps;
- }
- var offset = this.style("stroke-dashoffset").numValueOrDefault(1);
- if (typeof ctx.lineDashOffset != "undefined") {
- ctx.lineDashOffset = offset;
- } else if (typeof ctx.webkitLineDashOffset != "undefined") {
- ctx.webkitLineDashOffset = offset;
- } else if (typeof ctx.mozDashOffset != "undefined") {
- ctx.mozDashOffset = offset;
- }
- }
- // font
- if (typeof ctx.font != "undefined") {
- ctx.font = svg.Font.CreateFont(this.style("font-style").value, this.style("font-variant").value, this.style("font-weight").value, this.style("font-size").hasValue() ? this.style("font-size").toPixels() + "px" : "", this.style("font-family").value).toString();
- }
- // transform
- if (this.attribute("transform").hasValue()) {
- var transform = new svg.Transform(this.attribute("transform").value);
- transform.apply(ctx);
- }
- // clip
- if (this.style("clip-path").hasValue()) {
- var clip = this.style("clip-path").getDefinition();
- if (clip != null) clip.apply(ctx);
- }
- // opacity
- if (this.style("opacity").hasValue()) {
- ctx.globalAlpha = this.style("opacity").numValue();
- }
- };
- };
- svg.Element.RenderedElementBase.prototype = new svg.Element.ElementBase();
- svg.Element.PathElementBase = function(node) {
- this.base = svg.Element.RenderedElementBase;
- this.base(node);
- this.path = function(ctx) {
- if (ctx != null) ctx.beginPath();
- return new svg.BoundingBox();
- };
- this.renderChildren = function(ctx) {
- this.path(ctx);
- svg.Mouse.checkPath(this, ctx);
- if (ctx.fillStyle != "") {
- if (this.attribute("fill-rule").hasValue()) {
- ctx.fill(this.attribute("fill-rule").value);
- } else {
- ctx.fill();
- }
- }
- if (ctx.strokeStyle != "") ctx.stroke();
- var markers = this.getMarkers();
- if (markers != null) {
- if (this.style("marker-start").isUrlDefinition()) {
- var marker = this.style("marker-start").getDefinition();
- marker.render(ctx, markers[0][0], markers[0][1]);
- }
- if (this.style("marker-mid").isUrlDefinition()) {
- var marker = this.style("marker-mid").getDefinition();
- for (var i = 1; i < markers.length - 1; i++) {
- marker.render(ctx, markers[i][0], markers[i][1]);
- }
- }
- if (this.style("marker-end").isUrlDefinition()) {
- var marker = this.style("marker-end").getDefinition();
- marker.render(ctx, markers[markers.length - 1][0], markers[markers.length - 1][1]);
- }
- }
- };
- this.getBoundingBox = function() {
- return this.path();
- };
- this.getMarkers = function() {
- return null;
- };
- };
- svg.Element.PathElementBase.prototype = new svg.Element.RenderedElementBase();
- // svg element
- svg.Element.svg = function(node) {
- this.base = svg.Element.RenderedElementBase;
- this.base(node);
- this.baseClearContext = this.clearContext;
- this.clearContext = function(ctx) {
- this.baseClearContext(ctx);
- svg.ViewPort.RemoveCurrent();
- };
- this.baseSetContext = this.setContext;
- this.setContext = function(ctx) {
- // initial values
- ctx.strokeStyle = "rgba(0,0,0,0)";
- ctx.lineCap = "butt";
- ctx.lineJoin = "miter";
- ctx.miterLimit = 4;
- this.baseSetContext(ctx);
- // create new view port
- if (!this.attribute("x").hasValue()) this.attribute("x", true).value = 0;
- if (!this.attribute("y").hasValue()) this.attribute("y", true).value = 0;
- ctx.translate(this.attribute("x").toPixels("x"), this.attribute("y").toPixels("y"));
- var width = svg.ViewPort.width();
- var height = svg.ViewPort.height();
- if (!this.attribute("width").hasValue()) this.attribute("width", true).value = "100%";
- if (!this.attribute("height").hasValue()) this.attribute("height", true).value = "100%";
- if (typeof this.root == "undefined") {
- width = this.attribute("width").toPixels("x");
- height = this.attribute("height").toPixels("y");
- var x = 0;
- var y = 0;
- if (this.attribute("refX").hasValue() && this.attribute("refY").hasValue()) {
- x = -this.attribute("refX").toPixels("x");
- y = -this.attribute("refY").toPixels("y");
- }
- ctx.beginPath();
- ctx.moveTo(x, y);
- ctx.lineTo(width, y);
- ctx.lineTo(width, height);
- ctx.lineTo(x, height);
- ctx.closePath();
- ctx.clip();
- }
- svg.ViewPort.SetCurrent(width, height);
- // viewbox
- if (this.attribute("viewBox").hasValue()) {
- var viewBox = svg.ToNumberArray(this.attribute("viewBox").value);
- var minX = viewBox[0];
- var minY = viewBox[1];
- width = viewBox[2];
- height = viewBox[3];
- svg.AspectRatio(ctx, this.attribute("preserveAspectRatio").value, svg.ViewPort.width(), width, svg.ViewPort.height(), height, minX, minY, this.attribute("refX").value, this.attribute("refY").value);
- svg.ViewPort.RemoveCurrent();
- svg.ViewPort.SetCurrent(viewBox[2], viewBox[3]);
- }
- };
- };
- svg.Element.svg.prototype = new svg.Element.RenderedElementBase();
- // rect element
- svg.Element.rect = function(node) {
- this.base = svg.Element.PathElementBase;
- this.base(node);
- this.path = function(ctx) {
- var x = this.attribute("x").toPixels("x");
- var y = this.attribute("y").toPixels("y");
- var width = this.attribute("width").toPixels("x");
- var height = this.attribute("height").toPixels("y");
- var rx = this.attribute("rx").toPixels("x");
- var ry = this.attribute("ry").toPixels("y");
- if (this.attribute("rx").hasValue() && !this.attribute("ry").hasValue()) ry = rx;
- if (this.attribute("ry").hasValue() && !this.attribute("rx").hasValue()) rx = ry;
- rx = Math.min(rx, width / 2);
- ry = Math.min(ry, height / 2);
- if (ctx != null) {
- ctx.beginPath();
- ctx.moveTo(x + rx, y);
- ctx.lineTo(x + width - rx, y);
- ctx.quadraticCurveTo(x + width, y, x + width, y + ry);
- ctx.lineTo(x + width, y + height - ry);
- ctx.quadraticCurveTo(x + width, y + height, x + width - rx, y + height);
- ctx.lineTo(x + rx, y + height);
- ctx.quadraticCurveTo(x, y + height, x, y + height - ry);
- ctx.lineTo(x, y + ry);
- ctx.quadraticCurveTo(x, y, x + rx, y);
- ctx.closePath();
- }
- return new svg.BoundingBox(x, y, x + width, y + height);
- };
- };
- svg.Element.rect.prototype = new svg.Element.PathElementBase();
- // circle element
- svg.Element.circle = function(node) {
- this.base = svg.Element.PathElementBase;
- this.base(node);
- this.path = function(ctx) {
- var cx = this.attribute("cx").toPixels("x");
- var cy = this.attribute("cy").toPixels("y");
- var r = this.attribute("r").toPixels();
- if (ctx != null) {
- ctx.beginPath();
- ctx.arc(cx, cy, r, 0, Math.PI * 2, true);
- ctx.closePath();
- }
- return new svg.BoundingBox(cx - r, cy - r, cx + r, cy + r);
- };
- };
- svg.Element.circle.prototype = new svg.Element.PathElementBase();
- // ellipse element
- svg.Element.ellipse = function(node) {
- this.base = svg.Element.PathElementBase;
- this.base(node);
- this.path = function(ctx) {
- var KAPPA = 4 * ((Math.sqrt(2) - 1) / 3);
- var rx = this.attribute("rx").toPixels("x");
- var ry = this.attribute("ry").toPixels("y");
- var cx = this.attribute("cx").toPixels("x");
- var cy = this.attribute("cy").toPixels("y");
- if (ctx != null) {
- ctx.beginPath();
- ctx.moveTo(cx, cy - ry);
- ctx.bezierCurveTo(cx + KAPPA * rx, cy - ry, cx + rx, cy - KAPPA * ry, cx + rx, cy);
- ctx.bezierCurveTo(cx + rx, cy + KAPPA * ry, cx + KAPPA * rx, cy + ry, cx, cy + ry);
- ctx.bezierCurveTo(cx - KAPPA * rx, cy + ry, cx - rx, cy + KAPPA * ry, cx - rx, cy);
- ctx.bezierCurveTo(cx - rx, cy - KAPPA * ry, cx - KAPPA * rx, cy - ry, cx, cy - ry);
- ctx.closePath();
- }
- return new svg.BoundingBox(cx - rx, cy - ry, cx + rx, cy + ry);
- };
- };
- svg.Element.ellipse.prototype = new svg.Element.PathElementBase();
- // line element
- svg.Element.line = function(node) {
- this.base = svg.Element.PathElementBase;
- this.base(node);
- this.getPoints = function() {
- return [ new svg.Point(this.attribute("x1").toPixels("x"), this.attribute("y1").toPixels("y")), new svg.Point(this.attribute("x2").toPixels("x"), this.attribute("y2").toPixels("y")) ];
- };
- this.path = function(ctx) {
- var points = this.getPoints();
- if (ctx != null) {
- ctx.beginPath();
- ctx.moveTo(points[0].x, points[0].y);
- ctx.lineTo(points[1].x, points[1].y);
- }
- return new svg.BoundingBox(points[0].x, points[0].y, points[1].x, points[1].y);
- };
- this.getMarkers = function() {
- var points = this.getPoints();
- var a = points[0].angleTo(points[1]);
- return [ [ points[0], a ], [ points[1], a ] ];
- };
- };
- svg.Element.line.prototype = new svg.Element.PathElementBase();
- // polyline element
- svg.Element.polyline = function(node) {
- this.base = svg.Element.PathElementBase;
- this.base(node);
- this.points = svg.CreatePath(this.attribute("points").value);
- this.path = function(ctx) {
- var bb = new svg.BoundingBox(this.points[0].x, this.points[0].y);
- if (ctx != null) {
- ctx.beginPath();
- ctx.moveTo(this.points[0].x, this.points[0].y);
- }
- for (var i = 1; i < this.points.length; i++) {
- bb.addPoint(this.points[i].x, this.points[i].y);
- if (ctx != null) ctx.lineTo(this.points[i].x, this.points[i].y);
- }
- return bb;
- };
- this.getMarkers = function() {
- var markers = [];
- for (var i = 0; i < this.points.length - 1; i++) {
- markers.push([ this.points[i], this.points[i].angleTo(this.points[i + 1]) ]);
- }
- markers.push([ this.points[this.points.length - 1], markers[markers.length - 1][1] ]);
- return markers;
- };
- };
- svg.Element.polyline.prototype = new svg.Element.PathElementBase();
- // polygon element
- svg.Element.polygon = function(node) {
- this.base = svg.Element.polyline;
- this.base(node);
- this.basePath = this.path;
- this.path = function(ctx) {
- var bb = this.basePath(ctx);
- if (ctx != null) {
- ctx.lineTo(this.points[0].x, this.points[0].y);
- ctx.closePath();
- }
- return bb;
- };
- };
- svg.Element.polygon.prototype = new svg.Element.polyline();
- // path element
- svg.Element.path = function(node) {
- this.base = svg.Element.PathElementBase;
- this.base(node);
- var d = this.attribute("d").value;
- // TODO: convert to real lexer based on http://www.w3.org/TR/SVG11/paths.html#PathDataBNF
- d = d.replace(/,/gm, " ");
- // get rid of all commas
- d = d.replace(/([MmZzLlHhVvCcSsQqTtAa])([MmZzLlHhVvCcSsQqTtAa])/gm, "$1 $2");
- // separate commands from commands
- d = d.replace(/([MmZzLlHhVvCcSsQqTtAa])([MmZzLlHhVvCcSsQqTtAa])/gm, "$1 $2");
- // separate commands from commands
- d = d.replace(/([MmZzLlHhVvCcSsQqTtAa])([^\s])/gm, "$1 $2");
- // separate commands from points
- d = d.replace(/([^\s])([MmZzLlHhVvCcSsQqTtAa])/gm, "$1 $2");
- // separate commands from points
- d = d.replace(/([0-9])([+\-])/gm, "$1 $2");
- // separate digits when no comma
- d = d.replace(/(\.[0-9]*)(\.)/gm, "$1 $2");
- // separate digits when no comma
- d = d.replace(/([Aa](\s+[0-9]+){3})\s+([01])\s*([01])/gm, "$1 $3 $4 ");
- // shorthand elliptical arc path syntax
- d = svg.compressSpaces(d);
- // compress multiple spaces
- d = svg.trim(d);
- this.PathParser = new function(d) {
- this.tokens = d.split(" ");
- this.reset = function() {
- this.i = -1;
- this.command = "";
- this.previousCommand = "";
- this.start = new svg.Point(0, 0);
- this.control = new svg.Point(0, 0);
- this.current = new svg.Point(0, 0);
- this.points = [];
- this.angles = [];
- };
- this.isEnd = function() {
- return this.i >= this.tokens.length - 1;
- };
- this.isCommandOrEnd = function() {
- if (this.isEnd()) return true;
- return this.tokens[this.i + 1].match(/^[A-Za-z]$/) != null;
- };
- this.isRelativeCommand = function() {
- switch (this.command) {
- case "m":
- case "l":
- case "h":
- case "v":
- case "c":
- case "s":
- case "q":
- case "t":
- case "a":
- case "z":
- return true;
- break;
- }
- return false;
- };
- this.getToken = function() {
- this.i++;
- return this.tokens[this.i];
- };
- this.getScalar = function() {
- return parseFloat(this.getToken());
- };
- this.nextCommand = function() {
- this.previousCommand = this.command;
- this.command = this.getToken();
- };
- this.getPoint = function() {
- var p = new svg.Point(this.getScalar(), this.getScalar());
- return this.makeAbsolute(p);
- };
- this.getAsControlPoint = function() {
- var p = this.getPoint();
- this.control = p;
- return p;
- };
- this.getAsCurrentPoint = function() {
- var p = this.getPoint();
- this.current = p;
- return p;
- };
- this.getReflectedControlPoint = function() {
- if (this.previousCommand.toLowerCase() != "c" && this.previousCommand.toLowerCase() != "s" && this.previousCommand.toLowerCase() != "q" && this.previousCommand.toLowerCase() != "t") {
- return this.current;
- }
- // reflect point
- var p = new svg.Point(2 * this.current.x - this.control.x, 2 * this.current.y - this.control.y);
- return p;
- };
- this.makeAbsolute = function(p) {
- if (this.isRelativeCommand()) {
- p.x += this.current.x;
- p.y += this.current.y;
- }
- return p;
- };
- this.addMarker = function(p, from, priorTo) {
- // if the last angle isn't filled in because we didn't have this point yet ...
- if (priorTo != null && this.angles.length > 0 && this.angles[this.angles.length - 1] == null) {
- this.angles[this.angles.length - 1] = this.points[this.points.length - 1].angleTo(priorTo);
- }
- this.addMarkerAngle(p, from == null ? null : from.angleTo(p));
- };
- this.addMarkerAngle = function(p, a) {
- this.points.push(p);
- this.angles.push(a);
- };
- this.getMarkerPoints = function() {
- return this.points;
- };
- this.getMarkerAngles = function() {
- for (var i = 0; i < this.angles.length; i++) {
- if (this.angles[i] == null) {
- for (var j = i + 1; j < this.angles.length; j++) {
- if (this.angles[j] != null) {
- this.angles[i] = this.angles[j];
- break;
- }
- }
- }
- }
- return this.angles;
- };
- }(d);
- this.path = function(ctx) {
- var pp = this.PathParser;
- pp.reset();
- var bb = new svg.BoundingBox();
- if (ctx != null) ctx.beginPath();
- while (!pp.isEnd()) {
- pp.nextCommand();
- switch (pp.command) {
- case "M":
- case "m":
- var p = pp.getAsCurrentPoint();
- pp.addMarker(p);
- bb.addPoint(p.x, p.y);
- if (ctx != null) ctx.moveTo(p.x, p.y);
- pp.start = pp.current;
- while (!pp.isCommandOrEnd()) {
- var p = pp.getAsCurrentPoint();
- pp.addMarker(p, pp.start);
- bb.addPoint(p.x, p.y);
- if (ctx != null) ctx.lineTo(p.x, p.y);
- }
- break;
- case "L":
- case "l":
- while (!pp.isCommandOrEnd()) {
- var c = pp.current;
- var p = pp.getAsCurrentPoint();
- pp.addMarker(p, c);
- bb.addPoint(p.x, p.y);
- if (ctx != null) ctx.lineTo(p.x, p.y);
- }
- break;
- case "H":
- case "h":
- while (!pp.isCommandOrEnd()) {
- var newP = new svg.Point((pp.isRelativeCommand() ? pp.current.x : 0) + pp.getScalar(), pp.current.y);
- pp.addMarker(newP, pp.current);
- pp.current = newP;
- bb.addPoint(pp.current.x, pp.current.y);
- if (ctx != null) ctx.lineTo(pp.current.x, pp.current.y);
- }
- break;
- case "V":
- case "v":
- while (!pp.isCommandOrEnd()) {
- var newP = new svg.Point(pp.current.x, (pp.isRelativeCommand() ? pp.current.y : 0) + pp.getScalar());
- pp.addMarker(newP, pp.current);
- pp.current = newP;
- bb.addPoint(pp.current.x, pp.current.y);
- if (ctx != null) ctx.lineTo(pp.current.x, pp.current.y);
- }
- break;
- case "C":
- case "c":
- while (!pp.isCommandOrEnd()) {
- var curr = pp.current;
- var p1 = pp.getPoint();
- var cntrl = pp.getAsControlPoint();
- var cp = pp.getAsCurrentPoint();
- pp.addMarker(cp, cntrl, p1);
- bb.addBezierCurve(curr.x, curr.y, p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
- if (ctx != null) ctx.bezierCurveTo(p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
- }
- break;
- case "S":
- case "s":
- while (!pp.isCommandOrEnd()) {
- var curr = pp.current;
- var p1 = pp.getReflectedControlPoint();
- var cntrl = pp.getAsControlPoint();
- var cp = pp.getAsCurrentPoint();
- pp.addMarker(cp, cntrl, p1);
- bb.addBezierCurve(curr.x, curr.y, p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
- if (ctx != null) ctx.bezierCurveTo(p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
- }
- break;
- case "Q":
- case "q":
- while (!pp.isCommandOrEnd()) {
- var curr = pp.current;
- var cntrl = pp.getAsControlPoint();
- var cp = pp.getAsCurrentPoint();
- pp.addMarker(cp, cntrl, cntrl);
- bb.addQuadraticCurve(curr.x, curr.y, cntrl.x, cntrl.y, cp.x, cp.y);
- if (ctx != null) ctx.quadraticCurveTo(cntrl.x, cntrl.y, cp.x, cp.y);
- }
- break;
- case "T":
- case "t":
- while (!pp.isCommandOrEnd()) {
- var curr = pp.current;
- var cntrl = pp.getReflectedControlPoint();
- pp.control = cntrl;
- var cp = pp.getAsCurrentPoint();
- pp.addMarker(cp, cntrl, cntrl);
- bb.addQuadraticCurve(curr.x, curr.y, cntrl.x, cntrl.y, cp.x, cp.y);
- if (ctx != null) ctx.quadraticCurveTo(cntrl.x, cntrl.y, cp.x, cp.y);
- }
- break;
- case "A":
- case "a":
- while (!pp.isCommandOrEnd()) {
- var curr = pp.current;
- var rx = pp.getScalar();
- var ry = pp.getScalar();
- var xAxisRotation = pp.getScalar() * (Math.PI / 180);
- var largeArcFlag = pp.getScalar();
- var sweepFlag = pp.getScalar();
- var cp = pp.getAsCurrentPoint();
- // Conversion from endpoint to center parameterization
- // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
- // x1', y1'
- var currp = new svg.Point(Math.cos(xAxisRotation) * (curr.x - cp.x) / 2 + Math.sin(xAxisRotation) * (curr.y - cp.y) / 2, -Math.sin(xAxisRotation) * (curr.x - cp.x) / 2 + Math.cos(xAxisRotation) * (curr.y - cp.y) / 2);
- // adjust radii
- var l = Math.pow(currp.x, 2) / Math.pow(rx, 2) + Math.pow(currp.y, 2) / Math.pow(ry, 2);
- if (l > 1) {
- rx *= Math.sqrt(l);
- ry *= Math.sqrt(l);
- }
- // cx', cy'
- var s = (largeArcFlag == sweepFlag ? -1 : 1) * Math.sqrt((Math.pow(rx, 2) * Math.pow(ry, 2) - Math.pow(rx, 2) * Math.pow(currp.y, 2) - Math.pow(ry, 2) * Math.pow(currp.x, 2)) / (Math.pow(rx, 2) * Math.pow(currp.y, 2) + Math.pow(ry, 2) * Math.pow(currp.x, 2)));
- if (isNaN(s)) s = 0;
- var cpp = new svg.Point(s * rx * currp.y / ry, s * -ry * currp.x / rx);
- // cx, cy
- var centp = new svg.Point((curr.x + cp.x) / 2 + Math.cos(xAxisRotation) * cpp.x - Math.sin(xAxisRotation) * cpp.y, (curr.y + cp.y) / 2 + Math.sin(xAxisRotation) * cpp.x + Math.cos(xAxisRotation) * cpp.y);
- // vector magnitude
- var m = function(v) {
- return Math.sqrt(Math.pow(v[0], 2) + Math.pow(v[1], 2));
- };
- // ratio between two vectors
- var r = function(u, v) {
- return (u[0] * v[0] + u[1] * v[1]) / (m(u) * m(v));
- };
- // angle between two vectors
- var a = function(u, v) {
- return (u[0] * v[1] < u[1] * v[0] ? -1 : 1) * Math.acos(r(u, v));
- };
- // initial angle
- var a1 = a([ 1, 0 ], [ (currp.x - cpp.x) / rx, (currp.y - cpp.y) / ry ]);
- // angle delta
- var u = [ (currp.x - cpp.x) / rx, (currp.y - cpp.y) / ry ];
- var v = [ (-currp.x - cpp.x) / rx, (-currp.y - cpp.y) / ry ];
- var ad = a(u, v);
- if (r(u, v) <= -1) ad = Math.PI;
- if (r(u, v) >= 1) ad = 0;
- // for markers
- var dir = 1 - sweepFlag ? 1 : -1;
- var ah = a1 + dir * (ad / 2);
- var halfWay = new svg.Point(centp.x + rx * Math.cos(ah), centp.y + ry * Math.sin(ah));
- pp.addMarkerAngle(halfWay, ah - dir * Math.PI / 2);
- pp.addMarkerAngle(cp, ah - dir * Math.PI);
- bb.addPoint(cp.x, cp.y);
- // TODO: this is too naive, make it better
- if (ctx != null) {
- var r = rx > ry ? rx : ry;
- var sx = rx > ry ? 1 : rx / ry;
- var sy = rx > ry ? ry / rx : 1;
- ctx.translate(centp.x, centp.y);
- ctx.rotate(xAxisRotation);
- ctx.scale(sx, sy);
- ctx.arc(0, 0, r, a1, a1 + ad, 1 - sweepFlag);
- ctx.scale(1 / sx, 1 / sy);
- ctx.rotate(-xAxisRotation);
- ctx.translate(-centp.x, -centp.y);
- }
- }
- break;
- case "Z":
- case "z":
- if (ctx != null) ctx.closePath();
- pp.current = pp.start;
- }
- }
- return bb;
- };
- this.getMarkers = function() {
- var points = this.PathParser.getMarkerPoints();
- var angles = this.PathParser.getMarkerAngles();
- var markers = [];
- for (var i = 0; i < points.length; i++) {
- markers.push([ points[i], angles[i] ]);
- }
- return markers;
- };
- };
- svg.Element.path.prototype = new svg.Element.PathElementBase();
- // pattern element
- svg.Element.pattern = function(node) {
- this.base = svg.Element.ElementBase;
- this.base(node);
- this.createPattern = function(ctx, element) {
- var width = this.attribute("width").toPixels("x", true);
- var height = this.attribute("height").toPixels("y", true);
- // render me using a temporary svg element
- var tempSvg = new svg.Element.svg();
- tempSvg.attributes["viewBox"] = new svg.Property("viewBox", this.attribute("viewBox").value);
- tempSvg.attributes["width"] = new svg.Property("width", width + "px");
- tempSvg.attributes["height"] = new svg.Property("height", height + "px");
- tempSvg.attributes["transform"] = new svg.Property("transform", this.attribute("patternTransform").value);
- tempSvg.children = this.children;
- var c = document.createElement("canvas");
- c.width = width;
- c.height = height;
- var cctx = c.getContext("2d");
- if (this.attribute("x").hasValue() && this.attribute("y").hasValue()) {
- cctx.translate(this.attribute("x").toPixels("x", true), this.attribute("y").toPixels("y", true));
- }
- // render 3x3 grid so when we transform there's no white space on edges
- for (var x = -1; x <= 1; x++) {
- for (var y = -1; y <= 1; y++) {
- cctx.save();
- cctx.translate(x * c.width, y * c.height);
- tempSvg.render(cctx);
- cctx.restore();
- }
- }
- var pattern = ctx.createPattern(c, "repeat");
- return pattern;
- };
- };
- svg.Element.pattern.prototype = new svg.Element.ElementBase();
- // marker element
- svg.Element.marker = function(node) {
- this.base = svg.Element.ElementBase;
- this.base(node);
- this.baseRender = this.render;
- this.render = function(ctx, point, angle) {
- ctx.translate(point.x, point.y);
- if (this.attribute("orient").valueOrDefault("auto") == "auto") ctx.rotate(angle);
- if (this.attribute("markerUnits").valueOrDefault("strokeWidth") == "strokeWidth") ctx.scale(ctx.lineWidth, ctx.lineWidth);
- ctx.save();
- // render me using a temporary svg element
- var tempSvg = new svg.Element.svg();
- tempSvg.attributes["viewBox"] = new svg.Property("viewBox", this.attribute("viewBox").value);
- tempSvg.attributes["refX"] = new svg.Property("refX", this.attribute("refX").value);
- tempSvg.attributes["refY"] = new svg.Property("refY", this.attribute("refY").value);
- tempSvg.attributes["width"] = new svg.Property("width", this.attribute("markerWidth").value);
- tempSvg.attributes["height"] = new svg.Property("height", this.attribute("markerHeight").value);
- tempSvg.attributes["fill"] = new svg.Property("fill", this.attribute("fill").valueOrDefault("black"));
- tempSvg.attributes["stroke"] = new svg.Property("stroke", this.attribute("stroke").valueOrDefault("none"));
- tempSvg.children = this.children;
- tempSvg.render(ctx);
- ctx.restore();
- if (this.attribute("markerUnits").valueOrDefault("strokeWidth") == "strokeWidth") ctx.scale(1 / ctx.lineWidth, 1 / ctx.lineWidth);
- if (this.attribute("orient").valueOrDefault("auto") == "auto") ctx.rotate(-angle);
- ctx.translate(-point.x, -point.y);
- };
- };
- svg.Element.marker.prototype = new svg.Element.ElementBase();
- // definitions element
- svg.Element.defs = function(node) {
- this.base = svg.Element.ElementBase;
- this.base(node);
- this.render = function(ctx) {};
- };
- svg.Element.defs.prototype = new svg.Element.ElementBase();
- // base for gradients
- svg.Element.GradientBase = function(node) {
- this.base = svg.Element.ElementBase;
- this.base(node);
- this.gradientUnits = this.attribute("gradientUnits").valueOrDefault("objectBoundingBox");
- this.stops = [];
- for (var i = 0; i < this.children.length; i++) {
- var child = this.children[i];
- if (child.type == "stop") this.stops.push(child);
- }
- this.getGradient = function() {};
- this.createGradient = function(ctx, element, parentOpacityProp) {
- var stopsContainer = this;
- if (this.getHrefAttribute().hasValue()) {
- stopsContainer = this.getHrefAttribute().getDefinition();
- }
- var addParentOpacity = function(color) {
- if (parentOpacityProp.hasValue()) {
- var p = new svg.Property("color", color);
- return p.addOpacity(parentOpacityProp.value).value;
- }
- return color;
- };
- var g = this.getGradient(ctx, element);
- if (g == null) return addParentOpacity(stopsContainer.stops[stopsContainer.stops.length - 1].color);
- for (var i = 0; i < stopsContainer.stops.length; i++) {
- g.addColorStop(stopsContainer.stops[i].offset, addParentOpacity(stopsContainer.stops[i].color));
- }
- if (this.attribute("gradientTransform").hasValue()) {
- // render as transformed pattern on temporary canvas
- var rootView = svg.ViewPort.viewPorts[0];
- var rect = new svg.Element.rect();
- rect.attributes["x"] = new svg.Property("x", -svg.MAX_VIRTUAL_PIXELS / 3);
- rect.attributes["y"] = new svg.Property("y", -svg.MAX_VIRTUAL_PIXELS / 3);
- rect.attributes["width"] = new svg.Property("width", svg.MAX_VIRTUAL_PIXELS);
- rect.attributes["height"] = new svg.Property("height", svg.MAX_VIRTUAL_PIXELS);
- var group = new svg.Element.g();
- group.attributes["transform"] = new svg.Property("transform", this.attribute("gradientTransform").value);
- group.children = [ rect ];
- var tempSvg = new svg.Element.svg();
- tempSvg.attributes["x"] = new svg.Property("x", 0);
- tempSvg.attributes["y"] = new svg.Property("y", 0);
- tempSvg.attributes["width"] = new svg.Property("width", rootView.width);
- tempSvg.attributes["height"] = new svg.Property("height", rootView.height);
- tempSvg.children = [ group ];
- var c = document.createElement("canvas");
- c.width = rootView.width;
- c.height = rootView.height;
- var tempCtx = c.getContext("2d");
- tempCtx.fillStyle = g;
- tempSvg.render(tempCtx);
- return tempCtx.createPattern(c, "no-repeat");
- }
- return g;
- };
- };
- svg.Element.GradientBase.prototype = new svg.Element.ElementBase();
- // linear gradient element
- svg.Element.linearGradient = function(node) {
- this.base = svg.Element.GradientBase;
- this.base(node);
- this.getGradient = function(ctx, element) {
- var bb = element.getBoundingBox();
- if (!this.attribute("x1").hasValue() && !this.attribute("y1").hasValue() && !this.attribute("x2").hasValue() && !this.attribute("y2").hasValue()) {
- this.attribute("x1", true).value = 0;
- this.attribute("y1", true).value = 0;
- this.attribute("x2", true).value = 1;
- this.attribute("y2", true).value = 0;
- }
- var x1 = this.gradientUnits == "objectBoundingBox" ? bb.x() + bb.width() * this.attribute("x1").numValue() : this.attribute("x1").toPixels("x");
- var y1 = this.gradientUnits == "objectBoundingBox" ? bb.y() + bb.height() * this.attribute("y1").numValue() : this.attribute("y1").toPixels("y");
- var x2 = this.gradientUnits == "objectBoundingBox" ? bb.x() + bb.width() * this.attribute("x2").numValue() : this.attribute("x2").toPixels("x");
- var y2 = this.gradientUnits == "objectBoundingBox" ? bb.y() + bb.height() * this.attribute("y2").numValue() : this.attribute("y2").toPixels("y");
- if (x1 == x2 && y1 == y2) return null;
- return ctx.createLinearGradient(x1, y1, x2, y2);
- };
- };
- svg.Element.linearGradient.prototype = new svg.Element.GradientBase();
- // radial gradient element
- svg.Element.radialGradient = function(node) {
- this.base = svg.Element.GradientBase;
- this.base(node);
- this.getGradient = function(ctx, element) {
- var bb = element.getBoundingBox();
- if (!this.attribute("cx").hasValue()) this.attribute("cx", true).value = "50%";
- if (!this.attribute("cy").hasValue()) this.attribute("cy", true).value = "50%";
- if (!this.attribute("r").hasValue()) this.attribute("r", true).value = "50%";
- var cx = this.gradientUnits == "objectBoundingBox" ? bb.x() + bb.width() * this.attribute("cx").numValue() : this.attribute("cx").toPixels("x");
- var cy = this.gradientUnits == "objectBoundingBox" ? bb.y() + bb.height() * this.attribute("cy").numValue() : this.attribute("cy").toPixels("y");
- var fx = cx;
- var fy = cy;
- if (this.attribute("fx").hasValue()) {
- fx = this.gradientUnits == "objectBoundingBox" ? bb.x() + bb.width() * this.attribute("fx").numValue() : this.attribute("fx").toPixels("x");
- }
- if (this.attribute("fy").hasValue()) {
- fy = this.gradientUnits == "objectBoundingBox" ? bb.y() + bb.height() * this.attribute("fy").numValue() : this.attribute("fy").toPixels("y");
- }
- var r = this.gradientUnits == "objectBoundingBox" ? (bb.width() + bb.height()) / 2 * this.attribute("r").numValue() : this.attribute("r").toPixels();
- return ctx.createRadialGradient(fx, fy, 0, cx, cy, r);
- };
- };
- svg.Element.radialGradient.prototype = new svg.Element.GradientBase();
- // gradient stop element
- svg.Element.stop = function(node) {
- this.base = svg.Element.ElementBase;
- this.base(node);
- this.offset = this.attribute("offset").numValue();
- if (this.offset < 0) this.offset = 0;
- if (this.offset > 1) this.offset = 1;
- var stopColor = this.style("stop-color");
- if (this.style("stop-opacity").hasValue()) stopColor = stopColor.addOpacity(this.style("stop-opacity").value);
- this.color = stopColor.value;
- };
- svg.Element.stop.prototype = new svg.Element.ElementBase();
- // animation base element
- svg.Element.AnimateBase = function(node) {
- this.base = svg.Element.ElementBase;
- this.base(node);
- svg.Animations.push(this);
- this.duration = 0;
- this.begin = this.attribute("begin").toMilliseconds();
- this.maxDuration = this.begin + this.attribute("dur").toMilliseconds();
- this.getProperty = function() {
- var attributeType = this.attribute("attributeType").value;
- var attributeName = this.attribute("attributeName").value;
- if (attributeType == "CSS") {
- return this.parent.style(attributeName, true);
- }
- return this.parent.attribute(attributeName, true);
- };
- this.initialValue = null;
- this.initialUnits = "";
- this.removed = false;
- this.calcValue = function() {
- // OVERRIDE ME!
- return "";
- };
- this.update = function(delta) {
- // set initial value
- if (this.initialValue == null) {
- this.initialValue = this.getProperty().value;
- this.initialUnits = this.getProperty().getUnits();
- }
- // if we're past the end time
- if (this.duration > this.maxDuration) {
- // loop for indefinitely repeating animations
- if (this.attribute("repeatCount").value == "indefinite" || this.attribute("repeatDur").value == "indefinite") {
- this.duration = 0;
- } else if (this.attribute("fill").valueOrDefault("remove") == "remove" && !this.removed) {
- this.removed = true;
- this.getProperty().value = this.initialValue;
- return true;
- } else {
- return false;
- }
- }
- this.duration = this.duration + delta;
- // if we're past the begin time
- var updated = false;
- if (this.begin < this.duration) {
- var newValue = this.calcValue();
- // tween
- if (this.attribute("type").hasValue()) {
- // for transform, etc.
- var type = this.attribute("type").value;
- newValue = type + "(" + newValue + ")";
- }
- this.getProperty().value = newValue;
- updated = true;
- }
- return updated;
- };
- this.from = this.attribute("from");
- this.to = this.attribute("to");
- this.values = this.attribute("values");
- if (this.values.hasValue()) this.values.value = this.values.value.split(";");
- // fraction of duration we've covered
- this.progress = function() {
- var ret = {
- progress: (this.duration - this.begin) / (this.maxDuration - this.begin)
- };
- if (this.values.hasValue()) {
- var p = ret.progress * (this.values.value.length - 1);
- var lb = Math.floor(p), ub = Math.ceil(p);
- ret.from = new svg.Property("from", parseFloat(this.values.value[lb]));
- ret.to = new svg.Property("to", parseFloat(this.values.value[ub]));
- ret.progress = (p - lb) / (ub - lb);
- } else {
- ret.from = this.from;
- ret.to = this.to;
- }
- return ret;
- };
- };
- svg.Element.AnimateBase.prototype = new svg.Element.ElementBase();
- // animate element
- svg.Element.animate = function(node) {
- this.base = svg.Element.AnimateBase;
- this.base(node);
- this.calcValue = function() {
- var p = this.progress();
- // tween value linearly
- var newValue = p.from.numValue() + (p.to.numValue() - p.from.numValue()) * p.progress;
- return newValue + this.initialUnits;
- };
- };
- svg.Element.animate.prototype = new svg.Element.AnimateBase();
- // animate color element
- svg.Element.animateColor = function(node) {
- this.base = svg.Element.AnimateBase;
- this.base(node);
- this.calcValue = function() {
- var p = this.progress();
- var from = new RGBColor(p.from.value);
- var to = new RGBColor(p.to.value);
- if (from.ok && to.ok) {
- // tween color linearly
- var r = from.r + (to.r - from.r) * p.progress;
- var g = from.g + (to.g - from.g) * p.progress;
- var b = from.b + (to.b - from.b) * p.progress;
- return "rgb(" + parseInt(r, 10) + "," + parseInt(g, 10) + "," + parseInt(b, 10) + ")";
- }
- return this.attribute("from").value;
- };
- };
- svg.Element.animateColor.prototype = new svg.Element.AnimateBase();
- // animate transform element
- svg.Element.animateTransform = function(node) {
- this.base = svg.Element.AnimateBase;
- this.base(node);
- this.calcValue = function() {
- var p = this.progress();
- // tween value linearly
- var from = svg.ToNumberArray(p.from.value);
- var to = svg.ToNumberArray(p.to.value);
- var newValue = "";
- for (var i = 0; i < from.length; i++) {
- newValue += from[i] + (to[i] - from[i]) * p.progress + " ";
- }
- return newValue;
- };
- };
- svg.Element.animateTransform.prototype = new svg.Element.animate();
- // font element
- svg.Element.font = function(node) {
- this.base = svg.Element.ElementBase;
- this.base(node);
- this.horizAdvX = this.attribute("horiz-adv-x").numValue();
- this.isRTL = false;
- this.isArabic = false;
- this.fontFace = null;
- this.missingGlyph = null;
- this.glyphs = [];
- for (var i = 0; i < this.children.length; i++) {
- var child = this.children[i];
- if (child.type == "font-face") {
- this.fontFace = child;
- if (child.style("font-family").hasValue()) {
- svg.Definitions[child.style("font-family").value] = this;
- }
- } else if (child.type == "missing-glyph") this.missingGlyph = child; else if (child.type == "glyph") {
- if (child.arabicForm != "") {
- this.isRTL = true;
- this.isArabic = true;
- if (typeof this.glyphs[child.unicode] == "undefined") this.glyphs[child.unicode] = [];
- this.glyphs[child.unicode][child.arabicForm] = child;
- } else {
- this.glyphs[child.unicode] = child;
- }
- }
- }
- };
- svg.Element.font.prototype = new svg.Element.ElementBase();
- // font-face element
- svg.Element.fontface = function(node) {
- this.base = svg.Element.ElementBase;
- this.base(node);
- this.ascent = this.attribute("ascent").value;
- this.descent = this.attribute("descent").value;
- this.unitsPerEm = this.attribute("units-per-em").numValue();
- };
- svg.Element.fontface.prototype = new svg.Element.ElementBase();
- // missing-glyph element
- svg.Element.missingglyph = function(node) {
- this.base = svg.Element.path;
- this.base(node);
- this.horizAdvX = 0;
- };
- svg.Element.missingglyph.prototype = new svg.Element.path();
- // glyph element
- svg.Element.glyph = function(node) {
- this.base = svg.Element.path;
- this.base(node);
- this.horizAdvX = this.attribute("horiz-adv-x").numValue();
- this.unicode = this.attribute("unicode").value;
- this.arabicForm = this.attribute("arabic-form").value;
- };
- svg.Element.glyph.prototype = new svg.Element.path();
- // text element
- svg.Element.text = function(node) {
- this.captureTextNodes = true;
- this.base = svg.Element.RenderedElementBase;
- this.base(node);
- this.baseSetContext = this.setContext;
- this.setContext = function(ctx) {
- this.baseSetContext(ctx);
- if (this.style("dominant-baseline").hasValue()) ctx.textBaseline = this.style("dominant-baseline").value;
- if (this.style("alignment-baseline").hasValue()) ctx.textBaseline = this.style("alignment-baseline").value;
- };
- this.getBoundingBox = function() {
- // TODO: implement
- return new svg.BoundingBox(this.attribute("x").toPixels("x"), this.attribute("y").toPixels("y"), 0, 0);
- };
- this.renderChildren = function(ctx) {
- this.x = this.attribute("x").toPixels("x");
- this.y = this.attribute("y").toPixels("y");
- this.x += this.getAnchorDelta(ctx, this, 0);
- for (var i = 0; i < this.children.length; i++) {
- this.renderChild(ctx, this, i);
- }
- };
- this.getAnchorDelta = function(ctx, parent, startI) {
- var textAnchor = this.style("text-anchor").valueOrDefault("start");
- if (textAnchor != "start") {
- var width = 0;
- for (var i = startI; i < parent.children.length; i++) {
- var child = parent.children[i];
- if (i > startI && child.attribute("x").hasValue()) break;
- // new group
- width += child.measureTextRecursive(ctx);
- }
- return -1 * (textAnchor == "end" ? width : width / 2);
- }
- return 0;
- };
- this.renderChild = function(ctx, parent, i) {
- var child = parent.children[i];
- if (child.attribute("x").hasValue()) {
- child.x = child.attribute("x").toPixels("x") + this.getAnchorDelta(ctx, parent, i);
- } else {
- if (this.attribute("dx").hasValue()) this.x += this.attribute("dx").toPixels("x");
- if (child.attribute("dx").hasValue()) this.x += child.attribute("dx").toPixels("x");
- child.x = this.x;
- }
- this.x = child.x + child.measureText(ctx);
- if (child.attribute("y").hasValue()) {
- child.y = child.attribute("y").toPixels("y");
- } else {
- if (this.attribute("dy").hasValue()) this.y += this.attribute("dy").toPixels("y");
- if (child.attribute("dy").hasValue()) this.y += child.attribute("dy").toPixels("y");
- child.y = this.y;
- }
- this.y = child.y;
- child.render(ctx);
- for (var i = 0; i < child.children.length; i++) {
- this.renderChild(ctx, child, i);
- }
- };
- };
- svg.Element.text.prototype = new svg.Element.RenderedElementBase();
- // text base
- svg.Element.TextElementBase = function(node) {
- this.base = svg.Element.RenderedElementBase;
- this.base(node);
- this.getGlyph = function(font, text, i) {
- var c = text[i];
- var glyph = null;
- if (font.isArabic) {
- var arabicForm = "isolated";
- if ((i == 0 || text[i - 1] == " ") && i < text.length - 2 && text[i + 1] != " ") arabicForm = "terminal";
- if (i > 0 && text[i - 1] != " " && i < text.length - 2 && text[i + 1] != " ") arabicForm = "medial";
- if (i > 0 && text[i - 1] != " " && (i == text.length - 1 || text[i + 1] == " ")) arabicForm = "initial";
- if (typeof font.glyphs[c] != "undefined") {
- glyph = font.glyphs[c][arabicForm];
- if (glyph == null && font.glyphs[c].type == "glyph") glyph = font.glyphs[c];
- }
- } else {
- glyph = font.glyphs[c];
- }
- if (glyph == null) glyph = font.missingGlyph;
- return glyph;
- };
- this.renderChildren = function(ctx) {
- var customFont = this.parent.style("font-family").getDefinition();
- if (customFont != null) {
- var fontSize = this.parent.style("font-size").numValueOrDefault(svg.Font.Parse(svg.ctx.font).fontSize);
- var fontStyle = this.parent.style("font-style").valueOrDefault(svg.Font.Parse(svg.ctx.font).fontStyle);
- var text = this.getText();
- if (customFont.isRTL) text = text.split("").reverse().join("");
- var dx = svg.ToNumberArray(this.parent.attribute("dx").value);
- for (var i = 0; i < text.length; i++) {
- var glyph = this.getGlyph(customFont, text, i);
- var scale = fontSize / customFont.fontFace.unitsPerEm;
- ctx.translate(this.x, this.y);
- ctx.scale(scale, -scale);
- var lw = ctx.lineWidth;
- ctx.lineWidth = ctx.lineWidth * customFont.fontFace.unitsPerEm / fontSize;
- if (fontStyle == "italic") ctx.transform(1, 0, .4, 1, 0, 0);
- glyph.render(ctx);
- if (fontStyle == "italic") ctx.transform(1, 0, -.4, 1, 0, 0);
- ctx.lineWidth = lw;
- ctx.scale(1 / scale, -1 / scale);
- ctx.translate(-this.x, -this.y);
- this.x += fontSize * (glyph.horizAdvX || customFont.horizAdvX) / customFont.fontFace.unitsPerEm;
- if (typeof dx[i] != "undefined" && !isNaN(dx[i])) {
- this.x += dx[i];
- }
- }
- return;
- }
- if (ctx.fillStyle != "") ctx.fillText(svg.compressSpaces(this.getText()), this.x, this.y);
- if (ctx.strokeStyle != "") ctx.strokeText(svg.compressSpaces(this.getText()), this.x, this.y);
- };
- this.getText = function() {};
- this.measureTextRecursive = function(ctx) {
- var width = this.measureText(ctx);
- for (var i = 0; i < this.children.length; i++) {
- width += this.children[i].measureTextRecursive(ctx);
- }
- return width;
- };
- this.measureText = function(ctx) {
- var customFont = this.parent.style("font-family").getDefinition();
- if (customFont != null) {
- var fontSize = this.parent.style("font-size").numValueOrDefault(svg.Font.Parse(svg.ctx.font).fontSize);
- var measure = 0;
- var text = this.getText();
- if (customFont.isRTL) text = text.split("").reverse().join("");
- var dx = svg.ToNumberArray(this.parent.attribute("dx").value);
- for (var i = 0; i < text.length; i++) {
- var glyph = this.getGlyph(customFont, text, i);
- measure += (glyph.horizAdvX || customFont.horizAdvX) * fontSize / customFont.fontFace.unitsPerEm;
- if (typeof dx[i] != "undefined" && !isNaN(dx[i])) {
- measure += dx[i];
- }
- }
- return measure;
- }
- var textToMeasure = svg.compressSpaces(this.getText());
- if (!ctx.measureText) return textToMeasure.length * 10;
- ctx.save();
- this.setContext(ctx);
- var width = ctx.measureText(textToMeasure).width;
- ctx.restore();
- return width;
- };
- };
- svg.Element.TextElementBase.prototype = new svg.Element.RenderedElementBase();
- // tspan
- svg.Element.tspan = function(node) {
- this.captureTextNodes = true;
- this.base = svg.Element.TextElementBase;
- this.base(node);
- this.text = node.nodeValue || node.text || "";
- this.getText = function() {
- return this.text;
- };
- };
- svg.Element.tspan.prototype = new svg.Element.TextElementBase();
- // tref
- svg.Element.tref = function(node) {
- this.base = svg.Element.TextElementBase;
- this.base(node);
- this.getText = function() {
- var element = this.getHrefAttribute().getDefinition();
- if (element != null) return element.children[0].getText();
- };
- };
- svg.Element.tref.prototype = new svg.Element.TextElementBase();
- // a element
- svg.Element.a = function(node) {
- this.base = svg.Element.TextElementBase;
- this.base(node);
- this.hasText = true;
- for (var i = 0; i < node.childNodes.length; i++) {
- if (node.childNodes[i].nodeType != 3) this.hasText = false;
- }
- // this might contain text
- this.text = this.hasText ? node.childNodes[0].nodeValue : "";
- this.getText = function() {
- return this.text;
- };
- this.baseRenderChildren = this.renderChildren;
- this.renderChildren = function(ctx) {
- if (this.hasText) {
- // render as text element
- this.baseRenderChildren(ctx);
- var fontSize = new svg.Property("fontSize", svg.Font.Parse(svg.ctx.font).fontSize);
- svg.Mouse.checkBoundingBox(this, new svg.BoundingBox(this.x, this.y - fontSize.toPixels("y"), this.x + this.measureText(ctx), this.y));
- } else {
- // render as temporary group
- var g = new svg.Element.g();
- g.children = this.children;
- g.parent = this;
- g.render(ctx);
- }
- };
- this.onclick = function() {
- window.open(this.getHrefAttribute().value);
- };
- this.onmousemove = function() {
- svg.ctx.canvas.style.cursor = "pointer";
- };
- };
- svg.Element.a.prototype = new svg.Element.TextElementBase();
- // image element
- svg.Element.image = function(node) {
- this.base = svg.Element.RenderedElementBase;
- this.base(node);
- var href = this.getHrefAttribute().value;
- var isSvg = href.match(/\.svg$/);
- svg.Images.push(this);
- this.loaded = false;
- if (!isSvg) {
- this.img = document.createElement("img");
- var self = this;
- this.img.onload = function() {
- self.loaded = true;
- };
- this.img.onerror = function() {
- if (typeof console != "undefined") {
- console.log('ERROR: image "' + href + '" not found');
- self.loaded = true;
- }
- };
- this.img.src = href;
- } else {
- this.img = svg.ajax(href);
- this.loaded = true;
- }
- this.renderChildren = function(ctx) {
- var x = this.attribute("x").toPixels("x");
- var y = this.attribute("y").toPixels("y");
- var width = this.attribute("width").toPixels("x");
- var height = this.attribute("height").toPixels("y");
- if (width == 0 || height == 0) return;
- ctx.save();
- if (isSvg) {
- ctx.drawSvg(this.img, x, y, width, height);
- } else {
- ctx.translate(x, y);
- svg.AspectRatio(ctx, this.attribute("preserveAspectRatio").value, width, this.img.width, height, this.img.height, 0, 0);
- ctx.drawImage(this.img, 0, 0);
- }
- ctx.restore();
- };
- this.getBoundingBox = function() {
- var x = this.attribute("x").toPixels("x");
- var y = this.attribute("y").toPixels("y");
- var width = this.attribute("width").toPixels("x");
- var height = this.attribute("height").toPixels("y");
- return new svg.BoundingBox(x, y, x + width, y + height);
- };
- };
- svg.Element.image.prototype = new svg.Element.RenderedElementBase();
- // group element
- svg.Element.g = function(node) {
- this.base = svg.Element.RenderedElementBase;
- this.base(node);
- this.getBoundingBox = function() {
- var bb = new svg.BoundingBox();
- for (var i = 0; i < this.children.length; i++) {
- bb.addBoundingBox(this.children[i].getBoundingBox());
- }
- return bb;
- };
- };
- svg.Element.g.prototype = new svg.Element.RenderedElementBase();
- // symbol element
- svg.Element.symbol = function(node) {
- this.base = svg.Element.RenderedElementBase;
- this.base(node);
- this.baseSetContext = this.setContext;
- this.setContext = function(ctx) {
- this.baseSetContext(ctx);
- // viewbox
- if (this.attribute("viewBox").hasValue()) {
- var viewBox = svg.ToNumberArray(this.attribute("viewBox").value);
- var minX = viewBox[0];
- var minY = viewBox[1];
- width = viewBox[2];
- height = viewBox[3];
- svg.AspectRatio(ctx, this.attribute("preserveAspectRatio").value, this.attribute("width").toPixels("x"), width, this.attribute("height").toPixels("y"), height, minX, minY);
- svg.ViewPort.SetCurrent(viewBox[2], viewBox[3]);
- }
- };
- };
- svg.Element.symbol.prototype = new svg.Element.RenderedElementBase();
- // style element
- svg.Element.style = function(node) {
- this.base = svg.Element.ElementBase;
- this.base(node);
- // text, or spaces then CDATA
- var css = "";
- for (var i = 0; i < node.childNodes.length; i++) {
- css += node.childNodes[i].nodeValue;
- }
- css = css.replace(/(\/\*([^*]|[\r\n]|(\*+([^*\/]|[\r\n])))*\*+\/)|(^[\s]*\/\/.*)/gm, "");
- // remove comments
- css = svg.compressSpaces(css);
- // replace whitespace
- var cssDefs = css.split("}");
- for (var i = 0; i < cssDefs.length; i++) {
- if (svg.trim(cssDefs[i]) != "") {
- var cssDef = cssDefs[i].split("{");
- var cssClasses = cssDef[0].split(",");
- var cssProps = cssDef[1].split(";");
- for (var j = 0; j < cssClasses.length; j++) {
- var cssClass = svg.trim(cssClasses[j]);
- if (cssClass != "") {
- var props = {};
- for (var k = 0; k < cssProps.length; k++) {
- var prop = cssProps[k].indexOf(":");
- var name = cssProps[k].substr(0, prop);
- var value = cssProps[k].substr(prop + 1, cssProps[k].length - prop);
- if (name != null && value != null) {
- props[svg.trim(name)] = new svg.Property(svg.trim(name), svg.trim(value));
- }
- }
- svg.Styles[cssClass] = props;
- if (cssClass == "@font-face") {
- var fontFamily = props["font-family"].value.replace(/"/g, "");
- var srcs = props["src"].value.split(",");
- for (var s = 0; s < srcs.length; s++) {
- if (srcs[s].indexOf('format("svg")') > 0) {
- var urlStart = srcs[s].indexOf("url");
- var urlEnd = srcs[s].indexOf(")", urlStart);
- var url = srcs[s].substr(urlStart + 5, urlEnd - urlStart - 6);
- var doc = svg.parseXml(svg.ajax(url));
- var fonts = doc.getElementsByTagName("font");
- for (var f = 0; f < fonts.length; f++) {
- var font = svg.CreateElement(fonts[f]);
- svg.Definitions[fontFamily] = font;
- }
- }
- }
- }
- }
- }
- }
- }
- };
- svg.Element.style.prototype = new svg.Element.ElementBase();
- // use element
- svg.Element.use = function(node) {
- this.base = svg.Element.RenderedElementBase;
- this.base(node);
- this.baseSetContext = this.setContext;
- this.setContext = function(ctx) {
- this.baseSetContext(ctx);
- if (this.attribute("x").hasValue()) ctx.translate(this.attribute("x").toPixels("x"), 0);
- if (this.attribute("y").hasValue()) ctx.translate(0, this.attribute("y").toPixels("y"));
- };
- this.getDefinition = function() {
- var element = this.getHrefAttribute().getDefinition();
- if (this.attribute("width").hasValue()) element.attribute("width", true).value = this.attribute("width").value;
- if (this.attribute("height").hasValue()) element.attribute("height", true).value = this.attribute("height").value;
- return element;
- };
- this.path = function(ctx) {
- var element = this.getDefinition();
- if (element != null) element.path(ctx);
- };
- this.getBoundingBox = function() {
- var element = this.getDefinition();
- if (element != null) return element.getBoundingBox();
- };
- this.renderChildren = function(ctx) {
- var element = this.getDefinition();
- if (element != null) {
- // temporarily detach from parent and render
- var oldParent = element.parent;
- element.parent = null;
- element.render(ctx);
- element.parent = oldParent;
- }
- };
- };
- svg.Element.use.prototype = new svg.Element.RenderedElementBase();
- // mask element
- svg.Element.mask = function(node) {
- this.base = svg.Element.ElementBase;
- this.base(node);
- this.apply = function(ctx, element) {
- // render as temp svg
- var x = this.attribute("x").toPixels("x");
- var y = this.attribute("y").toPixels("y");
- var width = this.attribute("width").toPixels("x");
- var height = this.attribute("height").toPixels("y");
- if (width == 0 && height == 0) {
- var bb = new svg.BoundingBox();
- for (var i = 0; i < this.children.length; i++) {
- bb.addBoundingBox(this.children[i].getBoundingBox());
- }
- var x = Math.floor(bb.x1);
- var y = Math.floor(bb.y1);
- var width = Math.floor(bb.width());
- var height = Math.floor(bb.height());
- }
- // temporarily remove mask to avoid recursion
- var mask = element.attribute("mask").value;
- element.attribute("mask").value = "";
- var cMask = document.createElement("canvas");
- cMask.width = x + width;
- cMask.height = y + height;
- var maskCtx = cMask.getContext("2d");
- this.renderChildren(maskCtx);
- var c = document.createElement("canvas");
- c.width = x + width;
- c.height = y + height;
- var tempCtx = c.getContext("2d");
- element.render(tempCtx);
- tempCtx.globalCompositeOperation = "destination-in";
- tempCtx.fillStyle = maskCtx.createPattern(cMask, "no-repeat");
- tempCtx.fillRect(0, 0, x + width, y + height);
- ctx.fillStyle = tempCtx.createPattern(c, "no-repeat");
- ctx.fillRect(0, 0, x + width, y + height);
- // reassign mask
- element.attribute("mask").value = mask;
- };
- this.render = function(ctx) {};
- };
- svg.Element.mask.prototype = new svg.Element.ElementBase();
- // clip element
- svg.Element.clipPath = function(node) {
- this.base = svg.Element.ElementBase;
- this.base(node);
- this.apply = function(ctx) {
- for (var i = 0; i < this.children.length; i++) {
- var child = this.children[i];
- if (typeof child.path != "undefined") {
- var transform = null;
- if (child.attribute("transform").hasValue()) {
- transform = new svg.Transform(child.attribute("transform").value);
- transform.apply(ctx);
- }
- child.path(ctx);
- ctx.clip();
- if (transform) {
- transform.unapply(ctx);
- }
- }
- }
- };
- this.render = function(ctx) {};
- };
- svg.Element.clipPath.prototype = new svg.Element.ElementBase();
- // filters
- svg.Element.filter = function(node) {
- this.base = svg.Element.ElementBase;
- this.base(node);
- this.apply = function(ctx, element) {
- // render as temp svg
- var bb = element.getBoundingBox();
- var x = Math.floor(bb.x1);
- var y = Math.floor(bb.y1);
- var width = Math.floor(bb.width());
- var height = Math.floor(bb.height());
- // temporarily remove filter to avoid recursion
- var filter = element.style("filter").value;
- element.style("filter").value = "";
- var px = 0, py = 0;
- for (var i = 0; i < this.children.length; i++) {
- var efd = this.children[i].extraFilterDistance || 0;
- px = Math.max(px, efd);
- py = Math.max(py, efd);
- }
- var c = document.createElement("canvas");
- c.width = width + 2 * px;
- c.height = height + 2 * py;
- var tempCtx = c.getContext("2d");
- tempCtx.translate(-x + px, -y + py);
- element.render(tempCtx);
- // apply filters
- for (var i = 0; i < this.children.length; i++) {
- this.children[i].apply(tempCtx, 0, 0, width + 2 * px, height + 2 * py);
- }
- // render on me
- ctx.drawImage(c, 0, 0, width + 2 * px, height + 2 * py, x - px, y - py, width + 2 * px, height + 2 * py);
- // reassign filter
- element.style("filter", true).value = filter;
- };
- this.render = function(ctx) {};
- };
- svg.Element.filter.prototype = new svg.Element.ElementBase();
- svg.Element.feMorphology = function(node) {
- this.base = svg.Element.ElementBase;
- this.base(node);
- this.apply = function(ctx, x, y, width, height) {};
- };
- svg.Element.feMorphology.prototype = new svg.Element.ElementBase();
- svg.Element.feColorMatrix = function(node) {
- this.base = svg.Element.ElementBase;
- this.base(node);
- function imGet(img, x, y, width, height, rgba) {
- return img[y * width * 4 + x * 4 + rgba];
- }
- function imSet(img, x, y, width, height, rgba, val) {
- img[y * width * 4 + x * 4 + rgba] = val;
- }
- this.apply = function(ctx, x, y, width, height) {
- // only supporting grayscale for now per Issue 195, need to extend to all matrix
- // assuming x==0 && y==0 for now
- var srcData = ctx.getImageData(0, 0, width, height);
- for (var y = 0; y < height; y++) {
- for (var x = 0; x < width; x++) {
- var r = imGet(srcData.data, x, y, width, height, 0);
- var g = imGet(srcData.data, x, y, width, height, 1);
- var b = imGet(srcData.data, x, y, width, height, 2);
- var gray = (r + g + b) / 3;
- imSet(srcData.data, x, y, width, height, 0, gray);
- imSet(srcData.data, x, y, width, height, 1, gray);
- imSet(srcData.data, x, y, width, height, 2, gray);
- }
- }
- ctx.clearRect(0, 0, width, height);
- ctx.putImageData(srcData, 0, 0);
- };
- };
- svg.Element.feColorMatrix.prototype = new svg.Element.ElementBase();
- svg.Element.feGaussianBlur = function(node) {
- this.base = svg.Element.ElementBase;
- this.base(node);
- this.blurRadius = Math.floor(this.attribute("stdDeviation").numValue());
- this.extraFilterDistance = this.blurRadius;
- this.apply = function(ctx, x, y, width, height) {
- if (typeof stackBlurCanvasRGBA == "undefined") {
- if (typeof console != "undefined") {
- console.log("ERROR: StackBlur.js must be included for blur to work");
- }
- return;
- }
- // StackBlur requires canvas be on document
- ctx.canvas.id = svg.UniqueId();
- ctx.canvas.style.display = "none";
- document.body.appendChild(ctx.canvas);
- stackBlurCanvasRGBA(ctx.canvas.id, x, y, width, height, this.blurRadius);
- document.body.removeChild(ctx.canvas);
- };
- };
- svg.Element.feGaussianBlur.prototype = new svg.Element.ElementBase();
- // title element, do nothing
- svg.Element.title = function(node) {};
- svg.Element.title.prototype = new svg.Element.ElementBase();
- // desc element, do nothing
- svg.Element.desc = function(node) {};
- svg.Element.desc.prototype = new svg.Element.ElementBase();
- svg.Element.MISSING = function(node) {
- if (typeof console != "undefined") {
- console.log("ERROR: Element '" + node.nodeName + "' not yet implemented.");
- }
- };
- svg.Element.MISSING.prototype = new svg.Element.ElementBase();
- // element factory
- svg.CreateElement = function(node) {
- var className = node.nodeName.replace(/^[^:]+:/, "");
- // remove namespace
- className = className.replace(/\-/g, "");
- // remove dashes
- var e = null;
- if (typeof svg.Element[className] != "undefined") {
- e = new svg.Element[className](node);
- } else {
- e = new svg.Element.MISSING(node);
- }
- e.type = node.nodeName;
- return e;
- };
- // load from url
- svg.load = function(ctx, url) {
- svg.loadXml(ctx, svg.ajax(url));
- };
- // load from xml
- svg.loadXml = function(ctx, xml) {
- svg.loadXmlDoc(ctx, svg.parseXml(xml));
- };
- svg.loadXmlDoc = function(ctx, dom) {
- svg.init(ctx);
- var mapXY = function(p) {
- var e = ctx.canvas;
- while (e) {
- p.x -= e.offsetLeft;
- p.y -= e.offsetTop;
- e = e.offsetParent;
- }
- if (window.scrollX) p.x += window.scrollX;
- if (window.scrollY) p.y += window.scrollY;
- return p;
- };
- // bind mouse
- if (svg.opts["ignoreMouse"] != true) {
- ctx.canvas.onclick = function(e) {
- var p = mapXY(new svg.Point(e != null ? e.clientX : event.clientX, e != null ? e.clientY : event.clientY));
- svg.Mouse.onclick(p.x, p.y);
- };
- ctx.canvas.onmousemove = function(e) {
- var p = mapXY(new svg.Point(e != null ? e.clientX : event.clientX, e != null ? e.clientY : event.clientY));
- svg.Mouse.onmousemove(p.x, p.y);
- };
- }
- var e = svg.CreateElement(dom.documentElement);
- e.root = true;
- // render loop
- var isFirstRender = true;
- var draw = function() {
- svg.ViewPort.Clear();
- if (ctx.canvas.parentNode) svg.ViewPort.SetCurrent(ctx.canvas.parentNode.clientWidth, ctx.canvas.parentNode.clientHeight);
- if (svg.opts["ignoreDimensions"] != true) {
- // set canvas size
- if (e.style("width").hasValue()) {
- ctx.canvas.width = e.style("width").toPixels("x");
- ctx.canvas.style.width = ctx.canvas.width + "px";
- }
- if (e.style("height").hasValue()) {
- ctx.canvas.height = e.style("height").toPixels("y");
- ctx.canvas.style.height = ctx.canvas.height + "px";
- }
- }
- var cWidth = ctx.canvas.clientWidth || ctx.canvas.width;
- var cHeight = ctx.canvas.clientHeight || ctx.canvas.height;
- if (svg.opts["ignoreDimensions"] == true && e.style("width").hasValue() && e.style("height").hasValue()) {
- cWidth = e.style("width").toPixels("x");
- cHeight = e.style("height").toPixels("y");
- }
- svg.ViewPort.SetCurrent(cWidth, cHeight);
- if (svg.opts["offsetX"] != null) e.attribute("x", true).value = svg.opts["offsetX"];
- if (svg.opts["offsetY"] != null) e.attribute("y", true).value = svg.opts["offsetY"];
- if (svg.opts["scaleWidth"] != null && svg.opts["scaleHeight"] != null) {
- var xRatio = 1, yRatio = 1, viewBox = svg.ToNumberArray(e.attribute("viewBox").value);
- if (e.attribute("width").hasValue()) xRatio = e.attribute("width").toPixels("x") / svg.opts["scaleWidth"]; else if (!isNaN(viewBox[2])) xRatio = viewBox[2] / svg.opts["scaleWidth"];
- if (e.attribute("height").hasValue()) yRatio = e.attribute("height").toPixels("y") / svg.opts["scaleHeight"]; else if (!isNaN(viewBox[3])) yRatio = viewBox[3] / svg.opts["scaleHeight"];
- e.attribute("width", true).value = svg.opts["scaleWidth"];
- e.attribute("height", true).value = svg.opts["scaleHeight"];
- e.attribute("viewBox", true).value = "0 0 " + cWidth * xRatio + " " + cHeight * yRatio;
- e.attribute("preserveAspectRatio", true).value = "none";
- }
- // clear and render
- if (svg.opts["ignoreClear"] != true) {
- ctx.clearRect(0, 0, cWidth, cHeight);
- }
- e.render(ctx);
- if (isFirstRender) {
- isFirstRender = false;
- if (typeof svg.opts["renderCallback"] == "function") svg.opts["renderCallback"](dom);
- }
- };
- var waitingForImages = true;
- if (svg.ImagesLoaded()) {
- waitingForImages = false;
- draw();
- }
- svg.intervalID = setInterval(function() {
- var needUpdate = false;
- if (waitingForImages && svg.ImagesLoaded()) {
- waitingForImages = false;
- needUpdate = true;
- }
- // need update from mouse events?
- if (svg.opts["ignoreMouse"] != true) {
- needUpdate = needUpdate | svg.Mouse.hasEvents();
- }
- // need update from animations?
- if (svg.opts["ignoreAnimation"] != true) {
- for (var i = 0; i < svg.Animations.length; i++) {
- needUpdate = needUpdate | svg.Animations[i].update(1e3 / svg.FRAMERATE);
- }
- }
- // need update from redraw?
- if (typeof svg.opts["forceRedraw"] == "function") {
- if (svg.opts["forceRedraw"]() == true) needUpdate = true;
- }
- // render if needed
- if (needUpdate) {
- draw();
- svg.Mouse.runEvents();
- }
- }, 1e3 / svg.FRAMERATE);
- };
- svg.stop = function() {
- if (svg.intervalID) {
- clearInterval(svg.intervalID);
- }
- };
- svg.Mouse = new function() {
- this.events = [];
- this.hasEvents = function() {
- return this.events.length != 0;
- };
- this.onclick = function(x, y) {
- this.events.push({
- type: "onclick",
- x: x,
- y: y,
- run: function(e) {
- if (e.onclick) e.onclick();
- }
- });
- };
- this.onmousemove = function(x, y) {
- this.events.push({
- type: "onmousemove",
- x: x,
- y: y,
- run: function(e) {
- if (e.onmousemove) e.onmousemove();
- }
- });
- };
- this.eventElements = [];
- this.checkPath = function(element, ctx) {
- for (var i = 0; i < this.events.length; i++) {
- var e = this.events[i];
- if (ctx.isPointInPath && ctx.isPointInPath(e.x, e.y)) this.eventElements[i] = element;
- }
- };
- this.checkBoundingBox = function(element, bb) {
- for (var i = 0; i < this.events.length; i++) {
- var e = this.events[i];
- if (bb.isPointInBox(e.x, e.y)) this.eventElements[i] = element;
- }
- };
- this.runEvents = function() {
- svg.ctx.canvas.style.cursor = "";
- for (var i = 0; i < this.events.length; i++) {
- var e = this.events[i];
- var element = this.eventElements[i];
- while (element) {
- e.run(element);
- element = element.parent;
- }
- }
- // done running, clear
- this.events = [];
- this.eventElements = [];
- };
- }();
- return svg;
- }
- })();
- if (typeof CanvasRenderingContext2D != "undefined") {
- CanvasRenderingContext2D.prototype.drawSvg = function(s, dx, dy, dw, dh) {
- canvg(this.canvas, s, {
- ignoreMouse: true,
- ignoreAnimation: true,
- ignoreDimensions: true,
- ignoreClear: true,
- offsetX: dx,
- offsetY: dy,
- scaleWidth: dw,
- scaleHeight: dh
- });
- };
- }
- return canvg;
- }
- };
- /*!
- * 输出转换器,提供输出支持
- */
- _p[1] = {
- value: function(require) {
- var kity = _p.r(34), canvg = _p.r(0);
- return kity.createClass("Output", {
- constructor: function(formula) {
- this.formula = formula;
- },
- toJPG: function(cb) {
- toImage(this.formula, "image/jpeg", cb);
- },
- toPNG: function(cb) {
- toImage(this.formula, "image/png", cb);
- }
- });
- function toImage(formula, type, cb) {
- var rectSpace = formula.container.getRenderBox();
- return getBase64DataURL(formula.node.ownerDocument, {
- width: rectSpace.width,
- height: rectSpace.height,
- content: getSVGContent(formula.node)
- }, type, cb);
- }
- function getBase64DataURL(doc, data, type, cb) {
- var canvas = null, args = arguments, ctx = null;
- if (true) {
- drawToCanvas.apply(null, args);
- } else {
- canvas = getImageCanvas(doc, data.width, data.height, type);
- ctx = canvas.getContext("2d");
- var image = new Image();
- image.onload = function() {
- try {
- ctx.drawImage(image, 0, 0);
- cb(canvas.toDataURL(type));
- } catch (e) {
- drawToCanvas.apply(null, args);
- }
- };
- image.src = getSVGDataURL(data.content);
- }
- }
- function getSVGContent(svgNode) {
- var tmp = svgNode.ownerDocument.createElement("div"), start = [ '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="', svgNode.getAttribute("width"), '" height="', svgNode.getAttribute("height"), '">' ];
- tmp.appendChild(svgNode.cloneNode(true));
- return tmp.innerHTML.replace(/<svg[^>]+?>/i, start.join("")).replace(/ /g, "");
- }
- function getSVGDataURL(data) {
- return "data:image/svg+xml;base64," + window.btoa(unescape(encodeURIComponent(data)));
- }
- function getImageCanvas(doc, width, height, type) {
- var canvas = doc.createElement("canvas"), ctx = canvas.getContext("2d");
- canvas.width = width;
- canvas.height = height;
- if (type !== "image/png") {
- ctx.fillStyle = "white";
- ctx.fillRect(0, 0, canvas.width, canvas.height);
- }
- return canvas;
- }
- function drawToCanvas(doc, data, type, cb) {
- var canvas = getImageCanvas(doc, data.width, data.height, type);
- canvas.style.cssText = "position: absolute; top: 0; left: 100000px; z-index: -1;";
- window.setTimeout(function() {
- doc.body.appendChild(canvas);
- canvg(canvas, data.content);
- doc.body.removeChild(canvas);
- cb(canvas.toDataURL(type));
- }, 0);
- }
- }
- };
- /*!
- * 所有字符的列表
- */
- _p[2] = {
- value: function() {
- return [ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "ȷ", "ı", "α", "β", "γ", "δ", "ε", "ζ", "η", "θ", "ι", "κ", "λ", "μ", "ν", "ξ", "ο", "π", "ρ", "ς", "σ", "τ", "υ", "φ", "χ", "ψ", "ω", "ϑ", "ϕ", "ϖ", "Ϟ", "Ϝ", "ϵ", "ϱ", "Ϲ", "ℜ", "ℵ", "ℑ", "℧", "ℶ", "ℷ", "ℸ", "ð", "ℏ", "⅁", "ℎ", "∂", "℘", "⅌", "Ⅎ", "∁", "ℓ", "Ⓢ", "(", ")", "Γ", "Δ", "Ε", "Ζ", "Η", "Θ", "Ι", "Κ", "Λ", "Μ", "Ν", "Ξ", "Ο", "Π", "Ρ", "Σ", "Τ", "Υ", "Φ", "Χ", "Ψ", "Ω", "Α", "Β", "#", "!", "$", "%", "&", "∠", "′", "‵", "★", "◆", "■", "▲", "▼", "⊤", "⊥", "♣", "♠", "♢", "♡", "∃", "∄", "♭", "♮", "♯", "∀", "∞", "∡", "∇", "¬", "∢", "√", "△", "▽", "∅", "ø", "◇", "◀", "▸", "[", "]", "{", "}", "〈", "〉", "ϰ", ",", ".", "/", ":", ";", "?", "\\", "⋮", "⋯", "⋰", "…", "@", """, "'", "|", "^", "`", "“", "_", "*", "+", "-", "∐", "⊼", "⊻", "◯", "⊡", "⊟", "⊞", "⊠", "•", "∩", "∪", "⋒", "⋓", "⋐", "⋑", "·", "▪", "◦", "⊛", "⊚", "⊖", "⊙", "⊝", "⊕", "⊗", "⊘", "±", "∓", "⋏", "⋎", "†", "‡", "⋄", "÷", "⋇", "∔", "⌭", "⋗", "⋖", "⋉", "⋊", "⋋", "⋌", "⊓", "⊔", "⊑", "⊒", "⊏", "⊐", "⋆", "×", "⊳", "⊲", "⊵", "⊴", "⊎", "∨", "∧", "≀", "<", "=", ">", "≈", "≇", "≍", "≒", "≓", "≊", "∽", "≁", "≂", "≃", "⋍", "≏", "≎", "≗", "≅", "⋞", "⋟", "≐", "≑", "≖", "⪖", "⪕", "≡", "≥", "≤", "≦", "≧", "⩾", "⩽", "≫", "≪", "≨", "≩", "⋘", "⋙", "⪇", "⪈", "⪉", "⪊", "⋧", "⋦", "⪆", "⪅", "⋛", "⋚", "⪋", "⪌", "≷", "≶", "≳", "≲", "⌮", "⌯", "≯", "≱", "≰", "≮", "⌱", "⌰", "⌲", "⌳", "≬", "⊀", "⊁", "⋠", "⋡", "≺", "≻", "≼", "≽", "≾", "≿", "⊂", "⊃", "⊈", "⊉", "⊆", "⊇", "⊊", "⊋", "⪷", "⪸", "⪯", "⪰", "⪹", "⪺", "⪵", "⪶", "⋨", "⋩", "∼", "≜", "↶", "↷", "↺", "↻", "↾", "↿", "⇂", "⇃", "⇄", "⇆", "⇈", "⇊", "⇋", "⇌", "⇍", "⇎", "⇏", "⇐", "⇑", "⇒", "⇓", "⇔", "⇕", "⇚", "⇛", "⇝", "↫", "↬", "↭", "↮", "←", "↑", "→", "↓", "↔", "↕", "↖", "↗", "↘", "↙", "↞", "↠", "↢", "↣", "↰", "↱", "⊢", "⊣", "⊨", "⊩", "⊪", "⊭", "⊯", "⊸", "⊺", "⋔", "⋪", "⋫", "⋬", "⋭", "⌈", "⌉", "⌊", "⌋", "⫋", "⫌", "⫅", "⫆", "∈", "∋", "∝", "∤", "∦", "∴", "∵", "∍", "⋈", "⌢", "⌣", "∣", "∥", "⏐", "⏑", "⏒", "⏓", "⫇", "⫈", "⊮", "⊬", "⫉", "⏔", "⏕", "⏖", "⏗", "⇇", "⇉", "↼", "↽", "⇀", "⇁", "↚", "↛", "⟵", "⟶", "⟷", "⟹", "⟸", "⟺", "≢", "≠", "∉" ];
- }
- };
- /*!
- * 字符配置
- */
- _p[3] = {
- value: function() {
- return {
- // 默认字体
- defaultFont: "KF AMS MAIN"
- };
- }
- };
- /*!
- * 工厂方法,创建兼容各浏览器的text实现
- */
- _p[4] = {
- value: function(require) {
- var kity = _p.r(34), divNode = document.createElement("div"), NAMESPACE = "http://www.w3.org/XML/1998/namespace";
- function createText(content) {
- var text = new kity.Text();
- // Non-IE
- if ("innerHTML" in text.node) {
- text.node.setAttributeNS(NAMESPACE, "xml:space", "preserve");
- } else {
- if (content.indexOf(" ") != -1) {
- content = convertContent(content);
- }
- }
- text.setContent(content);
- return text;
- }
- /**
- * 构建节点来转换内容
- */
- function convertContent(content) {
- divNode.innerHTML = '<svg><text gg="asfdas">' + content.replace(/\s/gi, " ") + "</text></svg>";
- return divNode.firstChild.firstChild.textContent;
- }
- return {
- create: function(content) {
- return createText(content);
- }
- };
- }
- };
- /**
- * 文本
- */
- _p[5] = {
- value: function(require) {
- var kity = _p.r(34), FONT_CONF = _p.r(47).font, FontManager = _p.r(25), TextFactory = _p.r(4);
- return kity.createClass("Text", {
- base: _p.r(46),
- constructor: function(content, fontFamily) {
- this.callBase();
- this.fontFamily = fontFamily;
- this.fontSize = 50;
- this.content = content || "";
- // 移除多余的节点
- this.box.remove();
- this.translationContent = this.translation(this.content);
- this.contentShape = new kity.Group();
- this.contentNode = this.createContent();
- this.contentShape.addShape(this.contentNode);
- this.addShape(this.contentShape);
- },
- createContent: function() {
- var contentNode = TextFactory.create(this.translationContent);
- contentNode.setAttr({
- "font-family": this.fontFamily,
- "font-size": 50,
- x: 0,
- y: FONT_CONF.offset
- });
- return contentNode;
- },
- setFamily: function(fontFamily) {
- this.fontFamily = fontFamily;
- this.contentNode.setAttr("font-family", fontFamily);
- },
- setFontSize: function(fontSize) {
- this.fontSize = fontSize;
- this.contentNode.setAttr("font-size", fontSize + "px");
- this.contentNode.setAttr("y", fontSize / 50 * FONT_CONF.offset);
- },
- getBaseHeight: function() {
- var chars = this.contentShape.getItems(), currentChar = null, index = 0, height = 0;
- while (currentChar = chars[index]) {
- height = Math.max(height, currentChar.getHeight());
- index++;
- }
- return height;
- },
- translation: function(content) {
- var fontFamily = this.fontFamily;
- // 首先特殊处理掉两个相连的"`"符号
- return content.replace(/``/g, "“").replace(/\\([a-zA-Z,]+)\\/g, function(match, input) {
- if (input === ",") {
- return " ";
- }
- var data = FontManager.getCharacterValue(input, fontFamily);
- if (!data) {
- return "";
- }
- return data;
- });
- }
- });
- }
- };
- /**
- * 定义公式中各种对象的类型
- */
- _p[6] = {
- value: function() {
- return {
- UNKNOWN: -1,
- EXP: 0,
- COMPOUND_EXP: 1,
- OP: 2
- };
- }
- };
- /**
- * 定义公式中上下标的类型
- */
- _p[7] = {
- value: function() {
- return {
- SIDE: "side",
- FOLLOW: "follow"
- };
- }
- };
- /**
- * 下标表达式
- */
- _p[8] = {
- value: function(require) {
- var kity = _p.r(34);
- return kity.createClass("SubscriptExpression", {
- base: _p.r(17),
- constructor: function(operand, subscript) {
- this.callBase(operand, null, subscript);
- this.setFlag("Subscript");
- }
- });
- }
- };
- /**
- * 上标表达式
- */
- _p[9] = {
- value: function(require) {
- var kity = _p.r(34);
- return kity.createClass("SuperscriptExpression", {
- base: _p.r(17),
- constructor: function(operand, superscript) {
- this.callBase(operand, superscript, null);
- this.setFlag("Superscript");
- }
- });
- }
- };
- /**
- * 二元操作表达式
- */
- _p[10] = {
- value: function(require) {
- var kity = _p.r(34);
- return kity.createClass("BinaryExpression", {
- base: _p.r(19),
- constructor: function(firstOperand, lastOperand) {
- this.callBase();
- this.setFirstOperand(firstOperand);
- this.setLastOperand(lastOperand);
- },
- setFirstOperand: function(operand) {
- return this.setOperand(operand, 0);
- },
- getFirstOperand: function() {
- return this.getOperand(0);
- },
- setLastOperand: function(operand) {
- return this.setOperand(operand, 1);
- },
- getLastOperand: function() {
- return this.getOperand(1);
- }
- });
- }
- };
- /**
- * 自动增长括号表达式
- */
- _p[11] = {
- value: function(require) {
- var kity = _p.r(34), BracketsOperator = _p.r(35);
- return kity.createClass("BracketsExpression", {
- base: _p.r(19),
- /**
- * 构造函数调用方式:
- * new Constructor( 左括号, 右括号, 表达式 )
- * 或者
- * new Constructor( 括号, 表达式 ), 该构造函数转换成上面的构造函数,是: new Constructor( 括号, 括号, 表达式 )
- * @param left 左括号
- * @param right 右括号
- * @param exp 表达式
- */
- constructor: function(left, right, exp) {
- this.callBase();
- this.setFlag("Brackets");
- // 参数整理
- if (arguments.length === 2) {
- exp = right;
- right = left;
- }
- this.leftSymbol = left;
- this.rightSymbol = right;
- this.setOperator(new BracketsOperator());
- this.setOperand(exp, 0);
- },
- getLeftSymbol: function() {
- return this.leftSymbol;
- },
- getRightSymbol: function() {
- return this.rightSymbol;
- }
- });
- }
- };
- /**
- * 组合表达式
- * 可以组合多个表达式
- */
- _p[12] = {
- value: function(require) {
- var kity = _p.r(34), FONT_CONF = _p.r(47).font, CombinationOperator = _p.r(36);
- return kity.createClass("CombinationExpression", {
- base: _p.r(19),
- constructor: function() {
- this.callBase();
- this.setFlag("Combination");
- this.setOperator(new CombinationOperator());
- kity.Utils.each(arguments, function(operand, index) {
- this.setOperand(operand, index);
- }, this);
- },
- getRenderBox: function(refer) {
- var rectBox = this.callBase(refer);
- if (this.getOperands().length === 0) {
- rectBox.height = FONT_CONF.spaceHeight;
- }
- return rectBox;
- },
- getBaseline: function(refer) {
- var maxBaseline = 0, operands = this.getOperands();
- if (operands.length === 0) {
- return this.callBase(refer);
- }
- kity.Utils.each(operands, function(operand) {
- maxBaseline = Math.max(operand.getBaseline(refer), maxBaseline);
- });
- return maxBaseline;
- },
- getMeanline: function(refer) {
- var minMeanline = 1e7, operands = this.getOperands();
- if (operands.length === 0) {
- return this.callBase(refer);
- }
- kity.Utils.each(operands, function(operand) {
- minMeanline = Math.min(operand.getMeanline(refer), minMeanline);
- });
- return minMeanline;
- }
- });
- }
- };
- /**
- * 分数表达式
- */
- _p[13] = {
- value: function(require) {
- var kity = _p.r(34), FractionOperator = _p.r(38);
- return kity.createClass("FractionExpression", {
- base: _p.r(10),
- constructor: function(upOperand, downOperand) {
- this.callBase(upOperand, downOperand);
- this.setFlag("Fraction");
- this.setOperator(new FractionOperator());
- },
- /*------- 重写分数结构的baseline和mealine计算方式 */
- getBaseline: function(refer) {
- var downOperand = this.getOperand(1), rectBox = downOperand.getRenderBox(refer);
- return rectBox.y + downOperand.getBaselineProportion() * rectBox.height;
- },
- getMeanline: function(refer) {
- var upOperand = this.getOperand(0), rectBox = upOperand.getRenderBox(refer);
- return upOperand.getMeanlineProportion() * rectBox.height;
- }
- });
- }
- };
- /**
- * 函数表达式
- */
- _p[14] = {
- value: function(require) {
- var kity = _p.r(34), FUNC_CONF = _p.r(47).func, FunctionOperator = _p.r(39);
- return kity.createClass("FunctionExpression", {
- base: _p.r(19),
- /**
- * function表达式构造函数
- * @param funcName function名称
- * @param expr 函数表达式
- * @param sup 上标
- * @param sub 下标
- */
- constructor: function(funcName, expr, sup, sub) {
- this.callBase();
- this.setFlag("Func");
- this.funcName = funcName;
- this.setOperator(new FunctionOperator(funcName));
- this.setExpr(expr);
- this.setSuperscript(sup);
- this.setSubscript(sub);
- },
- // 当前函数应用的script位置是否是在侧面
- isSideScript: function() {
- return !FUNC_CONF["ud-script"][this.funcName];
- },
- setExpr: function(expr) {
- return this.setOperand(expr, 0);
- },
- setSuperscript: function(sub) {
- return this.setOperand(sub, 1);
- },
- setSubscript: function(sub) {
- return this.setOperand(sub, 2);
- }
- });
- }
- };
- /**
- * 积分表达式
- */
- _p[15] = {
- value: function(require) {
- var kity = _p.r(34), IntegrationOperator = _p.r(40), IntegrationExpression = kity.createClass("IntegrationExpression", {
- base: _p.r(19),
- /**
- * 构造积分表达式
- * @param integrand 被积函数
- * @param supOperand 上限
- * @param subOperand 下限
- */
- constructor: function(integrand, superscript, subscript) {
- this.callBase();
- this.setFlag("Integration");
- this.setOperator(new IntegrationOperator());
- this.setIntegrand(integrand);
- this.setSuperscript(superscript);
- this.setSubscript(subscript);
- },
- setType: function(type) {
- this.getOperator().setType(type);
- return this;
- },
- resetType: function() {
- this.getOperator().resetType();
- return this;
- },
- setIntegrand: function(integrand) {
- this.setOperand(integrand, 0);
- },
- setSuperscript: function(sup) {
- this.setOperand(sup, 1);
- },
- setSubscript: function(sub) {
- this.setOperand(sub, 2);
- }
- });
- return IntegrationExpression;
- }
- };
- /**
- * 方根表达式
- */
- _p[16] = {
- value: function(require) {
- var kity = _p.r(34), RadicalOperator = _p.r(42);
- return kity.createClass("RadicalExpression", {
- base: _p.r(10),
- /**
- * 构造开方表达式
- * @param radicand 被开方数
- * @param exponent 指数
- */
- constructor: function(radicand, exponent) {
- this.callBase(radicand, exponent);
- this.setFlag("Radicand");
- this.setOperator(new RadicalOperator());
- },
- setRadicand: function(operand) {
- return this.setFirstOperand(operand);
- },
- getRadicand: function() {
- return this.getFirstOperand();
- },
- setExponent: function(operand) {
- return this.setLastOperand(operand);
- },
- getExponent: function() {
- return this.getLastOperand();
- }
- });
- }
- };
- /**
- * 上标表达式
- */
- _p[17] = {
- value: function(require) {
- var kity = _p.r(34), ScriptOperator = _p.r(43);
- return kity.createClass("ScriptExpression", {
- base: _p.r(19),
- constructor: function(operand, superscript, subscript) {
- this.callBase();
- this.setFlag("Script");
- this.setOperator(new ScriptOperator());
- this.setOpd(operand);
- this.setSuperscript(superscript);
- this.setSubscript(subscript);
- },
- setOpd: function(operand) {
- this.setOperand(operand, 0);
- },
- setSuperscript: function(sup) {
- this.setOperand(sup, 1);
- },
- setSubscript: function(sub) {
- this.setOperand(sub, 2);
- }
- });
- }
- };
- /**
- * 求和表达式
- */
- _p[18] = {
- value: function(require) {
- var kity = _p.r(34), SummationOperator = _p.r(44);
- return kity.createClass("SummationExpression", {
- base: _p.r(19),
- /**
- * 构造求和表达式
- * @param expr 求和表达式
- * @param upOperand 上标
- * @param downOperand 下标
- */
- constructor: function(expr, superscript, subscript) {
- this.callBase();
- this.setFlag("Summation");
- this.setOperator(new SummationOperator());
- this.setExpr(expr);
- this.setSuperscript(superscript);
- this.setSubscript(subscript);
- },
- setExpr: function(expr) {
- this.setOperand(expr, 0);
- },
- setSuperscript: function(sup) {
- this.setOperand(sup, 1);
- },
- setSubscript: function(sub) {
- this.setOperand(sub, 2);
- }
- });
- }
- };
- /**
- * 复合表达式
- * @abstract
- */
- _p[19] = {
- value: function(require) {
- var kity = _p.r(34), GTYPE = _p.r(6), Expression = _p.r(21);
- return kity.createClass("CompoundExpression", {
- base: _p.r(21),
- constructor: function() {
- this.callBase();
- this.type = GTYPE.COMPOUND_EXP;
- this.operands = [];
- this.operator = null;
- this.operatorBox = new kity.Group();
- this.operatorBox.setAttr("data-type", "kf-editor-exp-op-box");
- this.operandBox = new kity.Group();
- this.operandBox.setAttr("data-type", "kf-editor-exp-operand-box");
- this.setChildren(0, this.operatorBox);
- this.setChildren(1, this.operandBox);
- },
- // 操作符存储在第1位置
- setOperator: function(operator) {
- if (operator === undefined) {
- return this;
- }
- if (this.operator) {
- this.operator.remove();
- }
- this.operatorBox.addShape(operator);
- this.operator = operator;
- this.operator.setParentExpression(this);
- // 表达式关联到操作符
- operator.expression = this;
- return this;
- },
- getOperator: function() {
- return this.operator;
- },
- // 操作数存储位置是从1开始
- setOperand: function(operand, index, isWrap) {
- // 不包装操作数
- if (isWrap === false) {
- this.operands[index] = operand;
- return this;
- }
- operand = Expression.wrap(operand);
- if (this.operands[index]) {
- this.operands[index].remove();
- }
- this.operands[index] = operand;
- this.operandBox.addShape(operand);
- return this;
- },
- getOperand: function(index) {
- return this.operands[index];
- },
- getOperands: function() {
- return this.operands;
- },
- addedCall: function() {
- this.operator.applyOperand.apply(this.operator, this.operands);
- return this;
- }
- });
- }
- };
- /**
- * 空表达式
- * 该表达式主要用途是用于站位
- */
- _p[20] = {
- value: function(require) {
- var kity = _p.r(34), FONT_CONF = _p.r(47).font, Expression = _p.r(21), EmptyExpression = kity.createClass("EmptyExpression", {
- base: Expression,
- constructor: function() {
- this.callBase();
- this.setFlag("Empty");
- },
- getRenderBox: function() {
- return {
- width: 0,
- height: FONT_CONF.spaceHeight,
- x: 0,
- y: 0
- };
- }
- });
- EmptyExpression.isEmpty = function(target) {
- return target instanceof EmptyExpression;
- };
- // 注册打包函数
- Expression.registerWrap("empty", function(operand) {
- if (operand === null || operand === undefined) {
- return new EmptyExpression();
- }
- });
- return EmptyExpression;
- }
- };
- /**
- * 基础表达式, 该类是表达式和操作数的高层抽象
- * @abstract
- */
- _p[21] = {
- value: function(require) {
- var kity = _p.r(34), GTYPE = _p.r(6), FONT_CONF = _p.r(47).font, // 打包函数列表
- WRAP_FN = [], // 注册的打包函数的名称与其在注册器列表中的索引之间的对应关系
- WRAP_FN_INDEX = {}, Expression = kity.createClass("Expression", {
- base: _p.r(46),
- constructor: function() {
- this.callBase();
- this.type = GTYPE.EXP;
- // 表达式的上下偏移
- this._offset = {
- top: 0,
- bottom: 0
- };
- this.children = [];
- this.box.fill("transparent").setAttr("data-type", "kf-editor-exp-box");
- this.box.setAttr("data-type", "kf-editor-exp-bg-box");
- this.expContent = new kity.Group();
- this.expContent.setAttr("data-type", "kf-editor-exp-content-box");
- this.addShape(this.expContent);
- },
- getChildren: function() {
- return this.children;
- },
- getChild: function(index) {
- return this.children[index] || null;
- },
- getTopOffset: function() {
- return this._offset.top;
- },
- getBottomOffset: function() {
- return this._offset.bottom;
- },
- getOffset: function() {
- return this._offset;
- },
- setTopOffset: function(val) {
- this._offset.top = val;
- },
- setBottomOffset: function(val) {
- this._offset.bottom = val;
- },
- setOffset: function(top, bottom) {
- this._offset.top = top;
- this._offset.bottom = bottom;
- },
- setFlag: function(flag) {
- this.setAttr("data-flag", flag || "Expression");
- },
- setChildren: function(index, exp) {
- // 首先清理掉之前的表达式
- if (this.children[index]) {
- this.children[index].remove();
- }
- this.children[index] = exp;
- this.expContent.addShape(exp);
- },
- getBaselineProportion: function() {
- return FONT_CONF.baselinePosition;
- },
- getMeanlineProportion: function() {
- return FONT_CONF.meanlinePosition;
- },
- getBaseline: function(refer) {
- // 上偏移3px
- return this.getRenderBox(refer).height * FONT_CONF.baselinePosition - 3;
- },
- getMeanline: function(refer) {
- // 上偏移1px
- return this.getRenderBox(refer).height * FONT_CONF.meanlinePosition - 1;
- },
- getAscenderline: function() {
- return this.getFixRenderBox().height * FONT_CONF.ascenderPosition;
- },
- getDescenderline: function() {
- return this.getFixRenderBox().height * FONT_CONF.descenderPosition;
- },
- translateElement: function(x, y) {
- this.expContent.translate(x, y);
- },
- expand: function(width, height) {
- var renderBox = this.getFixRenderBox();
- this.setBoxSize(renderBox.width + width, renderBox.height + height);
- },
- getBaseWidth: function() {
- return this.getWidth();
- },
- getBaseHeight: function() {
- return this.getHeight();
- },
- updateBoxSize: function() {
- var renderBox = this.expContent.getFixRenderBox();
- this.setBoxSize(renderBox.width, renderBox.height);
- },
- getBox: function() {
- return this.box;
- }
- });
- // 表达式自动打包
- kity.Utils.extend(Expression, {
- registerWrap: function(name, fn) {
- WRAP_FN_INDEX[name] = WRAP_FN.length;
- WRAP_FN.push(fn);
- },
- revokeWrap: function(name) {
- var fn = null;
- if (name in WRAP_FN_INDEX) {
- fn = WRAP_FN[WRAP_FN_INDEX[name]];
- WRAP_FN[WRAP_FN_INDEX[name]] = null;
- delete WRAP_FN_INDEX[name];
- }
- return fn;
- },
- // 打包函数
- wrap: function(operand) {
- var result;
- kity.Utils.each(WRAP_FN, function(fn) {
- if (!fn) {
- return;
- }
- result = fn(operand);
- if (result) {
- return false;
- }
- });
- return result;
- }
- });
- return Expression;
- }
- };
- /**
- * Text表达式
- */
- _p[22] = {
- value: function(require) {
- var Text = _p.r(5), kity = _p.r(34), FONT_CONF = _p.r(3), Expression = _p.r(21), TextExpression = kity.createClass("TextExpression", {
- base: _p.r(21),
- constructor: function(content, fontFamily) {
- this.callBase();
- this.fontFamily = fontFamily || FONT_CONF.defaultFont;
- this.setFlag("Text");
- this.content = content + "";
- this.textContent = new Text(this.content, this.fontFamily);
- this.setChildren(0, this.textContent);
- this.setChildren(1, new kity.Rect(0, 0, 0, 0).fill("transparent"));
- },
- setFamily: function(fontFamily) {
- this.textContent.setFamily(fontFamily);
- },
- setFontSize: function(fontSize) {
- this.textContent.setFontSize(fontSize);
- },
- addedCall: function() {
- var box = this.textContent.getFixRenderBox();
- this.getChild(1).setSize(box.width, box.height);
- this.updateBoxSize();
- return this;
- }
- });
- // 注册文本表达式的打包函数
- Expression.registerWrap("text", function(operand) {
- var operandType = typeof operand;
- if (operandType === "number" || operandType === "string") {
- operand = new TextExpression(operand);
- }
- return operand;
- });
- return TextExpression;
- }
- };
- /*!
- * 字体信息检测模板,用于检测浏览器的字体信息
- */
- _p[23] = {
- value: function() {
- return [ '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">', '<text id="abcd" font-family="KF AMS MAIN" font-size="50" x="0" y="0">x</text>', "</svg>" ];
- }
- };
- /*!
- * 字体安装器
- */
- _p[24] = {
- value: function(require) {
- var kity = _p.r(34), FontManager = _p.r(25), $ = _p.r(33), FONT_CONF = _p.r(47).font, CHAR_LIST = _p.r(2), NODE_LIST = [];
- return kity.createClass("FontInstaller", {
- constructor: function(doc, resource) {
- this.callBase();
- this.resource = resource || "../src/resource/";
- this.doc = doc;
- },
- // 挂载字体
- mount: function(callback) {
- var fontList = FontManager.getFontList(), count = 0, _self = this;
- kity.Utils.each(fontList, function(fontInfo) {
- count++;
- fontInfo.meta.src = _self.resource + fontInfo.meta.src;
- _self.createFontStyle(fontInfo);
- preload(_self.doc, fontInfo, function() {
- count--;
- if (count === 0) {
- complete(_self.doc, callback);
- }
- });
- });
- },
- createFontStyle: function(fontInfo) {
- var stylesheet = this.doc.createElement("style"), tpl = '@font-face{\nfont-family: "${fontFamily}";\nsrc: url("${src}");\n}';
- stylesheet.setAttribute("type", "text/css");
- stylesheet.innerHTML = tpl.replace("${fontFamily}", fontInfo.meta.fontFamily).replace("${src}", fontInfo.meta.src);
- this.doc.head.appendChild(stylesheet);
- }
- });
- function preload(doc, fontInfo, callback) {
- $.get(fontInfo.meta.src, function(data, state) {
- if (state === "success") {
- applyFonts(doc, fontInfo);
- }
- callback();
- });
- }
- function complete(doc, callback) {
- window.setTimeout(function() {
- initFontSystemInfo(doc);
- removeTmpNode();
- callback();
- }, 100);
- }
- function applyFonts(doc, fontInfo) {
- var node = document.createElement("div"), fontFamily = fontInfo.meta.fontFamily;
- node.style.cssText = "position: absolute; top: -10000px; left: -100000px;";
- node.style.fontFamily = fontFamily;
- node.innerHTML = CHAR_LIST.join("");
- doc.body.appendChild(node);
- NODE_LIST.push(node);
- }
- /**
- * 计算字体系统信息
- */
- function initFontSystemInfo(doc) {
- var tmpNode = doc.createElement("div");
- tmpNode.style.cssText = "position: absolute; top: 0; left: -100000px;";
- tmpNode.innerHTML = _p.r(23).join("");
- doc.body.appendChild(tmpNode);
- var rectBox = tmpNode.getElementsByTagName("text")[0].getBBox();
- // text实际占用空间
- FONT_CONF.spaceHeight = rectBox.height;
- // text顶部空间
- FONT_CONF.topSpace = -rectBox.y - FONT_CONF.baseline;
- FONT_CONF.bottomSpace = FONT_CONF.spaceHeight - FONT_CONF.topSpace - FONT_CONF.baseHeight;
- // text偏移值
- FONT_CONF.offset = FONT_CONF.baseline + FONT_CONF.topSpace;
- // baseline比例
- FONT_CONF.baselinePosition = (FONT_CONF.topSpace + FONT_CONF.baseline) / FONT_CONF.spaceHeight;
- // meanline比例
- FONT_CONF.meanlinePosition = (FONT_CONF.topSpace + FONT_CONF.meanline) / FONT_CONF.spaceHeight;
- // 上下延伸性比例
- FONT_CONF.ascenderPosition = FONT_CONF.topSpace / FONT_CONF.spaceHeight;
- FONT_CONF.descenderPosition = (FONT_CONF.topSpace + FONT_CONF.baseHeight) / FONT_CONF.spaceHeight;
- doc.body.removeChild(tmpNode);
- }
- function removeTmpNode() {
- kity.Utils.each(NODE_LIST, function(node) {
- node.parentNode.removeChild(node);
- });
- NODE_LIST = [];
- }
- }
- };
- /*!
- * 字体管理器
- */
- _p[25] = {
- value: function(require) {
- var FONT_LIST = {}, kity = _p.r(34), CONF = _p.r(47).font.list;
- // init
- (function() {
- kity.Utils.each(CONF, function(fontData) {
- FONT_LIST[fontData.meta.fontFamily] = fontData;
- });
- })();
- return {
- getFontList: function() {
- return FONT_LIST;
- },
- getCharacterValue: function(key, fontFamily) {
- if (!FONT_LIST[fontFamily]) {
- return null;
- }
- return FONT_LIST[fontFamily].map[key] || null;
- }
- };
- }
- };
- /*!
- * 双线字体
- */
- _p[26] = {
- value: function() {
- return {
- meta: {
- fontFamily: "KF AMS BB",
- src: "KF_AMS_BB.woff"
- }
- };
- }
- };
- /*!
- * 手写体
- */
- _p[27] = {
- value: function() {
- return {
- meta: {
- fontFamily: "KF AMS CAL",
- src: "KF_AMS_CAL.woff"
- }
- };
- }
- };
- /*!
- * 花体
- */
- _p[28] = {
- value: function() {
- return {
- meta: {
- fontFamily: "KF AMS FRAK",
- src: "KF_AMS_FRAK.woff"
- }
- };
- }
- };
- /*!
- * 字体主文件
- */
- _p[29] = {
- value: function() {
- return {
- meta: {
- fontFamily: "KF AMS MAIN",
- src: "KF_AMS_MAIN.woff"
- },
- map: {
- // char
- Alpha: "Α",
- Beta: "Β",
- Gamma: "Γ",
- Delta: "Δ",
- Epsilon: "Ε",
- Zeta: "Ζ",
- Eta: "Η",
- Theta: "Θ",
- Iota: "Ι",
- Kappa: "Κ",
- Lambda: "Λ",
- Mu: "Μ",
- Nu: "Ν",
- Xi: "Ξ",
- Omicron: "Ο",
- Pi: "Π",
- Rho: "Ρ",
- Sigma: "Σ",
- Tau: "Τ",
- Upsilon: "Υ",
- Phi: "Φ",
- Chi: "Χ",
- Psi: "Ψ",
- Omega: "Ω",
- alpha: "α",
- beta: "β",
- gamma: "γ",
- delta: "δ",
- epsilon: "ε",
- zeta: "ζ",
- eta: "η",
- theta: "θ",
- iota: "ι",
- kappa: "κ",
- lambda: "λ",
- mu: "μ",
- nu: "ν",
- xi: "ξ",
- omicron: "ο",
- pi: "π",
- rho: "ρ",
- sigma: "σ",
- tau: "τ",
- upsilon: "υ",
- phi: "φ",
- varkappa: "ϰ",
- chi: "χ",
- psi: "ψ",
- omega: "ω",
- digamma: "Ϝ",
- varepsilon: "ϵ",
- varrho: "ϱ",
- varphi: "ϕ",
- vartheta: "ϑ",
- varpi: "ϖ",
- varsigma: "Ϲ",
- aleph: "ℵ",
- beth: "ℶ",
- daleth: "ℸ",
- gimel: "ℷ",
- eth: "ð",
- hbar: "ℎ",
- hslash: "ℏ",
- mho: "℧",
- partial: "∂",
- wp: "℘",
- Game: "⅁",
- Bbbk: "⅌",
- Finv: "Ⅎ",
- Im: "ℑ",
- Re: "ℜ",
- complement: "∁",
- ell: "ℓ",
- circledS: "Ⓢ",
- imath: "ı",
- jmath: "ȷ",
- // symbol
- doublecap: "⋒",
- Cap: "⋒",
- doublecup: "⋓",
- Cup: "⋓",
- ast: "*",
- divideontimes: "⋇",
- rightthreetimes: "⋌",
- leftthreetimes: "⋋",
- cdot: "·",
- odot: "⊙",
- dotplus: "∔",
- rtimes: "⋊",
- ltimes: "⋉",
- centerdot: "▪",
- doublebarwedge: "⌭",
- setminus: "⒁",
- amalg: "∐",
- circ: "◦",
- bigcirc: "◯",
- gtrdot: "⋗",
- lessdot: "⋖",
- smallsetminus: "⒅",
- circledast: "⊛",
- circledcirc: "⊚",
- sqcap: "⊓",
- sqcup: "⊔",
- barwedge: "⊼",
- circleddash: "⊝",
- star: "⋆",
- bigtriangledown: "▽",
- bigtriangleup: "△",
- cup: "∪",
- cap: "∩",
- times: "×",
- mp: "∓",
- pm: "±",
- triangleleft: "⊲",
- triangleright: "⊳",
- boxdot: "⊡",
- curlyvee: "⋏",
- curlywedge: "⋎",
- boxminus: "⊟",
- boxtimes: "⊠",
- ominus: "⊖",
- oplus: "⊕",
- oslash: "⊘",
- otimes: "⊗",
- uplus: "⊎",
- boxplus: "⊞",
- dagger: "†",
- ddagger: "‡",
- vee: "∨",
- lor: "∨",
- veebar: "⊻",
- bullet: "•",
- diamond: "⋄",
- wedge: "∧",
- land: "∧",
- div: "÷",
- wr: "≀",
- geqq: "≧",
- lll: "⋘",
- llless: "⋘",
- ggg: "⋙",
- gggtr: "⋙",
- preccurlyeq: "≼",
- geqslant: "⩾",
- lnapprox: "⪉",
- preceq: "⪯",
- gg: "≫",
- lneq: "⪇",
- precnapprox: "⪹",
- approx: "≈",
- lneqq: "≨",
- precneqq: "⪵",
- approxeq: "≊",
- gnapprox: "⪊",
- lnsim: "⋦",
- precnsim: "⋨",
- asymp: "≍",
- gneq: "⪈",
- lvertneqq: "⌮",
- precsim: "≾",
- backsim: "∽",
- gneqq: "≩",
- ncong: "≇",
- risingdotseq: "≓",
- backsimeq: "⋍",
- gnsim: "⋧",
- sim: "∼",
- simeq: "≃",
- bumpeq: "≏",
- gtrapprox: "⪆",
- ngeq: "≱",
- Bumpeq: "≎",
- gtreqless: "⋛",
- ngeqq: "⌱",
- succ: "≻",
- circeq: "≗",
- gtreqqless: "⪌",
- ngeqslant: "⌳",
- succapprox: "⪸",
- cong: "≅",
- gtrless: "≷",
- ngtr: "≯",
- succcurlyeq: "≽",
- curlyeqprec: "⋞",
- gtrsim: "≳",
- nleq: "≰",
- succeq: "⪰",
- curlyeqsucc: "⋟",
- gvertneqq: "⌯",
- neq: "≠",
- ne: "≠",
- nequiv: "≢",
- nleqq: "⌰",
- succnapprox: "⪺",
- doteq: "≐",
- leq: "≤",
- le: "≤",
- nleqslant: "⌲",
- succneqq: "⪶",
- doteqdot: "≑",
- Doteq: "≑",
- leqq: "≦",
- nless: "≮",
- succnsim: "⋩",
- leqslant: "⩽",
- nprec: "⊀",
- succsim: "≿",
- eqsim: "≂",
- lessapprox: "⪅",
- npreceq: "⋠",
- eqslantgtr: "⪖",
- lesseqgtr: "⋚",
- nsim: "≁",
- eqslantless: "⪕",
- lesseqqgtr: "⪋",
- nsucc: "⊁",
- triangleq: "≜",
- eqcirc: "≖",
- equiv: "≡",
- lessgtr: "≶",
- nsucceq: "⋡",
- fallingdotseq: "≒",
- lesssim: "≲",
- prec: "≺",
- geq: "≥",
- ge: "≥",
- ll: "≪",
- precapprox: "⪷",
- // arrows
- uparrow: "↑",
- downarrow: "↓",
- updownarrow: "↕",
- Uparrow: "⇑",
- Downarrow: "⇓",
- Updownarrow: "⇕",
- circlearrowleft: "↺",
- circlearrowright: "↻",
- curvearrowleft: "↶",
- curvearrowright: "↷",
- downdownarrows: "⇊",
- downharpoonleft: "⇃",
- downharpoonright: "⇂",
- leftarrow: "←",
- gets: "←",
- Leftarrow: "⇐",
- leftarrowtail: "↢",
- leftharpoondown: "↽",
- leftharpoonup: "↼",
- leftleftarrows: "⇇",
- leftrightarrow: "↔",
- Leftrightarrow: "⇔",
- leftrightarrows: "⇄",
- leftrightharpoons: "⇋",
- leftrightsquigarrow: "↭",
- Lleftarrow: "⇚",
- looparrowleft: "↫",
- looparrowright: "↬",
- multimap: "⊸",
- nLeftarrow: "⇍",
- nRightarrow: "⇏",
- nLeftrightarrow: "⇎",
- nearrow: "↗",
- nleftarrow: "↚",
- nleftrightarrow: "↮",
- nrightarrow: "↛",
- nwarrow: "↖",
- rightarrow: "→",
- to: "→",
- Rightarrow: "⇒",
- rightarrowtail: "↣",
- rightharpoondown: "⇁",
- rightharpoonup: "⇀",
- rightleftarrows: "⇆",
- rightleftharpoons: "⇌",
- rightrightarrows: "⇉",
- rightsquigarrow: "⇝",
- Rrightarrow: "⇛",
- searrow: "↘",
- swarrow: "↙",
- twoheadleftarrow: "↞",
- twoheadrightarrow: "↠",
- upharpoonleft: "↿",
- upharpoonright: "↾",
- restriction: "↾",
- upuparrows: "⇈",
- Lsh: "↰",
- Rsh: "↱",
- longleftarrow: "⟵",
- longrightarrow: "⟶",
- Longleftarrow: "⟸",
- Longrightarrow: "⟹",
- implies: "⟹",
- longleftrightarrow: "⟷",
- Longleftrightarrow: "⟺",
- // relation
- backepsilon: "∍",
- because: "∵",
- therefore: "∴",
- between: "≬",
- blacktriangleleft: "◀",
- blacktriangleright: "▸",
- dashv: "⊣",
- bowtie: "⋈",
- frown: "⌢",
- "in": "∈",
- notin: "∉",
- mid: "∣",
- parallel: "∥",
- models: "⊨",
- ni: "∋",
- owns: "∋",
- nmid: "∤",
- nparallel: "∦",
- nshortmid: "⏒",
- nshortparallel: "⏓",
- nsubseteq: "⊈",
- nsubseteqq: "⫇",
- nsupseteq: "⊉",
- nsupseteqq: "⫈",
- ntriangleleft: "⋪",
- ntrianglelefteq: "⋬",
- ntriangleright: "⋫",
- ntrianglerighteq: "⋭",
- nvdash: "⊬",
- nVdash: "⊮",
- nvDash: "⊭",
- nVDash: "⊯",
- perp: "⊥",
- pitchfork: "⋔",
- propto: "∝",
- shortmid: "⏐",
- shortparallel: "⏑",
- smile: "⌣",
- sqsubset: "⊏",
- sqsubseteq: "⊑",
- sqsupset: "⊐",
- sqsupseteq: "⊒",
- subset: "⊂",
- Subset: "⋐",
- subseteq: "⊆",
- subseteqq: "⫅",
- subsetneq: "⊊",
- subsetneqq: "⫋",
- supset: "⊃",
- Supset: "⋑",
- supseteq: "⊇",
- supseteqq: "⫆",
- supsetneq: "⊋",
- supsetneqq: "⫌",
- trianglelefteq: "⊴",
- trianglerighteq: "⊵",
- varpropto: "⫉",
- varsubsetneq: "⏔",
- varsubsetneqq: "⏖",
- varsupsetneq: "⏕",
- varsupsetneqq: "⏗",
- vdash: "⊢",
- Vdash: "⊩",
- vDash: "⊨",
- Vvdash: "⊪",
- vert: "|",
- Vert: "ǁ",
- "|": "ǁ",
- "{": "{",
- "}": "}",
- backslash: "\\",
- langle: "〈",
- rangle: "〉",
- lceil: "⌈",
- rceil: "⌉",
- lbrace: "{",
- rbrace: "}",
- lfloor: "⌊",
- rfloor: "⌋",
- cdots: "⋯",
- ddots: "⋰",
- vdots: "⋮",
- dots: "…",
- ldots: "…",
- "#": "#",
- bot: "⊥",
- angle: "∠",
- backprime: "‵",
- bigstar: "★",
- blacklozenge: "◆",
- blacksquare: "■",
- blacktriangle: "▲",
- blacktriangledown: "▼",
- clubsuit: "♣",
- diagdown: "⒁",
- diagup: "⒂",
- diamondsuit: "♢",
- emptyset: "ø",
- exists: "∃",
- flat: "♭",
- forall: "∀",
- heartsuit: "♡",
- infty: "∞",
- lozenge: "◇",
- measuredangle: "∡",
- nabla: "∇",
- natural: "♮",
- neg: "¬",
- lnot: "¬",
- nexists: "∄",
- prime: "′",
- sharp: "♯",
- spadesuit: "♠",
- sphericalangle: "∢",
- surd: "√",
- top: "⊤",
- varnothing: "∅",
- triangle: "△",
- triangledown: "▽"
- }
- };
- }
- };
- /*!
- * 罗马字体
- */
- _p[30] = {
- value: function() {
- return {
- meta: {
- fontFamily: "KF AMS ROMAN",
- src: "KF_AMS_ROMAN.woff"
- }
- };
- }
- };
- /**
- * 公式对象,表达式容器
- */
- _p[31] = {
- value: function(require) {
- var kity = _p.r(34), GTYPE = _p.r(6), FontManager = _p.r(25), FontInstaller = _p.r(24), DEFAULT_OPTIONS = {
- fontsize: 50,
- autoresize: true,
- padding: [ 0 ]
- }, Output = _p.r(1), EXPRESSION_INTERVAL = 10, ExpressionWrap = kity.createClass("ExpressionWrap", {
- constructor: function(exp, config) {
- this.wrap = new kity.Group();
- this.bg = new kity.Rect(0, 0, 0, 0).fill("transparent");
- this.exp = exp;
- this.config = config;
- this.wrap.setAttr("data-type", "kf-exp-wrap");
- this.bg.setAttr("data-type", "kf-exp-wrap-bg");
- this.wrap.addShape(this.bg);
- this.wrap.addShape(this.exp);
- },
- getWrapShape: function() {
- return this.wrap;
- },
- getExpression: function() {
- return this.exp;
- },
- getBackground: function() {
- return this.bg;
- },
- resize: function() {
- var padding = this.config.padding, expBox = this.exp.getFixRenderBox();
- if (padding.length === 1) {
- padding[1] = padding[0];
- }
- this.bg.setSize(padding[1] * 2 + expBox.width, padding[0] * 2 + expBox.height);
- this.exp.translate(padding[1], padding[0]);
- }
- }), Formula = kity.createClass("Formula", {
- base: _p.r(32),
- constructor: function(container, config) {
- this.callBase(container);
- this.expressions = [];
- this.fontInstaller = new FontInstaller(this);
- this.config = kity.Utils.extend({}, DEFAULT_OPTIONS, config);
- this.initEnvironment();
- this.initInnerFont();
- },
- getContentContainer: function() {
- return this.container;
- },
- initEnvironment: function() {
- this.zoom = this.config.fontsize / 50;
- if ("width" in this.config) {
- this.setWidth(this.config.width);
- }
- if ("height" in this.config) {
- this.setHeight(this.config.height);
- }
- this.node.setAttribute("font-size", DEFAULT_OPTIONS.fontsize);
- },
- initInnerFont: function() {
- var fontList = FontManager.getFontList(), _self = this;
- kity.Utils.each(fontList, function(fontInfo) {
- createFontStyle(fontInfo);
- });
- function createFontStyle(fontInfo) {
- var stylesheet = _self.doc.createElement("style"), tpl = '@font-face{font-family: "${fontFamily}";font-style: normal;src: url("${src}") format("woff");}';
- stylesheet.setAttribute("type", "text/css");
- stylesheet.innerHTML = tpl.replace("${fontFamily}", fontInfo.meta.fontFamily).replace("${src}", fontInfo.meta.src);
- _self.resourceNode.appendChild(stylesheet);
- }
- },
- insertExpression: function(expression, index) {
- var expWrap = this.wrap(expression);
- // clear zoom
- this.container.clearTransform();
- this.expressions.splice(index, 0, expWrap.getWrapShape());
- this.addShape(expWrap.getWrapShape());
- notifyExpression.call(this, expWrap.getExpression());
- expWrap.resize();
- correctOffset.call(this);
- this.resetZoom();
- this.config.autoresize && this.resize();
- },
- appendExpression: function(expression) {
- this.insertExpression(expression, this.expressions.length);
- },
- resize: function() {
- var renderBox = this.container.getRenderBox("paper");
- this.node.setAttribute("width", renderBox.width);
- this.node.setAttribute("height", renderBox.height);
- },
- resetZoom: function() {
- var zoomLevel = this.zoom / this.getBaseZoom();
- if (zoomLevel !== 0) {
- this.container.scale(zoomLevel);
- }
- },
- wrap: function(exp) {
- return new ExpressionWrap(exp, this.config);
- },
- clear: function() {
- this.callBase();
- this.expressions = [];
- },
- clearExpressions: function() {
- kity.Utils.each(this.expressions, function(exp) {
- exp.remove();
- });
- this.expressions = [];
- },
- toJPG: function(cb) {
- new Output(this).toJPG(cb);
- },
- toPNG: function(cb) {
- new Output(this).toPNG(cb);
- }
- });
- kity.Utils.extend(Formula, {
- registerFont: function(fontData) {
- FontManager.registerFont(fontData);
- }
- });
- // 调整表达式之间的偏移
- function correctOffset() {
- var exprOffset = 0;
- kity.Utils.each(this.expressions, function(expr) {
- var box = null;
- if (!expr) {
- return;
- }
- expr.setMatrix(new kity.Matrix(1, 0, 0, 1, 0, 0));
- box = expr.getFixRenderBox();
- expr.translate(0 - box.x, exprOffset);
- exprOffset += box.height + EXPRESSION_INTERVAL;
- });
- return this;
- }
- // 通知表达式已接入到paper
- function notifyExpression(expression) {
- var len = 0;
- if (!expression) {
- return;
- }
- if (expression.getType() === GTYPE.EXP) {
- for (var i = 0, len = expression.getChildren().length; i < len; i++) {
- notifyExpression(expression.getChild(i));
- }
- } else if (expression.getType() === GTYPE.COMPOUND_EXP) {
- // 操作数处理
- for (var i = 0, len = expression.getOperands().length; i < len; i++) {
- notifyExpression(expression.getOperand(i));
- }
- // 处理操作符
- notifyExpression(expression.getOperator());
- }
- expression.addedCall && expression.addedCall();
- }
- return Formula;
- }
- };
- /**
- * 公式专用paper
- */
- _p[32] = {
- value: function(require) {
- var kity = _p.r(34);
- return kity.createClass("FPaper", {
- base: kity.Paper,
- constructor: function(container) {
- this.callBase(container);
- this.doc = container.ownerDocument;
- this.container = new kity.Group();
- this.container.setAttr("data-type", "kf-container");
- this.background = new kity.Group();
- this.background.setAttr("data-type", "kf-bg");
- this.baseZoom = 1;
- this.zoom = 1;
- this.base("addShape", this.background);
- this.base("addShape", this.container);
- },
- getZoom: function() {
- return this.zoom;
- },
- getBaseZoom: function() {
- return this.baseZoom;
- },
- addShape: function(shape, pos) {
- return this.container.addShape(shape, pos);
- },
- getBackground: function() {
- return this.background;
- },
- removeShape: function(pos) {
- return this.container.removeShape(pos);
- },
- clear: function() {
- return this.container.clear();
- }
- });
- }
- };
- /**
- * jquery
- */
- _p[33] = {
- value: function() {
- if (!window.jQuery) {
- throw new Error("Missing jQuery");
- }
- return window.jQuery;
- }
- };
- /**
- * kity库封包
- */
- _p[34] = {
- value: function() {
- if (!window.kity) {
- throw new Error("Missing Kity Graphic Lib");
- }
- return window.kity;
- }
- };
- /**
- * 小括号操作符:()
- */
- _p[35] = {
- value: function(require) {
- var kity = _p.r(34), Text = _p.r(5);
- return kity.createClass("BracketsOperator", {
- base: _p.r(41),
- constructor: function() {
- this.callBase("Brackets");
- },
- applyOperand: function(exp) {
- generate.call(this, exp);
- }
- });
- function generate(exp) {
- var left = this.getParentExpression().getLeftSymbol(), right = this.getParentExpression().getRightSymbol(), fontSize = exp.getFixRenderBox().height, group = new kity.Group(), offset = 0, leftOp = new Text(left, "KF AMS MAIN").fill("black"), rightOp = new Text(right, "KF AMS MAIN").fill("black");
- leftOp.setFontSize(fontSize);
- rightOp.setFontSize(fontSize);
- this.addOperatorShape(group.addShape(leftOp).addShape(rightOp));
- offset += leftOp.getFixRenderBox().width;
- exp.translate(offset, 0);
- offset += exp.getFixRenderBox().width;
- rightOp.translate(offset, 0);
- }
- }
- };
- /**
- * 组合操作符
- * 操作多个表达式组合在一起
- */
- _p[36] = {
- value: function(require) {
- var kity = _p.r(34);
- return kity.createClass("CombinationOperator", {
- base: _p.r(41),
- constructor: function() {
- this.callBase("Combination");
- },
- applyOperand: function() {
- // 偏移量
- var offsetX = 0, // 操作数
- operands = arguments, // 操作对象最大高度
- maxHeight = 0, // 垂直距离最大偏移
- maxOffsetTop = 0, maxOffsetBottom = 0, cached = [], // 偏移集合
- offsets = [];
- kity.Utils.each(operands, function(operand) {
- var box = operand.getFixRenderBox(), offsetY = operand.getOffset();
- box.height -= offsetY.top + offsetY.bottom;
- cached.push(box);
- offsets.push(offsetY);
- maxOffsetTop = Math.max(offsetY.top, maxOffsetTop);
- maxOffsetBottom = Math.max(offsetY.bottom, maxOffsetBottom);
- maxHeight = Math.max(box.height, maxHeight);
- });
- kity.Utils.each(operands, function(operand, index) {
- var box = cached[index];
- operand.translate(offsetX - box.x, (maxHeight - (box.y + box.height)) / 2 + maxOffsetBottom - offsets[index].bottom);
- offsetX += box.width;
- });
- this.parentExpression.setOffset(maxOffsetTop, maxOffsetBottom);
- this.parentExpression.updateBoxSize();
- }
- });
- }
- };
- /*!
- * 上下标控制器
- */
- _p[37] = {
- value: function(require) {
- var kity = _p.r(34), EmptyExpression = _p.r(20), defaultOptions = {
- subOffset: 0,
- supOffset: 0,
- // 上下标的默认缩放值
- zoom: .66
- };
- return kity.createClass("ScriptController", {
- constructor: function(opObj, target, sup, sub, options) {
- this.observer = opObj.getParentExpression();
- this.target = target;
- this.sup = sup;
- this.sub = sub;
- this.options = kity.Utils.extend({}, defaultOptions, options);
- },
- // 上下标记
- applyUpDown: function() {
- var target = this.target, sup = this.sup, sub = this.sub, options = this.options;
- sup.scale(options.zoom);
- sub.scale(options.zoom);
- var targetBox = target.getFixRenderBox();
- if (EmptyExpression.isEmpty(sup) && EmptyExpression.isEmpty(sub)) {
- return {
- width: targetBox.width,
- height: targetBox.height,
- top: 0,
- bottom: 0
- };
- } else {
- // 上标
- if (!EmptyExpression.isEmpty(sup) && EmptyExpression.isEmpty(sub)) {
- return this.applyUp(target, sup);
- } else if (EmptyExpression.isEmpty(sup) && !EmptyExpression.isEmpty(sub)) {
- return this.applyDown(target, sub);
- } else {
- return this.applyUpDownScript(target, sup, sub);
- }
- }
- },
- /**
- * 返回应用上下标后的空间占用情况,其中的key各自的意义是:
- * top: 上空间偏移
- * bottom: 下空间偏移
- * width: 当前整个图形的实际占用空间的width
- * height: 当前整个图形的实际占用空间的height
- * @returns {*}
- */
- applySide: function() {
- var target = this.target, sup = this.sup, sub = this.sub;
- if (EmptyExpression.isEmpty(sup) && EmptyExpression.isEmpty(sub)) {
- var targetRectBox = target.getRenderBox(this.observer);
- return {
- width: targetRectBox.width,
- height: targetRectBox.height,
- top: 0,
- bottom: 0
- };
- } else {
- // 下标处理
- if (EmptyExpression.isEmpty(sup) && !EmptyExpression.isEmpty(sub)) {
- return this.applySideSub(target, sub);
- } else if (!EmptyExpression.isEmpty(sup) && EmptyExpression.isEmpty(sub)) {
- return this.applySideSuper(target, sup);
- } else {
- return this.applySideScript(target, sup, sub);
- }
- }
- },
- applySideSuper: function(target, sup) {
- sup.scale(this.options.zoom);
- var targetRectBox = target.getRenderBox(this.observer), supRectBox = sup.getRenderBox(this.observer), targetMeanline = target.getMeanline(this.observer), supBaseline = sup.getBaseline(this.observer), positionline = targetMeanline, diff = supBaseline - positionline, space = {
- top: 0,
- bottom: 0,
- width: targetRectBox.width + supRectBox.width,
- height: targetRectBox.height
- };
- sup.translate(targetRectBox.width, 0);
- if (this.options.supOffset) {
- sup.translate(this.options.supOffset, 0);
- }
- if (diff > 0) {
- target.translate(0, diff);
- space.bottom = diff;
- space.height += diff;
- } else {
- sup.translate(0, -diff);
- }
- return space;
- },
- applySideSub: function(target, sub) {
- sub.scale(this.options.zoom);
- var targetRectBox = target.getRenderBox(this.observer), subRectBox = sub.getRenderBox(this.observer), subOffset = sub.getOffset(), targetBaseline = target.getBaseline(this.observer), // 下标定位线
- subPosition = (subRectBox.height + subOffset.top + subOffset.bottom) / 2, diff = targetRectBox.height - targetBaseline - subPosition, space = {
- top: 0,
- bottom: 0,
- width: targetRectBox.width + subRectBox.width,
- height: targetRectBox.height
- };
- // 定位下标位置
- sub.translate(targetRectBox.width, subOffset.top + targetBaseline - subPosition);
- if (this.options.subOffset) {
- sub.translate(this.options.subOffset, 0);
- }
- if (diff < 0) {
- space.top = -diff;
- space.height -= diff;
- }
- return space;
- },
- applySideScript: function(target, sup, sub) {
- sup.scale(this.options.zoom);
- sub.scale(this.options.zoom);
- var targetRectBox = target.getRenderBox(this.observer), subRectBox = sub.getRenderBox(this.observer), supRectBox = sup.getRenderBox(this.observer), targetMeanline = target.getMeanline(this.observer), targetBaseline = target.getBaseline(this.observer), supBaseline = sup.getBaseline(this.observer), // 上下标都存在时, 下标的定位以上伸线为准
- subAscenderline = sub.getAscenderline(this.observer), supPosition = targetMeanline, subPosition = targetMeanline + (targetBaseline - targetMeanline) * 2 / 3, topDiff = supPosition - supBaseline, bottomDiff = targetRectBox.height - subPosition - (subRectBox.height - subAscenderline), space = {
- top: 0,
- bottom: 0,
- width: targetRectBox.width + Math.max(subRectBox.width, supRectBox.width),
- height: targetRectBox.height
- };
- sup.translate(targetRectBox.width, topDiff);
- sub.translate(targetRectBox.width, subPosition - subAscenderline);
- if (this.options.supOffset) {
- sup.translate(this.options.supOffset, 0);
- }
- if (this.options.subOffset) {
- sub.translate(this.options.subOffset, 0);
- }
- // 定位纠正
- if (topDiff > 0) {
- if (bottomDiff < 0) {
- targetRectBox.height -= bottomDiff;
- space.top = -bottomDiff;
- }
- } else {
- target.translate(0, -topDiff);
- sup.translate(0, -topDiff);
- sub.translate(0, -topDiff);
- space.height -= topDiff;
- if (bottomDiff > 0) {
- space.bottom = -topDiff;
- } else {
- space.height -= bottomDiff;
- // 比较上下偏移, 获取正确的偏移值
- topDiff = -topDiff;
- bottomDiff = -bottomDiff;
- if (topDiff > bottomDiff) {
- space.bottom = topDiff - bottomDiff;
- } else {
- space.top = bottomDiff - topDiff;
- }
- }
- }
- return space;
- },
- applyUp: function(target, sup) {
- var supBox = sup.getFixRenderBox(), targetBox = target.getFixRenderBox(), space = {
- width: Math.max(targetBox.width, supBox.width),
- height: supBox.height + targetBox.height,
- top: 0,
- bottom: supBox.height
- };
- sup.translate((space.width - supBox.width) / 2, 0);
- target.translate((space.width - targetBox.width) / 2, supBox.height);
- return space;
- },
- applyDown: function(target, sub) {
- var subBox = sub.getFixRenderBox(), targetBox = target.getFixRenderBox(), space = {
- width: Math.max(targetBox.width, subBox.width),
- height: subBox.height + targetBox.height,
- top: subBox.height,
- bottom: 0
- };
- sub.translate((space.width - subBox.width) / 2, targetBox.height);
- target.translate((space.width - targetBox.width) / 2, 0);
- return space;
- },
- applyUpDownScript: function(target, sup, sub) {
- var supBox = sup.getFixRenderBox(), subBox = sub.getFixRenderBox(), targetBox = target.getFixRenderBox(), space = {
- width: Math.max(targetBox.width, supBox.width, subBox.width),
- height: supBox.height + subBox.height + targetBox.height,
- top: 0,
- bottom: 0
- };
- sup.translate((space.width - supBox.width) / 2, 0);
- target.translate((space.width - targetBox.width) / 2, supBox.height);
- sub.translate((space.width - subBox.width) / 2, supBox.height + targetBox.height);
- return space;
- }
- });
- }
- };
- /**
- * 分数操作符
- */
- _p[38] = {
- value: function(require) {
- var kity = _p.r(34), ZOOM = _p.r(47).zoom;
- return kity.createClass("FractionOperator", {
- base: _p.r(41),
- constructor: function() {
- this.callBase("Fraction");
- },
- applyOperand: function(upOperand, downOperand) {
- upOperand.scale(ZOOM);
- downOperand.scale(ZOOM);
- var upWidth = Math.ceil(upOperand.getWidth()), downWidth = Math.ceil(downOperand.getWidth()), upHeight = Math.ceil(upOperand.getHeight()), downHeight = Math.ceil(downOperand.getHeight()), // 分数线overflow值
- overflow = 3, // 整体padding
- padding = 1, maxWidth = Math.max(upWidth, downWidth), maxHeight = Math.max(upHeight, downHeight), operatorShape = generateOperator(maxWidth, overflow);
- this.addOperatorShape(operatorShape);
- upOperand.translate((maxWidth - upWidth) / 2 + overflow, 0);
- operatorShape.translate(0, upHeight + 1);
- // 下部不需要偏移
- downOperand.translate((maxWidth - downWidth) / 2 + overflow, upHeight + operatorShape.getHeight() + 1 * 2);
- this.parentExpression.setOffset(maxHeight - upHeight, maxHeight - downHeight);
- this.parentExpression.expand(padding * 2, padding * 2);
- this.parentExpression.translateElement(padding, padding);
- }
- });
- function generateOperator(width, overflow) {
- return new kity.Rect(width + overflow * 2, 1).fill("black");
- }
- }
- };
- /**
- * 函数操作符
- */
- _p[39] = {
- value: function(require) {
- var kity = _p.r(34), Text = _p.r(5), ScriptController = _p.r(37);
- return kity.createClass("FunctionOperator", {
- base: _p.r(41),
- constructor: function(funcName) {
- this.callBase("Function: " + funcName);
- this.funcName = funcName;
- },
- /*
- * 积分操作符应用操作数
- * @param expr 函数表达式
- * @param sup 上限
- * @param sub 下限
- */
- applyOperand: function(expr, sup, sub) {
- var opShape = generateOperator.call(this), expBox = expr.getFixRenderBox(), scriptHanlder = this.parentExpression.isSideScript() ? "applySide" : "applyUpDown", space = new ScriptController(this, opShape, sup, sub, {
- zoom: .5
- })[scriptHanlder](), padding = 5, diff = (space.height + space.top + space.bottom - expBox.height) / 2;
- // 应用偏移, 使图形在正确的位置上
- opShape.translate(0, space.top);
- sup.translate(0, space.top);
- sub.translate(0, space.top);
- if (diff >= 0) {
- expr.translate(space.width + padding, diff);
- } else {
- diff = -diff;
- opShape.translate(0, diff);
- sup.translate(0, diff);
- sub.translate(0, diff);
- expr.translate(space.width + padding, 0);
- }
- // 只扩展左边, 不扩展右边, 所以padding不 *2
- this.parentExpression.expand(padding, padding * 2);
- this.parentExpression.translateElement(padding, padding);
- }
- });
- /* 返回操作符对象 */
- function generateOperator() {
- var opShape = new Text(this.funcName, "KF AMS ROMAN");
- this.addOperatorShape(opShape);
- // 为操作符图形创建baseline和meanline方法
- opShape.getBaseline = function() {
- return opShape.getFixRenderBox().height;
- };
- opShape.getMeanline = function() {
- return 0;
- };
- return opShape;
- }
- }
- };
- /**
- * 积分操作符:∫
- */
- _p[40] = {
- value: function(require) {
- var kity = _p.r(34), ScriptController = _p.r(37);
- return kity.createClass("IntegrationOperator", {
- base: _p.r(41),
- constructor: function(type) {
- this.callBase("Integration");
- // 默认是普通单重积分
- this.opType = type || 1;
- },
- setType: function(type) {
- this.opType = type | 0;
- },
- // 重置类型
- resetType: function() {
- this.opType = 1;
- },
- applyOperand: function(exp, sup, sub) {
- var opShape = this.getOperatorShape(), padding = 3, expBox = exp.getFixRenderBox(), space = new ScriptController(this, opShape, sup, sub, {
- supOffset: 3,
- subOffset: -15
- }).applySide(), diff = (space.height + space.top - expBox.height) / 2;
- opShape.translate(0, space.top);
- sup.translate(0, space.top);
- sub.translate(0, space.top);
- if (diff >= 0) {
- exp.translate(space.width + padding, diff);
- } else {
- diff = -diff;
- opShape.translate(0, diff);
- sup.translate(0, diff);
- sub.translate(0, diff);
- exp.translate(space.width + padding, 0);
- }
- this.parentExpression.expand(padding, padding * 2);
- this.parentExpression.translateElement(padding, padding);
- },
- getOperatorShape: function() {
- var pathData = "M1.318,48.226c0,0,0.044,0.066,0.134,0.134c0.292,0.313,0.626,0.447,1.006,0.447c0.246,0.022,0.358-0.044,0.604-0.268 c0.782-0.782,1.497-2.838,2.324-6.727c0.514-2.369,0.938-4.693,1.586-8.448C8.559,24.068,9.9,17.878,11.978,9.52 c0.917-3.553,1.922-7.576,3.866-8.983C16.247,0.246,16.739,0,17.274,0c1.564,0,2.503,1.162,2.592,2.57 c0,0.827-0.424,1.386-1.273,1.386c-0.671,0-1.229-0.514-1.229-1.251c0-0.805,0.514-1.095,1.185-1.274 c0.022,0-0.291-0.29-0.425-0.379c-0.201-0.134-0.514-0.224-0.737-0.224c-0.067,0-0.112,0-0.157,0.022 c-0.469,0.134-0.983,0.939-1.453,2.234c-0.537,1.475-0.961,3.174-1.631,6.548c-0.424,2.101-0.693,3.464-1.229,6.727 c-1.608,9.185-2.949,15.487-5.006,23.756c-0.514,2.034-0.849,3.24-1.207,4.335c-0.559,1.698-1.162,2.95-1.811,3.799 c-0.514,0.715-1.385,1.408-2.436,1.408c-1.363,0-2.391-1.185-2.458-2.592c0-0.804,0.447-1.363,1.273-1.363 c0.671,0,1.229,0.514,1.229,1.251C2.503,47.757,1.989,48.047,1.318,48.226z", group = new kity.Group(), opGroup = new kity.Group(), opShape = new kity.Path(pathData).fill("black"), opBox = new kity.Rect(0, 0, 0, 0).fill("transparent"), tmpShape = null;
- opGroup.addShape(opShape);
- group.addShape(opBox);
- group.addShape(opGroup);
- this.addOperatorShape(group);
- for (var i = 1; i < this.opType; i++) {
- tmpShape = new kity.Use(opShape).translate(opShape.getWidth() / 2 * i, 0);
- opGroup.addShape(tmpShape);
- }
- opGroup.scale(1.6);
- tmpShape = null;
- // 为操作符图形创建baseline和meanline方法
- group.getBaseline = function() {
- return opGroup.getFixRenderBox().height;
- };
- group.getMeanline = function() {
- return 10;
- };
- return group;
- }
- });
- }
- };
- /**
- * 操作符抽象类
- * @abstract
- */
- _p[41] = {
- value: function(require) {
- var kity = _p.r(34), GTYPE = _p.r(6);
- return kity.createClass("Operator", {
- base: _p.r(46),
- constructor: function(operatorName) {
- this.callBase();
- this.type = GTYPE.OP;
- // 该操作符所属的表达式
- this.parentExpression = null;
- // 操作符名称
- this.operatorName = operatorName;
- // 操作符图形
- this.operatorShape = new kity.Group();
- this.addShape(this.operatorShape);
- },
- applyOperand: function() {
- throw new Error("applyOperand is abstract");
- },
- setParentExpression: function(exp) {
- this.parentExpression = exp;
- },
- getParentExpression: function() {
- return this.parentExpression;
- },
- clearParentExpression: function() {
- this.parentExpression = null;
- },
- // 提供给具体实现类附加其绘制的操作符图形的接口
- addOperatorShape: function(shpae) {
- return this.operatorShape.addShape(shpae);
- },
- getOperatorShape: function() {
- return this.operatorShape;
- }
- });
- }
- };
- /**
- * 开方操作符
- */
- _p[42] = {
- value: function(require) {
- var kity = _p.r(34), // 符号图形属性
- // 线条宽度
- SHAPE_DATA_WIDTH = 1, // 计算公式
- radians = 2 * Math.PI / 360, sin15 = Math.sin(15 * radians), cos15 = Math.cos(15 * radians), tan15 = Math.tan(15 * radians);
- return kity.createClass("RadicalOperator", {
- base: _p.r(41),
- constructor: function() {
- this.callBase("Radical");
- },
- applyOperand: function(radicand, exponent) {
- generateOperator.call(this, radicand, exponent);
- }
- });
- // 根据给定的操作数生成操作符的pathData
- // radicand 表示被开方数
- // exponent 表示指数
- function generateOperator(radicand, exponent) {
- var decoration = generateDecoration(radicand), vLine = generateVLine(radicand), padding = 5, hLine = generateHLine(radicand);
- this.addOperatorShape(decoration);
- this.addOperatorShape(vLine);
- this.addOperatorShape(hLine);
- adjustmentPosition.call(this, mergeShape(decoration, vLine, hLine), this.operatorShape, radicand, exponent);
- this.parentExpression.expand(0, padding * 2);
- this.parentExpression.translateElement(0, padding);
- }
- // 生成根号中的左边装饰部分
- function generateDecoration(radicand) {
- var shape = new kity.Path(), // 命名为a以便于精简表达式
- a = SHAPE_DATA_WIDTH, h = radicand.getHeight() / 3, drawer = shape.getDrawer();
- // 根号尾部左上角开始
- drawer.moveTo(0, cos15 * a * 6);
- drawer.lineBy(sin15 * a, cos15 * a);
- drawer.lineBy(cos15 * a * 3, -sin15 * a * 3);
- drawer.lineBy(tan15 * h, h);
- drawer.lineBy(sin15 * a * 3, -cos15 * a * 3);
- drawer.lineBy(-sin15 * h, -h);
- drawer.close();
- return shape.fill("black");
- }
- // 根据操作数生成根号的竖直线部分
- function generateVLine(operand) {
- var shape = new kity.Path(), // * 0.9 是为了在视觉上使斜线部分不至于太高
- h = operand.getHeight() * .9, drawer = shape.getDrawer();
- drawer.moveTo(tan15 * h, 0);
- drawer.lineTo(0, h);
- drawer.lineBy(sin15 * SHAPE_DATA_WIDTH * 3, cos15 * SHAPE_DATA_WIDTH * 3);
- drawer.lineBy(tan15 * h + sin15 * SHAPE_DATA_WIDTH * 3, -(h + 3 * SHAPE_DATA_WIDTH * cos15));
- drawer.close();
- return shape.fill("black");
- }
- // 根据操作数生成根号的水平线部分
- function generateHLine(operand) {
- // 表达式宽度
- var w = operand.getWidth() + 2 * SHAPE_DATA_WIDTH;
- return new kity.Rect(w, 2 * SHAPE_DATA_WIDTH).fill("black");
- }
- // 合并根号的各个部分, 并返回根号的关键点位置数据
- function mergeShape(decoration, vLine, hLine) {
- var decoBox = decoration.getFixRenderBox(), vLineBox = vLine.getFixRenderBox();
- vLine.translate(decoBox.width - sin15 * SHAPE_DATA_WIDTH * 3, 0);
- decoration.translate(0, vLineBox.height - decoBox.height);
- vLineBox = vLine.getFixRenderBox();
- hLine.translate(vLineBox.x + vLineBox.width - SHAPE_DATA_WIDTH / cos15, 0);
- // 返回关键点数据
- return {
- x: vLineBox.x + vLineBox.width - SHAPE_DATA_WIDTH / cos15,
- y: 0
- };
- }
- // 调整整个根号表达式的各个部分: 位置、操作符、被开方数、指数
- function adjustmentPosition(position, operator, radicand, exponent) {
- var exponentBox = null, opOffset = {
- x: 0,
- y: 0
- }, opBox = operator.getFixRenderBox();
- exponent.scale(.66);
- exponentBox = exponent.getFixRenderBox();
- if (exponentBox.width > 0 && exponentBox.height > 0) {
- opOffset.y = exponentBox.height - opBox.height / 2;
- // 指数不超出根号, 则移动指数
- if (opOffset.y < 0) {
- exponent.translate(0, -opOffset.y);
- opOffset.y = 0;
- }
- opOffset.x = exponentBox.width + opBox.height / 2 * tan15 - position.x;
- }
- operator.translate(opOffset.x, opOffset.y);
- radicand.translate(opOffset.x + position.x + SHAPE_DATA_WIDTH, opOffset.y + 2 * SHAPE_DATA_WIDTH);
- }
- }
- };
- /**
- * 上下标操作符
- */
- _p[43] = {
- value: function(require) {
- var kity = _p.r(34), ScriptController = _p.r(37);
- return kity.createClass("ScriptOperator", {
- base: _p.r(41),
- constructor: function(operatorName) {
- this.callBase(operatorName || "Script");
- },
- applyOperand: function(operand, sup, sub) {
- var padding = 1, parent = this.parentExpression, space = new ScriptController(this, operand, sup, sub).applySide();
- this.getOperatorShape();
- space && parent.setOffset(space.top, space.bottom);
- parent.expand(4, padding * 2);
- parent.translateElement(2, padding);
- }
- });
- }
- };
- /**
- * 求和操作符:∑
- */
- _p[44] = {
- value: function(require) {
- var kity = _p.r(34), ScriptController = _p.r(37);
- return kity.createClass("SummationOperator", {
- base: _p.r(41),
- constructor: function() {
- this.callBase("Summation");
- this.displayType = "equation";
- },
- applyOperand: function(expr, sup, sub) {
- var opShape = this.getOperatorShape(), expBox = expr.getFixRenderBox(), padding = 0, space = new ScriptController(this, opShape, sup, sub).applyUpDown(), diff = (space.height - space.top - space.bottom - expBox.height) / 2;
- if (diff >= 0) {
- expr.translate(space.width + padding, diff + space.bottom);
- } else {
- diff = -diff;
- opShape.translate(0, diff);
- sup.translate(0, diff);
- sub.translate(0, diff);
- expr.translate(space.width + padding, space.bottom);
- }
- this.parentExpression.setOffset(space.top, space.bottom);
- this.parentExpression.expand(padding, padding * 2);
- this.parentExpression.translateElement(padding, padding);
- },
- getOperatorShape: function() {
- var pathData = "M0.672,33.603c-0.432,0-0.648,0-0.648-0.264c0-0.024,0-0.144,0.24-0.432l12.433-14.569L0,0.96c0-0.264,0-0.72,0.024-0.792 C0.096,0.024,0.12,0,0.672,0h28.371l2.904,6.745h-0.6C30.531,4.8,28.898,3.72,28.298,3.336c-1.896-1.2-3.984-1.608-5.28-1.8 c-0.216-0.048-2.4-0.384-5.617-0.384H4.248l11.185,15.289c0.168,0.24,0.168,0.312,0.168,0.36c0,0.12-0.048,0.192-0.216,0.384 L3.168,31.515h14.474c4.608,0,6.96-0.624,7.464-0.744c2.76-0.72,5.305-2.352,6.241-4.848h0.6l-2.904,7.681H0.672z", operatorShape = new kity.Path(pathData).fill("black"), opBgShape = new kity.Rect(0, 0, 0, 0).fill("transparent"), group = new kity.Group(), opRenderBox = null;
- group.addShape(opBgShape);
- group.addShape(operatorShape);
- operatorShape.scale(1.6);
- this.addOperatorShape(group);
- opRenderBox = operatorShape.getFixRenderBox();
- if (this.displayType === "inline") {
- operatorShape.translate(5, 15);
- opBgShape.setSize(opRenderBox.width + 10, opRenderBox.height + 25);
- } else {
- operatorShape.translate(2, 5);
- opBgShape.setSize(opRenderBox.width + 4, opRenderBox.height + 8);
- }
- return group;
- }
- });
- }
- };
- /*!
- * 资源管理器
- * 负责管理资源的加载,并在资源ready之后提供Formula构造器
- */
- _p[45] = {
- value: function(require) {
- var kity = _p.r(34), cbList = [], RES_CONF = _p.r(47).resource, FontInstall = _p.r(24), Formula = _p.r(31), // 资源管理器就绪状态
- __readyState = false, // 资源管理器是否已启动
- inited = false;
- return {
- // 初始化
- ready: function(cb, options) {
- if (!inited) {
- inited = true;
- init(options);
- }
- if (__readyState) {
- window.setTimeout(function() {
- cb(Formula);
- }, 0);
- } else {
- cbList.push(cb);
- }
- }
- };
- /**
- * 资源初始化
- */
- function init(options) {
- options = kity.Utils.extend({}, RES_CONF, options);
- if (!/^(https?:)?\/\//.test(options.path)) {
- options.path = getFullPath(options.path);
- }
- new FontInstall(document, options.path).mount(complete);
- }
- function complete() {
- kity.Utils.each(cbList, function(cb) {
- cb(Formula);
- });
- }
- function getFullPath(path) {
- var pathname = location.pathname.split("/"), pathPart;
- pathname.length -= 1;
- pathname = pathname.join("/") + "/";
- pathPart = [ location.protocol, "//", location.host, pathname, path.replace(/^\//, "") ];
- return pathPart.join("");
- }
- }
- };
- /*!
- * 所有符号的基类
- * @abstract
- */
- _p[46] = {
- value: function(require) {
- var kity = _p.r(34), GTYPE = _p.r(6);
- return kity.createClass("SignGroup", {
- base: kity.Group,
- constructor: function() {
- this.callBase();
- this.box = new kity.Rect(0, 0, 0, 0);
- this.type = GTYPE.UNKNOWN;
- this.addShape(this.box);
- this.zoom = 1;
- },
- setZoom: function(zoom) {
- this.zoom = zoom;
- },
- getZoom: function() {
- return this.zoom;
- },
- setBoxSize: function(w, h) {
- return this.box.setSize(w, h);
- },
- setBoxWidth: function(w) {
- return this.box.setWidth(w);
- },
- setBoxHeight: function(h) {
- return this.box.setHeight(h);
- },
- getType: function() {
- return this.type;
- },
- getBaseHeight: function() {
- return this.getHeight();
- },
- getBaseWidth: function() {
- return this.getWidth();
- },
- addedCall: function() {}
- });
- }
- };
- /*!
- * 系统项目配置文件.
- */
- _p[47] = {
- value: function(require) {
- return {
- zoom: .66,
- font: {
- meanline: Math.round(380 / 1e3 * 50),
- baseline: Math.round(800 / 1e3 * 50),
- baseHeight: 50,
- // 系统字体列表
- list: [ _p.r(29), _p.r(27), _p.r(28), _p.r(26), _p.r(30) ]
- },
- /*------------------------- 资源配置*/
- resource: {
- path: "src/resource/"
- },
- // 函数相关配置
- func: {
- // 上下标在函数名上下两侧的函数列表
- "ud-script": {
- lim: true
- }
- }
- };
- }
- };
- /*!
- * 启动代码
- */
- _p[48] = {
- value: function(require) {
- window.kf = {
- // base
- ResourceManager: _p.r(45),
- Operator: _p.r(41),
- // expression
- Expression: _p.r(21),
- CompoundExpression: _p.r(19),
- TextExpression: _p.r(22),
- EmptyExpression: _p.r(20),
- CombinationExpression: _p.r(12),
- FunctionExpression: _p.r(14),
- FractionExpression: _p.r(13),
- IntegrationExpression: _p.r(15),
- RadicalExpression: _p.r(16),
- ScriptExpression: _p.r(17),
- SuperscriptExpression: _p.r(9),
- SubscriptExpression: _p.r(8),
- SummationExpression: _p.r(18),
- // Brackets expressoin
- BracketsExpression: _p.r(11)
- };
- }
- };
- var moduleMapping = {
- "kf.start": 48
- };
- function use(name) {
- _p.r([ moduleMapping[name] ]);
- }
- /**
- * 模块暴露
- */
- ( function ( global ) {
- var oldGetRenderBox = kity.Shape.getRenderBox;
- kity.extendClass(kity.Shape, {
- getFixRenderBox: function () {
- return this.getRenderBox( this.container.container );
- },
- getTranslate: function () {
- return this.transform.translate;
- }
- });
- // build环境中才含有use
- try {
- use( 'kf.start' );
- } catch ( e ) {
- }
- } )( this );
- })();
|