kity-formula-render.all.js 267 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757
  1. /*!
  2. * ====================================================
  3. * Kity Formula Render - v1.0.0 - 2014-07-30
  4. * https://github.com/kitygraph/formula
  5. * GitHub: https://github.com/kitygraph/formula.git
  6. * Copyright (c) 2014 Baidu Kity Group; Licensed MIT
  7. * ====================================================
  8. */
  9. (function () {
  10. var _p = {
  11. r: function(index) {
  12. if (_p[index].inited) {
  13. return _p[index].value;
  14. }
  15. if (typeof _p[index].value === "function") {
  16. var module = {
  17. exports: {}
  18. }, returnValue = _p[index].value(null, module.exports, module);
  19. _p[index].inited = true;
  20. _p[index].value = returnValue;
  21. if (returnValue !== undefined) {
  22. return returnValue;
  23. } else {
  24. for (var key in module.exports) {
  25. if (module.exports.hasOwnProperty(key)) {
  26. _p[index].inited = true;
  27. _p[index].value = module.exports;
  28. return module.exports;
  29. }
  30. }
  31. }
  32. } else {
  33. _p[index].inited = true;
  34. return _p[index].value;
  35. }
  36. }
  37. };
  38. /*!
  39. * canvg库封装
  40. * canvg官网: https://code.google.com/p/canvg/
  41. */
  42. _p[0] = {
  43. value: function(require) {
  44. /**
  45. * A class to parse color values
  46. * @author Stoyan Stefanov <sstoo@gmail.com>
  47. * @link http://www.phpied.com/rgb-color-parser-in-javascript/
  48. * @license Use it if you like it
  49. */
  50. function RGBColor(color_string) {
  51. this.ok = false;
  52. // strip any leading #
  53. if (color_string.charAt(0) == "#") {
  54. // remove # if any
  55. color_string = color_string.substr(1, 6);
  56. }
  57. color_string = color_string.replace(/ /g, "");
  58. color_string = color_string.toLowerCase();
  59. // before getting into regexps, try simple matches
  60. // and overwrite the input
  61. var simple_colors = {
  62. aliceblue: "f0f8ff",
  63. antiquewhite: "faebd7",
  64. aqua: "00ffff",
  65. aquamarine: "7fffd4",
  66. azure: "f0ffff",
  67. beige: "f5f5dc",
  68. bisque: "ffe4c4",
  69. black: "000000",
  70. blanchedalmond: "ffebcd",
  71. blue: "0000ff",
  72. blueviolet: "8a2be2",
  73. brown: "a52a2a",
  74. burlywood: "deb887",
  75. cadetblue: "5f9ea0",
  76. chartreuse: "7fff00",
  77. chocolate: "d2691e",
  78. coral: "ff7f50",
  79. cornflowerblue: "6495ed",
  80. cornsilk: "fff8dc",
  81. crimson: "dc143c",
  82. cyan: "00ffff",
  83. darkblue: "00008b",
  84. darkcyan: "008b8b",
  85. darkgoldenrod: "b8860b",
  86. darkgray: "a9a9a9",
  87. darkgreen: "006400",
  88. darkkhaki: "bdb76b",
  89. darkmagenta: "8b008b",
  90. darkolivegreen: "556b2f",
  91. darkorange: "ff8c00",
  92. darkorchid: "9932cc",
  93. darkred: "8b0000",
  94. darksalmon: "e9967a",
  95. darkseagreen: "8fbc8f",
  96. darkslateblue: "483d8b",
  97. darkslategray: "2f4f4f",
  98. darkturquoise: "00ced1",
  99. darkviolet: "9400d3",
  100. deeppink: "ff1493",
  101. deepskyblue: "00bfff",
  102. dimgray: "696969",
  103. dodgerblue: "1e90ff",
  104. feldspar: "d19275",
  105. firebrick: "b22222",
  106. floralwhite: "fffaf0",
  107. forestgreen: "228b22",
  108. fuchsia: "ff00ff",
  109. gainsboro: "dcdcdc",
  110. ghostwhite: "f8f8ff",
  111. gold: "ffd700",
  112. goldenrod: "daa520",
  113. gray: "808080",
  114. green: "008000",
  115. greenyellow: "adff2f",
  116. honeydew: "f0fff0",
  117. hotpink: "ff69b4",
  118. indianred: "cd5c5c",
  119. indigo: "4b0082",
  120. ivory: "fffff0",
  121. khaki: "f0e68c",
  122. lavender: "e6e6fa",
  123. lavenderblush: "fff0f5",
  124. lawngreen: "7cfc00",
  125. lemonchiffon: "fffacd",
  126. lightblue: "add8e6",
  127. lightcoral: "f08080",
  128. lightcyan: "e0ffff",
  129. lightgoldenrodyellow: "fafad2",
  130. lightgrey: "d3d3d3",
  131. lightgreen: "90ee90",
  132. lightpink: "ffb6c1",
  133. lightsalmon: "ffa07a",
  134. lightseagreen: "20b2aa",
  135. lightskyblue: "87cefa",
  136. lightslateblue: "8470ff",
  137. lightslategray: "778899",
  138. lightsteelblue: "b0c4de",
  139. lightyellow: "ffffe0",
  140. lime: "00ff00",
  141. limegreen: "32cd32",
  142. linen: "faf0e6",
  143. magenta: "ff00ff",
  144. maroon: "800000",
  145. mediumaquamarine: "66cdaa",
  146. mediumblue: "0000cd",
  147. mediumorchid: "ba55d3",
  148. mediumpurple: "9370d8",
  149. mediumseagreen: "3cb371",
  150. mediumslateblue: "7b68ee",
  151. mediumspringgreen: "00fa9a",
  152. mediumturquoise: "48d1cc",
  153. mediumvioletred: "c71585",
  154. midnightblue: "191970",
  155. mintcream: "f5fffa",
  156. mistyrose: "ffe4e1",
  157. moccasin: "ffe4b5",
  158. navajowhite: "ffdead",
  159. navy: "000080",
  160. oldlace: "fdf5e6",
  161. olive: "808000",
  162. olivedrab: "6b8e23",
  163. orange: "ffa500",
  164. orangered: "ff4500",
  165. orchid: "da70d6",
  166. palegoldenrod: "eee8aa",
  167. palegreen: "98fb98",
  168. paleturquoise: "afeeee",
  169. palevioletred: "d87093",
  170. papayawhip: "ffefd5",
  171. peachpuff: "ffdab9",
  172. peru: "cd853f",
  173. pink: "ffc0cb",
  174. plum: "dda0dd",
  175. powderblue: "b0e0e6",
  176. purple: "800080",
  177. red: "ff0000",
  178. rosybrown: "bc8f8f",
  179. royalblue: "4169e1",
  180. saddlebrown: "8b4513",
  181. salmon: "fa8072",
  182. sandybrown: "f4a460",
  183. seagreen: "2e8b57",
  184. seashell: "fff5ee",
  185. sienna: "a0522d",
  186. silver: "c0c0c0",
  187. skyblue: "87ceeb",
  188. slateblue: "6a5acd",
  189. slategray: "708090",
  190. snow: "fffafa",
  191. springgreen: "00ff7f",
  192. steelblue: "4682b4",
  193. tan: "d2b48c",
  194. teal: "008080",
  195. thistle: "d8bfd8",
  196. tomato: "ff6347",
  197. turquoise: "40e0d0",
  198. violet: "ee82ee",
  199. violetred: "d02090",
  200. wheat: "f5deb3",
  201. white: "ffffff",
  202. whitesmoke: "f5f5f5",
  203. yellow: "ffff00",
  204. yellowgreen: "9acd32"
  205. };
  206. for (var key in simple_colors) {
  207. if (color_string == key) {
  208. color_string = simple_colors[key];
  209. }
  210. }
  211. // emd of simple type-in colors
  212. // array of color definition objects
  213. var color_defs = [ {
  214. re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,
  215. example: [ "rgb(123, 234, 45)", "rgb(255,234,245)" ],
  216. process: function(bits) {
  217. return [ parseInt(bits[1]), parseInt(bits[2]), parseInt(bits[3]) ];
  218. }
  219. }, {
  220. re: /^(\w{2})(\w{2})(\w{2})$/,
  221. example: [ "#00ff00", "336699" ],
  222. process: function(bits) {
  223. return [ parseInt(bits[1], 16), parseInt(bits[2], 16), parseInt(bits[3], 16) ];
  224. }
  225. }, {
  226. re: /^(\w{1})(\w{1})(\w{1})$/,
  227. example: [ "#fb0", "f0f" ],
  228. process: function(bits) {
  229. return [ parseInt(bits[1] + bits[1], 16), parseInt(bits[2] + bits[2], 16), parseInt(bits[3] + bits[3], 16) ];
  230. }
  231. } ];
  232. // search through the definitions to find a match
  233. for (var i = 0; i < color_defs.length; i++) {
  234. var re = color_defs[i].re;
  235. var processor = color_defs[i].process;
  236. var bits = re.exec(color_string);
  237. if (bits) {
  238. channels = processor(bits);
  239. this.r = channels[0];
  240. this.g = channels[1];
  241. this.b = channels[2];
  242. this.ok = true;
  243. }
  244. }
  245. // validate/cleanup values
  246. this.r = this.r < 0 || isNaN(this.r) ? 0 : this.r > 255 ? 255 : this.r;
  247. this.g = this.g < 0 || isNaN(this.g) ? 0 : this.g > 255 ? 255 : this.g;
  248. this.b = this.b < 0 || isNaN(this.b) ? 0 : this.b > 255 ? 255 : this.b;
  249. // some getters
  250. this.toRGB = function() {
  251. return "rgb(" + this.r + ", " + this.g + ", " + this.b + ")";
  252. };
  253. this.toHex = function() {
  254. var r = this.r.toString(16);
  255. var g = this.g.toString(16);
  256. var b = this.b.toString(16);
  257. if (r.length == 1) r = "0" + r;
  258. if (g.length == 1) g = "0" + g;
  259. if (b.length == 1) b = "0" + b;
  260. return "#" + r + g + b;
  261. };
  262. // help
  263. this.getHelpXML = function() {
  264. var examples = new Array();
  265. // add regexps
  266. for (var i = 0; i < color_defs.length; i++) {
  267. var example = color_defs[i].example;
  268. for (var j = 0; j < example.length; j++) {
  269. examples[examples.length] = example[j];
  270. }
  271. }
  272. // add type-in colors
  273. for (var sc in simple_colors) {
  274. examples[examples.length] = sc;
  275. }
  276. var xml = document.createElement("ul");
  277. xml.setAttribute("id", "rgbcolor-examples");
  278. for (var i = 0; i < examples.length; i++) {
  279. try {
  280. var list_item = document.createElement("li");
  281. var list_color = new RGBColor(examples[i]);
  282. var example_div = document.createElement("div");
  283. example_div.style.cssText = "margin: 3px; " + "border: 1px solid black; " + "background:" + list_color.toHex() + "; " + "color:" + list_color.toHex();
  284. example_div.appendChild(document.createTextNode("test"));
  285. var list_item_value = document.createTextNode(" " + examples[i] + " -> " + list_color.toRGB() + " -> " + list_color.toHex());
  286. list_item.appendChild(example_div);
  287. list_item.appendChild(list_item_value);
  288. xml.appendChild(list_item);
  289. } catch (e) {}
  290. }
  291. return xml;
  292. };
  293. }
  294. /*
  295. StackBlur - a fast almost Gaussian Blur For Canvas
  296. Version: 0.5
  297. Author: Mario Klingemann
  298. Contact: mario@quasimondo.com
  299. Website: http://www.quasimondo.com/StackBlurForCanvas
  300. Twitter: @quasimondo
  301. In case you find this class useful - especially in commercial projects -
  302. I am not totally unhappy for a small donation to my PayPal account
  303. mario@quasimondo.de
  304. Or support me on flattr:
  305. https://flattr.com/thing/72791/StackBlur-a-fast-almost-Gaussian-Blur-Effect-for-CanvasJavascript
  306. Copyright (c) 2010 Mario Klingemann
  307. Permission is hereby granted, free of charge, to any person
  308. obtaining a copy of this software and associated documentation
  309. files (the "Software"), to deal in the Software without
  310. restriction, including without limitation the rights to use,
  311. copy, modify, merge, publish, distribute, sublicense, and/or sell
  312. copies of the Software, and to permit persons to whom the
  313. Software is furnished to do so, subject to the following
  314. conditions:
  315. The above copyright notice and this permission notice shall be
  316. included in all copies or substantial portions of the Software.
  317. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  318. EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  319. OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  320. NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  321. HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  322. WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  323. FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  324. OTHER DEALINGS IN THE SOFTWARE.
  325. */
  326. 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 ];
  327. 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 ];
  328. function stackBlurImage(imageID, canvasID, radius, blurAlphaChannel) {
  329. var img = document.getElementById(imageID);
  330. var w = img.naturalWidth;
  331. var h = img.naturalHeight;
  332. var canvas = document.getElementById(canvasID);
  333. canvas.style.width = w + "px";
  334. canvas.style.height = h + "px";
  335. canvas.width = w;
  336. canvas.height = h;
  337. var context = canvas.getContext("2d");
  338. context.clearRect(0, 0, w, h);
  339. context.drawImage(img, 0, 0);
  340. if (isNaN(radius) || radius < 1) return;
  341. if (blurAlphaChannel) stackBlurCanvasRGBA(canvasID, 0, 0, w, h, radius); else stackBlurCanvasRGB(canvasID, 0, 0, w, h, radius);
  342. }
  343. function stackBlurCanvasRGBA(id, top_x, top_y, width, height, radius) {
  344. if (isNaN(radius) || radius < 1) return;
  345. radius |= 0;
  346. var canvas = document.getElementById(id);
  347. var context = canvas.getContext("2d");
  348. var imageData;
  349. try {
  350. try {
  351. imageData = context.getImageData(top_x, top_y, width, height);
  352. } catch (e) {
  353. // NOTE: this part is supposedly only needed if you want to work with local files
  354. // so it might be okay to remove the whole try/catch block and just use
  355. // imageData = context.getImageData( top_x, top_y, width, height );
  356. try {
  357. netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
  358. imageData = context.getImageData(top_x, top_y, width, height);
  359. } catch (e) {
  360. alert("Cannot access local image");
  361. throw new Error("unable to access local image data: " + e);
  362. return;
  363. }
  364. }
  365. } catch (e) {
  366. alert("Cannot access image");
  367. throw new Error("unable to access image data: " + e);
  368. }
  369. var pixels = imageData.data;
  370. 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;
  371. var div = radius + radius + 1;
  372. var w4 = width << 2;
  373. var widthMinus1 = width - 1;
  374. var heightMinus1 = height - 1;
  375. var radiusPlus1 = radius + 1;
  376. var sumFactor = radiusPlus1 * (radiusPlus1 + 1) / 2;
  377. var stackStart = new BlurStack();
  378. var stack = stackStart;
  379. for (i = 1; i < div; i++) {
  380. stack = stack.next = new BlurStack();
  381. if (i == radiusPlus1) var stackEnd = stack;
  382. }
  383. stack.next = stackStart;
  384. var stackIn = null;
  385. var stackOut = null;
  386. yw = yi = 0;
  387. var mul_sum = mul_table[radius];
  388. var shg_sum = shg_table[radius];
  389. for (y = 0; y < height; y++) {
  390. r_in_sum = g_in_sum = b_in_sum = a_in_sum = r_sum = g_sum = b_sum = a_sum = 0;
  391. r_out_sum = radiusPlus1 * (pr = pixels[yi]);
  392. g_out_sum = radiusPlus1 * (pg = pixels[yi + 1]);
  393. b_out_sum = radiusPlus1 * (pb = pixels[yi + 2]);
  394. a_out_sum = radiusPlus1 * (pa = pixels[yi + 3]);
  395. r_sum += sumFactor * pr;
  396. g_sum += sumFactor * pg;
  397. b_sum += sumFactor * pb;
  398. a_sum += sumFactor * pa;
  399. stack = stackStart;
  400. for (i = 0; i < radiusPlus1; i++) {
  401. stack.r = pr;
  402. stack.g = pg;
  403. stack.b = pb;
  404. stack.a = pa;
  405. stack = stack.next;
  406. }
  407. for (i = 1; i < radiusPlus1; i++) {
  408. p = yi + ((widthMinus1 < i ? widthMinus1 : i) << 2);
  409. r_sum += (stack.r = pr = pixels[p]) * (rbs = radiusPlus1 - i);
  410. g_sum += (stack.g = pg = pixels[p + 1]) * rbs;
  411. b_sum += (stack.b = pb = pixels[p + 2]) * rbs;
  412. a_sum += (stack.a = pa = pixels[p + 3]) * rbs;
  413. r_in_sum += pr;
  414. g_in_sum += pg;
  415. b_in_sum += pb;
  416. a_in_sum += pa;
  417. stack = stack.next;
  418. }
  419. stackIn = stackStart;
  420. stackOut = stackEnd;
  421. for (x = 0; x < width; x++) {
  422. pixels[yi + 3] = pa = a_sum * mul_sum >> shg_sum;
  423. if (pa != 0) {
  424. pa = 255 / pa;
  425. pixels[yi] = (r_sum * mul_sum >> shg_sum) * pa;
  426. pixels[yi + 1] = (g_sum * mul_sum >> shg_sum) * pa;
  427. pixels[yi + 2] = (b_sum * mul_sum >> shg_sum) * pa;
  428. } else {
  429. pixels[yi] = pixels[yi + 1] = pixels[yi + 2] = 0;
  430. }
  431. r_sum -= r_out_sum;
  432. g_sum -= g_out_sum;
  433. b_sum -= b_out_sum;
  434. a_sum -= a_out_sum;
  435. r_out_sum -= stackIn.r;
  436. g_out_sum -= stackIn.g;
  437. b_out_sum -= stackIn.b;
  438. a_out_sum -= stackIn.a;
  439. p = yw + ((p = x + radius + 1) < widthMinus1 ? p : widthMinus1) << 2;
  440. r_in_sum += stackIn.r = pixels[p];
  441. g_in_sum += stackIn.g = pixels[p + 1];
  442. b_in_sum += stackIn.b = pixels[p + 2];
  443. a_in_sum += stackIn.a = pixels[p + 3];
  444. r_sum += r_in_sum;
  445. g_sum += g_in_sum;
  446. b_sum += b_in_sum;
  447. a_sum += a_in_sum;
  448. stackIn = stackIn.next;
  449. r_out_sum += pr = stackOut.r;
  450. g_out_sum += pg = stackOut.g;
  451. b_out_sum += pb = stackOut.b;
  452. a_out_sum += pa = stackOut.a;
  453. r_in_sum -= pr;
  454. g_in_sum -= pg;
  455. b_in_sum -= pb;
  456. a_in_sum -= pa;
  457. stackOut = stackOut.next;
  458. yi += 4;
  459. }
  460. yw += width;
  461. }
  462. for (x = 0; x < width; x++) {
  463. g_in_sum = b_in_sum = a_in_sum = r_in_sum = g_sum = b_sum = a_sum = r_sum = 0;
  464. yi = x << 2;
  465. r_out_sum = radiusPlus1 * (pr = pixels[yi]);
  466. g_out_sum = radiusPlus1 * (pg = pixels[yi + 1]);
  467. b_out_sum = radiusPlus1 * (pb = pixels[yi + 2]);
  468. a_out_sum = radiusPlus1 * (pa = pixels[yi + 3]);
  469. r_sum += sumFactor * pr;
  470. g_sum += sumFactor * pg;
  471. b_sum += sumFactor * pb;
  472. a_sum += sumFactor * pa;
  473. stack = stackStart;
  474. for (i = 0; i < radiusPlus1; i++) {
  475. stack.r = pr;
  476. stack.g = pg;
  477. stack.b = pb;
  478. stack.a = pa;
  479. stack = stack.next;
  480. }
  481. yp = width;
  482. for (i = 1; i <= radius; i++) {
  483. yi = yp + x << 2;
  484. r_sum += (stack.r = pr = pixels[yi]) * (rbs = radiusPlus1 - i);
  485. g_sum += (stack.g = pg = pixels[yi + 1]) * rbs;
  486. b_sum += (stack.b = pb = pixels[yi + 2]) * rbs;
  487. a_sum += (stack.a = pa = pixels[yi + 3]) * rbs;
  488. r_in_sum += pr;
  489. g_in_sum += pg;
  490. b_in_sum += pb;
  491. a_in_sum += pa;
  492. stack = stack.next;
  493. if (i < heightMinus1) {
  494. yp += width;
  495. }
  496. }
  497. yi = x;
  498. stackIn = stackStart;
  499. stackOut = stackEnd;
  500. for (y = 0; y < height; y++) {
  501. p = yi << 2;
  502. pixels[p + 3] = pa = a_sum * mul_sum >> shg_sum;
  503. if (pa > 0) {
  504. pa = 255 / pa;
  505. pixels[p] = (r_sum * mul_sum >> shg_sum) * pa;
  506. pixels[p + 1] = (g_sum * mul_sum >> shg_sum) * pa;
  507. pixels[p + 2] = (b_sum * mul_sum >> shg_sum) * pa;
  508. } else {
  509. pixels[p] = pixels[p + 1] = pixels[p + 2] = 0;
  510. }
  511. r_sum -= r_out_sum;
  512. g_sum -= g_out_sum;
  513. b_sum -= b_out_sum;
  514. a_sum -= a_out_sum;
  515. r_out_sum -= stackIn.r;
  516. g_out_sum -= stackIn.g;
  517. b_out_sum -= stackIn.b;
  518. a_out_sum -= stackIn.a;
  519. p = x + ((p = y + radiusPlus1) < heightMinus1 ? p : heightMinus1) * width << 2;
  520. r_sum += r_in_sum += stackIn.r = pixels[p];
  521. g_sum += g_in_sum += stackIn.g = pixels[p + 1];
  522. b_sum += b_in_sum += stackIn.b = pixels[p + 2];
  523. a_sum += a_in_sum += stackIn.a = pixels[p + 3];
  524. stackIn = stackIn.next;
  525. r_out_sum += pr = stackOut.r;
  526. g_out_sum += pg = stackOut.g;
  527. b_out_sum += pb = stackOut.b;
  528. a_out_sum += pa = stackOut.a;
  529. r_in_sum -= pr;
  530. g_in_sum -= pg;
  531. b_in_sum -= pb;
  532. a_in_sum -= pa;
  533. stackOut = stackOut.next;
  534. yi += width;
  535. }
  536. }
  537. context.putImageData(imageData, top_x, top_y);
  538. }
  539. function stackBlurCanvasRGB(id, top_x, top_y, width, height, radius) {
  540. if (isNaN(radius) || radius < 1) return;
  541. radius |= 0;
  542. var canvas = document.getElementById(id);
  543. var context = canvas.getContext("2d");
  544. var imageData;
  545. try {
  546. try {
  547. imageData = context.getImageData(top_x, top_y, width, height);
  548. } catch (e) {
  549. // NOTE: this part is supposedly only needed if you want to work with local files
  550. // so it might be okay to remove the whole try/catch block and just use
  551. // imageData = context.getImageData( top_x, top_y, width, height );
  552. try {
  553. netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
  554. imageData = context.getImageData(top_x, top_y, width, height);
  555. } catch (e) {
  556. alert("Cannot access local image");
  557. throw new Error("unable to access local image data: " + e);
  558. return;
  559. }
  560. }
  561. } catch (e) {
  562. alert("Cannot access image");
  563. throw new Error("unable to access image data: " + e);
  564. }
  565. var pixels = imageData.data;
  566. 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;
  567. var div = radius + radius + 1;
  568. var w4 = width << 2;
  569. var widthMinus1 = width - 1;
  570. var heightMinus1 = height - 1;
  571. var radiusPlus1 = radius + 1;
  572. var sumFactor = radiusPlus1 * (radiusPlus1 + 1) / 2;
  573. var stackStart = new BlurStack();
  574. var stack = stackStart;
  575. for (i = 1; i < div; i++) {
  576. stack = stack.next = new BlurStack();
  577. if (i == radiusPlus1) var stackEnd = stack;
  578. }
  579. stack.next = stackStart;
  580. var stackIn = null;
  581. var stackOut = null;
  582. yw = yi = 0;
  583. var mul_sum = mul_table[radius];
  584. var shg_sum = shg_table[radius];
  585. for (y = 0; y < height; y++) {
  586. r_in_sum = g_in_sum = b_in_sum = r_sum = g_sum = b_sum = 0;
  587. r_out_sum = radiusPlus1 * (pr = pixels[yi]);
  588. g_out_sum = radiusPlus1 * (pg = pixels[yi + 1]);
  589. b_out_sum = radiusPlus1 * (pb = pixels[yi + 2]);
  590. r_sum += sumFactor * pr;
  591. g_sum += sumFactor * pg;
  592. b_sum += sumFactor * pb;
  593. stack = stackStart;
  594. for (i = 0; i < radiusPlus1; i++) {
  595. stack.r = pr;
  596. stack.g = pg;
  597. stack.b = pb;
  598. stack = stack.next;
  599. }
  600. for (i = 1; i < radiusPlus1; i++) {
  601. p = yi + ((widthMinus1 < i ? widthMinus1 : i) << 2);
  602. r_sum += (stack.r = pr = pixels[p]) * (rbs = radiusPlus1 - i);
  603. g_sum += (stack.g = pg = pixels[p + 1]) * rbs;
  604. b_sum += (stack.b = pb = pixels[p + 2]) * rbs;
  605. r_in_sum += pr;
  606. g_in_sum += pg;
  607. b_in_sum += pb;
  608. stack = stack.next;
  609. }
  610. stackIn = stackStart;
  611. stackOut = stackEnd;
  612. for (x = 0; x < width; x++) {
  613. pixels[yi] = r_sum * mul_sum >> shg_sum;
  614. pixels[yi + 1] = g_sum * mul_sum >> shg_sum;
  615. pixels[yi + 2] = b_sum * mul_sum >> shg_sum;
  616. r_sum -= r_out_sum;
  617. g_sum -= g_out_sum;
  618. b_sum -= b_out_sum;
  619. r_out_sum -= stackIn.r;
  620. g_out_sum -= stackIn.g;
  621. b_out_sum -= stackIn.b;
  622. p = yw + ((p = x + radius + 1) < widthMinus1 ? p : widthMinus1) << 2;
  623. r_in_sum += stackIn.r = pixels[p];
  624. g_in_sum += stackIn.g = pixels[p + 1];
  625. b_in_sum += stackIn.b = pixels[p + 2];
  626. r_sum += r_in_sum;
  627. g_sum += g_in_sum;
  628. b_sum += b_in_sum;
  629. stackIn = stackIn.next;
  630. r_out_sum += pr = stackOut.r;
  631. g_out_sum += pg = stackOut.g;
  632. b_out_sum += pb = stackOut.b;
  633. r_in_sum -= pr;
  634. g_in_sum -= pg;
  635. b_in_sum -= pb;
  636. stackOut = stackOut.next;
  637. yi += 4;
  638. }
  639. yw += width;
  640. }
  641. for (x = 0; x < width; x++) {
  642. g_in_sum = b_in_sum = r_in_sum = g_sum = b_sum = r_sum = 0;
  643. yi = x << 2;
  644. r_out_sum = radiusPlus1 * (pr = pixels[yi]);
  645. g_out_sum = radiusPlus1 * (pg = pixels[yi + 1]);
  646. b_out_sum = radiusPlus1 * (pb = pixels[yi + 2]);
  647. r_sum += sumFactor * pr;
  648. g_sum += sumFactor * pg;
  649. b_sum += sumFactor * pb;
  650. stack = stackStart;
  651. for (i = 0; i < radiusPlus1; i++) {
  652. stack.r = pr;
  653. stack.g = pg;
  654. stack.b = pb;
  655. stack = stack.next;
  656. }
  657. yp = width;
  658. for (i = 1; i <= radius; i++) {
  659. yi = yp + x << 2;
  660. r_sum += (stack.r = pr = pixels[yi]) * (rbs = radiusPlus1 - i);
  661. g_sum += (stack.g = pg = pixels[yi + 1]) * rbs;
  662. b_sum += (stack.b = pb = pixels[yi + 2]) * rbs;
  663. r_in_sum += pr;
  664. g_in_sum += pg;
  665. b_in_sum += pb;
  666. stack = stack.next;
  667. if (i < heightMinus1) {
  668. yp += width;
  669. }
  670. }
  671. yi = x;
  672. stackIn = stackStart;
  673. stackOut = stackEnd;
  674. for (y = 0; y < height; y++) {
  675. p = yi << 2;
  676. pixels[p] = r_sum * mul_sum >> shg_sum;
  677. pixels[p + 1] = g_sum * mul_sum >> shg_sum;
  678. pixels[p + 2] = b_sum * mul_sum >> shg_sum;
  679. r_sum -= r_out_sum;
  680. g_sum -= g_out_sum;
  681. b_sum -= b_out_sum;
  682. r_out_sum -= stackIn.r;
  683. g_out_sum -= stackIn.g;
  684. b_out_sum -= stackIn.b;
  685. p = x + ((p = y + radiusPlus1) < heightMinus1 ? p : heightMinus1) * width << 2;
  686. r_sum += r_in_sum += stackIn.r = pixels[p];
  687. g_sum += g_in_sum += stackIn.g = pixels[p + 1];
  688. b_sum += b_in_sum += stackIn.b = pixels[p + 2];
  689. stackIn = stackIn.next;
  690. r_out_sum += pr = stackOut.r;
  691. g_out_sum += pg = stackOut.g;
  692. b_out_sum += pb = stackOut.b;
  693. r_in_sum -= pr;
  694. g_in_sum -= pg;
  695. b_in_sum -= pb;
  696. stackOut = stackOut.next;
  697. yi += width;
  698. }
  699. }
  700. context.putImageData(imageData, top_x, top_y);
  701. }
  702. function BlurStack() {
  703. this.r = 0;
  704. this.g = 0;
  705. this.b = 0;
  706. this.a = 0;
  707. this.next = null;
  708. }
  709. /*
  710. * canvg.js - Javascript SVG parser and renderer on Canvas
  711. * MIT Licensed
  712. * Gabe Lerner (gabelerner@gmail.com)
  713. * http://code.google.com/p/canvg/
  714. *
  715. * Requires: rgbcolor.js - http://www.phpied.com/rgb-color-parser-in-javascript/
  716. */
  717. (function() {
  718. // canvg(target, s)
  719. // empty parameters: replace all 'svg' elements on page with 'canvas' elements
  720. // target: canvas element or the id of a canvas element
  721. // s: svg string, url to svg file, or xml document
  722. // opts: optional hash of options
  723. // ignoreMouse: true => ignore mouse events
  724. // ignoreAnimation: true => ignore animations
  725. // ignoreDimensions: true => does not try to resize canvas
  726. // ignoreClear: true => does not clear canvas
  727. // offsetX: int => draws at a x offset
  728. // offsetY: int => draws at a y offset
  729. // scaleWidth: int => scales horizontally to width
  730. // scaleHeight: int => scales vertically to height
  731. // renderCallback: function => will call the function after the first render is completed
  732. // forceRedraw: function => will call the function on every frame, if it returns true, will redraw
  733. this.canvg = function(target, s, opts) {
  734. // no parameters
  735. if (target == null && s == null && opts == null) {
  736. var svgTags = document.getElementsByTagName("svg");
  737. for (var i = 0; i < svgTags.length; i++) {
  738. var svgTag = svgTags[i];
  739. var c = document.createElement("canvas");
  740. c.width = svgTag.clientWidth;
  741. c.height = svgTag.clientHeight;
  742. svgTag.parentNode.insertBefore(c, svgTag);
  743. svgTag.parentNode.removeChild(svgTag);
  744. var div = document.createElement("div");
  745. div.appendChild(svgTag);
  746. canvg(c, div.innerHTML);
  747. }
  748. return;
  749. }
  750. opts = opts || {};
  751. if (typeof target == "string") {
  752. target = document.getElementById(target);
  753. }
  754. // store class on canvas
  755. if (target.svg != null) target.svg.stop();
  756. var svg = build();
  757. // on i.e. 8 for flash canvas, we can't assign the property so check for it
  758. if (!(target.childNodes.length == 1 && target.childNodes[0].nodeName == "OBJECT")) target.svg = svg;
  759. svg.opts = opts;
  760. var ctx = target.getContext("2d");
  761. if (typeof s.documentElement != "undefined") {
  762. // load from xml doc
  763. svg.loadXmlDoc(ctx, s);
  764. } else if (s.substr(0, 1) == "<") {
  765. // load from xml string
  766. svg.loadXml(ctx, s);
  767. } else {
  768. // load from url
  769. svg.load(ctx, s);
  770. }
  771. };
  772. function build() {
  773. var svg = {};
  774. svg.FRAMERATE = 30;
  775. svg.MAX_VIRTUAL_PIXELS = 3e4;
  776. // globals
  777. svg.init = function(ctx) {
  778. var uniqueId = 0;
  779. svg.UniqueId = function() {
  780. uniqueId++;
  781. return "canvg" + uniqueId;
  782. };
  783. svg.Definitions = {};
  784. svg.Styles = {};
  785. svg.Animations = [];
  786. svg.Images = [];
  787. svg.ctx = ctx;
  788. svg.ViewPort = new function() {
  789. this.viewPorts = [];
  790. this.Clear = function() {
  791. this.viewPorts = [];
  792. };
  793. this.SetCurrent = function(width, height) {
  794. this.viewPorts.push({
  795. width: width,
  796. height: height
  797. });
  798. };
  799. this.RemoveCurrent = function() {
  800. this.viewPorts.pop();
  801. };
  802. this.Current = function() {
  803. return this.viewPorts[this.viewPorts.length - 1];
  804. };
  805. this.width = function() {
  806. return this.Current().width;
  807. };
  808. this.height = function() {
  809. return this.Current().height;
  810. };
  811. this.ComputeSize = function(d) {
  812. if (d != null && typeof d == "number") return d;
  813. if (d == "x") return this.width();
  814. if (d == "y") return this.height();
  815. return Math.sqrt(Math.pow(this.width(), 2) + Math.pow(this.height(), 2)) / Math.sqrt(2);
  816. };
  817. }();
  818. };
  819. svg.init();
  820. // images loaded
  821. svg.ImagesLoaded = function() {
  822. for (var i = 0; i < svg.Images.length; i++) {
  823. if (!svg.Images[i].loaded) return false;
  824. }
  825. return true;
  826. };
  827. // trim
  828. svg.trim = function(s) {
  829. return s.replace(/^\s+|\s+$/g, "");
  830. };
  831. // compress spaces
  832. svg.compressSpaces = function(s) {
  833. return s.replace(/[\s\r\t\n]+/gm, " ");
  834. };
  835. // ajax
  836. svg.ajax = function(url) {
  837. var AJAX;
  838. if (window.XMLHttpRequest) {
  839. AJAX = new XMLHttpRequest();
  840. } else {
  841. AJAX = new ActiveXObject("Microsoft.XMLHTTP");
  842. }
  843. if (AJAX) {
  844. AJAX.open("GET", url, false);
  845. AJAX.send(null);
  846. return AJAX.responseText;
  847. }
  848. return null;
  849. };
  850. // parse xml
  851. svg.parseXml = function(xml) {
  852. if (window.DOMParser) {
  853. var parser = new DOMParser();
  854. return parser.parseFromString(xml, "text/xml");
  855. } else {
  856. xml = xml.replace(/<!DOCTYPE svg[^>]*>/, "");
  857. var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
  858. xmlDoc.async = "false";
  859. xmlDoc.loadXML(xml);
  860. return xmlDoc;
  861. }
  862. };
  863. svg.Property = function(name, value) {
  864. this.name = name;
  865. this.value = value;
  866. };
  867. svg.Property.prototype.getValue = function() {
  868. return this.value;
  869. };
  870. svg.Property.prototype.hasValue = function() {
  871. return this.value != null && this.value !== "";
  872. };
  873. // return the numerical value of the property
  874. svg.Property.prototype.numValue = function() {
  875. if (!this.hasValue()) return 0;
  876. var n = parseFloat(this.value);
  877. if ((this.value + "").match(/%$/)) {
  878. n = n / 100;
  879. }
  880. return n;
  881. };
  882. svg.Property.prototype.valueOrDefault = function(def) {
  883. if (this.hasValue()) return this.value;
  884. return def;
  885. };
  886. svg.Property.prototype.numValueOrDefault = function(def) {
  887. if (this.hasValue()) return this.numValue();
  888. return def;
  889. };
  890. // color extensions
  891. // augment the current color value with the opacity
  892. svg.Property.prototype.addOpacity = function(opacity) {
  893. var newValue = this.value;
  894. if (opacity != null && opacity != "" && typeof this.value == "string") {
  895. // can only add opacity to colors, not patterns
  896. var color = new RGBColor(this.value);
  897. if (color.ok) {
  898. newValue = "rgba(" + color.r + ", " + color.g + ", " + color.b + ", " + opacity + ")";
  899. }
  900. }
  901. return new svg.Property(this.name, newValue);
  902. };
  903. // definition extensions
  904. // get the definition from the definitions table
  905. svg.Property.prototype.getDefinition = function() {
  906. var name = this.value.match(/#([^\)'"]+)/);
  907. if (name) {
  908. name = name[1];
  909. }
  910. if (!name) {
  911. name = this.value;
  912. }
  913. return svg.Definitions[name];
  914. };
  915. svg.Property.prototype.isUrlDefinition = function() {
  916. return this.value.indexOf("url(") == 0;
  917. };
  918. svg.Property.prototype.getFillStyleDefinition = function(e, opacityProp) {
  919. var def = this.getDefinition();
  920. // gradient
  921. if (def != null && def.createGradient) {
  922. return def.createGradient(svg.ctx, e, opacityProp);
  923. }
  924. // pattern
  925. if (def != null && def.createPattern) {
  926. if (def.getHrefAttribute().hasValue()) {
  927. var pt = def.attribute("patternTransform");
  928. def = def.getHrefAttribute().getDefinition();
  929. if (pt.hasValue()) {
  930. def.attribute("patternTransform", true).value = pt.value;
  931. }
  932. }
  933. return def.createPattern(svg.ctx, e);
  934. }
  935. return null;
  936. };
  937. // length extensions
  938. svg.Property.prototype.getDPI = function(viewPort) {
  939. return 96;
  940. };
  941. svg.Property.prototype.getEM = function(viewPort) {
  942. var em = 12;
  943. var fontSize = new svg.Property("fontSize", svg.Font.Parse(svg.ctx.font).fontSize);
  944. if (fontSize.hasValue()) em = fontSize.toPixels(viewPort);
  945. return em;
  946. };
  947. svg.Property.prototype.getUnits = function() {
  948. var s = this.value + "";
  949. return s.replace(/[0-9\.\-]/g, "");
  950. };
  951. // get the length as pixels
  952. svg.Property.prototype.toPixels = function(viewPort, processPercent) {
  953. if (!this.hasValue()) return 0;
  954. var s = this.value + "";
  955. if (s.match(/em$/)) return this.numValue() * this.getEM(viewPort);
  956. if (s.match(/ex$/)) return this.numValue() * this.getEM(viewPort) / 2;
  957. if (s.match(/px$/)) return this.numValue();
  958. if (s.match(/pt$/)) return this.numValue() * this.getDPI(viewPort) * (1 / 72);
  959. if (s.match(/pc$/)) return this.numValue() * 15;
  960. if (s.match(/cm$/)) return this.numValue() * this.getDPI(viewPort) / 2.54;
  961. if (s.match(/mm$/)) return this.numValue() * this.getDPI(viewPort) / 25.4;
  962. if (s.match(/in$/)) return this.numValue() * this.getDPI(viewPort);
  963. if (s.match(/%$/)) return this.numValue() * svg.ViewPort.ComputeSize(viewPort);
  964. var n = this.numValue();
  965. if (processPercent && n < 1) return n * svg.ViewPort.ComputeSize(viewPort);
  966. return n;
  967. };
  968. // time extensions
  969. // get the time as milliseconds
  970. svg.Property.prototype.toMilliseconds = function() {
  971. if (!this.hasValue()) return 0;
  972. var s = this.value + "";
  973. if (s.match(/s$/)) return this.numValue() * 1e3;
  974. if (s.match(/ms$/)) return this.numValue();
  975. return this.numValue();
  976. };
  977. // angle extensions
  978. // get the angle as radians
  979. svg.Property.prototype.toRadians = function() {
  980. if (!this.hasValue()) return 0;
  981. var s = this.value + "";
  982. if (s.match(/deg$/)) return this.numValue() * (Math.PI / 180);
  983. if (s.match(/grad$/)) return this.numValue() * (Math.PI / 200);
  984. if (s.match(/rad$/)) return this.numValue();
  985. return this.numValue() * (Math.PI / 180);
  986. };
  987. // fonts
  988. svg.Font = new function() {
  989. this.Styles = "normal|italic|oblique|inherit";
  990. this.Variants = "normal|small-caps|inherit";
  991. this.Weights = "normal|bold|bolder|lighter|100|200|300|400|500|600|700|800|900|inherit";
  992. this.CreateFont = function(fontStyle, fontVariant, fontWeight, fontSize, fontFamily, inherit) {
  993. var f = inherit != null ? this.Parse(inherit) : this.CreateFont("", "", "", "", "", svg.ctx.font);
  994. return {
  995. fontFamily: fontFamily || f.fontFamily,
  996. fontSize: fontSize || f.fontSize,
  997. fontStyle: fontStyle || f.fontStyle,
  998. fontWeight: fontWeight || f.fontWeight,
  999. fontVariant: fontVariant || f.fontVariant,
  1000. toString: function() {
  1001. return [ this.fontStyle, this.fontVariant, this.fontWeight, this.fontSize, this.fontFamily ].join(" ");
  1002. }
  1003. };
  1004. };
  1005. var that = this;
  1006. this.Parse = function(s) {
  1007. var f = {};
  1008. var d = svg.trim(svg.compressSpaces(s || "")).split(" ");
  1009. var set = {
  1010. fontSize: false,
  1011. fontStyle: false,
  1012. fontWeight: false,
  1013. fontVariant: false
  1014. };
  1015. var ff = "";
  1016. for (var i = 0; i < d.length; i++) {
  1017. if (!set.fontStyle && that.Styles.indexOf(d[i]) != -1) {
  1018. if (d[i] != "inherit") f.fontStyle = d[i];
  1019. set.fontStyle = true;
  1020. } else if (!set.fontVariant && that.Variants.indexOf(d[i]) != -1) {
  1021. if (d[i] != "inherit") f.fontVariant = d[i];
  1022. set.fontStyle = set.fontVariant = true;
  1023. } else if (!set.fontWeight && that.Weights.indexOf(d[i]) != -1) {
  1024. if (d[i] != "inherit") f.fontWeight = d[i];
  1025. set.fontStyle = set.fontVariant = set.fontWeight = true;
  1026. } else if (!set.fontSize) {
  1027. if (d[i] != "inherit") f.fontSize = d[i].split("/")[0];
  1028. set.fontStyle = set.fontVariant = set.fontWeight = set.fontSize = true;
  1029. } else {
  1030. if (d[i] != "inherit") ff += d[i];
  1031. }
  1032. }
  1033. if (ff != "") f.fontFamily = ff;
  1034. return f;
  1035. };
  1036. }();
  1037. // points and paths
  1038. svg.ToNumberArray = function(s) {
  1039. var a = svg.trim(svg.compressSpaces((s || "").replace(/,/g, " "))).split(" ");
  1040. for (var i = 0; i < a.length; i++) {
  1041. a[i] = parseFloat(a[i]);
  1042. }
  1043. return a;
  1044. };
  1045. svg.Point = function(x, y) {
  1046. this.x = x;
  1047. this.y = y;
  1048. };
  1049. svg.Point.prototype.angleTo = function(p) {
  1050. return Math.atan2(p.y - this.y, p.x - this.x);
  1051. };
  1052. svg.Point.prototype.applyTransform = function(v) {
  1053. var xp = this.x * v[0] + this.y * v[2] + v[4];
  1054. var yp = this.x * v[1] + this.y * v[3] + v[5];
  1055. this.x = xp;
  1056. this.y = yp;
  1057. };
  1058. svg.CreatePoint = function(s) {
  1059. var a = svg.ToNumberArray(s);
  1060. return new svg.Point(a[0], a[1]);
  1061. };
  1062. svg.CreatePath = function(s) {
  1063. var a = svg.ToNumberArray(s);
  1064. var path = [];
  1065. for (var i = 0; i < a.length; i += 2) {
  1066. path.push(new svg.Point(a[i], a[i + 1]));
  1067. }
  1068. return path;
  1069. };
  1070. // bounding box
  1071. svg.BoundingBox = function(x1, y1, x2, y2) {
  1072. // pass in initial points if you want
  1073. this.x1 = Number.NaN;
  1074. this.y1 = Number.NaN;
  1075. this.x2 = Number.NaN;
  1076. this.y2 = Number.NaN;
  1077. this.x = function() {
  1078. return this.x1;
  1079. };
  1080. this.y = function() {
  1081. return this.y1;
  1082. };
  1083. this.width = function() {
  1084. return this.x2 - this.x1;
  1085. };
  1086. this.height = function() {
  1087. return this.y2 - this.y1;
  1088. };
  1089. this.addPoint = function(x, y) {
  1090. if (x != null) {
  1091. if (isNaN(this.x1) || isNaN(this.x2)) {
  1092. this.x1 = x;
  1093. this.x2 = x;
  1094. }
  1095. if (x < this.x1) this.x1 = x;
  1096. if (x > this.x2) this.x2 = x;
  1097. }
  1098. if (y != null) {
  1099. if (isNaN(this.y1) || isNaN(this.y2)) {
  1100. this.y1 = y;
  1101. this.y2 = y;
  1102. }
  1103. if (y < this.y1) this.y1 = y;
  1104. if (y > this.y2) this.y2 = y;
  1105. }
  1106. };
  1107. this.addX = function(x) {
  1108. this.addPoint(x, null);
  1109. };
  1110. this.addY = function(y) {
  1111. this.addPoint(null, y);
  1112. };
  1113. this.addBoundingBox = function(bb) {
  1114. this.addPoint(bb.x1, bb.y1);
  1115. this.addPoint(bb.x2, bb.y2);
  1116. };
  1117. this.addQuadraticCurve = function(p0x, p0y, p1x, p1y, p2x, p2y) {
  1118. var cp1x = p0x + 2 / 3 * (p1x - p0x);
  1119. // CP1 = QP0 + 2/3 *(QP1-QP0)
  1120. var cp1y = p0y + 2 / 3 * (p1y - p0y);
  1121. // CP1 = QP0 + 2/3 *(QP1-QP0)
  1122. var cp2x = cp1x + 1 / 3 * (p2x - p0x);
  1123. // CP2 = CP1 + 1/3 *(QP2-QP0)
  1124. var cp2y = cp1y + 1 / 3 * (p2y - p0y);
  1125. // CP2 = CP1 + 1/3 *(QP2-QP0)
  1126. this.addBezierCurve(p0x, p0y, cp1x, cp2x, cp1y, cp2y, p2x, p2y);
  1127. };
  1128. this.addBezierCurve = function(p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y) {
  1129. // from http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html
  1130. var p0 = [ p0x, p0y ], p1 = [ p1x, p1y ], p2 = [ p2x, p2y ], p3 = [ p3x, p3y ];
  1131. this.addPoint(p0[0], p0[1]);
  1132. this.addPoint(p3[0], p3[1]);
  1133. for (i = 0; i <= 1; i++) {
  1134. var f = function(t) {
  1135. 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];
  1136. };
  1137. var b = 6 * p0[i] - 12 * p1[i] + 6 * p2[i];
  1138. var a = -3 * p0[i] + 9 * p1[i] - 9 * p2[i] + 3 * p3[i];
  1139. var c = 3 * p1[i] - 3 * p0[i];
  1140. if (a == 0) {
  1141. if (b == 0) continue;
  1142. var t = -c / b;
  1143. if (0 < t && t < 1) {
  1144. if (i == 0) this.addX(f(t));
  1145. if (i == 1) this.addY(f(t));
  1146. }
  1147. continue;
  1148. }
  1149. var b2ac = Math.pow(b, 2) - 4 * c * a;
  1150. if (b2ac < 0) continue;
  1151. var t1 = (-b + Math.sqrt(b2ac)) / (2 * a);
  1152. if (0 < t1 && t1 < 1) {
  1153. if (i == 0) this.addX(f(t1));
  1154. if (i == 1) this.addY(f(t1));
  1155. }
  1156. var t2 = (-b - Math.sqrt(b2ac)) / (2 * a);
  1157. if (0 < t2 && t2 < 1) {
  1158. if (i == 0) this.addX(f(t2));
  1159. if (i == 1) this.addY(f(t2));
  1160. }
  1161. }
  1162. };
  1163. this.isPointInBox = function(x, y) {
  1164. return this.x1 <= x && x <= this.x2 && this.y1 <= y && y <= this.y2;
  1165. };
  1166. this.addPoint(x1, y1);
  1167. this.addPoint(x2, y2);
  1168. };
  1169. // transforms
  1170. svg.Transform = function(v) {
  1171. var that = this;
  1172. this.Type = {};
  1173. // translate
  1174. this.Type.translate = function(s) {
  1175. this.p = svg.CreatePoint(s);
  1176. this.apply = function(ctx) {
  1177. ctx.translate(this.p.x || 0, this.p.y || 0);
  1178. };
  1179. this.unapply = function(ctx) {
  1180. ctx.translate(-1 * this.p.x || 0, -1 * this.p.y || 0);
  1181. };
  1182. this.applyToPoint = function(p) {
  1183. p.applyTransform([ 1, 0, 0, 1, this.p.x || 0, this.p.y || 0 ]);
  1184. };
  1185. };
  1186. // rotate
  1187. this.Type.rotate = function(s) {
  1188. var a = svg.ToNumberArray(s);
  1189. this.angle = new svg.Property("angle", a[0]);
  1190. this.cx = a[1] || 0;
  1191. this.cy = a[2] || 0;
  1192. this.apply = function(ctx) {
  1193. ctx.translate(this.cx, this.cy);
  1194. ctx.rotate(this.angle.toRadians());
  1195. ctx.translate(-this.cx, -this.cy);
  1196. };
  1197. this.unapply = function(ctx) {
  1198. ctx.translate(this.cx, this.cy);
  1199. ctx.rotate(-1 * this.angle.toRadians());
  1200. ctx.translate(-this.cx, -this.cy);
  1201. };
  1202. this.applyToPoint = function(p) {
  1203. var a = this.angle.toRadians();
  1204. p.applyTransform([ 1, 0, 0, 1, this.p.x || 0, this.p.y || 0 ]);
  1205. p.applyTransform([ Math.cos(a), Math.sin(a), -Math.sin(a), Math.cos(a), 0, 0 ]);
  1206. p.applyTransform([ 1, 0, 0, 1, -this.p.x || 0, -this.p.y || 0 ]);
  1207. };
  1208. };
  1209. this.Type.scale = function(s) {
  1210. this.p = svg.CreatePoint(s);
  1211. this.apply = function(ctx) {
  1212. ctx.scale(this.p.x || 1, this.p.y || this.p.x || 1);
  1213. };
  1214. this.unapply = function(ctx) {
  1215. ctx.scale(1 / this.p.x || 1, 1 / this.p.y || this.p.x || 1);
  1216. };
  1217. this.applyToPoint = function(p) {
  1218. p.applyTransform([ this.p.x || 0, 0, 0, this.p.y || 0, 0, 0 ]);
  1219. };
  1220. };
  1221. this.Type.matrix = function(s) {
  1222. this.m = svg.ToNumberArray(s);
  1223. this.apply = function(ctx) {
  1224. ctx.transform(this.m[0], this.m[1], this.m[2], this.m[3], this.m[4], this.m[5]);
  1225. };
  1226. this.applyToPoint = function(p) {
  1227. p.applyTransform(this.m);
  1228. };
  1229. };
  1230. this.Type.SkewBase = function(s) {
  1231. this.base = that.Type.matrix;
  1232. this.base(s);
  1233. this.angle = new svg.Property("angle", s);
  1234. };
  1235. this.Type.SkewBase.prototype = new this.Type.matrix();
  1236. this.Type.skewX = function(s) {
  1237. this.base = that.Type.SkewBase;
  1238. this.base(s);
  1239. this.m = [ 1, 0, Math.tan(this.angle.toRadians()), 1, 0, 0 ];
  1240. };
  1241. this.Type.skewX.prototype = new this.Type.SkewBase();
  1242. this.Type.skewY = function(s) {
  1243. this.base = that.Type.SkewBase;
  1244. this.base(s);
  1245. this.m = [ 1, Math.tan(this.angle.toRadians()), 0, 1, 0, 0 ];
  1246. };
  1247. this.Type.skewY.prototype = new this.Type.SkewBase();
  1248. this.transforms = [];
  1249. this.apply = function(ctx) {
  1250. for (var i = 0; i < this.transforms.length; i++) {
  1251. this.transforms[i].apply(ctx);
  1252. }
  1253. };
  1254. this.unapply = function(ctx) {
  1255. for (var i = this.transforms.length - 1; i >= 0; i--) {
  1256. this.transforms[i].unapply(ctx);
  1257. }
  1258. };
  1259. this.applyToPoint = function(p) {
  1260. for (var i = 0; i < this.transforms.length; i++) {
  1261. this.transforms[i].applyToPoint(p);
  1262. }
  1263. };
  1264. var data = svg.trim(svg.compressSpaces(v)).replace(/\)(\s?,\s?)/g, ") ").split(/\s(?=[a-z])/);
  1265. for (var i = 0; i < data.length; i++) {
  1266. var type = svg.trim(data[i].split("(")[0]);
  1267. var s = data[i].split("(")[1].replace(")", "");
  1268. var transform = new this.Type[type](s);
  1269. transform.type = type;
  1270. this.transforms.push(transform);
  1271. }
  1272. };
  1273. // aspect ratio
  1274. svg.AspectRatio = function(ctx, aspectRatio, width, desiredWidth, height, desiredHeight, minX, minY, refX, refY) {
  1275. // aspect ratio - http://www.w3.org/TR/SVG/coords.html#PreserveAspectRatioAttribute
  1276. aspectRatio = svg.compressSpaces(aspectRatio);
  1277. aspectRatio = aspectRatio.replace(/^defer\s/, "");
  1278. // ignore defer
  1279. var align = aspectRatio.split(" ")[0] || "xMidYMid";
  1280. var meetOrSlice = aspectRatio.split(" ")[1] || "meet";
  1281. // calculate scale
  1282. var scaleX = width / desiredWidth;
  1283. var scaleY = height / desiredHeight;
  1284. var scaleMin = Math.min(scaleX, scaleY);
  1285. var scaleMax = Math.max(scaleX, scaleY);
  1286. if (meetOrSlice == "meet") {
  1287. desiredWidth *= scaleMin;
  1288. desiredHeight *= scaleMin;
  1289. }
  1290. if (meetOrSlice == "slice") {
  1291. desiredWidth *= scaleMax;
  1292. desiredHeight *= scaleMax;
  1293. }
  1294. refX = new svg.Property("refX", refX);
  1295. refY = new svg.Property("refY", refY);
  1296. if (refX.hasValue() && refY.hasValue()) {
  1297. ctx.translate(-scaleMin * refX.toPixels("x"), -scaleMin * refY.toPixels("y"));
  1298. } else {
  1299. // align
  1300. if (align.match(/^xMid/) && (meetOrSlice == "meet" && scaleMin == scaleY || meetOrSlice == "slice" && scaleMax == scaleY)) ctx.translate(width / 2 - desiredWidth / 2, 0);
  1301. if (align.match(/YMid$/) && (meetOrSlice == "meet" && scaleMin == scaleX || meetOrSlice == "slice" && scaleMax == scaleX)) ctx.translate(0, height / 2 - desiredHeight / 2);
  1302. if (align.match(/^xMax/) && (meetOrSlice == "meet" && scaleMin == scaleY || meetOrSlice == "slice" && scaleMax == scaleY)) ctx.translate(width - desiredWidth, 0);
  1303. if (align.match(/YMax$/) && (meetOrSlice == "meet" && scaleMin == scaleX || meetOrSlice == "slice" && scaleMax == scaleX)) ctx.translate(0, height - desiredHeight);
  1304. }
  1305. // scale
  1306. if (align == "none") ctx.scale(scaleX, scaleY); else if (meetOrSlice == "meet") ctx.scale(scaleMin, scaleMin); else if (meetOrSlice == "slice") ctx.scale(scaleMax, scaleMax);
  1307. // translate
  1308. ctx.translate(minX == null ? 0 : -minX, minY == null ? 0 : -minY);
  1309. };
  1310. // elements
  1311. svg.Element = {};
  1312. svg.EmptyProperty = new svg.Property("EMPTY", "");
  1313. svg.Element.ElementBase = function(node) {
  1314. this.attributes = {};
  1315. this.styles = {};
  1316. this.children = [];
  1317. // get or create attribute
  1318. this.attribute = function(name, createIfNotExists) {
  1319. var a = this.attributes[name];
  1320. if (a != null) return a;
  1321. if (createIfNotExists == true) {
  1322. a = new svg.Property(name, "");
  1323. this.attributes[name] = a;
  1324. }
  1325. return a || svg.EmptyProperty;
  1326. };
  1327. this.getHrefAttribute = function() {
  1328. for (var a in this.attributes) {
  1329. if (a.match(/:href$/)) {
  1330. return this.attributes[a];
  1331. }
  1332. }
  1333. return svg.EmptyProperty;
  1334. };
  1335. // get or create style, crawls up node tree
  1336. this.style = function(name, createIfNotExists) {
  1337. var s = this.styles[name];
  1338. if (s != null) return s;
  1339. var a = this.attribute(name);
  1340. if (a != null && a.hasValue()) {
  1341. this.styles[name] = a;
  1342. // move up to me to cache
  1343. return a;
  1344. }
  1345. var p = this.parent;
  1346. if (p != null) {
  1347. var ps = p.style(name);
  1348. if (ps != null && ps.hasValue()) {
  1349. return ps;
  1350. }
  1351. }
  1352. if (createIfNotExists == true) {
  1353. s = new svg.Property(name, "");
  1354. this.styles[name] = s;
  1355. }
  1356. return s || svg.EmptyProperty;
  1357. };
  1358. // base render
  1359. this.render = function(ctx) {
  1360. // don't render display=none
  1361. if (this.style("display").value == "none") return;
  1362. // don't render visibility=hidden
  1363. if (this.attribute("visibility").value == "hidden") return;
  1364. ctx.save();
  1365. if (this.attribute("mask").hasValue()) {
  1366. // mask
  1367. var mask = this.attribute("mask").getDefinition();
  1368. if (mask != null) mask.apply(ctx, this);
  1369. } else if (this.style("filter").hasValue()) {
  1370. // filter
  1371. var filter = this.style("filter").getDefinition();
  1372. if (filter != null) filter.apply(ctx, this);
  1373. } else {
  1374. this.setContext(ctx);
  1375. this.renderChildren(ctx);
  1376. this.clearContext(ctx);
  1377. }
  1378. ctx.restore();
  1379. };
  1380. // base set context
  1381. this.setContext = function(ctx) {};
  1382. // base clear context
  1383. this.clearContext = function(ctx) {};
  1384. // base render children
  1385. this.renderChildren = function(ctx) {
  1386. for (var i = 0; i < this.children.length; i++) {
  1387. this.children[i].render(ctx);
  1388. }
  1389. };
  1390. this.addChild = function(childNode, create) {
  1391. var child = childNode;
  1392. if (create) child = svg.CreateElement(childNode);
  1393. child.parent = this;
  1394. this.children.push(child);
  1395. };
  1396. if (node != null && node.nodeType == 1) {
  1397. //ELEMENT_NODE
  1398. // add children
  1399. for (var i = 0; i < node.childNodes.length; i++) {
  1400. var childNode = node.childNodes[i];
  1401. if (childNode.nodeType == 1) this.addChild(childNode, true);
  1402. //ELEMENT_NODE
  1403. if (this.captureTextNodes && childNode.nodeType == 3) {
  1404. var text = childNode.nodeValue || childNode.text || "";
  1405. if (svg.trim(svg.compressSpaces(text)) != "") {
  1406. this.addChild(new svg.Element.tspan(childNode), false);
  1407. }
  1408. }
  1409. }
  1410. // add attributes
  1411. for (var i = 0; i < node.attributes.length; i++) {
  1412. var attribute = node.attributes[i];
  1413. this.attributes[attribute.nodeName] = new svg.Property(attribute.nodeName, attribute.nodeValue);
  1414. }
  1415. // add tag styles
  1416. var styles = svg.Styles[node.nodeName];
  1417. if (styles != null) {
  1418. for (var name in styles) {
  1419. this.styles[name] = styles[name];
  1420. }
  1421. }
  1422. // add class styles
  1423. if (this.attribute("class").hasValue()) {
  1424. var classes = svg.compressSpaces(this.attribute("class").value).split(" ");
  1425. for (var j = 0; j < classes.length; j++) {
  1426. styles = svg.Styles["." + classes[j]];
  1427. if (styles != null) {
  1428. for (var name in styles) {
  1429. this.styles[name] = styles[name];
  1430. }
  1431. }
  1432. styles = svg.Styles[node.nodeName + "." + classes[j]];
  1433. if (styles != null) {
  1434. for (var name in styles) {
  1435. this.styles[name] = styles[name];
  1436. }
  1437. }
  1438. }
  1439. }
  1440. // add id styles
  1441. if (this.attribute("id").hasValue()) {
  1442. var styles = svg.Styles["#" + this.attribute("id").value];
  1443. if (styles != null) {
  1444. for (var name in styles) {
  1445. this.styles[name] = styles[name];
  1446. }
  1447. }
  1448. }
  1449. // add inline styles
  1450. if (this.attribute("style").hasValue()) {
  1451. var styles = this.attribute("style").value.split(";");
  1452. for (var i = 0; i < styles.length; i++) {
  1453. if (svg.trim(styles[i]) != "") {
  1454. var style = styles[i].split(":");
  1455. var name = svg.trim(style[0]);
  1456. var value = svg.trim(style[1]);
  1457. this.styles[name] = new svg.Property(name, value);
  1458. }
  1459. }
  1460. }
  1461. // add id
  1462. if (this.attribute("id").hasValue()) {
  1463. if (svg.Definitions[this.attribute("id").value] == null) {
  1464. svg.Definitions[this.attribute("id").value] = this;
  1465. }
  1466. }
  1467. }
  1468. };
  1469. svg.Element.RenderedElementBase = function(node) {
  1470. this.base = svg.Element.ElementBase;
  1471. this.base(node);
  1472. this.setContext = function(ctx) {
  1473. // fill
  1474. if (this.style("fill").isUrlDefinition()) {
  1475. var fs = this.style("fill").getFillStyleDefinition(this, this.style("fill-opacity"));
  1476. if (fs != null) ctx.fillStyle = fs;
  1477. } else if (this.style("fill").hasValue()) {
  1478. var fillStyle = this.style("fill");
  1479. if (fillStyle.value == "currentColor") fillStyle.value = this.style("color").value;
  1480. ctx.fillStyle = fillStyle.value == "none" ? "rgba(0,0,0,0)" : fillStyle.value;
  1481. }
  1482. if (this.style("fill-opacity").hasValue()) {
  1483. var fillStyle = new svg.Property("fill", ctx.fillStyle);
  1484. fillStyle = fillStyle.addOpacity(this.style("fill-opacity").value);
  1485. ctx.fillStyle = fillStyle.value;
  1486. }
  1487. // stroke
  1488. if (this.style("stroke").isUrlDefinition()) {
  1489. var fs = this.style("stroke").getFillStyleDefinition(this, this.style("stroke-opacity"));
  1490. if (fs != null) ctx.strokeStyle = fs;
  1491. } else if (this.style("stroke").hasValue()) {
  1492. var strokeStyle = this.style("stroke");
  1493. if (strokeStyle.value == "currentColor") strokeStyle.value = this.style("color").value;
  1494. ctx.strokeStyle = strokeStyle.value == "none" ? "rgba(0,0,0,0)" : strokeStyle.value;
  1495. }
  1496. if (this.style("stroke-opacity").hasValue()) {
  1497. var strokeStyle = new svg.Property("stroke", ctx.strokeStyle);
  1498. strokeStyle = strokeStyle.addOpacity(this.style("stroke-opacity").value);
  1499. ctx.strokeStyle = strokeStyle.value;
  1500. }
  1501. if (this.style("stroke-width").hasValue()) {
  1502. var newLineWidth = this.style("stroke-width").toPixels();
  1503. ctx.lineWidth = newLineWidth == 0 ? .001 : newLineWidth;
  1504. }
  1505. if (this.style("stroke-linecap").hasValue()) ctx.lineCap = this.style("stroke-linecap").value;
  1506. if (this.style("stroke-linejoin").hasValue()) ctx.lineJoin = this.style("stroke-linejoin").value;
  1507. if (this.style("stroke-miterlimit").hasValue()) ctx.miterLimit = this.style("stroke-miterlimit").value;
  1508. if (this.style("stroke-dasharray").hasValue()) {
  1509. var gaps = svg.ToNumberArray(this.style("stroke-dasharray").value);
  1510. if (typeof ctx.setLineDash != "undefined") {
  1511. ctx.setLineDash(gaps);
  1512. } else if (typeof ctx.webkitLineDash != "undefined") {
  1513. ctx.webkitLineDash = gaps;
  1514. } else if (typeof ctx.mozDash != "undefined") {
  1515. ctx.mozDash = gaps;
  1516. }
  1517. var offset = this.style("stroke-dashoffset").numValueOrDefault(1);
  1518. if (typeof ctx.lineDashOffset != "undefined") {
  1519. ctx.lineDashOffset = offset;
  1520. } else if (typeof ctx.webkitLineDashOffset != "undefined") {
  1521. ctx.webkitLineDashOffset = offset;
  1522. } else if (typeof ctx.mozDashOffset != "undefined") {
  1523. ctx.mozDashOffset = offset;
  1524. }
  1525. }
  1526. // font
  1527. if (typeof ctx.font != "undefined") {
  1528. 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();
  1529. }
  1530. // transform
  1531. if (this.attribute("transform").hasValue()) {
  1532. var transform = new svg.Transform(this.attribute("transform").value);
  1533. transform.apply(ctx);
  1534. }
  1535. // clip
  1536. if (this.style("clip-path").hasValue()) {
  1537. var clip = this.style("clip-path").getDefinition();
  1538. if (clip != null) clip.apply(ctx);
  1539. }
  1540. // opacity
  1541. if (this.style("opacity").hasValue()) {
  1542. ctx.globalAlpha = this.style("opacity").numValue();
  1543. }
  1544. };
  1545. };
  1546. svg.Element.RenderedElementBase.prototype = new svg.Element.ElementBase();
  1547. svg.Element.PathElementBase = function(node) {
  1548. this.base = svg.Element.RenderedElementBase;
  1549. this.base(node);
  1550. this.path = function(ctx) {
  1551. if (ctx != null) ctx.beginPath();
  1552. return new svg.BoundingBox();
  1553. };
  1554. this.renderChildren = function(ctx) {
  1555. this.path(ctx);
  1556. svg.Mouse.checkPath(this, ctx);
  1557. if (ctx.fillStyle != "") {
  1558. if (this.attribute("fill-rule").hasValue()) {
  1559. ctx.fill(this.attribute("fill-rule").value);
  1560. } else {
  1561. ctx.fill();
  1562. }
  1563. }
  1564. if (ctx.strokeStyle != "") ctx.stroke();
  1565. var markers = this.getMarkers();
  1566. if (markers != null) {
  1567. if (this.style("marker-start").isUrlDefinition()) {
  1568. var marker = this.style("marker-start").getDefinition();
  1569. marker.render(ctx, markers[0][0], markers[0][1]);
  1570. }
  1571. if (this.style("marker-mid").isUrlDefinition()) {
  1572. var marker = this.style("marker-mid").getDefinition();
  1573. for (var i = 1; i < markers.length - 1; i++) {
  1574. marker.render(ctx, markers[i][0], markers[i][1]);
  1575. }
  1576. }
  1577. if (this.style("marker-end").isUrlDefinition()) {
  1578. var marker = this.style("marker-end").getDefinition();
  1579. marker.render(ctx, markers[markers.length - 1][0], markers[markers.length - 1][1]);
  1580. }
  1581. }
  1582. };
  1583. this.getBoundingBox = function() {
  1584. return this.path();
  1585. };
  1586. this.getMarkers = function() {
  1587. return null;
  1588. };
  1589. };
  1590. svg.Element.PathElementBase.prototype = new svg.Element.RenderedElementBase();
  1591. // svg element
  1592. svg.Element.svg = function(node) {
  1593. this.base = svg.Element.RenderedElementBase;
  1594. this.base(node);
  1595. this.baseClearContext = this.clearContext;
  1596. this.clearContext = function(ctx) {
  1597. this.baseClearContext(ctx);
  1598. svg.ViewPort.RemoveCurrent();
  1599. };
  1600. this.baseSetContext = this.setContext;
  1601. this.setContext = function(ctx) {
  1602. // initial values
  1603. ctx.strokeStyle = "rgba(0,0,0,0)";
  1604. ctx.lineCap = "butt";
  1605. ctx.lineJoin = "miter";
  1606. ctx.miterLimit = 4;
  1607. this.baseSetContext(ctx);
  1608. // create new view port
  1609. if (!this.attribute("x").hasValue()) this.attribute("x", true).value = 0;
  1610. if (!this.attribute("y").hasValue()) this.attribute("y", true).value = 0;
  1611. ctx.translate(this.attribute("x").toPixels("x"), this.attribute("y").toPixels("y"));
  1612. var width = svg.ViewPort.width();
  1613. var height = svg.ViewPort.height();
  1614. if (!this.attribute("width").hasValue()) this.attribute("width", true).value = "100%";
  1615. if (!this.attribute("height").hasValue()) this.attribute("height", true).value = "100%";
  1616. if (typeof this.root == "undefined") {
  1617. width = this.attribute("width").toPixels("x");
  1618. height = this.attribute("height").toPixels("y");
  1619. var x = 0;
  1620. var y = 0;
  1621. if (this.attribute("refX").hasValue() && this.attribute("refY").hasValue()) {
  1622. x = -this.attribute("refX").toPixels("x");
  1623. y = -this.attribute("refY").toPixels("y");
  1624. }
  1625. ctx.beginPath();
  1626. ctx.moveTo(x, y);
  1627. ctx.lineTo(width, y);
  1628. ctx.lineTo(width, height);
  1629. ctx.lineTo(x, height);
  1630. ctx.closePath();
  1631. ctx.clip();
  1632. }
  1633. svg.ViewPort.SetCurrent(width, height);
  1634. // viewbox
  1635. if (this.attribute("viewBox").hasValue()) {
  1636. var viewBox = svg.ToNumberArray(this.attribute("viewBox").value);
  1637. var minX = viewBox[0];
  1638. var minY = viewBox[1];
  1639. width = viewBox[2];
  1640. height = viewBox[3];
  1641. 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);
  1642. svg.ViewPort.RemoveCurrent();
  1643. svg.ViewPort.SetCurrent(viewBox[2], viewBox[3]);
  1644. }
  1645. };
  1646. };
  1647. svg.Element.svg.prototype = new svg.Element.RenderedElementBase();
  1648. // rect element
  1649. svg.Element.rect = function(node) {
  1650. this.base = svg.Element.PathElementBase;
  1651. this.base(node);
  1652. this.path = function(ctx) {
  1653. var x = this.attribute("x").toPixels("x");
  1654. var y = this.attribute("y").toPixels("y");
  1655. var width = this.attribute("width").toPixels("x");
  1656. var height = this.attribute("height").toPixels("y");
  1657. var rx = this.attribute("rx").toPixels("x");
  1658. var ry = this.attribute("ry").toPixels("y");
  1659. if (this.attribute("rx").hasValue() && !this.attribute("ry").hasValue()) ry = rx;
  1660. if (this.attribute("ry").hasValue() && !this.attribute("rx").hasValue()) rx = ry;
  1661. rx = Math.min(rx, width / 2);
  1662. ry = Math.min(ry, height / 2);
  1663. if (ctx != null) {
  1664. ctx.beginPath();
  1665. ctx.moveTo(x + rx, y);
  1666. ctx.lineTo(x + width - rx, y);
  1667. ctx.quadraticCurveTo(x + width, y, x + width, y + ry);
  1668. ctx.lineTo(x + width, y + height - ry);
  1669. ctx.quadraticCurveTo(x + width, y + height, x + width - rx, y + height);
  1670. ctx.lineTo(x + rx, y + height);
  1671. ctx.quadraticCurveTo(x, y + height, x, y + height - ry);
  1672. ctx.lineTo(x, y + ry);
  1673. ctx.quadraticCurveTo(x, y, x + rx, y);
  1674. ctx.closePath();
  1675. }
  1676. return new svg.BoundingBox(x, y, x + width, y + height);
  1677. };
  1678. };
  1679. svg.Element.rect.prototype = new svg.Element.PathElementBase();
  1680. // circle element
  1681. svg.Element.circle = function(node) {
  1682. this.base = svg.Element.PathElementBase;
  1683. this.base(node);
  1684. this.path = function(ctx) {
  1685. var cx = this.attribute("cx").toPixels("x");
  1686. var cy = this.attribute("cy").toPixels("y");
  1687. var r = this.attribute("r").toPixels();
  1688. if (ctx != null) {
  1689. ctx.beginPath();
  1690. ctx.arc(cx, cy, r, 0, Math.PI * 2, true);
  1691. ctx.closePath();
  1692. }
  1693. return new svg.BoundingBox(cx - r, cy - r, cx + r, cy + r);
  1694. };
  1695. };
  1696. svg.Element.circle.prototype = new svg.Element.PathElementBase();
  1697. // ellipse element
  1698. svg.Element.ellipse = function(node) {
  1699. this.base = svg.Element.PathElementBase;
  1700. this.base(node);
  1701. this.path = function(ctx) {
  1702. var KAPPA = 4 * ((Math.sqrt(2) - 1) / 3);
  1703. var rx = this.attribute("rx").toPixels("x");
  1704. var ry = this.attribute("ry").toPixels("y");
  1705. var cx = this.attribute("cx").toPixels("x");
  1706. var cy = this.attribute("cy").toPixels("y");
  1707. if (ctx != null) {
  1708. ctx.beginPath();
  1709. ctx.moveTo(cx, cy - ry);
  1710. ctx.bezierCurveTo(cx + KAPPA * rx, cy - ry, cx + rx, cy - KAPPA * ry, cx + rx, cy);
  1711. ctx.bezierCurveTo(cx + rx, cy + KAPPA * ry, cx + KAPPA * rx, cy + ry, cx, cy + ry);
  1712. ctx.bezierCurveTo(cx - KAPPA * rx, cy + ry, cx - rx, cy + KAPPA * ry, cx - rx, cy);
  1713. ctx.bezierCurveTo(cx - rx, cy - KAPPA * ry, cx - KAPPA * rx, cy - ry, cx, cy - ry);
  1714. ctx.closePath();
  1715. }
  1716. return new svg.BoundingBox(cx - rx, cy - ry, cx + rx, cy + ry);
  1717. };
  1718. };
  1719. svg.Element.ellipse.prototype = new svg.Element.PathElementBase();
  1720. // line element
  1721. svg.Element.line = function(node) {
  1722. this.base = svg.Element.PathElementBase;
  1723. this.base(node);
  1724. this.getPoints = function() {
  1725. 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")) ];
  1726. };
  1727. this.path = function(ctx) {
  1728. var points = this.getPoints();
  1729. if (ctx != null) {
  1730. ctx.beginPath();
  1731. ctx.moveTo(points[0].x, points[0].y);
  1732. ctx.lineTo(points[1].x, points[1].y);
  1733. }
  1734. return new svg.BoundingBox(points[0].x, points[0].y, points[1].x, points[1].y);
  1735. };
  1736. this.getMarkers = function() {
  1737. var points = this.getPoints();
  1738. var a = points[0].angleTo(points[1]);
  1739. return [ [ points[0], a ], [ points[1], a ] ];
  1740. };
  1741. };
  1742. svg.Element.line.prototype = new svg.Element.PathElementBase();
  1743. // polyline element
  1744. svg.Element.polyline = function(node) {
  1745. this.base = svg.Element.PathElementBase;
  1746. this.base(node);
  1747. this.points = svg.CreatePath(this.attribute("points").value);
  1748. this.path = function(ctx) {
  1749. var bb = new svg.BoundingBox(this.points[0].x, this.points[0].y);
  1750. if (ctx != null) {
  1751. ctx.beginPath();
  1752. ctx.moveTo(this.points[0].x, this.points[0].y);
  1753. }
  1754. for (var i = 1; i < this.points.length; i++) {
  1755. bb.addPoint(this.points[i].x, this.points[i].y);
  1756. if (ctx != null) ctx.lineTo(this.points[i].x, this.points[i].y);
  1757. }
  1758. return bb;
  1759. };
  1760. this.getMarkers = function() {
  1761. var markers = [];
  1762. for (var i = 0; i < this.points.length - 1; i++) {
  1763. markers.push([ this.points[i], this.points[i].angleTo(this.points[i + 1]) ]);
  1764. }
  1765. markers.push([ this.points[this.points.length - 1], markers[markers.length - 1][1] ]);
  1766. return markers;
  1767. };
  1768. };
  1769. svg.Element.polyline.prototype = new svg.Element.PathElementBase();
  1770. // polygon element
  1771. svg.Element.polygon = function(node) {
  1772. this.base = svg.Element.polyline;
  1773. this.base(node);
  1774. this.basePath = this.path;
  1775. this.path = function(ctx) {
  1776. var bb = this.basePath(ctx);
  1777. if (ctx != null) {
  1778. ctx.lineTo(this.points[0].x, this.points[0].y);
  1779. ctx.closePath();
  1780. }
  1781. return bb;
  1782. };
  1783. };
  1784. svg.Element.polygon.prototype = new svg.Element.polyline();
  1785. // path element
  1786. svg.Element.path = function(node) {
  1787. this.base = svg.Element.PathElementBase;
  1788. this.base(node);
  1789. var d = this.attribute("d").value;
  1790. // TODO: convert to real lexer based on http://www.w3.org/TR/SVG11/paths.html#PathDataBNF
  1791. d = d.replace(/,/gm, " ");
  1792. // get rid of all commas
  1793. d = d.replace(/([MmZzLlHhVvCcSsQqTtAa])([MmZzLlHhVvCcSsQqTtAa])/gm, "$1 $2");
  1794. // separate commands from commands
  1795. d = d.replace(/([MmZzLlHhVvCcSsQqTtAa])([MmZzLlHhVvCcSsQqTtAa])/gm, "$1 $2");
  1796. // separate commands from commands
  1797. d = d.replace(/([MmZzLlHhVvCcSsQqTtAa])([^\s])/gm, "$1 $2");
  1798. // separate commands from points
  1799. d = d.replace(/([^\s])([MmZzLlHhVvCcSsQqTtAa])/gm, "$1 $2");
  1800. // separate commands from points
  1801. d = d.replace(/([0-9])([+\-])/gm, "$1 $2");
  1802. // separate digits when no comma
  1803. d = d.replace(/(\.[0-9]*)(\.)/gm, "$1 $2");
  1804. // separate digits when no comma
  1805. d = d.replace(/([Aa](\s+[0-9]+){3})\s+([01])\s*([01])/gm, "$1 $3 $4 ");
  1806. // shorthand elliptical arc path syntax
  1807. d = svg.compressSpaces(d);
  1808. // compress multiple spaces
  1809. d = svg.trim(d);
  1810. this.PathParser = new function(d) {
  1811. this.tokens = d.split(" ");
  1812. this.reset = function() {
  1813. this.i = -1;
  1814. this.command = "";
  1815. this.previousCommand = "";
  1816. this.start = new svg.Point(0, 0);
  1817. this.control = new svg.Point(0, 0);
  1818. this.current = new svg.Point(0, 0);
  1819. this.points = [];
  1820. this.angles = [];
  1821. };
  1822. this.isEnd = function() {
  1823. return this.i >= this.tokens.length - 1;
  1824. };
  1825. this.isCommandOrEnd = function() {
  1826. if (this.isEnd()) return true;
  1827. return this.tokens[this.i + 1].match(/^[A-Za-z]$/) != null;
  1828. };
  1829. this.isRelativeCommand = function() {
  1830. switch (this.command) {
  1831. case "m":
  1832. case "l":
  1833. case "h":
  1834. case "v":
  1835. case "c":
  1836. case "s":
  1837. case "q":
  1838. case "t":
  1839. case "a":
  1840. case "z":
  1841. return true;
  1842. break;
  1843. }
  1844. return false;
  1845. };
  1846. this.getToken = function() {
  1847. this.i++;
  1848. return this.tokens[this.i];
  1849. };
  1850. this.getScalar = function() {
  1851. return parseFloat(this.getToken());
  1852. };
  1853. this.nextCommand = function() {
  1854. this.previousCommand = this.command;
  1855. this.command = this.getToken();
  1856. };
  1857. this.getPoint = function() {
  1858. var p = new svg.Point(this.getScalar(), this.getScalar());
  1859. return this.makeAbsolute(p);
  1860. };
  1861. this.getAsControlPoint = function() {
  1862. var p = this.getPoint();
  1863. this.control = p;
  1864. return p;
  1865. };
  1866. this.getAsCurrentPoint = function() {
  1867. var p = this.getPoint();
  1868. this.current = p;
  1869. return p;
  1870. };
  1871. this.getReflectedControlPoint = function() {
  1872. if (this.previousCommand.toLowerCase() != "c" && this.previousCommand.toLowerCase() != "s" && this.previousCommand.toLowerCase() != "q" && this.previousCommand.toLowerCase() != "t") {
  1873. return this.current;
  1874. }
  1875. // reflect point
  1876. var p = new svg.Point(2 * this.current.x - this.control.x, 2 * this.current.y - this.control.y);
  1877. return p;
  1878. };
  1879. this.makeAbsolute = function(p) {
  1880. if (this.isRelativeCommand()) {
  1881. p.x += this.current.x;
  1882. p.y += this.current.y;
  1883. }
  1884. return p;
  1885. };
  1886. this.addMarker = function(p, from, priorTo) {
  1887. // if the last angle isn't filled in because we didn't have this point yet ...
  1888. if (priorTo != null && this.angles.length > 0 && this.angles[this.angles.length - 1] == null) {
  1889. this.angles[this.angles.length - 1] = this.points[this.points.length - 1].angleTo(priorTo);
  1890. }
  1891. this.addMarkerAngle(p, from == null ? null : from.angleTo(p));
  1892. };
  1893. this.addMarkerAngle = function(p, a) {
  1894. this.points.push(p);
  1895. this.angles.push(a);
  1896. };
  1897. this.getMarkerPoints = function() {
  1898. return this.points;
  1899. };
  1900. this.getMarkerAngles = function() {
  1901. for (var i = 0; i < this.angles.length; i++) {
  1902. if (this.angles[i] == null) {
  1903. for (var j = i + 1; j < this.angles.length; j++) {
  1904. if (this.angles[j] != null) {
  1905. this.angles[i] = this.angles[j];
  1906. break;
  1907. }
  1908. }
  1909. }
  1910. }
  1911. return this.angles;
  1912. };
  1913. }(d);
  1914. this.path = function(ctx) {
  1915. var pp = this.PathParser;
  1916. pp.reset();
  1917. var bb = new svg.BoundingBox();
  1918. if (ctx != null) ctx.beginPath();
  1919. while (!pp.isEnd()) {
  1920. pp.nextCommand();
  1921. switch (pp.command) {
  1922. case "M":
  1923. case "m":
  1924. var p = pp.getAsCurrentPoint();
  1925. pp.addMarker(p);
  1926. bb.addPoint(p.x, p.y);
  1927. if (ctx != null) ctx.moveTo(p.x, p.y);
  1928. pp.start = pp.current;
  1929. while (!pp.isCommandOrEnd()) {
  1930. var p = pp.getAsCurrentPoint();
  1931. pp.addMarker(p, pp.start);
  1932. bb.addPoint(p.x, p.y);
  1933. if (ctx != null) ctx.lineTo(p.x, p.y);
  1934. }
  1935. break;
  1936. case "L":
  1937. case "l":
  1938. while (!pp.isCommandOrEnd()) {
  1939. var c = pp.current;
  1940. var p = pp.getAsCurrentPoint();
  1941. pp.addMarker(p, c);
  1942. bb.addPoint(p.x, p.y);
  1943. if (ctx != null) ctx.lineTo(p.x, p.y);
  1944. }
  1945. break;
  1946. case "H":
  1947. case "h":
  1948. while (!pp.isCommandOrEnd()) {
  1949. var newP = new svg.Point((pp.isRelativeCommand() ? pp.current.x : 0) + pp.getScalar(), pp.current.y);
  1950. pp.addMarker(newP, pp.current);
  1951. pp.current = newP;
  1952. bb.addPoint(pp.current.x, pp.current.y);
  1953. if (ctx != null) ctx.lineTo(pp.current.x, pp.current.y);
  1954. }
  1955. break;
  1956. case "V":
  1957. case "v":
  1958. while (!pp.isCommandOrEnd()) {
  1959. var newP = new svg.Point(pp.current.x, (pp.isRelativeCommand() ? pp.current.y : 0) + pp.getScalar());
  1960. pp.addMarker(newP, pp.current);
  1961. pp.current = newP;
  1962. bb.addPoint(pp.current.x, pp.current.y);
  1963. if (ctx != null) ctx.lineTo(pp.current.x, pp.current.y);
  1964. }
  1965. break;
  1966. case "C":
  1967. case "c":
  1968. while (!pp.isCommandOrEnd()) {
  1969. var curr = pp.current;
  1970. var p1 = pp.getPoint();
  1971. var cntrl = pp.getAsControlPoint();
  1972. var cp = pp.getAsCurrentPoint();
  1973. pp.addMarker(cp, cntrl, p1);
  1974. bb.addBezierCurve(curr.x, curr.y, p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
  1975. if (ctx != null) ctx.bezierCurveTo(p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
  1976. }
  1977. break;
  1978. case "S":
  1979. case "s":
  1980. while (!pp.isCommandOrEnd()) {
  1981. var curr = pp.current;
  1982. var p1 = pp.getReflectedControlPoint();
  1983. var cntrl = pp.getAsControlPoint();
  1984. var cp = pp.getAsCurrentPoint();
  1985. pp.addMarker(cp, cntrl, p1);
  1986. bb.addBezierCurve(curr.x, curr.y, p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
  1987. if (ctx != null) ctx.bezierCurveTo(p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
  1988. }
  1989. break;
  1990. case "Q":
  1991. case "q":
  1992. while (!pp.isCommandOrEnd()) {
  1993. var curr = pp.current;
  1994. var cntrl = pp.getAsControlPoint();
  1995. var cp = pp.getAsCurrentPoint();
  1996. pp.addMarker(cp, cntrl, cntrl);
  1997. bb.addQuadraticCurve(curr.x, curr.y, cntrl.x, cntrl.y, cp.x, cp.y);
  1998. if (ctx != null) ctx.quadraticCurveTo(cntrl.x, cntrl.y, cp.x, cp.y);
  1999. }
  2000. break;
  2001. case "T":
  2002. case "t":
  2003. while (!pp.isCommandOrEnd()) {
  2004. var curr = pp.current;
  2005. var cntrl = pp.getReflectedControlPoint();
  2006. pp.control = cntrl;
  2007. var cp = pp.getAsCurrentPoint();
  2008. pp.addMarker(cp, cntrl, cntrl);
  2009. bb.addQuadraticCurve(curr.x, curr.y, cntrl.x, cntrl.y, cp.x, cp.y);
  2010. if (ctx != null) ctx.quadraticCurveTo(cntrl.x, cntrl.y, cp.x, cp.y);
  2011. }
  2012. break;
  2013. case "A":
  2014. case "a":
  2015. while (!pp.isCommandOrEnd()) {
  2016. var curr = pp.current;
  2017. var rx = pp.getScalar();
  2018. var ry = pp.getScalar();
  2019. var xAxisRotation = pp.getScalar() * (Math.PI / 180);
  2020. var largeArcFlag = pp.getScalar();
  2021. var sweepFlag = pp.getScalar();
  2022. var cp = pp.getAsCurrentPoint();
  2023. // Conversion from endpoint to center parameterization
  2024. // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
  2025. // x1', y1'
  2026. 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);
  2027. // adjust radii
  2028. var l = Math.pow(currp.x, 2) / Math.pow(rx, 2) + Math.pow(currp.y, 2) / Math.pow(ry, 2);
  2029. if (l > 1) {
  2030. rx *= Math.sqrt(l);
  2031. ry *= Math.sqrt(l);
  2032. }
  2033. // cx', cy'
  2034. 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)));
  2035. if (isNaN(s)) s = 0;
  2036. var cpp = new svg.Point(s * rx * currp.y / ry, s * -ry * currp.x / rx);
  2037. // cx, cy
  2038. 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);
  2039. // vector magnitude
  2040. var m = function(v) {
  2041. return Math.sqrt(Math.pow(v[0], 2) + Math.pow(v[1], 2));
  2042. };
  2043. // ratio between two vectors
  2044. var r = function(u, v) {
  2045. return (u[0] * v[0] + u[1] * v[1]) / (m(u) * m(v));
  2046. };
  2047. // angle between two vectors
  2048. var a = function(u, v) {
  2049. return (u[0] * v[1] < u[1] * v[0] ? -1 : 1) * Math.acos(r(u, v));
  2050. };
  2051. // initial angle
  2052. var a1 = a([ 1, 0 ], [ (currp.x - cpp.x) / rx, (currp.y - cpp.y) / ry ]);
  2053. // angle delta
  2054. var u = [ (currp.x - cpp.x) / rx, (currp.y - cpp.y) / ry ];
  2055. var v = [ (-currp.x - cpp.x) / rx, (-currp.y - cpp.y) / ry ];
  2056. var ad = a(u, v);
  2057. if (r(u, v) <= -1) ad = Math.PI;
  2058. if (r(u, v) >= 1) ad = 0;
  2059. // for markers
  2060. var dir = 1 - sweepFlag ? 1 : -1;
  2061. var ah = a1 + dir * (ad / 2);
  2062. var halfWay = new svg.Point(centp.x + rx * Math.cos(ah), centp.y + ry * Math.sin(ah));
  2063. pp.addMarkerAngle(halfWay, ah - dir * Math.PI / 2);
  2064. pp.addMarkerAngle(cp, ah - dir * Math.PI);
  2065. bb.addPoint(cp.x, cp.y);
  2066. // TODO: this is too naive, make it better
  2067. if (ctx != null) {
  2068. var r = rx > ry ? rx : ry;
  2069. var sx = rx > ry ? 1 : rx / ry;
  2070. var sy = rx > ry ? ry / rx : 1;
  2071. ctx.translate(centp.x, centp.y);
  2072. ctx.rotate(xAxisRotation);
  2073. ctx.scale(sx, sy);
  2074. ctx.arc(0, 0, r, a1, a1 + ad, 1 - sweepFlag);
  2075. ctx.scale(1 / sx, 1 / sy);
  2076. ctx.rotate(-xAxisRotation);
  2077. ctx.translate(-centp.x, -centp.y);
  2078. }
  2079. }
  2080. break;
  2081. case "Z":
  2082. case "z":
  2083. if (ctx != null) ctx.closePath();
  2084. pp.current = pp.start;
  2085. }
  2086. }
  2087. return bb;
  2088. };
  2089. this.getMarkers = function() {
  2090. var points = this.PathParser.getMarkerPoints();
  2091. var angles = this.PathParser.getMarkerAngles();
  2092. var markers = [];
  2093. for (var i = 0; i < points.length; i++) {
  2094. markers.push([ points[i], angles[i] ]);
  2095. }
  2096. return markers;
  2097. };
  2098. };
  2099. svg.Element.path.prototype = new svg.Element.PathElementBase();
  2100. // pattern element
  2101. svg.Element.pattern = function(node) {
  2102. this.base = svg.Element.ElementBase;
  2103. this.base(node);
  2104. this.createPattern = function(ctx, element) {
  2105. var width = this.attribute("width").toPixels("x", true);
  2106. var height = this.attribute("height").toPixels("y", true);
  2107. // render me using a temporary svg element
  2108. var tempSvg = new svg.Element.svg();
  2109. tempSvg.attributes["viewBox"] = new svg.Property("viewBox", this.attribute("viewBox").value);
  2110. tempSvg.attributes["width"] = new svg.Property("width", width + "px");
  2111. tempSvg.attributes["height"] = new svg.Property("height", height + "px");
  2112. tempSvg.attributes["transform"] = new svg.Property("transform", this.attribute("patternTransform").value);
  2113. tempSvg.children = this.children;
  2114. var c = document.createElement("canvas");
  2115. c.width = width;
  2116. c.height = height;
  2117. var cctx = c.getContext("2d");
  2118. if (this.attribute("x").hasValue() && this.attribute("y").hasValue()) {
  2119. cctx.translate(this.attribute("x").toPixels("x", true), this.attribute("y").toPixels("y", true));
  2120. }
  2121. // render 3x3 grid so when we transform there's no white space on edges
  2122. for (var x = -1; x <= 1; x++) {
  2123. for (var y = -1; y <= 1; y++) {
  2124. cctx.save();
  2125. cctx.translate(x * c.width, y * c.height);
  2126. tempSvg.render(cctx);
  2127. cctx.restore();
  2128. }
  2129. }
  2130. var pattern = ctx.createPattern(c, "repeat");
  2131. return pattern;
  2132. };
  2133. };
  2134. svg.Element.pattern.prototype = new svg.Element.ElementBase();
  2135. // marker element
  2136. svg.Element.marker = function(node) {
  2137. this.base = svg.Element.ElementBase;
  2138. this.base(node);
  2139. this.baseRender = this.render;
  2140. this.render = function(ctx, point, angle) {
  2141. ctx.translate(point.x, point.y);
  2142. if (this.attribute("orient").valueOrDefault("auto") == "auto") ctx.rotate(angle);
  2143. if (this.attribute("markerUnits").valueOrDefault("strokeWidth") == "strokeWidth") ctx.scale(ctx.lineWidth, ctx.lineWidth);
  2144. ctx.save();
  2145. // render me using a temporary svg element
  2146. var tempSvg = new svg.Element.svg();
  2147. tempSvg.attributes["viewBox"] = new svg.Property("viewBox", this.attribute("viewBox").value);
  2148. tempSvg.attributes["refX"] = new svg.Property("refX", this.attribute("refX").value);
  2149. tempSvg.attributes["refY"] = new svg.Property("refY", this.attribute("refY").value);
  2150. tempSvg.attributes["width"] = new svg.Property("width", this.attribute("markerWidth").value);
  2151. tempSvg.attributes["height"] = new svg.Property("height", this.attribute("markerHeight").value);
  2152. tempSvg.attributes["fill"] = new svg.Property("fill", this.attribute("fill").valueOrDefault("black"));
  2153. tempSvg.attributes["stroke"] = new svg.Property("stroke", this.attribute("stroke").valueOrDefault("none"));
  2154. tempSvg.children = this.children;
  2155. tempSvg.render(ctx);
  2156. ctx.restore();
  2157. if (this.attribute("markerUnits").valueOrDefault("strokeWidth") == "strokeWidth") ctx.scale(1 / ctx.lineWidth, 1 / ctx.lineWidth);
  2158. if (this.attribute("orient").valueOrDefault("auto") == "auto") ctx.rotate(-angle);
  2159. ctx.translate(-point.x, -point.y);
  2160. };
  2161. };
  2162. svg.Element.marker.prototype = new svg.Element.ElementBase();
  2163. // definitions element
  2164. svg.Element.defs = function(node) {
  2165. this.base = svg.Element.ElementBase;
  2166. this.base(node);
  2167. this.render = function(ctx) {};
  2168. };
  2169. svg.Element.defs.prototype = new svg.Element.ElementBase();
  2170. // base for gradients
  2171. svg.Element.GradientBase = function(node) {
  2172. this.base = svg.Element.ElementBase;
  2173. this.base(node);
  2174. this.gradientUnits = this.attribute("gradientUnits").valueOrDefault("objectBoundingBox");
  2175. this.stops = [];
  2176. for (var i = 0; i < this.children.length; i++) {
  2177. var child = this.children[i];
  2178. if (child.type == "stop") this.stops.push(child);
  2179. }
  2180. this.getGradient = function() {};
  2181. this.createGradient = function(ctx, element, parentOpacityProp) {
  2182. var stopsContainer = this;
  2183. if (this.getHrefAttribute().hasValue()) {
  2184. stopsContainer = this.getHrefAttribute().getDefinition();
  2185. }
  2186. var addParentOpacity = function(color) {
  2187. if (parentOpacityProp.hasValue()) {
  2188. var p = new svg.Property("color", color);
  2189. return p.addOpacity(parentOpacityProp.value).value;
  2190. }
  2191. return color;
  2192. };
  2193. var g = this.getGradient(ctx, element);
  2194. if (g == null) return addParentOpacity(stopsContainer.stops[stopsContainer.stops.length - 1].color);
  2195. for (var i = 0; i < stopsContainer.stops.length; i++) {
  2196. g.addColorStop(stopsContainer.stops[i].offset, addParentOpacity(stopsContainer.stops[i].color));
  2197. }
  2198. if (this.attribute("gradientTransform").hasValue()) {
  2199. // render as transformed pattern on temporary canvas
  2200. var rootView = svg.ViewPort.viewPorts[0];
  2201. var rect = new svg.Element.rect();
  2202. rect.attributes["x"] = new svg.Property("x", -svg.MAX_VIRTUAL_PIXELS / 3);
  2203. rect.attributes["y"] = new svg.Property("y", -svg.MAX_VIRTUAL_PIXELS / 3);
  2204. rect.attributes["width"] = new svg.Property("width", svg.MAX_VIRTUAL_PIXELS);
  2205. rect.attributes["height"] = new svg.Property("height", svg.MAX_VIRTUAL_PIXELS);
  2206. var group = new svg.Element.g();
  2207. group.attributes["transform"] = new svg.Property("transform", this.attribute("gradientTransform").value);
  2208. group.children = [ rect ];
  2209. var tempSvg = new svg.Element.svg();
  2210. tempSvg.attributes["x"] = new svg.Property("x", 0);
  2211. tempSvg.attributes["y"] = new svg.Property("y", 0);
  2212. tempSvg.attributes["width"] = new svg.Property("width", rootView.width);
  2213. tempSvg.attributes["height"] = new svg.Property("height", rootView.height);
  2214. tempSvg.children = [ group ];
  2215. var c = document.createElement("canvas");
  2216. c.width = rootView.width;
  2217. c.height = rootView.height;
  2218. var tempCtx = c.getContext("2d");
  2219. tempCtx.fillStyle = g;
  2220. tempSvg.render(tempCtx);
  2221. return tempCtx.createPattern(c, "no-repeat");
  2222. }
  2223. return g;
  2224. };
  2225. };
  2226. svg.Element.GradientBase.prototype = new svg.Element.ElementBase();
  2227. // linear gradient element
  2228. svg.Element.linearGradient = function(node) {
  2229. this.base = svg.Element.GradientBase;
  2230. this.base(node);
  2231. this.getGradient = function(ctx, element) {
  2232. var bb = element.getBoundingBox();
  2233. if (!this.attribute("x1").hasValue() && !this.attribute("y1").hasValue() && !this.attribute("x2").hasValue() && !this.attribute("y2").hasValue()) {
  2234. this.attribute("x1", true).value = 0;
  2235. this.attribute("y1", true).value = 0;
  2236. this.attribute("x2", true).value = 1;
  2237. this.attribute("y2", true).value = 0;
  2238. }
  2239. var x1 = this.gradientUnits == "objectBoundingBox" ? bb.x() + bb.width() * this.attribute("x1").numValue() : this.attribute("x1").toPixels("x");
  2240. var y1 = this.gradientUnits == "objectBoundingBox" ? bb.y() + bb.height() * this.attribute("y1").numValue() : this.attribute("y1").toPixels("y");
  2241. var x2 = this.gradientUnits == "objectBoundingBox" ? bb.x() + bb.width() * this.attribute("x2").numValue() : this.attribute("x2").toPixels("x");
  2242. var y2 = this.gradientUnits == "objectBoundingBox" ? bb.y() + bb.height() * this.attribute("y2").numValue() : this.attribute("y2").toPixels("y");
  2243. if (x1 == x2 && y1 == y2) return null;
  2244. return ctx.createLinearGradient(x1, y1, x2, y2);
  2245. };
  2246. };
  2247. svg.Element.linearGradient.prototype = new svg.Element.GradientBase();
  2248. // radial gradient element
  2249. svg.Element.radialGradient = function(node) {
  2250. this.base = svg.Element.GradientBase;
  2251. this.base(node);
  2252. this.getGradient = function(ctx, element) {
  2253. var bb = element.getBoundingBox();
  2254. if (!this.attribute("cx").hasValue()) this.attribute("cx", true).value = "50%";
  2255. if (!this.attribute("cy").hasValue()) this.attribute("cy", true).value = "50%";
  2256. if (!this.attribute("r").hasValue()) this.attribute("r", true).value = "50%";
  2257. var cx = this.gradientUnits == "objectBoundingBox" ? bb.x() + bb.width() * this.attribute("cx").numValue() : this.attribute("cx").toPixels("x");
  2258. var cy = this.gradientUnits == "objectBoundingBox" ? bb.y() + bb.height() * this.attribute("cy").numValue() : this.attribute("cy").toPixels("y");
  2259. var fx = cx;
  2260. var fy = cy;
  2261. if (this.attribute("fx").hasValue()) {
  2262. fx = this.gradientUnits == "objectBoundingBox" ? bb.x() + bb.width() * this.attribute("fx").numValue() : this.attribute("fx").toPixels("x");
  2263. }
  2264. if (this.attribute("fy").hasValue()) {
  2265. fy = this.gradientUnits == "objectBoundingBox" ? bb.y() + bb.height() * this.attribute("fy").numValue() : this.attribute("fy").toPixels("y");
  2266. }
  2267. var r = this.gradientUnits == "objectBoundingBox" ? (bb.width() + bb.height()) / 2 * this.attribute("r").numValue() : this.attribute("r").toPixels();
  2268. return ctx.createRadialGradient(fx, fy, 0, cx, cy, r);
  2269. };
  2270. };
  2271. svg.Element.radialGradient.prototype = new svg.Element.GradientBase();
  2272. // gradient stop element
  2273. svg.Element.stop = function(node) {
  2274. this.base = svg.Element.ElementBase;
  2275. this.base(node);
  2276. this.offset = this.attribute("offset").numValue();
  2277. if (this.offset < 0) this.offset = 0;
  2278. if (this.offset > 1) this.offset = 1;
  2279. var stopColor = this.style("stop-color");
  2280. if (this.style("stop-opacity").hasValue()) stopColor = stopColor.addOpacity(this.style("stop-opacity").value);
  2281. this.color = stopColor.value;
  2282. };
  2283. svg.Element.stop.prototype = new svg.Element.ElementBase();
  2284. // animation base element
  2285. svg.Element.AnimateBase = function(node) {
  2286. this.base = svg.Element.ElementBase;
  2287. this.base(node);
  2288. svg.Animations.push(this);
  2289. this.duration = 0;
  2290. this.begin = this.attribute("begin").toMilliseconds();
  2291. this.maxDuration = this.begin + this.attribute("dur").toMilliseconds();
  2292. this.getProperty = function() {
  2293. var attributeType = this.attribute("attributeType").value;
  2294. var attributeName = this.attribute("attributeName").value;
  2295. if (attributeType == "CSS") {
  2296. return this.parent.style(attributeName, true);
  2297. }
  2298. return this.parent.attribute(attributeName, true);
  2299. };
  2300. this.initialValue = null;
  2301. this.initialUnits = "";
  2302. this.removed = false;
  2303. this.calcValue = function() {
  2304. // OVERRIDE ME!
  2305. return "";
  2306. };
  2307. this.update = function(delta) {
  2308. // set initial value
  2309. if (this.initialValue == null) {
  2310. this.initialValue = this.getProperty().value;
  2311. this.initialUnits = this.getProperty().getUnits();
  2312. }
  2313. // if we're past the end time
  2314. if (this.duration > this.maxDuration) {
  2315. // loop for indefinitely repeating animations
  2316. if (this.attribute("repeatCount").value == "indefinite" || this.attribute("repeatDur").value == "indefinite") {
  2317. this.duration = 0;
  2318. } else if (this.attribute("fill").valueOrDefault("remove") == "remove" && !this.removed) {
  2319. this.removed = true;
  2320. this.getProperty().value = this.initialValue;
  2321. return true;
  2322. } else {
  2323. return false;
  2324. }
  2325. }
  2326. this.duration = this.duration + delta;
  2327. // if we're past the begin time
  2328. var updated = false;
  2329. if (this.begin < this.duration) {
  2330. var newValue = this.calcValue();
  2331. // tween
  2332. if (this.attribute("type").hasValue()) {
  2333. // for transform, etc.
  2334. var type = this.attribute("type").value;
  2335. newValue = type + "(" + newValue + ")";
  2336. }
  2337. this.getProperty().value = newValue;
  2338. updated = true;
  2339. }
  2340. return updated;
  2341. };
  2342. this.from = this.attribute("from");
  2343. this.to = this.attribute("to");
  2344. this.values = this.attribute("values");
  2345. if (this.values.hasValue()) this.values.value = this.values.value.split(";");
  2346. // fraction of duration we've covered
  2347. this.progress = function() {
  2348. var ret = {
  2349. progress: (this.duration - this.begin) / (this.maxDuration - this.begin)
  2350. };
  2351. if (this.values.hasValue()) {
  2352. var p = ret.progress * (this.values.value.length - 1);
  2353. var lb = Math.floor(p), ub = Math.ceil(p);
  2354. ret.from = new svg.Property("from", parseFloat(this.values.value[lb]));
  2355. ret.to = new svg.Property("to", parseFloat(this.values.value[ub]));
  2356. ret.progress = (p - lb) / (ub - lb);
  2357. } else {
  2358. ret.from = this.from;
  2359. ret.to = this.to;
  2360. }
  2361. return ret;
  2362. };
  2363. };
  2364. svg.Element.AnimateBase.prototype = new svg.Element.ElementBase();
  2365. // animate element
  2366. svg.Element.animate = function(node) {
  2367. this.base = svg.Element.AnimateBase;
  2368. this.base(node);
  2369. this.calcValue = function() {
  2370. var p = this.progress();
  2371. // tween value linearly
  2372. var newValue = p.from.numValue() + (p.to.numValue() - p.from.numValue()) * p.progress;
  2373. return newValue + this.initialUnits;
  2374. };
  2375. };
  2376. svg.Element.animate.prototype = new svg.Element.AnimateBase();
  2377. // animate color element
  2378. svg.Element.animateColor = function(node) {
  2379. this.base = svg.Element.AnimateBase;
  2380. this.base(node);
  2381. this.calcValue = function() {
  2382. var p = this.progress();
  2383. var from = new RGBColor(p.from.value);
  2384. var to = new RGBColor(p.to.value);
  2385. if (from.ok && to.ok) {
  2386. // tween color linearly
  2387. var r = from.r + (to.r - from.r) * p.progress;
  2388. var g = from.g + (to.g - from.g) * p.progress;
  2389. var b = from.b + (to.b - from.b) * p.progress;
  2390. return "rgb(" + parseInt(r, 10) + "," + parseInt(g, 10) + "," + parseInt(b, 10) + ")";
  2391. }
  2392. return this.attribute("from").value;
  2393. };
  2394. };
  2395. svg.Element.animateColor.prototype = new svg.Element.AnimateBase();
  2396. // animate transform element
  2397. svg.Element.animateTransform = function(node) {
  2398. this.base = svg.Element.AnimateBase;
  2399. this.base(node);
  2400. this.calcValue = function() {
  2401. var p = this.progress();
  2402. // tween value linearly
  2403. var from = svg.ToNumberArray(p.from.value);
  2404. var to = svg.ToNumberArray(p.to.value);
  2405. var newValue = "";
  2406. for (var i = 0; i < from.length; i++) {
  2407. newValue += from[i] + (to[i] - from[i]) * p.progress + " ";
  2408. }
  2409. return newValue;
  2410. };
  2411. };
  2412. svg.Element.animateTransform.prototype = new svg.Element.animate();
  2413. // font element
  2414. svg.Element.font = function(node) {
  2415. this.base = svg.Element.ElementBase;
  2416. this.base(node);
  2417. this.horizAdvX = this.attribute("horiz-adv-x").numValue();
  2418. this.isRTL = false;
  2419. this.isArabic = false;
  2420. this.fontFace = null;
  2421. this.missingGlyph = null;
  2422. this.glyphs = [];
  2423. for (var i = 0; i < this.children.length; i++) {
  2424. var child = this.children[i];
  2425. if (child.type == "font-face") {
  2426. this.fontFace = child;
  2427. if (child.style("font-family").hasValue()) {
  2428. svg.Definitions[child.style("font-family").value] = this;
  2429. }
  2430. } else if (child.type == "missing-glyph") this.missingGlyph = child; else if (child.type == "glyph") {
  2431. if (child.arabicForm != "") {
  2432. this.isRTL = true;
  2433. this.isArabic = true;
  2434. if (typeof this.glyphs[child.unicode] == "undefined") this.glyphs[child.unicode] = [];
  2435. this.glyphs[child.unicode][child.arabicForm] = child;
  2436. } else {
  2437. this.glyphs[child.unicode] = child;
  2438. }
  2439. }
  2440. }
  2441. };
  2442. svg.Element.font.prototype = new svg.Element.ElementBase();
  2443. // font-face element
  2444. svg.Element.fontface = function(node) {
  2445. this.base = svg.Element.ElementBase;
  2446. this.base(node);
  2447. this.ascent = this.attribute("ascent").value;
  2448. this.descent = this.attribute("descent").value;
  2449. this.unitsPerEm = this.attribute("units-per-em").numValue();
  2450. };
  2451. svg.Element.fontface.prototype = new svg.Element.ElementBase();
  2452. // missing-glyph element
  2453. svg.Element.missingglyph = function(node) {
  2454. this.base = svg.Element.path;
  2455. this.base(node);
  2456. this.horizAdvX = 0;
  2457. };
  2458. svg.Element.missingglyph.prototype = new svg.Element.path();
  2459. // glyph element
  2460. svg.Element.glyph = function(node) {
  2461. this.base = svg.Element.path;
  2462. this.base(node);
  2463. this.horizAdvX = this.attribute("horiz-adv-x").numValue();
  2464. this.unicode = this.attribute("unicode").value;
  2465. this.arabicForm = this.attribute("arabic-form").value;
  2466. };
  2467. svg.Element.glyph.prototype = new svg.Element.path();
  2468. // text element
  2469. svg.Element.text = function(node) {
  2470. this.captureTextNodes = true;
  2471. this.base = svg.Element.RenderedElementBase;
  2472. this.base(node);
  2473. this.baseSetContext = this.setContext;
  2474. this.setContext = function(ctx) {
  2475. this.baseSetContext(ctx);
  2476. if (this.style("dominant-baseline").hasValue()) ctx.textBaseline = this.style("dominant-baseline").value;
  2477. if (this.style("alignment-baseline").hasValue()) ctx.textBaseline = this.style("alignment-baseline").value;
  2478. };
  2479. this.getBoundingBox = function() {
  2480. // TODO: implement
  2481. return new svg.BoundingBox(this.attribute("x").toPixels("x"), this.attribute("y").toPixels("y"), 0, 0);
  2482. };
  2483. this.renderChildren = function(ctx) {
  2484. this.x = this.attribute("x").toPixels("x");
  2485. this.y = this.attribute("y").toPixels("y");
  2486. this.x += this.getAnchorDelta(ctx, this, 0);
  2487. for (var i = 0; i < this.children.length; i++) {
  2488. this.renderChild(ctx, this, i);
  2489. }
  2490. };
  2491. this.getAnchorDelta = function(ctx, parent, startI) {
  2492. var textAnchor = this.style("text-anchor").valueOrDefault("start");
  2493. if (textAnchor != "start") {
  2494. var width = 0;
  2495. for (var i = startI; i < parent.children.length; i++) {
  2496. var child = parent.children[i];
  2497. if (i > startI && child.attribute("x").hasValue()) break;
  2498. // new group
  2499. width += child.measureTextRecursive(ctx);
  2500. }
  2501. return -1 * (textAnchor == "end" ? width : width / 2);
  2502. }
  2503. return 0;
  2504. };
  2505. this.renderChild = function(ctx, parent, i) {
  2506. var child = parent.children[i];
  2507. if (child.attribute("x").hasValue()) {
  2508. child.x = child.attribute("x").toPixels("x") + this.getAnchorDelta(ctx, parent, i);
  2509. } else {
  2510. if (this.attribute("dx").hasValue()) this.x += this.attribute("dx").toPixels("x");
  2511. if (child.attribute("dx").hasValue()) this.x += child.attribute("dx").toPixels("x");
  2512. child.x = this.x;
  2513. }
  2514. this.x = child.x + child.measureText(ctx);
  2515. if (child.attribute("y").hasValue()) {
  2516. child.y = child.attribute("y").toPixels("y");
  2517. } else {
  2518. if (this.attribute("dy").hasValue()) this.y += this.attribute("dy").toPixels("y");
  2519. if (child.attribute("dy").hasValue()) this.y += child.attribute("dy").toPixels("y");
  2520. child.y = this.y;
  2521. }
  2522. this.y = child.y;
  2523. child.render(ctx);
  2524. for (var i = 0; i < child.children.length; i++) {
  2525. this.renderChild(ctx, child, i);
  2526. }
  2527. };
  2528. };
  2529. svg.Element.text.prototype = new svg.Element.RenderedElementBase();
  2530. // text base
  2531. svg.Element.TextElementBase = function(node) {
  2532. this.base = svg.Element.RenderedElementBase;
  2533. this.base(node);
  2534. this.getGlyph = function(font, text, i) {
  2535. var c = text[i];
  2536. var glyph = null;
  2537. if (font.isArabic) {
  2538. var arabicForm = "isolated";
  2539. if ((i == 0 || text[i - 1] == " ") && i < text.length - 2 && text[i + 1] != " ") arabicForm = "terminal";
  2540. if (i > 0 && text[i - 1] != " " && i < text.length - 2 && text[i + 1] != " ") arabicForm = "medial";
  2541. if (i > 0 && text[i - 1] != " " && (i == text.length - 1 || text[i + 1] == " ")) arabicForm = "initial";
  2542. if (typeof font.glyphs[c] != "undefined") {
  2543. glyph = font.glyphs[c][arabicForm];
  2544. if (glyph == null && font.glyphs[c].type == "glyph") glyph = font.glyphs[c];
  2545. }
  2546. } else {
  2547. glyph = font.glyphs[c];
  2548. }
  2549. if (glyph == null) glyph = font.missingGlyph;
  2550. return glyph;
  2551. };
  2552. this.renderChildren = function(ctx) {
  2553. var customFont = this.parent.style("font-family").getDefinition();
  2554. if (customFont != null) {
  2555. var fontSize = this.parent.style("font-size").numValueOrDefault(svg.Font.Parse(svg.ctx.font).fontSize);
  2556. var fontStyle = this.parent.style("font-style").valueOrDefault(svg.Font.Parse(svg.ctx.font).fontStyle);
  2557. var text = this.getText();
  2558. if (customFont.isRTL) text = text.split("").reverse().join("");
  2559. var dx = svg.ToNumberArray(this.parent.attribute("dx").value);
  2560. for (var i = 0; i < text.length; i++) {
  2561. var glyph = this.getGlyph(customFont, text, i);
  2562. var scale = fontSize / customFont.fontFace.unitsPerEm;
  2563. ctx.translate(this.x, this.y);
  2564. ctx.scale(scale, -scale);
  2565. var lw = ctx.lineWidth;
  2566. ctx.lineWidth = ctx.lineWidth * customFont.fontFace.unitsPerEm / fontSize;
  2567. if (fontStyle == "italic") ctx.transform(1, 0, .4, 1, 0, 0);
  2568. glyph.render(ctx);
  2569. if (fontStyle == "italic") ctx.transform(1, 0, -.4, 1, 0, 0);
  2570. ctx.lineWidth = lw;
  2571. ctx.scale(1 / scale, -1 / scale);
  2572. ctx.translate(-this.x, -this.y);
  2573. this.x += fontSize * (glyph.horizAdvX || customFont.horizAdvX) / customFont.fontFace.unitsPerEm;
  2574. if (typeof dx[i] != "undefined" && !isNaN(dx[i])) {
  2575. this.x += dx[i];
  2576. }
  2577. }
  2578. return;
  2579. }
  2580. if (ctx.fillStyle != "") ctx.fillText(svg.compressSpaces(this.getText()), this.x, this.y);
  2581. if (ctx.strokeStyle != "") ctx.strokeText(svg.compressSpaces(this.getText()), this.x, this.y);
  2582. };
  2583. this.getText = function() {};
  2584. this.measureTextRecursive = function(ctx) {
  2585. var width = this.measureText(ctx);
  2586. for (var i = 0; i < this.children.length; i++) {
  2587. width += this.children[i].measureTextRecursive(ctx);
  2588. }
  2589. return width;
  2590. };
  2591. this.measureText = function(ctx) {
  2592. var customFont = this.parent.style("font-family").getDefinition();
  2593. if (customFont != null) {
  2594. var fontSize = this.parent.style("font-size").numValueOrDefault(svg.Font.Parse(svg.ctx.font).fontSize);
  2595. var measure = 0;
  2596. var text = this.getText();
  2597. if (customFont.isRTL) text = text.split("").reverse().join("");
  2598. var dx = svg.ToNumberArray(this.parent.attribute("dx").value);
  2599. for (var i = 0; i < text.length; i++) {
  2600. var glyph = this.getGlyph(customFont, text, i);
  2601. measure += (glyph.horizAdvX || customFont.horizAdvX) * fontSize / customFont.fontFace.unitsPerEm;
  2602. if (typeof dx[i] != "undefined" && !isNaN(dx[i])) {
  2603. measure += dx[i];
  2604. }
  2605. }
  2606. return measure;
  2607. }
  2608. var textToMeasure = svg.compressSpaces(this.getText());
  2609. if (!ctx.measureText) return textToMeasure.length * 10;
  2610. ctx.save();
  2611. this.setContext(ctx);
  2612. var width = ctx.measureText(textToMeasure).width;
  2613. ctx.restore();
  2614. return width;
  2615. };
  2616. };
  2617. svg.Element.TextElementBase.prototype = new svg.Element.RenderedElementBase();
  2618. // tspan
  2619. svg.Element.tspan = function(node) {
  2620. this.captureTextNodes = true;
  2621. this.base = svg.Element.TextElementBase;
  2622. this.base(node);
  2623. this.text = node.nodeValue || node.text || "";
  2624. this.getText = function() {
  2625. return this.text;
  2626. };
  2627. };
  2628. svg.Element.tspan.prototype = new svg.Element.TextElementBase();
  2629. // tref
  2630. svg.Element.tref = function(node) {
  2631. this.base = svg.Element.TextElementBase;
  2632. this.base(node);
  2633. this.getText = function() {
  2634. var element = this.getHrefAttribute().getDefinition();
  2635. if (element != null) return element.children[0].getText();
  2636. };
  2637. };
  2638. svg.Element.tref.prototype = new svg.Element.TextElementBase();
  2639. // a element
  2640. svg.Element.a = function(node) {
  2641. this.base = svg.Element.TextElementBase;
  2642. this.base(node);
  2643. this.hasText = true;
  2644. for (var i = 0; i < node.childNodes.length; i++) {
  2645. if (node.childNodes[i].nodeType != 3) this.hasText = false;
  2646. }
  2647. // this might contain text
  2648. this.text = this.hasText ? node.childNodes[0].nodeValue : "";
  2649. this.getText = function() {
  2650. return this.text;
  2651. };
  2652. this.baseRenderChildren = this.renderChildren;
  2653. this.renderChildren = function(ctx) {
  2654. if (this.hasText) {
  2655. // render as text element
  2656. this.baseRenderChildren(ctx);
  2657. var fontSize = new svg.Property("fontSize", svg.Font.Parse(svg.ctx.font).fontSize);
  2658. svg.Mouse.checkBoundingBox(this, new svg.BoundingBox(this.x, this.y - fontSize.toPixels("y"), this.x + this.measureText(ctx), this.y));
  2659. } else {
  2660. // render as temporary group
  2661. var g = new svg.Element.g();
  2662. g.children = this.children;
  2663. g.parent = this;
  2664. g.render(ctx);
  2665. }
  2666. };
  2667. this.onclick = function() {
  2668. window.open(this.getHrefAttribute().value);
  2669. };
  2670. this.onmousemove = function() {
  2671. svg.ctx.canvas.style.cursor = "pointer";
  2672. };
  2673. };
  2674. svg.Element.a.prototype = new svg.Element.TextElementBase();
  2675. // image element
  2676. svg.Element.image = function(node) {
  2677. this.base = svg.Element.RenderedElementBase;
  2678. this.base(node);
  2679. var href = this.getHrefAttribute().value;
  2680. var isSvg = href.match(/\.svg$/);
  2681. svg.Images.push(this);
  2682. this.loaded = false;
  2683. if (!isSvg) {
  2684. this.img = document.createElement("img");
  2685. var self = this;
  2686. this.img.onload = function() {
  2687. self.loaded = true;
  2688. };
  2689. this.img.onerror = function() {
  2690. if (typeof console != "undefined") {
  2691. console.log('ERROR: image "' + href + '" not found');
  2692. self.loaded = true;
  2693. }
  2694. };
  2695. this.img.src = href;
  2696. } else {
  2697. this.img = svg.ajax(href);
  2698. this.loaded = true;
  2699. }
  2700. this.renderChildren = function(ctx) {
  2701. var x = this.attribute("x").toPixels("x");
  2702. var y = this.attribute("y").toPixels("y");
  2703. var width = this.attribute("width").toPixels("x");
  2704. var height = this.attribute("height").toPixels("y");
  2705. if (width == 0 || height == 0) return;
  2706. ctx.save();
  2707. if (isSvg) {
  2708. ctx.drawSvg(this.img, x, y, width, height);
  2709. } else {
  2710. ctx.translate(x, y);
  2711. svg.AspectRatio(ctx, this.attribute("preserveAspectRatio").value, width, this.img.width, height, this.img.height, 0, 0);
  2712. ctx.drawImage(this.img, 0, 0);
  2713. }
  2714. ctx.restore();
  2715. };
  2716. this.getBoundingBox = function() {
  2717. var x = this.attribute("x").toPixels("x");
  2718. var y = this.attribute("y").toPixels("y");
  2719. var width = this.attribute("width").toPixels("x");
  2720. var height = this.attribute("height").toPixels("y");
  2721. return new svg.BoundingBox(x, y, x + width, y + height);
  2722. };
  2723. };
  2724. svg.Element.image.prototype = new svg.Element.RenderedElementBase();
  2725. // group element
  2726. svg.Element.g = function(node) {
  2727. this.base = svg.Element.RenderedElementBase;
  2728. this.base(node);
  2729. this.getBoundingBox = function() {
  2730. var bb = new svg.BoundingBox();
  2731. for (var i = 0; i < this.children.length; i++) {
  2732. bb.addBoundingBox(this.children[i].getBoundingBox());
  2733. }
  2734. return bb;
  2735. };
  2736. };
  2737. svg.Element.g.prototype = new svg.Element.RenderedElementBase();
  2738. // symbol element
  2739. svg.Element.symbol = function(node) {
  2740. this.base = svg.Element.RenderedElementBase;
  2741. this.base(node);
  2742. this.baseSetContext = this.setContext;
  2743. this.setContext = function(ctx) {
  2744. this.baseSetContext(ctx);
  2745. // viewbox
  2746. if (this.attribute("viewBox").hasValue()) {
  2747. var viewBox = svg.ToNumberArray(this.attribute("viewBox").value);
  2748. var minX = viewBox[0];
  2749. var minY = viewBox[1];
  2750. width = viewBox[2];
  2751. height = viewBox[3];
  2752. svg.AspectRatio(ctx, this.attribute("preserveAspectRatio").value, this.attribute("width").toPixels("x"), width, this.attribute("height").toPixels("y"), height, minX, minY);
  2753. svg.ViewPort.SetCurrent(viewBox[2], viewBox[3]);
  2754. }
  2755. };
  2756. };
  2757. svg.Element.symbol.prototype = new svg.Element.RenderedElementBase();
  2758. // style element
  2759. svg.Element.style = function(node) {
  2760. this.base = svg.Element.ElementBase;
  2761. this.base(node);
  2762. // text, or spaces then CDATA
  2763. var css = "";
  2764. for (var i = 0; i < node.childNodes.length; i++) {
  2765. css += node.childNodes[i].nodeValue;
  2766. }
  2767. css = css.replace(/(\/\*([^*]|[\r\n]|(\*+([^*\/]|[\r\n])))*\*+\/)|(^[\s]*\/\/.*)/gm, "");
  2768. // remove comments
  2769. css = svg.compressSpaces(css);
  2770. // replace whitespace
  2771. var cssDefs = css.split("}");
  2772. for (var i = 0; i < cssDefs.length; i++) {
  2773. if (svg.trim(cssDefs[i]) != "") {
  2774. var cssDef = cssDefs[i].split("{");
  2775. var cssClasses = cssDef[0].split(",");
  2776. var cssProps = cssDef[1].split(";");
  2777. for (var j = 0; j < cssClasses.length; j++) {
  2778. var cssClass = svg.trim(cssClasses[j]);
  2779. if (cssClass != "") {
  2780. var props = {};
  2781. for (var k = 0; k < cssProps.length; k++) {
  2782. var prop = cssProps[k].indexOf(":");
  2783. var name = cssProps[k].substr(0, prop);
  2784. var value = cssProps[k].substr(prop + 1, cssProps[k].length - prop);
  2785. if (name != null && value != null) {
  2786. props[svg.trim(name)] = new svg.Property(svg.trim(name), svg.trim(value));
  2787. }
  2788. }
  2789. svg.Styles[cssClass] = props;
  2790. if (cssClass == "@font-face") {
  2791. var fontFamily = props["font-family"].value.replace(/"/g, "");
  2792. var srcs = props["src"].value.split(",");
  2793. for (var s = 0; s < srcs.length; s++) {
  2794. if (srcs[s].indexOf('format("svg")') > 0) {
  2795. var urlStart = srcs[s].indexOf("url");
  2796. var urlEnd = srcs[s].indexOf(")", urlStart);
  2797. var url = srcs[s].substr(urlStart + 5, urlEnd - urlStart - 6);
  2798. var doc = svg.parseXml(svg.ajax(url));
  2799. var fonts = doc.getElementsByTagName("font");
  2800. for (var f = 0; f < fonts.length; f++) {
  2801. var font = svg.CreateElement(fonts[f]);
  2802. svg.Definitions[fontFamily] = font;
  2803. }
  2804. }
  2805. }
  2806. }
  2807. }
  2808. }
  2809. }
  2810. }
  2811. };
  2812. svg.Element.style.prototype = new svg.Element.ElementBase();
  2813. // use element
  2814. svg.Element.use = function(node) {
  2815. this.base = svg.Element.RenderedElementBase;
  2816. this.base(node);
  2817. this.baseSetContext = this.setContext;
  2818. this.setContext = function(ctx) {
  2819. this.baseSetContext(ctx);
  2820. if (this.attribute("x").hasValue()) ctx.translate(this.attribute("x").toPixels("x"), 0);
  2821. if (this.attribute("y").hasValue()) ctx.translate(0, this.attribute("y").toPixels("y"));
  2822. };
  2823. this.getDefinition = function() {
  2824. var element = this.getHrefAttribute().getDefinition();
  2825. if (this.attribute("width").hasValue()) element.attribute("width", true).value = this.attribute("width").value;
  2826. if (this.attribute("height").hasValue()) element.attribute("height", true).value = this.attribute("height").value;
  2827. return element;
  2828. };
  2829. this.path = function(ctx) {
  2830. var element = this.getDefinition();
  2831. if (element != null) element.path(ctx);
  2832. };
  2833. this.getBoundingBox = function() {
  2834. var element = this.getDefinition();
  2835. if (element != null) return element.getBoundingBox();
  2836. };
  2837. this.renderChildren = function(ctx) {
  2838. var element = this.getDefinition();
  2839. if (element != null) {
  2840. // temporarily detach from parent and render
  2841. var oldParent = element.parent;
  2842. element.parent = null;
  2843. element.render(ctx);
  2844. element.parent = oldParent;
  2845. }
  2846. };
  2847. };
  2848. svg.Element.use.prototype = new svg.Element.RenderedElementBase();
  2849. // mask element
  2850. svg.Element.mask = function(node) {
  2851. this.base = svg.Element.ElementBase;
  2852. this.base(node);
  2853. this.apply = function(ctx, element) {
  2854. // render as temp svg
  2855. var x = this.attribute("x").toPixels("x");
  2856. var y = this.attribute("y").toPixels("y");
  2857. var width = this.attribute("width").toPixels("x");
  2858. var height = this.attribute("height").toPixels("y");
  2859. if (width == 0 && height == 0) {
  2860. var bb = new svg.BoundingBox();
  2861. for (var i = 0; i < this.children.length; i++) {
  2862. bb.addBoundingBox(this.children[i].getBoundingBox());
  2863. }
  2864. var x = Math.floor(bb.x1);
  2865. var y = Math.floor(bb.y1);
  2866. var width = Math.floor(bb.width());
  2867. var height = Math.floor(bb.height());
  2868. }
  2869. // temporarily remove mask to avoid recursion
  2870. var mask = element.attribute("mask").value;
  2871. element.attribute("mask").value = "";
  2872. var cMask = document.createElement("canvas");
  2873. cMask.width = x + width;
  2874. cMask.height = y + height;
  2875. var maskCtx = cMask.getContext("2d");
  2876. this.renderChildren(maskCtx);
  2877. var c = document.createElement("canvas");
  2878. c.width = x + width;
  2879. c.height = y + height;
  2880. var tempCtx = c.getContext("2d");
  2881. element.render(tempCtx);
  2882. tempCtx.globalCompositeOperation = "destination-in";
  2883. tempCtx.fillStyle = maskCtx.createPattern(cMask, "no-repeat");
  2884. tempCtx.fillRect(0, 0, x + width, y + height);
  2885. ctx.fillStyle = tempCtx.createPattern(c, "no-repeat");
  2886. ctx.fillRect(0, 0, x + width, y + height);
  2887. // reassign mask
  2888. element.attribute("mask").value = mask;
  2889. };
  2890. this.render = function(ctx) {};
  2891. };
  2892. svg.Element.mask.prototype = new svg.Element.ElementBase();
  2893. // clip element
  2894. svg.Element.clipPath = function(node) {
  2895. this.base = svg.Element.ElementBase;
  2896. this.base(node);
  2897. this.apply = function(ctx) {
  2898. for (var i = 0; i < this.children.length; i++) {
  2899. var child = this.children[i];
  2900. if (typeof child.path != "undefined") {
  2901. var transform = null;
  2902. if (child.attribute("transform").hasValue()) {
  2903. transform = new svg.Transform(child.attribute("transform").value);
  2904. transform.apply(ctx);
  2905. }
  2906. child.path(ctx);
  2907. ctx.clip();
  2908. if (transform) {
  2909. transform.unapply(ctx);
  2910. }
  2911. }
  2912. }
  2913. };
  2914. this.render = function(ctx) {};
  2915. };
  2916. svg.Element.clipPath.prototype = new svg.Element.ElementBase();
  2917. // filters
  2918. svg.Element.filter = function(node) {
  2919. this.base = svg.Element.ElementBase;
  2920. this.base(node);
  2921. this.apply = function(ctx, element) {
  2922. // render as temp svg
  2923. var bb = element.getBoundingBox();
  2924. var x = Math.floor(bb.x1);
  2925. var y = Math.floor(bb.y1);
  2926. var width = Math.floor(bb.width());
  2927. var height = Math.floor(bb.height());
  2928. // temporarily remove filter to avoid recursion
  2929. var filter = element.style("filter").value;
  2930. element.style("filter").value = "";
  2931. var px = 0, py = 0;
  2932. for (var i = 0; i < this.children.length; i++) {
  2933. var efd = this.children[i].extraFilterDistance || 0;
  2934. px = Math.max(px, efd);
  2935. py = Math.max(py, efd);
  2936. }
  2937. var c = document.createElement("canvas");
  2938. c.width = width + 2 * px;
  2939. c.height = height + 2 * py;
  2940. var tempCtx = c.getContext("2d");
  2941. tempCtx.translate(-x + px, -y + py);
  2942. element.render(tempCtx);
  2943. // apply filters
  2944. for (var i = 0; i < this.children.length; i++) {
  2945. this.children[i].apply(tempCtx, 0, 0, width + 2 * px, height + 2 * py);
  2946. }
  2947. // render on me
  2948. ctx.drawImage(c, 0, 0, width + 2 * px, height + 2 * py, x - px, y - py, width + 2 * px, height + 2 * py);
  2949. // reassign filter
  2950. element.style("filter", true).value = filter;
  2951. };
  2952. this.render = function(ctx) {};
  2953. };
  2954. svg.Element.filter.prototype = new svg.Element.ElementBase();
  2955. svg.Element.feMorphology = function(node) {
  2956. this.base = svg.Element.ElementBase;
  2957. this.base(node);
  2958. this.apply = function(ctx, x, y, width, height) {};
  2959. };
  2960. svg.Element.feMorphology.prototype = new svg.Element.ElementBase();
  2961. svg.Element.feColorMatrix = function(node) {
  2962. this.base = svg.Element.ElementBase;
  2963. this.base(node);
  2964. function imGet(img, x, y, width, height, rgba) {
  2965. return img[y * width * 4 + x * 4 + rgba];
  2966. }
  2967. function imSet(img, x, y, width, height, rgba, val) {
  2968. img[y * width * 4 + x * 4 + rgba] = val;
  2969. }
  2970. this.apply = function(ctx, x, y, width, height) {
  2971. // only supporting grayscale for now per Issue 195, need to extend to all matrix
  2972. // assuming x==0 && y==0 for now
  2973. var srcData = ctx.getImageData(0, 0, width, height);
  2974. for (var y = 0; y < height; y++) {
  2975. for (var x = 0; x < width; x++) {
  2976. var r = imGet(srcData.data, x, y, width, height, 0);
  2977. var g = imGet(srcData.data, x, y, width, height, 1);
  2978. var b = imGet(srcData.data, x, y, width, height, 2);
  2979. var gray = (r + g + b) / 3;
  2980. imSet(srcData.data, x, y, width, height, 0, gray);
  2981. imSet(srcData.data, x, y, width, height, 1, gray);
  2982. imSet(srcData.data, x, y, width, height, 2, gray);
  2983. }
  2984. }
  2985. ctx.clearRect(0, 0, width, height);
  2986. ctx.putImageData(srcData, 0, 0);
  2987. };
  2988. };
  2989. svg.Element.feColorMatrix.prototype = new svg.Element.ElementBase();
  2990. svg.Element.feGaussianBlur = function(node) {
  2991. this.base = svg.Element.ElementBase;
  2992. this.base(node);
  2993. this.blurRadius = Math.floor(this.attribute("stdDeviation").numValue());
  2994. this.extraFilterDistance = this.blurRadius;
  2995. this.apply = function(ctx, x, y, width, height) {
  2996. if (typeof stackBlurCanvasRGBA == "undefined") {
  2997. if (typeof console != "undefined") {
  2998. console.log("ERROR: StackBlur.js must be included for blur to work");
  2999. }
  3000. return;
  3001. }
  3002. // StackBlur requires canvas be on document
  3003. ctx.canvas.id = svg.UniqueId();
  3004. ctx.canvas.style.display = "none";
  3005. document.body.appendChild(ctx.canvas);
  3006. stackBlurCanvasRGBA(ctx.canvas.id, x, y, width, height, this.blurRadius);
  3007. document.body.removeChild(ctx.canvas);
  3008. };
  3009. };
  3010. svg.Element.feGaussianBlur.prototype = new svg.Element.ElementBase();
  3011. // title element, do nothing
  3012. svg.Element.title = function(node) {};
  3013. svg.Element.title.prototype = new svg.Element.ElementBase();
  3014. // desc element, do nothing
  3015. svg.Element.desc = function(node) {};
  3016. svg.Element.desc.prototype = new svg.Element.ElementBase();
  3017. svg.Element.MISSING = function(node) {
  3018. if (typeof console != "undefined") {
  3019. console.log("ERROR: Element '" + node.nodeName + "' not yet implemented.");
  3020. }
  3021. };
  3022. svg.Element.MISSING.prototype = new svg.Element.ElementBase();
  3023. // element factory
  3024. svg.CreateElement = function(node) {
  3025. var className = node.nodeName.replace(/^[^:]+:/, "");
  3026. // remove namespace
  3027. className = className.replace(/\-/g, "");
  3028. // remove dashes
  3029. var e = null;
  3030. if (typeof svg.Element[className] != "undefined") {
  3031. e = new svg.Element[className](node);
  3032. } else {
  3033. e = new svg.Element.MISSING(node);
  3034. }
  3035. e.type = node.nodeName;
  3036. return e;
  3037. };
  3038. // load from url
  3039. svg.load = function(ctx, url) {
  3040. svg.loadXml(ctx, svg.ajax(url));
  3041. };
  3042. // load from xml
  3043. svg.loadXml = function(ctx, xml) {
  3044. svg.loadXmlDoc(ctx, svg.parseXml(xml));
  3045. };
  3046. svg.loadXmlDoc = function(ctx, dom) {
  3047. svg.init(ctx);
  3048. var mapXY = function(p) {
  3049. var e = ctx.canvas;
  3050. while (e) {
  3051. p.x -= e.offsetLeft;
  3052. p.y -= e.offsetTop;
  3053. e = e.offsetParent;
  3054. }
  3055. if (window.scrollX) p.x += window.scrollX;
  3056. if (window.scrollY) p.y += window.scrollY;
  3057. return p;
  3058. };
  3059. // bind mouse
  3060. if (svg.opts["ignoreMouse"] != true) {
  3061. ctx.canvas.onclick = function(e) {
  3062. var p = mapXY(new svg.Point(e != null ? e.clientX : event.clientX, e != null ? e.clientY : event.clientY));
  3063. svg.Mouse.onclick(p.x, p.y);
  3064. };
  3065. ctx.canvas.onmousemove = function(e) {
  3066. var p = mapXY(new svg.Point(e != null ? e.clientX : event.clientX, e != null ? e.clientY : event.clientY));
  3067. svg.Mouse.onmousemove(p.x, p.y);
  3068. };
  3069. }
  3070. var e = svg.CreateElement(dom.documentElement);
  3071. e.root = true;
  3072. // render loop
  3073. var isFirstRender = true;
  3074. var draw = function() {
  3075. svg.ViewPort.Clear();
  3076. if (ctx.canvas.parentNode) svg.ViewPort.SetCurrent(ctx.canvas.parentNode.clientWidth, ctx.canvas.parentNode.clientHeight);
  3077. if (svg.opts["ignoreDimensions"] != true) {
  3078. // set canvas size
  3079. if (e.style("width").hasValue()) {
  3080. ctx.canvas.width = e.style("width").toPixels("x");
  3081. ctx.canvas.style.width = ctx.canvas.width + "px";
  3082. }
  3083. if (e.style("height").hasValue()) {
  3084. ctx.canvas.height = e.style("height").toPixels("y");
  3085. ctx.canvas.style.height = ctx.canvas.height + "px";
  3086. }
  3087. }
  3088. var cWidth = ctx.canvas.clientWidth || ctx.canvas.width;
  3089. var cHeight = ctx.canvas.clientHeight || ctx.canvas.height;
  3090. if (svg.opts["ignoreDimensions"] == true && e.style("width").hasValue() && e.style("height").hasValue()) {
  3091. cWidth = e.style("width").toPixels("x");
  3092. cHeight = e.style("height").toPixels("y");
  3093. }
  3094. svg.ViewPort.SetCurrent(cWidth, cHeight);
  3095. if (svg.opts["offsetX"] != null) e.attribute("x", true).value = svg.opts["offsetX"];
  3096. if (svg.opts["offsetY"] != null) e.attribute("y", true).value = svg.opts["offsetY"];
  3097. if (svg.opts["scaleWidth"] != null && svg.opts["scaleHeight"] != null) {
  3098. var xRatio = 1, yRatio = 1, viewBox = svg.ToNumberArray(e.attribute("viewBox").value);
  3099. 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"];
  3100. 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"];
  3101. e.attribute("width", true).value = svg.opts["scaleWidth"];
  3102. e.attribute("height", true).value = svg.opts["scaleHeight"];
  3103. e.attribute("viewBox", true).value = "0 0 " + cWidth * xRatio + " " + cHeight * yRatio;
  3104. e.attribute("preserveAspectRatio", true).value = "none";
  3105. }
  3106. // clear and render
  3107. if (svg.opts["ignoreClear"] != true) {
  3108. ctx.clearRect(0, 0, cWidth, cHeight);
  3109. }
  3110. e.render(ctx);
  3111. if (isFirstRender) {
  3112. isFirstRender = false;
  3113. if (typeof svg.opts["renderCallback"] == "function") svg.opts["renderCallback"](dom);
  3114. }
  3115. };
  3116. var waitingForImages = true;
  3117. if (svg.ImagesLoaded()) {
  3118. waitingForImages = false;
  3119. draw();
  3120. }
  3121. svg.intervalID = setInterval(function() {
  3122. var needUpdate = false;
  3123. if (waitingForImages && svg.ImagesLoaded()) {
  3124. waitingForImages = false;
  3125. needUpdate = true;
  3126. }
  3127. // need update from mouse events?
  3128. if (svg.opts["ignoreMouse"] != true) {
  3129. needUpdate = needUpdate | svg.Mouse.hasEvents();
  3130. }
  3131. // need update from animations?
  3132. if (svg.opts["ignoreAnimation"] != true) {
  3133. for (var i = 0; i < svg.Animations.length; i++) {
  3134. needUpdate = needUpdate | svg.Animations[i].update(1e3 / svg.FRAMERATE);
  3135. }
  3136. }
  3137. // need update from redraw?
  3138. if (typeof svg.opts["forceRedraw"] == "function") {
  3139. if (svg.opts["forceRedraw"]() == true) needUpdate = true;
  3140. }
  3141. // render if needed
  3142. if (needUpdate) {
  3143. draw();
  3144. svg.Mouse.runEvents();
  3145. }
  3146. }, 1e3 / svg.FRAMERATE);
  3147. };
  3148. svg.stop = function() {
  3149. if (svg.intervalID) {
  3150. clearInterval(svg.intervalID);
  3151. }
  3152. };
  3153. svg.Mouse = new function() {
  3154. this.events = [];
  3155. this.hasEvents = function() {
  3156. return this.events.length != 0;
  3157. };
  3158. this.onclick = function(x, y) {
  3159. this.events.push({
  3160. type: "onclick",
  3161. x: x,
  3162. y: y,
  3163. run: function(e) {
  3164. if (e.onclick) e.onclick();
  3165. }
  3166. });
  3167. };
  3168. this.onmousemove = function(x, y) {
  3169. this.events.push({
  3170. type: "onmousemove",
  3171. x: x,
  3172. y: y,
  3173. run: function(e) {
  3174. if (e.onmousemove) e.onmousemove();
  3175. }
  3176. });
  3177. };
  3178. this.eventElements = [];
  3179. this.checkPath = function(element, ctx) {
  3180. for (var i = 0; i < this.events.length; i++) {
  3181. var e = this.events[i];
  3182. if (ctx.isPointInPath && ctx.isPointInPath(e.x, e.y)) this.eventElements[i] = element;
  3183. }
  3184. };
  3185. this.checkBoundingBox = function(element, bb) {
  3186. for (var i = 0; i < this.events.length; i++) {
  3187. var e = this.events[i];
  3188. if (bb.isPointInBox(e.x, e.y)) this.eventElements[i] = element;
  3189. }
  3190. };
  3191. this.runEvents = function() {
  3192. svg.ctx.canvas.style.cursor = "";
  3193. for (var i = 0; i < this.events.length; i++) {
  3194. var e = this.events[i];
  3195. var element = this.eventElements[i];
  3196. while (element) {
  3197. e.run(element);
  3198. element = element.parent;
  3199. }
  3200. }
  3201. // done running, clear
  3202. this.events = [];
  3203. this.eventElements = [];
  3204. };
  3205. }();
  3206. return svg;
  3207. }
  3208. })();
  3209. if (typeof CanvasRenderingContext2D != "undefined") {
  3210. CanvasRenderingContext2D.prototype.drawSvg = function(s, dx, dy, dw, dh) {
  3211. canvg(this.canvas, s, {
  3212. ignoreMouse: true,
  3213. ignoreAnimation: true,
  3214. ignoreDimensions: true,
  3215. ignoreClear: true,
  3216. offsetX: dx,
  3217. offsetY: dy,
  3218. scaleWidth: dw,
  3219. scaleHeight: dh
  3220. });
  3221. };
  3222. }
  3223. return canvg;
  3224. }
  3225. };
  3226. /*!
  3227. * 输出转换器,提供输出支持
  3228. */
  3229. _p[1] = {
  3230. value: function(require) {
  3231. var kity = _p.r(34), canvg = _p.r(0);
  3232. return kity.createClass("Output", {
  3233. constructor: function(formula) {
  3234. this.formula = formula;
  3235. },
  3236. toJPG: function(cb) {
  3237. toImage(this.formula, "image/jpeg", cb);
  3238. },
  3239. toPNG: function(cb) {
  3240. toImage(this.formula, "image/png", cb);
  3241. }
  3242. });
  3243. function toImage(formula, type, cb) {
  3244. var rectSpace = formula.container.getRenderBox();
  3245. return getBase64DataURL(formula.node.ownerDocument, {
  3246. width: rectSpace.width,
  3247. height: rectSpace.height,
  3248. content: getSVGContent(formula.node)
  3249. }, type, cb);
  3250. }
  3251. function getBase64DataURL(doc, data, type, cb) {
  3252. var canvas = null, args = arguments, ctx = null;
  3253. if (true) {
  3254. drawToCanvas.apply(null, args);
  3255. } else {
  3256. canvas = getImageCanvas(doc, data.width, data.height, type);
  3257. ctx = canvas.getContext("2d");
  3258. var image = new Image();
  3259. image.onload = function() {
  3260. try {
  3261. ctx.drawImage(image, 0, 0);
  3262. cb(canvas.toDataURL(type));
  3263. } catch (e) {
  3264. drawToCanvas.apply(null, args);
  3265. }
  3266. };
  3267. image.src = getSVGDataURL(data.content);
  3268. }
  3269. }
  3270. function getSVGContent(svgNode) {
  3271. 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"), '">' ];
  3272. tmp.appendChild(svgNode.cloneNode(true));
  3273. return tmp.innerHTML.replace(/<svg[^>]+?>/i, start.join("")).replace(/&nbsp;/g, "");
  3274. }
  3275. function getSVGDataURL(data) {
  3276. return "data:image/svg+xml;base64," + window.btoa(unescape(encodeURIComponent(data)));
  3277. }
  3278. function getImageCanvas(doc, width, height, type) {
  3279. var canvas = doc.createElement("canvas"), ctx = canvas.getContext("2d");
  3280. canvas.width = width;
  3281. canvas.height = height;
  3282. if (type !== "image/png") {
  3283. ctx.fillStyle = "white";
  3284. ctx.fillRect(0, 0, canvas.width, canvas.height);
  3285. }
  3286. return canvas;
  3287. }
  3288. function drawToCanvas(doc, data, type, cb) {
  3289. var canvas = getImageCanvas(doc, data.width, data.height, type);
  3290. canvas.style.cssText = "position: absolute; top: 0; left: 100000px; z-index: -1;";
  3291. window.setTimeout(function() {
  3292. doc.body.appendChild(canvas);
  3293. canvg(canvas, data.content);
  3294. doc.body.removeChild(canvas);
  3295. cb(canvas.toDataURL(type));
  3296. }, 0);
  3297. }
  3298. }
  3299. };
  3300. /*!
  3301. * 所有字符的列表
  3302. */
  3303. _p[2] = {
  3304. value: function() {
  3305. 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", "&#x237;", "&#x131;", "&#x3b1;", "&#x3b2;", "&#x3b3;", "&#x3b4;", "&#x3b5;", "&#x3b6;", "&#x3b7;", "&#x3b8;", "&#x3b9;", "&#x3ba;", "&#x3bb;", "&#x3bc;", "&#x3bd;", "&#x3be;", "&#x3bf;", "&#x3c0;", "&#x3c1;", "&#x3c2;", "&#x3c3;", "&#x3c4;", "&#x3c5;", "&#x3c6;", "&#x3c7;", "&#x3c8;", "&#x3c9;", "&#x3d1;", "&#x3d5;", "&#x3d6;", "&#x3de;", "&#x3dc;", "&#x3f5;", "&#x3f1;", "&#x3f9;", "&#x211c;", "&#x2135;", "&#x2111;", "&#x2127;", "&#x2136;", "&#x2137;", "&#x2138;", "&#xf0;", "&#x210f;", "&#x2141;", "&#x210e;", "&#x2202;", "&#x2118;", "&#x214c;", "&#x2132;", "&#x2201;", "&#x2113;", "&#x24c8;", "(", ")", "&#x393;", "&#x394;", "&#x395;", "&#x396;", "&#x397;", "&#x398;", "&#x399;", "&#x39a;", "&#x39b;", "&#x39c;", "&#x39d;", "&#x39e;", "&#x39f;", "&#x3a0;", "&#x3a1;", "&#x3a3;", "&#x3a4;", "&#x3a5;", "&#x3a6;", "&#x3a7;", "&#x3a8;", "&#x3a9;", "&#x391;", "&#x392;", "#", "!", "$", "%", "&#x26;", "&#x2220;", "&#x2032;", "&#x2035;", "&#x2605;", "&#x25c6;", "&#x25a0;", "&#x25b2;", "&#x25bc;", "&#x22a4;", "&#x22a5;", "&#x2663;", "&#x2660;", "&#x2662;", "&#x2661;", "&#x2203;", "&#x2204;", "&#x266d;", "&#x266e;", "&#x266f;", "&#x2200;", "&#x221e;", "&#x2221;", "&#x2207;", "&#xac;", "&#x2222;", "&#x221a;", "&#x25b3;", "&#x25bd;", "&#x2205;", "&#xf8;", "&#x25c7;", "&#x25c0;", "&#x25b8;", "[", "]", "{", "}", "&#x3008;", "&#x3009;", "&#x3f0;", ",", ".", "/", ":", ";", "?", "\\", "&#x22ee;", "&#x22ef;", "&#x22f0;", "&#x2026;", "@", "&#x22;", "'", "|", "^", "`", "&#x201c;", "_", "*", "+", "-", "&#x2210;", "&#x22bc;", "&#x22bb;", "&#x25ef;", "&#x22a1;", "&#x229f;", "&#x229e;", "&#x22a0;", "&#x2022;", "&#x2229;", "&#x222a;", "&#x22d2;", "&#x22d3;", "&#x22d0;", "&#x22d1;", "&#xb7;", "&#x25aa;", "&#x25e6;", "&#x229b;", "&#x229a;", "&#x2296;", "&#x2299;", "&#x229d;", "&#x2295;", "&#x2297;", "&#x2298;", "&#xb1;", "&#x2213;", "&#x22cf;", "&#x22ce;", "&#x2020;", "&#x2021;", "&#x22c4;", "&#xf7;", "&#x22c7;", "&#x2214;", "&#x232d;", "&#x22d7;", "&#x22d6;", "&#x22c9;", "&#x22ca;", "&#x22cb;", "&#x22cc;", "&#x2293;", "&#x2294;", "&#x2291;", "&#x2292;", "&#x228f;", "&#x2290;", "&#x22c6;", "&#xd7;", "&#x22b3;", "&#x22b2;", "&#x22b5;", "&#x22b4;", "&#x228e;", "&#x2228;", "&#x2227;", "&#x2240;", "&#x3c;", "=", "&#x3e;", "&#x2248;", "&#x2247;", "&#x224d;", "&#x2252;", "&#x2253;", "&#x224a;", "&#x223d;", "&#x2241;", "&#x2242;", "&#x2243;", "&#x22cd;", "&#x224f;", "&#x224e;", "&#x2257;", "&#x2245;", "&#x22de;", "&#x22df;", "&#x2250;", "&#x2251;", "&#x2256;", "&#x2a96;", "&#x2a95;", "&#x2261;", "&#x2265;", "&#x2264;", "&#x2266;", "&#x2267;", "&#x2a7e;", "&#x2a7d;", "&#x226b;", "&#x226a;", "&#x2268;", "&#x2269;", "&#x22d8;", "&#x22d9;", "&#x2a87;", "&#x2a88;", "&#x2a89;", "&#x2a8a;", "&#x22e7;", "&#x22e6;", "&#x2a86;", "&#x2a85;", "&#x22db;", "&#x22da;", "&#x2a8b;", "&#x2a8c;", "&#x2277;", "&#x2276;", "&#x2273;", "&#x2272;", "&#x232e;", "&#x232f;", "&#x226f;", "&#x2271;", "&#x2270;", "&#x226e;", "&#x2331;", "&#x2330;", "&#x2332;", "&#x2333;", "&#x226c;", "&#x2280;", "&#x2281;", "&#x22e0;", "&#x22e1;", "&#x227a;", "&#x227b;", "&#x227c;", "&#x227d;", "&#x227e;", "&#x227f;", "&#x2282;", "&#x2283;", "&#x2288;", "&#x2289;", "&#x2286;", "&#x2287;", "&#x228a;", "&#x228b;", "&#x2ab7;", "&#x2ab8;", "&#x2aaf;", "&#x2ab0;", "&#x2ab9;", "&#x2aba;", "&#x2ab5;", "&#x2ab6;", "&#x22e8;", "&#x22e9;", "&#x223c;", "&#x225c;", "&#x21b6;", "&#x21b7;", "&#x21ba;", "&#x21bb;", "&#x21be;", "&#x21bf;", "&#x21c2;", "&#x21c3;", "&#x21c4;", "&#x21c6;", "&#x21c8;", "&#x21ca;", "&#x21cb;", "&#x21cc;", "&#x21cd;", "&#x21ce;", "&#x21cf;", "&#x21d0;", "&#x21d1;", "&#x21d2;", "&#x21d3;", "&#x21d4;", "&#x21d5;", "&#x21da;", "&#x21db;", "&#x21dd;", "&#x21ab;", "&#x21ac;", "&#x21ad;", "&#x21ae;", "&#x2190;", "&#x2191;", "&#x2192;", "&#x2193;", "&#x2194;", "&#x2195;", "&#x2196;", "&#x2197;", "&#x2198;", "&#x2199;", "&#x219e;", "&#x21a0;", "&#x21a2;", "&#x21a3;", "&#x21b0;", "&#x21b1;", "&#x22a2;", "&#x22a3;", "&#x22a8;", "&#x22a9;", "&#x22aa;", "&#x22ad;", "&#x22af;", "&#x22b8;", "&#x22ba;", "&#x22d4;", "&#x22ea;", "&#x22eb;", "&#x22ec;", "&#x22ed;", "&#x2308;", "&#x2309;", "&#x230a;", "&#x230b;", "&#x2acb;", "&#x2acc;", "&#x2ac5;", "&#x2ac6;", "&#x2208;", "&#x220b;", "&#x221d;", "&#x2224;", "&#x2226;", "&#x2234;", "&#x2235;", "&#x220d;", "&#x22c8;", "&#x2322;", "&#x2323;", "&#x2223;", "&#x2225;", "&#x23d0;", "&#x23d1;", "&#x23d2;", "&#x23d3;", "&#x2ac7;", "&#x2ac8;", "&#x22ae;", "&#x22ac;", "&#x2ac9;", "&#x23d4;", "&#x23d5;", "&#x23d6;", "&#x23d7;", "&#x21c7;", "&#x21c9;", "&#x21bc;", "&#x21bd;", "&#x21c0;", "&#x21c1;", "&#x219a;", "&#x219b;", "&#x27f5;", "&#x27f6;", "&#x27f7;", "&#x27f9;", "&#x27f8;", "&#x27fa;", "&#x2262;", "&#x2260;", "&#x2209;" ];
  3306. }
  3307. };
  3308. /*!
  3309. * 字符配置
  3310. */
  3311. _p[3] = {
  3312. value: function() {
  3313. return {
  3314. // 默认字体
  3315. defaultFont: "KF AMS MAIN"
  3316. };
  3317. }
  3318. };
  3319. /*!
  3320. * 工厂方法,创建兼容各浏览器的text实现
  3321. */
  3322. _p[4] = {
  3323. value: function(require) {
  3324. var kity = _p.r(34), divNode = document.createElement("div"), NAMESPACE = "http://www.w3.org/XML/1998/namespace";
  3325. function createText(content) {
  3326. var text = new kity.Text();
  3327. // Non-IE
  3328. if ("innerHTML" in text.node) {
  3329. text.node.setAttributeNS(NAMESPACE, "xml:space", "preserve");
  3330. } else {
  3331. if (content.indexOf(" ") != -1) {
  3332. content = convertContent(content);
  3333. }
  3334. }
  3335. text.setContent(content);
  3336. return text;
  3337. }
  3338. /**
  3339. * 构建节点来转换内容
  3340. */
  3341. function convertContent(content) {
  3342. divNode.innerHTML = '<svg><text gg="asfdas">' + content.replace(/\s/gi, "&nbsp;") + "</text></svg>";
  3343. return divNode.firstChild.firstChild.textContent;
  3344. }
  3345. return {
  3346. create: function(content) {
  3347. return createText(content);
  3348. }
  3349. };
  3350. }
  3351. };
  3352. /**
  3353. * 文本
  3354. */
  3355. _p[5] = {
  3356. value: function(require) {
  3357. var kity = _p.r(34), FONT_CONF = _p.r(47).font, FontManager = _p.r(25), TextFactory = _p.r(4);
  3358. return kity.createClass("Text", {
  3359. base: _p.r(46),
  3360. constructor: function(content, fontFamily) {
  3361. this.callBase();
  3362. this.fontFamily = fontFamily;
  3363. this.fontSize = 50;
  3364. this.content = content || "";
  3365. // 移除多余的节点
  3366. this.box.remove();
  3367. this.translationContent = this.translation(this.content);
  3368. this.contentShape = new kity.Group();
  3369. this.contentNode = this.createContent();
  3370. this.contentShape.addShape(this.contentNode);
  3371. this.addShape(this.contentShape);
  3372. },
  3373. createContent: function() {
  3374. var contentNode = TextFactory.create(this.translationContent);
  3375. contentNode.setAttr({
  3376. "font-family": this.fontFamily,
  3377. "font-size": 50,
  3378. x: 0,
  3379. y: FONT_CONF.offset
  3380. });
  3381. return contentNode;
  3382. },
  3383. setFamily: function(fontFamily) {
  3384. this.fontFamily = fontFamily;
  3385. this.contentNode.setAttr("font-family", fontFamily);
  3386. },
  3387. setFontSize: function(fontSize) {
  3388. this.fontSize = fontSize;
  3389. this.contentNode.setAttr("font-size", fontSize + "px");
  3390. this.contentNode.setAttr("y", fontSize / 50 * FONT_CONF.offset);
  3391. },
  3392. getBaseHeight: function() {
  3393. var chars = this.contentShape.getItems(), currentChar = null, index = 0, height = 0;
  3394. while (currentChar = chars[index]) {
  3395. height = Math.max(height, currentChar.getHeight());
  3396. index++;
  3397. }
  3398. return height;
  3399. },
  3400. translation: function(content) {
  3401. var fontFamily = this.fontFamily;
  3402. // 首先特殊处理掉两个相连的"`"符号
  3403. return content.replace(/``/g, "“").replace(/\\([a-zA-Z,]+)\\/g, function(match, input) {
  3404. if (input === ",") {
  3405. return " ";
  3406. }
  3407. var data = FontManager.getCharacterValue(input, fontFamily);
  3408. if (!data) {
  3409. return "";
  3410. }
  3411. return data;
  3412. });
  3413. }
  3414. });
  3415. }
  3416. };
  3417. /**
  3418. * 定义公式中各种对象的类型
  3419. */
  3420. _p[6] = {
  3421. value: function() {
  3422. return {
  3423. UNKNOWN: -1,
  3424. EXP: 0,
  3425. COMPOUND_EXP: 1,
  3426. OP: 2
  3427. };
  3428. }
  3429. };
  3430. /**
  3431. * 定义公式中上下标的类型
  3432. */
  3433. _p[7] = {
  3434. value: function() {
  3435. return {
  3436. SIDE: "side",
  3437. FOLLOW: "follow"
  3438. };
  3439. }
  3440. };
  3441. /**
  3442. * 下标表达式
  3443. */
  3444. _p[8] = {
  3445. value: function(require) {
  3446. var kity = _p.r(34);
  3447. return kity.createClass("SubscriptExpression", {
  3448. base: _p.r(17),
  3449. constructor: function(operand, subscript) {
  3450. this.callBase(operand, null, subscript);
  3451. this.setFlag("Subscript");
  3452. }
  3453. });
  3454. }
  3455. };
  3456. /**
  3457. * 上标表达式
  3458. */
  3459. _p[9] = {
  3460. value: function(require) {
  3461. var kity = _p.r(34);
  3462. return kity.createClass("SuperscriptExpression", {
  3463. base: _p.r(17),
  3464. constructor: function(operand, superscript) {
  3465. this.callBase(operand, superscript, null);
  3466. this.setFlag("Superscript");
  3467. }
  3468. });
  3469. }
  3470. };
  3471. /**
  3472. * 二元操作表达式
  3473. */
  3474. _p[10] = {
  3475. value: function(require) {
  3476. var kity = _p.r(34);
  3477. return kity.createClass("BinaryExpression", {
  3478. base: _p.r(19),
  3479. constructor: function(firstOperand, lastOperand) {
  3480. this.callBase();
  3481. this.setFirstOperand(firstOperand);
  3482. this.setLastOperand(lastOperand);
  3483. },
  3484. setFirstOperand: function(operand) {
  3485. return this.setOperand(operand, 0);
  3486. },
  3487. getFirstOperand: function() {
  3488. return this.getOperand(0);
  3489. },
  3490. setLastOperand: function(operand) {
  3491. return this.setOperand(operand, 1);
  3492. },
  3493. getLastOperand: function() {
  3494. return this.getOperand(1);
  3495. }
  3496. });
  3497. }
  3498. };
  3499. /**
  3500. * 自动增长括号表达式
  3501. */
  3502. _p[11] = {
  3503. value: function(require) {
  3504. var kity = _p.r(34), BracketsOperator = _p.r(35);
  3505. return kity.createClass("BracketsExpression", {
  3506. base: _p.r(19),
  3507. /**
  3508. * 构造函数调用方式:
  3509. * new Constructor( 左括号, 右括号, 表达式 )
  3510. * 或者
  3511. * new Constructor( 括号, 表达式 ), 该构造函数转换成上面的构造函数,是: new Constructor( 括号, 括号, 表达式 )
  3512. * @param left 左括号
  3513. * @param right 右括号
  3514. * @param exp 表达式
  3515. */
  3516. constructor: function(left, right, exp) {
  3517. this.callBase();
  3518. this.setFlag("Brackets");
  3519. // 参数整理
  3520. if (arguments.length === 2) {
  3521. exp = right;
  3522. right = left;
  3523. }
  3524. this.leftSymbol = left;
  3525. this.rightSymbol = right;
  3526. this.setOperator(new BracketsOperator());
  3527. this.setOperand(exp, 0);
  3528. },
  3529. getLeftSymbol: function() {
  3530. return this.leftSymbol;
  3531. },
  3532. getRightSymbol: function() {
  3533. return this.rightSymbol;
  3534. }
  3535. });
  3536. }
  3537. };
  3538. /**
  3539. * 组合表达式
  3540. * 可以组合多个表达式
  3541. */
  3542. _p[12] = {
  3543. value: function(require) {
  3544. var kity = _p.r(34), FONT_CONF = _p.r(47).font, CombinationOperator = _p.r(36);
  3545. return kity.createClass("CombinationExpression", {
  3546. base: _p.r(19),
  3547. constructor: function() {
  3548. this.callBase();
  3549. this.setFlag("Combination");
  3550. this.setOperator(new CombinationOperator());
  3551. kity.Utils.each(arguments, function(operand, index) {
  3552. this.setOperand(operand, index);
  3553. }, this);
  3554. },
  3555. getRenderBox: function(refer) {
  3556. var rectBox = this.callBase(refer);
  3557. if (this.getOperands().length === 0) {
  3558. rectBox.height = FONT_CONF.spaceHeight;
  3559. }
  3560. return rectBox;
  3561. },
  3562. getBaseline: function(refer) {
  3563. var maxBaseline = 0, operands = this.getOperands();
  3564. if (operands.length === 0) {
  3565. return this.callBase(refer);
  3566. }
  3567. kity.Utils.each(operands, function(operand) {
  3568. maxBaseline = Math.max(operand.getBaseline(refer), maxBaseline);
  3569. });
  3570. return maxBaseline;
  3571. },
  3572. getMeanline: function(refer) {
  3573. var minMeanline = 1e7, operands = this.getOperands();
  3574. if (operands.length === 0) {
  3575. return this.callBase(refer);
  3576. }
  3577. kity.Utils.each(operands, function(operand) {
  3578. minMeanline = Math.min(operand.getMeanline(refer), minMeanline);
  3579. });
  3580. return minMeanline;
  3581. }
  3582. });
  3583. }
  3584. };
  3585. /**
  3586. * 分数表达式
  3587. */
  3588. _p[13] = {
  3589. value: function(require) {
  3590. var kity = _p.r(34), FractionOperator = _p.r(38);
  3591. return kity.createClass("FractionExpression", {
  3592. base: _p.r(10),
  3593. constructor: function(upOperand, downOperand) {
  3594. this.callBase(upOperand, downOperand);
  3595. this.setFlag("Fraction");
  3596. this.setOperator(new FractionOperator());
  3597. },
  3598. /*------- 重写分数结构的baseline和mealine计算方式 */
  3599. getBaseline: function(refer) {
  3600. var downOperand = this.getOperand(1), rectBox = downOperand.getRenderBox(refer);
  3601. return rectBox.y + downOperand.getBaselineProportion() * rectBox.height;
  3602. },
  3603. getMeanline: function(refer) {
  3604. var upOperand = this.getOperand(0), rectBox = upOperand.getRenderBox(refer);
  3605. return upOperand.getMeanlineProportion() * rectBox.height;
  3606. }
  3607. });
  3608. }
  3609. };
  3610. /**
  3611. * 函数表达式
  3612. */
  3613. _p[14] = {
  3614. value: function(require) {
  3615. var kity = _p.r(34), FUNC_CONF = _p.r(47).func, FunctionOperator = _p.r(39);
  3616. return kity.createClass("FunctionExpression", {
  3617. base: _p.r(19),
  3618. /**
  3619. * function表达式构造函数
  3620. * @param funcName function名称
  3621. * @param expr 函数表达式
  3622. * @param sup 上标
  3623. * @param sub 下标
  3624. */
  3625. constructor: function(funcName, expr, sup, sub) {
  3626. this.callBase();
  3627. this.setFlag("Func");
  3628. this.funcName = funcName;
  3629. this.setOperator(new FunctionOperator(funcName));
  3630. this.setExpr(expr);
  3631. this.setSuperscript(sup);
  3632. this.setSubscript(sub);
  3633. },
  3634. // 当前函数应用的script位置是否是在侧面
  3635. isSideScript: function() {
  3636. return !FUNC_CONF["ud-script"][this.funcName];
  3637. },
  3638. setExpr: function(expr) {
  3639. return this.setOperand(expr, 0);
  3640. },
  3641. setSuperscript: function(sub) {
  3642. return this.setOperand(sub, 1);
  3643. },
  3644. setSubscript: function(sub) {
  3645. return this.setOperand(sub, 2);
  3646. }
  3647. });
  3648. }
  3649. };
  3650. /**
  3651. * 积分表达式
  3652. */
  3653. _p[15] = {
  3654. value: function(require) {
  3655. var kity = _p.r(34), IntegrationOperator = _p.r(40), IntegrationExpression = kity.createClass("IntegrationExpression", {
  3656. base: _p.r(19),
  3657. /**
  3658. * 构造积分表达式
  3659. * @param integrand 被积函数
  3660. * @param supOperand 上限
  3661. * @param subOperand 下限
  3662. */
  3663. constructor: function(integrand, superscript, subscript) {
  3664. this.callBase();
  3665. this.setFlag("Integration");
  3666. this.setOperator(new IntegrationOperator());
  3667. this.setIntegrand(integrand);
  3668. this.setSuperscript(superscript);
  3669. this.setSubscript(subscript);
  3670. },
  3671. setType: function(type) {
  3672. this.getOperator().setType(type);
  3673. return this;
  3674. },
  3675. resetType: function() {
  3676. this.getOperator().resetType();
  3677. return this;
  3678. },
  3679. setIntegrand: function(integrand) {
  3680. this.setOperand(integrand, 0);
  3681. },
  3682. setSuperscript: function(sup) {
  3683. this.setOperand(sup, 1);
  3684. },
  3685. setSubscript: function(sub) {
  3686. this.setOperand(sub, 2);
  3687. }
  3688. });
  3689. return IntegrationExpression;
  3690. }
  3691. };
  3692. /**
  3693. * 方根表达式
  3694. */
  3695. _p[16] = {
  3696. value: function(require) {
  3697. var kity = _p.r(34), RadicalOperator = _p.r(42);
  3698. return kity.createClass("RadicalExpression", {
  3699. base: _p.r(10),
  3700. /**
  3701. * 构造开方表达式
  3702. * @param radicand 被开方数
  3703. * @param exponent 指数
  3704. */
  3705. constructor: function(radicand, exponent) {
  3706. this.callBase(radicand, exponent);
  3707. this.setFlag("Radicand");
  3708. this.setOperator(new RadicalOperator());
  3709. },
  3710. setRadicand: function(operand) {
  3711. return this.setFirstOperand(operand);
  3712. },
  3713. getRadicand: function() {
  3714. return this.getFirstOperand();
  3715. },
  3716. setExponent: function(operand) {
  3717. return this.setLastOperand(operand);
  3718. },
  3719. getExponent: function() {
  3720. return this.getLastOperand();
  3721. }
  3722. });
  3723. }
  3724. };
  3725. /**
  3726. * 上标表达式
  3727. */
  3728. _p[17] = {
  3729. value: function(require) {
  3730. var kity = _p.r(34), ScriptOperator = _p.r(43);
  3731. return kity.createClass("ScriptExpression", {
  3732. base: _p.r(19),
  3733. constructor: function(operand, superscript, subscript) {
  3734. this.callBase();
  3735. this.setFlag("Script");
  3736. this.setOperator(new ScriptOperator());
  3737. this.setOpd(operand);
  3738. this.setSuperscript(superscript);
  3739. this.setSubscript(subscript);
  3740. },
  3741. setOpd: function(operand) {
  3742. this.setOperand(operand, 0);
  3743. },
  3744. setSuperscript: function(sup) {
  3745. this.setOperand(sup, 1);
  3746. },
  3747. setSubscript: function(sub) {
  3748. this.setOperand(sub, 2);
  3749. }
  3750. });
  3751. }
  3752. };
  3753. /**
  3754. * 求和表达式
  3755. */
  3756. _p[18] = {
  3757. value: function(require) {
  3758. var kity = _p.r(34), SummationOperator = _p.r(44);
  3759. return kity.createClass("SummationExpression", {
  3760. base: _p.r(19),
  3761. /**
  3762. * 构造求和表达式
  3763. * @param expr 求和表达式
  3764. * @param upOperand 上标
  3765. * @param downOperand 下标
  3766. */
  3767. constructor: function(expr, superscript, subscript) {
  3768. this.callBase();
  3769. this.setFlag("Summation");
  3770. this.setOperator(new SummationOperator());
  3771. this.setExpr(expr);
  3772. this.setSuperscript(superscript);
  3773. this.setSubscript(subscript);
  3774. },
  3775. setExpr: function(expr) {
  3776. this.setOperand(expr, 0);
  3777. },
  3778. setSuperscript: function(sup) {
  3779. this.setOperand(sup, 1);
  3780. },
  3781. setSubscript: function(sub) {
  3782. this.setOperand(sub, 2);
  3783. }
  3784. });
  3785. }
  3786. };
  3787. /**
  3788. * 复合表达式
  3789. * @abstract
  3790. */
  3791. _p[19] = {
  3792. value: function(require) {
  3793. var kity = _p.r(34), GTYPE = _p.r(6), Expression = _p.r(21);
  3794. return kity.createClass("CompoundExpression", {
  3795. base: _p.r(21),
  3796. constructor: function() {
  3797. this.callBase();
  3798. this.type = GTYPE.COMPOUND_EXP;
  3799. this.operands = [];
  3800. this.operator = null;
  3801. this.operatorBox = new kity.Group();
  3802. this.operatorBox.setAttr("data-type", "kf-editor-exp-op-box");
  3803. this.operandBox = new kity.Group();
  3804. this.operandBox.setAttr("data-type", "kf-editor-exp-operand-box");
  3805. this.setChildren(0, this.operatorBox);
  3806. this.setChildren(1, this.operandBox);
  3807. },
  3808. // 操作符存储在第1位置
  3809. setOperator: function(operator) {
  3810. if (operator === undefined) {
  3811. return this;
  3812. }
  3813. if (this.operator) {
  3814. this.operator.remove();
  3815. }
  3816. this.operatorBox.addShape(operator);
  3817. this.operator = operator;
  3818. this.operator.setParentExpression(this);
  3819. // 表达式关联到操作符
  3820. operator.expression = this;
  3821. return this;
  3822. },
  3823. getOperator: function() {
  3824. return this.operator;
  3825. },
  3826. // 操作数存储位置是从1开始
  3827. setOperand: function(operand, index, isWrap) {
  3828. // 不包装操作数
  3829. if (isWrap === false) {
  3830. this.operands[index] = operand;
  3831. return this;
  3832. }
  3833. operand = Expression.wrap(operand);
  3834. if (this.operands[index]) {
  3835. this.operands[index].remove();
  3836. }
  3837. this.operands[index] = operand;
  3838. this.operandBox.addShape(operand);
  3839. return this;
  3840. },
  3841. getOperand: function(index) {
  3842. return this.operands[index];
  3843. },
  3844. getOperands: function() {
  3845. return this.operands;
  3846. },
  3847. addedCall: function() {
  3848. this.operator.applyOperand.apply(this.operator, this.operands);
  3849. return this;
  3850. }
  3851. });
  3852. }
  3853. };
  3854. /**
  3855. * 空表达式
  3856. * 该表达式主要用途是用于站位
  3857. */
  3858. _p[20] = {
  3859. value: function(require) {
  3860. var kity = _p.r(34), FONT_CONF = _p.r(47).font, Expression = _p.r(21), EmptyExpression = kity.createClass("EmptyExpression", {
  3861. base: Expression,
  3862. constructor: function() {
  3863. this.callBase();
  3864. this.setFlag("Empty");
  3865. },
  3866. getRenderBox: function() {
  3867. return {
  3868. width: 0,
  3869. height: FONT_CONF.spaceHeight,
  3870. x: 0,
  3871. y: 0
  3872. };
  3873. }
  3874. });
  3875. EmptyExpression.isEmpty = function(target) {
  3876. return target instanceof EmptyExpression;
  3877. };
  3878. // 注册打包函数
  3879. Expression.registerWrap("empty", function(operand) {
  3880. if (operand === null || operand === undefined) {
  3881. return new EmptyExpression();
  3882. }
  3883. });
  3884. return EmptyExpression;
  3885. }
  3886. };
  3887. /**
  3888. * 基础表达式, 该类是表达式和操作数的高层抽象
  3889. * @abstract
  3890. */
  3891. _p[21] = {
  3892. value: function(require) {
  3893. var kity = _p.r(34), GTYPE = _p.r(6), FONT_CONF = _p.r(47).font, // 打包函数列表
  3894. WRAP_FN = [], // 注册的打包函数的名称与其在注册器列表中的索引之间的对应关系
  3895. WRAP_FN_INDEX = {}, Expression = kity.createClass("Expression", {
  3896. base: _p.r(46),
  3897. constructor: function() {
  3898. this.callBase();
  3899. this.type = GTYPE.EXP;
  3900. // 表达式的上下偏移
  3901. this._offset = {
  3902. top: 0,
  3903. bottom: 0
  3904. };
  3905. this.children = [];
  3906. this.box.fill("transparent").setAttr("data-type", "kf-editor-exp-box");
  3907. this.box.setAttr("data-type", "kf-editor-exp-bg-box");
  3908. this.expContent = new kity.Group();
  3909. this.expContent.setAttr("data-type", "kf-editor-exp-content-box");
  3910. this.addShape(this.expContent);
  3911. },
  3912. getChildren: function() {
  3913. return this.children;
  3914. },
  3915. getChild: function(index) {
  3916. return this.children[index] || null;
  3917. },
  3918. getTopOffset: function() {
  3919. return this._offset.top;
  3920. },
  3921. getBottomOffset: function() {
  3922. return this._offset.bottom;
  3923. },
  3924. getOffset: function() {
  3925. return this._offset;
  3926. },
  3927. setTopOffset: function(val) {
  3928. this._offset.top = val;
  3929. },
  3930. setBottomOffset: function(val) {
  3931. this._offset.bottom = val;
  3932. },
  3933. setOffset: function(top, bottom) {
  3934. this._offset.top = top;
  3935. this._offset.bottom = bottom;
  3936. },
  3937. setFlag: function(flag) {
  3938. this.setAttr("data-flag", flag || "Expression");
  3939. },
  3940. setChildren: function(index, exp) {
  3941. // 首先清理掉之前的表达式
  3942. if (this.children[index]) {
  3943. this.children[index].remove();
  3944. }
  3945. this.children[index] = exp;
  3946. this.expContent.addShape(exp);
  3947. },
  3948. getBaselineProportion: function() {
  3949. return FONT_CONF.baselinePosition;
  3950. },
  3951. getMeanlineProportion: function() {
  3952. return FONT_CONF.meanlinePosition;
  3953. },
  3954. getBaseline: function(refer) {
  3955. // 上偏移3px
  3956. return this.getRenderBox(refer).height * FONT_CONF.baselinePosition - 3;
  3957. },
  3958. getMeanline: function(refer) {
  3959. // 上偏移1px
  3960. return this.getRenderBox(refer).height * FONT_CONF.meanlinePosition - 1;
  3961. },
  3962. getAscenderline: function() {
  3963. return this.getFixRenderBox().height * FONT_CONF.ascenderPosition;
  3964. },
  3965. getDescenderline: function() {
  3966. return this.getFixRenderBox().height * FONT_CONF.descenderPosition;
  3967. },
  3968. translateElement: function(x, y) {
  3969. this.expContent.translate(x, y);
  3970. },
  3971. expand: function(width, height) {
  3972. var renderBox = this.getFixRenderBox();
  3973. this.setBoxSize(renderBox.width + width, renderBox.height + height);
  3974. },
  3975. getBaseWidth: function() {
  3976. return this.getWidth();
  3977. },
  3978. getBaseHeight: function() {
  3979. return this.getHeight();
  3980. },
  3981. updateBoxSize: function() {
  3982. var renderBox = this.expContent.getFixRenderBox();
  3983. this.setBoxSize(renderBox.width, renderBox.height);
  3984. },
  3985. getBox: function() {
  3986. return this.box;
  3987. }
  3988. });
  3989. // 表达式自动打包
  3990. kity.Utils.extend(Expression, {
  3991. registerWrap: function(name, fn) {
  3992. WRAP_FN_INDEX[name] = WRAP_FN.length;
  3993. WRAP_FN.push(fn);
  3994. },
  3995. revokeWrap: function(name) {
  3996. var fn = null;
  3997. if (name in WRAP_FN_INDEX) {
  3998. fn = WRAP_FN[WRAP_FN_INDEX[name]];
  3999. WRAP_FN[WRAP_FN_INDEX[name]] = null;
  4000. delete WRAP_FN_INDEX[name];
  4001. }
  4002. return fn;
  4003. },
  4004. // 打包函数
  4005. wrap: function(operand) {
  4006. var result;
  4007. kity.Utils.each(WRAP_FN, function(fn) {
  4008. if (!fn) {
  4009. return;
  4010. }
  4011. result = fn(operand);
  4012. if (result) {
  4013. return false;
  4014. }
  4015. });
  4016. return result;
  4017. }
  4018. });
  4019. return Expression;
  4020. }
  4021. };
  4022. /**
  4023. * Text表达式
  4024. */
  4025. _p[22] = {
  4026. value: function(require) {
  4027. var Text = _p.r(5), kity = _p.r(34), FONT_CONF = _p.r(3), Expression = _p.r(21), TextExpression = kity.createClass("TextExpression", {
  4028. base: _p.r(21),
  4029. constructor: function(content, fontFamily) {
  4030. this.callBase();
  4031. this.fontFamily = fontFamily || FONT_CONF.defaultFont;
  4032. this.setFlag("Text");
  4033. this.content = content + "";
  4034. this.textContent = new Text(this.content, this.fontFamily);
  4035. this.setChildren(0, this.textContent);
  4036. this.setChildren(1, new kity.Rect(0, 0, 0, 0).fill("transparent"));
  4037. },
  4038. setFamily: function(fontFamily) {
  4039. this.textContent.setFamily(fontFamily);
  4040. },
  4041. setFontSize: function(fontSize) {
  4042. this.textContent.setFontSize(fontSize);
  4043. },
  4044. addedCall: function() {
  4045. var box = this.textContent.getFixRenderBox();
  4046. this.getChild(1).setSize(box.width, box.height);
  4047. this.updateBoxSize();
  4048. return this;
  4049. }
  4050. });
  4051. // 注册文本表达式的打包函数
  4052. Expression.registerWrap("text", function(operand) {
  4053. var operandType = typeof operand;
  4054. if (operandType === "number" || operandType === "string") {
  4055. operand = new TextExpression(operand);
  4056. }
  4057. return operand;
  4058. });
  4059. return TextExpression;
  4060. }
  4061. };
  4062. /*!
  4063. * 字体信息检测模板,用于检测浏览器的字体信息
  4064. */
  4065. _p[23] = {
  4066. value: function() {
  4067. 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>" ];
  4068. }
  4069. };
  4070. /*!
  4071. * 字体安装器
  4072. */
  4073. _p[24] = {
  4074. value: function(require) {
  4075. 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 = [];
  4076. return kity.createClass("FontInstaller", {
  4077. constructor: function(doc, resource) {
  4078. this.callBase();
  4079. this.resource = resource || "../src/resource/";
  4080. this.doc = doc;
  4081. },
  4082. // 挂载字体
  4083. mount: function(callback) {
  4084. var fontList = FontManager.getFontList(), count = 0, _self = this;
  4085. kity.Utils.each(fontList, function(fontInfo) {
  4086. count++;
  4087. fontInfo.meta.src = _self.resource + fontInfo.meta.src;
  4088. _self.createFontStyle(fontInfo);
  4089. preload(_self.doc, fontInfo, function() {
  4090. count--;
  4091. if (count === 0) {
  4092. complete(_self.doc, callback);
  4093. }
  4094. });
  4095. });
  4096. },
  4097. createFontStyle: function(fontInfo) {
  4098. var stylesheet = this.doc.createElement("style"), tpl = '@font-face{\nfont-family: "${fontFamily}";\nsrc: url("${src}");\n}';
  4099. stylesheet.setAttribute("type", "text/css");
  4100. stylesheet.innerHTML = tpl.replace("${fontFamily}", fontInfo.meta.fontFamily).replace("${src}", fontInfo.meta.src);
  4101. this.doc.head.appendChild(stylesheet);
  4102. }
  4103. });
  4104. function preload(doc, fontInfo, callback) {
  4105. $.get(fontInfo.meta.src, function(data, state) {
  4106. if (state === "success") {
  4107. applyFonts(doc, fontInfo);
  4108. }
  4109. callback();
  4110. });
  4111. }
  4112. function complete(doc, callback) {
  4113. window.setTimeout(function() {
  4114. initFontSystemInfo(doc);
  4115. removeTmpNode();
  4116. callback();
  4117. }, 100);
  4118. }
  4119. function applyFonts(doc, fontInfo) {
  4120. var node = document.createElement("div"), fontFamily = fontInfo.meta.fontFamily;
  4121. node.style.cssText = "position: absolute; top: -10000px; left: -100000px;";
  4122. node.style.fontFamily = fontFamily;
  4123. node.innerHTML = CHAR_LIST.join("");
  4124. doc.body.appendChild(node);
  4125. NODE_LIST.push(node);
  4126. }
  4127. /**
  4128. * 计算字体系统信息
  4129. */
  4130. function initFontSystemInfo(doc) {
  4131. var tmpNode = doc.createElement("div");
  4132. tmpNode.style.cssText = "position: absolute; top: 0; left: -100000px;";
  4133. tmpNode.innerHTML = _p.r(23).join("");
  4134. doc.body.appendChild(tmpNode);
  4135. var rectBox = tmpNode.getElementsByTagName("text")[0].getBBox();
  4136. // text实际占用空间
  4137. FONT_CONF.spaceHeight = rectBox.height;
  4138. // text顶部空间
  4139. FONT_CONF.topSpace = -rectBox.y - FONT_CONF.baseline;
  4140. FONT_CONF.bottomSpace = FONT_CONF.spaceHeight - FONT_CONF.topSpace - FONT_CONF.baseHeight;
  4141. // text偏移值
  4142. FONT_CONF.offset = FONT_CONF.baseline + FONT_CONF.topSpace;
  4143. // baseline比例
  4144. FONT_CONF.baselinePosition = (FONT_CONF.topSpace + FONT_CONF.baseline) / FONT_CONF.spaceHeight;
  4145. // meanline比例
  4146. FONT_CONF.meanlinePosition = (FONT_CONF.topSpace + FONT_CONF.meanline) / FONT_CONF.spaceHeight;
  4147. // 上下延伸性比例
  4148. FONT_CONF.ascenderPosition = FONT_CONF.topSpace / FONT_CONF.spaceHeight;
  4149. FONT_CONF.descenderPosition = (FONT_CONF.topSpace + FONT_CONF.baseHeight) / FONT_CONF.spaceHeight;
  4150. doc.body.removeChild(tmpNode);
  4151. }
  4152. function removeTmpNode() {
  4153. kity.Utils.each(NODE_LIST, function(node) {
  4154. node.parentNode.removeChild(node);
  4155. });
  4156. NODE_LIST = [];
  4157. }
  4158. }
  4159. };
  4160. /*!
  4161. * 字体管理器
  4162. */
  4163. _p[25] = {
  4164. value: function(require) {
  4165. var FONT_LIST = {}, kity = _p.r(34), CONF = _p.r(47).font.list;
  4166. // init
  4167. (function() {
  4168. kity.Utils.each(CONF, function(fontData) {
  4169. FONT_LIST[fontData.meta.fontFamily] = fontData;
  4170. });
  4171. })();
  4172. return {
  4173. getFontList: function() {
  4174. return FONT_LIST;
  4175. },
  4176. getCharacterValue: function(key, fontFamily) {
  4177. if (!FONT_LIST[fontFamily]) {
  4178. return null;
  4179. }
  4180. return FONT_LIST[fontFamily].map[key] || null;
  4181. }
  4182. };
  4183. }
  4184. };
  4185. /*!
  4186. * 双线字体
  4187. */
  4188. _p[26] = {
  4189. value: function() {
  4190. return {
  4191. meta: {
  4192. fontFamily: "KF AMS BB",
  4193. src: "KF_AMS_BB.woff"
  4194. }
  4195. };
  4196. }
  4197. };
  4198. /*!
  4199. * 手写体
  4200. */
  4201. _p[27] = {
  4202. value: function() {
  4203. return {
  4204. meta: {
  4205. fontFamily: "KF AMS CAL",
  4206. src: "KF_AMS_CAL.woff"
  4207. }
  4208. };
  4209. }
  4210. };
  4211. /*!
  4212. * 花体
  4213. */
  4214. _p[28] = {
  4215. value: function() {
  4216. return {
  4217. meta: {
  4218. fontFamily: "KF AMS FRAK",
  4219. src: "KF_AMS_FRAK.woff"
  4220. }
  4221. };
  4222. }
  4223. };
  4224. /*!
  4225. * 字体主文件
  4226. */
  4227. _p[29] = {
  4228. value: function() {
  4229. return {
  4230. meta: {
  4231. fontFamily: "KF AMS MAIN",
  4232. src: "KF_AMS_MAIN.woff"
  4233. },
  4234. map: {
  4235. // char
  4236. Alpha: "Α",
  4237. Beta: "Β",
  4238. Gamma: "Γ",
  4239. Delta: "Δ",
  4240. Epsilon: "Ε",
  4241. Zeta: "Ζ",
  4242. Eta: "Η",
  4243. Theta: "Θ",
  4244. Iota: "Ι",
  4245. Kappa: "Κ",
  4246. Lambda: "Λ",
  4247. Mu: "Μ",
  4248. Nu: "Ν",
  4249. Xi: "Ξ",
  4250. Omicron: "Ο",
  4251. Pi: "Π",
  4252. Rho: "Ρ",
  4253. Sigma: "Σ",
  4254. Tau: "Τ",
  4255. Upsilon: "Υ",
  4256. Phi: "Φ",
  4257. Chi: "Χ",
  4258. Psi: "Ψ",
  4259. Omega: "Ω",
  4260. alpha: "α",
  4261. beta: "β",
  4262. gamma: "γ",
  4263. delta: "δ",
  4264. epsilon: "ε",
  4265. zeta: "ζ",
  4266. eta: "η",
  4267. theta: "θ",
  4268. iota: "ι",
  4269. kappa: "κ",
  4270. lambda: "λ",
  4271. mu: "μ",
  4272. nu: "ν",
  4273. xi: "ξ",
  4274. omicron: "ο",
  4275. pi: "π",
  4276. rho: "ρ",
  4277. sigma: "σ",
  4278. tau: "τ",
  4279. upsilon: "υ",
  4280. phi: "φ",
  4281. varkappa: "ϰ",
  4282. chi: "χ",
  4283. psi: "ψ",
  4284. omega: "ω",
  4285. digamma: "Ϝ",
  4286. varepsilon: "ϵ",
  4287. varrho: "ϱ",
  4288. varphi: "ϕ",
  4289. vartheta: "ϑ",
  4290. varpi: "ϖ",
  4291. varsigma: "Ϲ",
  4292. aleph: "ℵ",
  4293. beth: "ℶ",
  4294. daleth: "ℸ",
  4295. gimel: "ℷ",
  4296. eth: "ð",
  4297. hbar: "ℎ",
  4298. hslash: "ℏ",
  4299. mho: "℧",
  4300. partial: "∂",
  4301. wp: "℘",
  4302. Game: "⅁",
  4303. Bbbk: "⅌",
  4304. Finv: "Ⅎ",
  4305. Im: "ℑ",
  4306. Re: "ℜ",
  4307. complement: "∁",
  4308. ell: "ℓ",
  4309. circledS: "Ⓢ",
  4310. imath: "ı",
  4311. jmath: "ȷ",
  4312. // symbol
  4313. doublecap: "⋒",
  4314. Cap: "⋒",
  4315. doublecup: "⋓",
  4316. Cup: "⋓",
  4317. ast: "*",
  4318. divideontimes: "⋇",
  4319. rightthreetimes: "⋌",
  4320. leftthreetimes: "⋋",
  4321. cdot: "·",
  4322. odot: "⊙",
  4323. dotplus: "∔",
  4324. rtimes: "⋊",
  4325. ltimes: "⋉",
  4326. centerdot: "▪",
  4327. doublebarwedge: "⌭",
  4328. setminus: "⒁",
  4329. amalg: "∐",
  4330. circ: "◦",
  4331. bigcirc: "◯",
  4332. gtrdot: "⋗",
  4333. lessdot: "⋖",
  4334. smallsetminus: "⒅",
  4335. circledast: "⊛",
  4336. circledcirc: "⊚",
  4337. sqcap: "⊓",
  4338. sqcup: "⊔",
  4339. barwedge: "⊼",
  4340. circleddash: "⊝",
  4341. star: "⋆",
  4342. bigtriangledown: "▽",
  4343. bigtriangleup: "△",
  4344. cup: "∪",
  4345. cap: "∩",
  4346. times: "×",
  4347. mp: "∓",
  4348. pm: "±",
  4349. triangleleft: "⊲",
  4350. triangleright: "⊳",
  4351. boxdot: "⊡",
  4352. curlyvee: "⋏",
  4353. curlywedge: "⋎",
  4354. boxminus: "⊟",
  4355. boxtimes: "⊠",
  4356. ominus: "⊖",
  4357. oplus: "⊕",
  4358. oslash: "⊘",
  4359. otimes: "⊗",
  4360. uplus: "⊎",
  4361. boxplus: "⊞",
  4362. dagger: "†",
  4363. ddagger: "‡",
  4364. vee: "∨",
  4365. lor: "∨",
  4366. veebar: "⊻",
  4367. bullet: "•",
  4368. diamond: "⋄",
  4369. wedge: "∧",
  4370. land: "∧",
  4371. div: "÷",
  4372. wr: "≀",
  4373. geqq: "≧",
  4374. lll: "⋘",
  4375. llless: "⋘",
  4376. ggg: "⋙",
  4377. gggtr: "⋙",
  4378. preccurlyeq: "≼",
  4379. geqslant: "⩾",
  4380. lnapprox: "⪉",
  4381. preceq: "⪯",
  4382. gg: "≫",
  4383. lneq: "⪇",
  4384. precnapprox: "⪹",
  4385. approx: "≈",
  4386. lneqq: "≨",
  4387. precneqq: "⪵",
  4388. approxeq: "≊",
  4389. gnapprox: "⪊",
  4390. lnsim: "⋦",
  4391. precnsim: "⋨",
  4392. asymp: "≍",
  4393. gneq: "⪈",
  4394. lvertneqq: "⌮",
  4395. precsim: "≾",
  4396. backsim: "∽",
  4397. gneqq: "≩",
  4398. ncong: "≇",
  4399. risingdotseq: "≓",
  4400. backsimeq: "⋍",
  4401. gnsim: "⋧",
  4402. sim: "∼",
  4403. simeq: "≃",
  4404. bumpeq: "≏",
  4405. gtrapprox: "⪆",
  4406. ngeq: "≱",
  4407. Bumpeq: "≎",
  4408. gtreqless: "⋛",
  4409. ngeqq: "⌱",
  4410. succ: "≻",
  4411. circeq: "≗",
  4412. gtreqqless: "⪌",
  4413. ngeqslant: "⌳",
  4414. succapprox: "⪸",
  4415. cong: "≅",
  4416. gtrless: "≷",
  4417. ngtr: "≯",
  4418. succcurlyeq: "≽",
  4419. curlyeqprec: "⋞",
  4420. gtrsim: "≳",
  4421. nleq: "≰",
  4422. succeq: "⪰",
  4423. curlyeqsucc: "⋟",
  4424. gvertneqq: "⌯",
  4425. neq: "≠",
  4426. ne: "≠",
  4427. nequiv: "≢",
  4428. nleqq: "⌰",
  4429. succnapprox: "⪺",
  4430. doteq: "≐",
  4431. leq: "≤",
  4432. le: "≤",
  4433. nleqslant: "⌲",
  4434. succneqq: "⪶",
  4435. doteqdot: "≑",
  4436. Doteq: "≑",
  4437. leqq: "≦",
  4438. nless: "≮",
  4439. succnsim: "⋩",
  4440. leqslant: "⩽",
  4441. nprec: "⊀",
  4442. succsim: "≿",
  4443. eqsim: "≂",
  4444. lessapprox: "⪅",
  4445. npreceq: "⋠",
  4446. eqslantgtr: "⪖",
  4447. lesseqgtr: "⋚",
  4448. nsim: "≁",
  4449. eqslantless: "⪕",
  4450. lesseqqgtr: "⪋",
  4451. nsucc: "⊁",
  4452. triangleq: "≜",
  4453. eqcirc: "≖",
  4454. equiv: "≡",
  4455. lessgtr: "≶",
  4456. nsucceq: "⋡",
  4457. fallingdotseq: "≒",
  4458. lesssim: "≲",
  4459. prec: "≺",
  4460. geq: "≥",
  4461. ge: "≥",
  4462. ll: "≪",
  4463. precapprox: "⪷",
  4464. // arrows
  4465. uparrow: "↑",
  4466. downarrow: "↓",
  4467. updownarrow: "↕",
  4468. Uparrow: "⇑",
  4469. Downarrow: "⇓",
  4470. Updownarrow: "⇕",
  4471. circlearrowleft: "↺",
  4472. circlearrowright: "↻",
  4473. curvearrowleft: "↶",
  4474. curvearrowright: "↷",
  4475. downdownarrows: "⇊",
  4476. downharpoonleft: "⇃",
  4477. downharpoonright: "⇂",
  4478. leftarrow: "←",
  4479. gets: "←",
  4480. Leftarrow: "⇐",
  4481. leftarrowtail: "↢",
  4482. leftharpoondown: "↽",
  4483. leftharpoonup: "↼",
  4484. leftleftarrows: "⇇",
  4485. leftrightarrow: "↔",
  4486. Leftrightarrow: "⇔",
  4487. leftrightarrows: "⇄",
  4488. leftrightharpoons: "⇋",
  4489. leftrightsquigarrow: "↭",
  4490. Lleftarrow: "⇚",
  4491. looparrowleft: "↫",
  4492. looparrowright: "↬",
  4493. multimap: "⊸",
  4494. nLeftarrow: "⇍",
  4495. nRightarrow: "⇏",
  4496. nLeftrightarrow: "⇎",
  4497. nearrow: "↗",
  4498. nleftarrow: "↚",
  4499. nleftrightarrow: "↮",
  4500. nrightarrow: "↛",
  4501. nwarrow: "↖",
  4502. rightarrow: "→",
  4503. to: "→",
  4504. Rightarrow: "⇒",
  4505. rightarrowtail: "↣",
  4506. rightharpoondown: "⇁",
  4507. rightharpoonup: "⇀",
  4508. rightleftarrows: "⇆",
  4509. rightleftharpoons: "⇌",
  4510. rightrightarrows: "⇉",
  4511. rightsquigarrow: "⇝",
  4512. Rrightarrow: "⇛",
  4513. searrow: "↘",
  4514. swarrow: "↙",
  4515. twoheadleftarrow: "↞",
  4516. twoheadrightarrow: "↠",
  4517. upharpoonleft: "↿",
  4518. upharpoonright: "↾",
  4519. restriction: "↾",
  4520. upuparrows: "⇈",
  4521. Lsh: "↰",
  4522. Rsh: "↱",
  4523. longleftarrow: "⟵",
  4524. longrightarrow: "⟶",
  4525. Longleftarrow: "⟸",
  4526. Longrightarrow: "⟹",
  4527. implies: "⟹",
  4528. longleftrightarrow: "⟷",
  4529. Longleftrightarrow: "⟺",
  4530. // relation
  4531. backepsilon: "∍",
  4532. because: "∵",
  4533. therefore: "∴",
  4534. between: "≬",
  4535. blacktriangleleft: "◀",
  4536. blacktriangleright: "▸",
  4537. dashv: "⊣",
  4538. bowtie: "⋈",
  4539. frown: "⌢",
  4540. "in": "∈",
  4541. notin: "∉",
  4542. mid: "∣",
  4543. parallel: "∥",
  4544. models: "⊨",
  4545. ni: "∋",
  4546. owns: "∋",
  4547. nmid: "∤",
  4548. nparallel: "∦",
  4549. nshortmid: "⏒",
  4550. nshortparallel: "⏓",
  4551. nsubseteq: "⊈",
  4552. nsubseteqq: "⫇",
  4553. nsupseteq: "⊉",
  4554. nsupseteqq: "⫈",
  4555. ntriangleleft: "⋪",
  4556. ntrianglelefteq: "⋬",
  4557. ntriangleright: "⋫",
  4558. ntrianglerighteq: "⋭",
  4559. nvdash: "⊬",
  4560. nVdash: "⊮",
  4561. nvDash: "⊭",
  4562. nVDash: "⊯",
  4563. perp: "⊥",
  4564. pitchfork: "⋔",
  4565. propto: "∝",
  4566. shortmid: "⏐",
  4567. shortparallel: "⏑",
  4568. smile: "⌣",
  4569. sqsubset: "⊏",
  4570. sqsubseteq: "⊑",
  4571. sqsupset: "⊐",
  4572. sqsupseteq: "⊒",
  4573. subset: "⊂",
  4574. Subset: "⋐",
  4575. subseteq: "⊆",
  4576. subseteqq: "⫅",
  4577. subsetneq: "⊊",
  4578. subsetneqq: "⫋",
  4579. supset: "⊃",
  4580. Supset: "⋑",
  4581. supseteq: "⊇",
  4582. supseteqq: "⫆",
  4583. supsetneq: "⊋",
  4584. supsetneqq: "⫌",
  4585. trianglelefteq: "⊴",
  4586. trianglerighteq: "⊵",
  4587. varpropto: "⫉",
  4588. varsubsetneq: "⏔",
  4589. varsubsetneqq: "⏖",
  4590. varsupsetneq: "⏕",
  4591. varsupsetneqq: "⏗",
  4592. vdash: "⊢",
  4593. Vdash: "⊩",
  4594. vDash: "⊨",
  4595. Vvdash: "⊪",
  4596. vert: "|",
  4597. Vert: "ǁ",
  4598. "|": "ǁ",
  4599. "{": "{",
  4600. "}": "}",
  4601. backslash: "\\",
  4602. langle: "〈",
  4603. rangle: "〉",
  4604. lceil: "⌈",
  4605. rceil: "⌉",
  4606. lbrace: "{",
  4607. rbrace: "}",
  4608. lfloor: "⌊",
  4609. rfloor: "⌋",
  4610. cdots: "⋯",
  4611. ddots: "⋰",
  4612. vdots: "⋮",
  4613. dots: "…",
  4614. ldots: "…",
  4615. "#": "#",
  4616. bot: "⊥",
  4617. angle: "∠",
  4618. backprime: "‵",
  4619. bigstar: "★",
  4620. blacklozenge: "◆",
  4621. blacksquare: "■",
  4622. blacktriangle: "▲",
  4623. blacktriangledown: "▼",
  4624. clubsuit: "♣",
  4625. diagdown: "⒁",
  4626. diagup: "⒂",
  4627. diamondsuit: "♢",
  4628. emptyset: "ø",
  4629. exists: "∃",
  4630. flat: "♭",
  4631. forall: "∀",
  4632. heartsuit: "♡",
  4633. infty: "∞",
  4634. lozenge: "◇",
  4635. measuredangle: "∡",
  4636. nabla: "∇",
  4637. natural: "♮",
  4638. neg: "¬",
  4639. lnot: "¬",
  4640. nexists: "∄",
  4641. prime: "′",
  4642. sharp: "♯",
  4643. spadesuit: "♠",
  4644. sphericalangle: "∢",
  4645. surd: "√",
  4646. top: "⊤",
  4647. varnothing: "∅",
  4648. triangle: "△",
  4649. triangledown: "▽"
  4650. }
  4651. };
  4652. }
  4653. };
  4654. /*!
  4655. * 罗马字体
  4656. */
  4657. _p[30] = {
  4658. value: function() {
  4659. return {
  4660. meta: {
  4661. fontFamily: "KF AMS ROMAN",
  4662. src: "KF_AMS_ROMAN.woff"
  4663. }
  4664. };
  4665. }
  4666. };
  4667. /**
  4668. * 公式对象,表达式容器
  4669. */
  4670. _p[31] = {
  4671. value: function(require) {
  4672. var kity = _p.r(34), GTYPE = _p.r(6), FontManager = _p.r(25), FontInstaller = _p.r(24), DEFAULT_OPTIONS = {
  4673. fontsize: 50,
  4674. autoresize: true,
  4675. padding: [ 0 ]
  4676. }, Output = _p.r(1), EXPRESSION_INTERVAL = 10, ExpressionWrap = kity.createClass("ExpressionWrap", {
  4677. constructor: function(exp, config) {
  4678. this.wrap = new kity.Group();
  4679. this.bg = new kity.Rect(0, 0, 0, 0).fill("transparent");
  4680. this.exp = exp;
  4681. this.config = config;
  4682. this.wrap.setAttr("data-type", "kf-exp-wrap");
  4683. this.bg.setAttr("data-type", "kf-exp-wrap-bg");
  4684. this.wrap.addShape(this.bg);
  4685. this.wrap.addShape(this.exp);
  4686. },
  4687. getWrapShape: function() {
  4688. return this.wrap;
  4689. },
  4690. getExpression: function() {
  4691. return this.exp;
  4692. },
  4693. getBackground: function() {
  4694. return this.bg;
  4695. },
  4696. resize: function() {
  4697. var padding = this.config.padding, expBox = this.exp.getFixRenderBox();
  4698. if (padding.length === 1) {
  4699. padding[1] = padding[0];
  4700. }
  4701. this.bg.setSize(padding[1] * 2 + expBox.width, padding[0] * 2 + expBox.height);
  4702. this.exp.translate(padding[1], padding[0]);
  4703. }
  4704. }), Formula = kity.createClass("Formula", {
  4705. base: _p.r(32),
  4706. constructor: function(container, config) {
  4707. this.callBase(container);
  4708. this.expressions = [];
  4709. this.fontInstaller = new FontInstaller(this);
  4710. this.config = kity.Utils.extend({}, DEFAULT_OPTIONS, config);
  4711. this.initEnvironment();
  4712. this.initInnerFont();
  4713. },
  4714. getContentContainer: function() {
  4715. return this.container;
  4716. },
  4717. initEnvironment: function() {
  4718. this.zoom = this.config.fontsize / 50;
  4719. if ("width" in this.config) {
  4720. this.setWidth(this.config.width);
  4721. }
  4722. if ("height" in this.config) {
  4723. this.setHeight(this.config.height);
  4724. }
  4725. this.node.setAttribute("font-size", DEFAULT_OPTIONS.fontsize);
  4726. },
  4727. initInnerFont: function() {
  4728. var fontList = FontManager.getFontList(), _self = this;
  4729. kity.Utils.each(fontList, function(fontInfo) {
  4730. createFontStyle(fontInfo);
  4731. });
  4732. function createFontStyle(fontInfo) {
  4733. var stylesheet = _self.doc.createElement("style"), tpl = '@font-face{font-family: "${fontFamily}";font-style: normal;src: url("${src}") format("woff");}';
  4734. stylesheet.setAttribute("type", "text/css");
  4735. stylesheet.innerHTML = tpl.replace("${fontFamily}", fontInfo.meta.fontFamily).replace("${src}", fontInfo.meta.src);
  4736. _self.resourceNode.appendChild(stylesheet);
  4737. }
  4738. },
  4739. insertExpression: function(expression, index) {
  4740. var expWrap = this.wrap(expression);
  4741. // clear zoom
  4742. this.container.clearTransform();
  4743. this.expressions.splice(index, 0, expWrap.getWrapShape());
  4744. this.addShape(expWrap.getWrapShape());
  4745. notifyExpression.call(this, expWrap.getExpression());
  4746. expWrap.resize();
  4747. correctOffset.call(this);
  4748. this.resetZoom();
  4749. this.config.autoresize && this.resize();
  4750. },
  4751. appendExpression: function(expression) {
  4752. this.insertExpression(expression, this.expressions.length);
  4753. },
  4754. resize: function() {
  4755. var renderBox = this.container.getRenderBox("paper");
  4756. this.node.setAttribute("width", renderBox.width);
  4757. this.node.setAttribute("height", renderBox.height);
  4758. },
  4759. resetZoom: function() {
  4760. var zoomLevel = this.zoom / this.getBaseZoom();
  4761. if (zoomLevel !== 0) {
  4762. this.container.scale(zoomLevel);
  4763. }
  4764. },
  4765. wrap: function(exp) {
  4766. return new ExpressionWrap(exp, this.config);
  4767. },
  4768. clear: function() {
  4769. this.callBase();
  4770. this.expressions = [];
  4771. },
  4772. clearExpressions: function() {
  4773. kity.Utils.each(this.expressions, function(exp) {
  4774. exp.remove();
  4775. });
  4776. this.expressions = [];
  4777. },
  4778. toJPG: function(cb) {
  4779. new Output(this).toJPG(cb);
  4780. },
  4781. toPNG: function(cb) {
  4782. new Output(this).toPNG(cb);
  4783. }
  4784. });
  4785. kity.Utils.extend(Formula, {
  4786. registerFont: function(fontData) {
  4787. FontManager.registerFont(fontData);
  4788. }
  4789. });
  4790. // 调整表达式之间的偏移
  4791. function correctOffset() {
  4792. var exprOffset = 0;
  4793. kity.Utils.each(this.expressions, function(expr) {
  4794. var box = null;
  4795. if (!expr) {
  4796. return;
  4797. }
  4798. expr.setMatrix(new kity.Matrix(1, 0, 0, 1, 0, 0));
  4799. box = expr.getFixRenderBox();
  4800. expr.translate(0 - box.x, exprOffset);
  4801. exprOffset += box.height + EXPRESSION_INTERVAL;
  4802. });
  4803. return this;
  4804. }
  4805. // 通知表达式已接入到paper
  4806. function notifyExpression(expression) {
  4807. var len = 0;
  4808. if (!expression) {
  4809. return;
  4810. }
  4811. if (expression.getType() === GTYPE.EXP) {
  4812. for (var i = 0, len = expression.getChildren().length; i < len; i++) {
  4813. notifyExpression(expression.getChild(i));
  4814. }
  4815. } else if (expression.getType() === GTYPE.COMPOUND_EXP) {
  4816. // 操作数处理
  4817. for (var i = 0, len = expression.getOperands().length; i < len; i++) {
  4818. notifyExpression(expression.getOperand(i));
  4819. }
  4820. // 处理操作符
  4821. notifyExpression(expression.getOperator());
  4822. }
  4823. expression.addedCall && expression.addedCall();
  4824. }
  4825. return Formula;
  4826. }
  4827. };
  4828. /**
  4829. * 公式专用paper
  4830. */
  4831. _p[32] = {
  4832. value: function(require) {
  4833. var kity = _p.r(34);
  4834. return kity.createClass("FPaper", {
  4835. base: kity.Paper,
  4836. constructor: function(container) {
  4837. this.callBase(container);
  4838. this.doc = container.ownerDocument;
  4839. this.container = new kity.Group();
  4840. this.container.setAttr("data-type", "kf-container");
  4841. this.background = new kity.Group();
  4842. this.background.setAttr("data-type", "kf-bg");
  4843. this.baseZoom = 1;
  4844. this.zoom = 1;
  4845. this.base("addShape", this.background);
  4846. this.base("addShape", this.container);
  4847. },
  4848. getZoom: function() {
  4849. return this.zoom;
  4850. },
  4851. getBaseZoom: function() {
  4852. return this.baseZoom;
  4853. },
  4854. addShape: function(shape, pos) {
  4855. return this.container.addShape(shape, pos);
  4856. },
  4857. getBackground: function() {
  4858. return this.background;
  4859. },
  4860. removeShape: function(pos) {
  4861. return this.container.removeShape(pos);
  4862. },
  4863. clear: function() {
  4864. return this.container.clear();
  4865. }
  4866. });
  4867. }
  4868. };
  4869. /**
  4870. * jquery
  4871. */
  4872. _p[33] = {
  4873. value: function() {
  4874. if (!window.jQuery) {
  4875. throw new Error("Missing jQuery");
  4876. }
  4877. return window.jQuery;
  4878. }
  4879. };
  4880. /**
  4881. * kity库封包
  4882. */
  4883. _p[34] = {
  4884. value: function() {
  4885. if (!window.kity) {
  4886. throw new Error("Missing Kity Graphic Lib");
  4887. }
  4888. return window.kity;
  4889. }
  4890. };
  4891. /**
  4892. * 小括号操作符:()
  4893. */
  4894. _p[35] = {
  4895. value: function(require) {
  4896. var kity = _p.r(34), Text = _p.r(5);
  4897. return kity.createClass("BracketsOperator", {
  4898. base: _p.r(41),
  4899. constructor: function() {
  4900. this.callBase("Brackets");
  4901. },
  4902. applyOperand: function(exp) {
  4903. generate.call(this, exp);
  4904. }
  4905. });
  4906. function generate(exp) {
  4907. 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");
  4908. leftOp.setFontSize(fontSize);
  4909. rightOp.setFontSize(fontSize);
  4910. this.addOperatorShape(group.addShape(leftOp).addShape(rightOp));
  4911. offset += leftOp.getFixRenderBox().width;
  4912. exp.translate(offset, 0);
  4913. offset += exp.getFixRenderBox().width;
  4914. rightOp.translate(offset, 0);
  4915. }
  4916. }
  4917. };
  4918. /**
  4919. * 组合操作符
  4920. * 操作多个表达式组合在一起
  4921. */
  4922. _p[36] = {
  4923. value: function(require) {
  4924. var kity = _p.r(34);
  4925. return kity.createClass("CombinationOperator", {
  4926. base: _p.r(41),
  4927. constructor: function() {
  4928. this.callBase("Combination");
  4929. },
  4930. applyOperand: function() {
  4931. // 偏移量
  4932. var offsetX = 0, // 操作数
  4933. operands = arguments, // 操作对象最大高度
  4934. maxHeight = 0, // 垂直距离最大偏移
  4935. maxOffsetTop = 0, maxOffsetBottom = 0, cached = [], // 偏移集合
  4936. offsets = [];
  4937. kity.Utils.each(operands, function(operand) {
  4938. var box = operand.getFixRenderBox(), offsetY = operand.getOffset();
  4939. box.height -= offsetY.top + offsetY.bottom;
  4940. cached.push(box);
  4941. offsets.push(offsetY);
  4942. maxOffsetTop = Math.max(offsetY.top, maxOffsetTop);
  4943. maxOffsetBottom = Math.max(offsetY.bottom, maxOffsetBottom);
  4944. maxHeight = Math.max(box.height, maxHeight);
  4945. });
  4946. kity.Utils.each(operands, function(operand, index) {
  4947. var box = cached[index];
  4948. operand.translate(offsetX - box.x, (maxHeight - (box.y + box.height)) / 2 + maxOffsetBottom - offsets[index].bottom);
  4949. offsetX += box.width;
  4950. });
  4951. this.parentExpression.setOffset(maxOffsetTop, maxOffsetBottom);
  4952. this.parentExpression.updateBoxSize();
  4953. }
  4954. });
  4955. }
  4956. };
  4957. /*!
  4958. * 上下标控制器
  4959. */
  4960. _p[37] = {
  4961. value: function(require) {
  4962. var kity = _p.r(34), EmptyExpression = _p.r(20), defaultOptions = {
  4963. subOffset: 0,
  4964. supOffset: 0,
  4965. // 上下标的默认缩放值
  4966. zoom: .66
  4967. };
  4968. return kity.createClass("ScriptController", {
  4969. constructor: function(opObj, target, sup, sub, options) {
  4970. this.observer = opObj.getParentExpression();
  4971. this.target = target;
  4972. this.sup = sup;
  4973. this.sub = sub;
  4974. this.options = kity.Utils.extend({}, defaultOptions, options);
  4975. },
  4976. // 上下标记
  4977. applyUpDown: function() {
  4978. var target = this.target, sup = this.sup, sub = this.sub, options = this.options;
  4979. sup.scale(options.zoom);
  4980. sub.scale(options.zoom);
  4981. var targetBox = target.getFixRenderBox();
  4982. if (EmptyExpression.isEmpty(sup) && EmptyExpression.isEmpty(sub)) {
  4983. return {
  4984. width: targetBox.width,
  4985. height: targetBox.height,
  4986. top: 0,
  4987. bottom: 0
  4988. };
  4989. } else {
  4990. // 上标
  4991. if (!EmptyExpression.isEmpty(sup) && EmptyExpression.isEmpty(sub)) {
  4992. return this.applyUp(target, sup);
  4993. } else if (EmptyExpression.isEmpty(sup) && !EmptyExpression.isEmpty(sub)) {
  4994. return this.applyDown(target, sub);
  4995. } else {
  4996. return this.applyUpDownScript(target, sup, sub);
  4997. }
  4998. }
  4999. },
  5000. /**
  5001. * 返回应用上下标后的空间占用情况,其中的key各自的意义是:
  5002. * top: 上空间偏移
  5003. * bottom: 下空间偏移
  5004. * width: 当前整个图形的实际占用空间的width
  5005. * height: 当前整个图形的实际占用空间的height
  5006. * @returns {*}
  5007. */
  5008. applySide: function() {
  5009. var target = this.target, sup = this.sup, sub = this.sub;
  5010. if (EmptyExpression.isEmpty(sup) && EmptyExpression.isEmpty(sub)) {
  5011. var targetRectBox = target.getRenderBox(this.observer);
  5012. return {
  5013. width: targetRectBox.width,
  5014. height: targetRectBox.height,
  5015. top: 0,
  5016. bottom: 0
  5017. };
  5018. } else {
  5019. // 下标处理
  5020. if (EmptyExpression.isEmpty(sup) && !EmptyExpression.isEmpty(sub)) {
  5021. return this.applySideSub(target, sub);
  5022. } else if (!EmptyExpression.isEmpty(sup) && EmptyExpression.isEmpty(sub)) {
  5023. return this.applySideSuper(target, sup);
  5024. } else {
  5025. return this.applySideScript(target, sup, sub);
  5026. }
  5027. }
  5028. },
  5029. applySideSuper: function(target, sup) {
  5030. sup.scale(this.options.zoom);
  5031. 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 = {
  5032. top: 0,
  5033. bottom: 0,
  5034. width: targetRectBox.width + supRectBox.width,
  5035. height: targetRectBox.height
  5036. };
  5037. sup.translate(targetRectBox.width, 0);
  5038. if (this.options.supOffset) {
  5039. sup.translate(this.options.supOffset, 0);
  5040. }
  5041. if (diff > 0) {
  5042. target.translate(0, diff);
  5043. space.bottom = diff;
  5044. space.height += diff;
  5045. } else {
  5046. sup.translate(0, -diff);
  5047. }
  5048. return space;
  5049. },
  5050. applySideSub: function(target, sub) {
  5051. sub.scale(this.options.zoom);
  5052. var targetRectBox = target.getRenderBox(this.observer), subRectBox = sub.getRenderBox(this.observer), subOffset = sub.getOffset(), targetBaseline = target.getBaseline(this.observer), // 下标定位线
  5053. subPosition = (subRectBox.height + subOffset.top + subOffset.bottom) / 2, diff = targetRectBox.height - targetBaseline - subPosition, space = {
  5054. top: 0,
  5055. bottom: 0,
  5056. width: targetRectBox.width + subRectBox.width,
  5057. height: targetRectBox.height
  5058. };
  5059. // 定位下标位置
  5060. sub.translate(targetRectBox.width, subOffset.top + targetBaseline - subPosition);
  5061. if (this.options.subOffset) {
  5062. sub.translate(this.options.subOffset, 0);
  5063. }
  5064. if (diff < 0) {
  5065. space.top = -diff;
  5066. space.height -= diff;
  5067. }
  5068. return space;
  5069. },
  5070. applySideScript: function(target, sup, sub) {
  5071. sup.scale(this.options.zoom);
  5072. sub.scale(this.options.zoom);
  5073. 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), // 上下标都存在时, 下标的定位以上伸线为准
  5074. subAscenderline = sub.getAscenderline(this.observer), supPosition = targetMeanline, subPosition = targetMeanline + (targetBaseline - targetMeanline) * 2 / 3, topDiff = supPosition - supBaseline, bottomDiff = targetRectBox.height - subPosition - (subRectBox.height - subAscenderline), space = {
  5075. top: 0,
  5076. bottom: 0,
  5077. width: targetRectBox.width + Math.max(subRectBox.width, supRectBox.width),
  5078. height: targetRectBox.height
  5079. };
  5080. sup.translate(targetRectBox.width, topDiff);
  5081. sub.translate(targetRectBox.width, subPosition - subAscenderline);
  5082. if (this.options.supOffset) {
  5083. sup.translate(this.options.supOffset, 0);
  5084. }
  5085. if (this.options.subOffset) {
  5086. sub.translate(this.options.subOffset, 0);
  5087. }
  5088. // 定位纠正
  5089. if (topDiff > 0) {
  5090. if (bottomDiff < 0) {
  5091. targetRectBox.height -= bottomDiff;
  5092. space.top = -bottomDiff;
  5093. }
  5094. } else {
  5095. target.translate(0, -topDiff);
  5096. sup.translate(0, -topDiff);
  5097. sub.translate(0, -topDiff);
  5098. space.height -= topDiff;
  5099. if (bottomDiff > 0) {
  5100. space.bottom = -topDiff;
  5101. } else {
  5102. space.height -= bottomDiff;
  5103. // 比较上下偏移, 获取正确的偏移值
  5104. topDiff = -topDiff;
  5105. bottomDiff = -bottomDiff;
  5106. if (topDiff > bottomDiff) {
  5107. space.bottom = topDiff - bottomDiff;
  5108. } else {
  5109. space.top = bottomDiff - topDiff;
  5110. }
  5111. }
  5112. }
  5113. return space;
  5114. },
  5115. applyUp: function(target, sup) {
  5116. var supBox = sup.getFixRenderBox(), targetBox = target.getFixRenderBox(), space = {
  5117. width: Math.max(targetBox.width, supBox.width),
  5118. height: supBox.height + targetBox.height,
  5119. top: 0,
  5120. bottom: supBox.height
  5121. };
  5122. sup.translate((space.width - supBox.width) / 2, 0);
  5123. target.translate((space.width - targetBox.width) / 2, supBox.height);
  5124. return space;
  5125. },
  5126. applyDown: function(target, sub) {
  5127. var subBox = sub.getFixRenderBox(), targetBox = target.getFixRenderBox(), space = {
  5128. width: Math.max(targetBox.width, subBox.width),
  5129. height: subBox.height + targetBox.height,
  5130. top: subBox.height,
  5131. bottom: 0
  5132. };
  5133. sub.translate((space.width - subBox.width) / 2, targetBox.height);
  5134. target.translate((space.width - targetBox.width) / 2, 0);
  5135. return space;
  5136. },
  5137. applyUpDownScript: function(target, sup, sub) {
  5138. var supBox = sup.getFixRenderBox(), subBox = sub.getFixRenderBox(), targetBox = target.getFixRenderBox(), space = {
  5139. width: Math.max(targetBox.width, supBox.width, subBox.width),
  5140. height: supBox.height + subBox.height + targetBox.height,
  5141. top: 0,
  5142. bottom: 0
  5143. };
  5144. sup.translate((space.width - supBox.width) / 2, 0);
  5145. target.translate((space.width - targetBox.width) / 2, supBox.height);
  5146. sub.translate((space.width - subBox.width) / 2, supBox.height + targetBox.height);
  5147. return space;
  5148. }
  5149. });
  5150. }
  5151. };
  5152. /**
  5153. * 分数操作符
  5154. */
  5155. _p[38] = {
  5156. value: function(require) {
  5157. var kity = _p.r(34), ZOOM = _p.r(47).zoom;
  5158. return kity.createClass("FractionOperator", {
  5159. base: _p.r(41),
  5160. constructor: function() {
  5161. this.callBase("Fraction");
  5162. },
  5163. applyOperand: function(upOperand, downOperand) {
  5164. upOperand.scale(ZOOM);
  5165. downOperand.scale(ZOOM);
  5166. var upWidth = Math.ceil(upOperand.getWidth()), downWidth = Math.ceil(downOperand.getWidth()), upHeight = Math.ceil(upOperand.getHeight()), downHeight = Math.ceil(downOperand.getHeight()), // 分数线overflow值
  5167. overflow = 3, // 整体padding
  5168. padding = 1, maxWidth = Math.max(upWidth, downWidth), maxHeight = Math.max(upHeight, downHeight), operatorShape = generateOperator(maxWidth, overflow);
  5169. this.addOperatorShape(operatorShape);
  5170. upOperand.translate((maxWidth - upWidth) / 2 + overflow, 0);
  5171. operatorShape.translate(0, upHeight + 1);
  5172. // 下部不需要偏移
  5173. downOperand.translate((maxWidth - downWidth) / 2 + overflow, upHeight + operatorShape.getHeight() + 1 * 2);
  5174. this.parentExpression.setOffset(maxHeight - upHeight, maxHeight - downHeight);
  5175. this.parentExpression.expand(padding * 2, padding * 2);
  5176. this.parentExpression.translateElement(padding, padding);
  5177. }
  5178. });
  5179. function generateOperator(width, overflow) {
  5180. return new kity.Rect(width + overflow * 2, 1).fill("black");
  5181. }
  5182. }
  5183. };
  5184. /**
  5185. * 函数操作符
  5186. */
  5187. _p[39] = {
  5188. value: function(require) {
  5189. var kity = _p.r(34), Text = _p.r(5), ScriptController = _p.r(37);
  5190. return kity.createClass("FunctionOperator", {
  5191. base: _p.r(41),
  5192. constructor: function(funcName) {
  5193. this.callBase("Function: " + funcName);
  5194. this.funcName = funcName;
  5195. },
  5196. /*
  5197. * 积分操作符应用操作数
  5198. * @param expr 函数表达式
  5199. * @param sup 上限
  5200. * @param sub 下限
  5201. */
  5202. applyOperand: function(expr, sup, sub) {
  5203. var opShape = generateOperator.call(this), expBox = expr.getFixRenderBox(), scriptHanlder = this.parentExpression.isSideScript() ? "applySide" : "applyUpDown", space = new ScriptController(this, opShape, sup, sub, {
  5204. zoom: .5
  5205. })[scriptHanlder](), padding = 5, diff = (space.height + space.top + space.bottom - expBox.height) / 2;
  5206. // 应用偏移, 使图形在正确的位置上
  5207. opShape.translate(0, space.top);
  5208. sup.translate(0, space.top);
  5209. sub.translate(0, space.top);
  5210. if (diff >= 0) {
  5211. expr.translate(space.width + padding, diff);
  5212. } else {
  5213. diff = -diff;
  5214. opShape.translate(0, diff);
  5215. sup.translate(0, diff);
  5216. sub.translate(0, diff);
  5217. expr.translate(space.width + padding, 0);
  5218. }
  5219. // 只扩展左边, 不扩展右边, 所以padding不 *2
  5220. this.parentExpression.expand(padding, padding * 2);
  5221. this.parentExpression.translateElement(padding, padding);
  5222. }
  5223. });
  5224. /* 返回操作符对象 */
  5225. function generateOperator() {
  5226. var opShape = new Text(this.funcName, "KF AMS ROMAN");
  5227. this.addOperatorShape(opShape);
  5228. // 为操作符图形创建baseline和meanline方法
  5229. opShape.getBaseline = function() {
  5230. return opShape.getFixRenderBox().height;
  5231. };
  5232. opShape.getMeanline = function() {
  5233. return 0;
  5234. };
  5235. return opShape;
  5236. }
  5237. }
  5238. };
  5239. /**
  5240. * 积分操作符:∫
  5241. */
  5242. _p[40] = {
  5243. value: function(require) {
  5244. var kity = _p.r(34), ScriptController = _p.r(37);
  5245. return kity.createClass("IntegrationOperator", {
  5246. base: _p.r(41),
  5247. constructor: function(type) {
  5248. this.callBase("Integration");
  5249. // 默认是普通单重积分
  5250. this.opType = type || 1;
  5251. },
  5252. setType: function(type) {
  5253. this.opType = type | 0;
  5254. },
  5255. // 重置类型
  5256. resetType: function() {
  5257. this.opType = 1;
  5258. },
  5259. applyOperand: function(exp, sup, sub) {
  5260. var opShape = this.getOperatorShape(), padding = 3, expBox = exp.getFixRenderBox(), space = new ScriptController(this, opShape, sup, sub, {
  5261. supOffset: 3,
  5262. subOffset: -15
  5263. }).applySide(), diff = (space.height + space.top - expBox.height) / 2;
  5264. opShape.translate(0, space.top);
  5265. sup.translate(0, space.top);
  5266. sub.translate(0, space.top);
  5267. if (diff >= 0) {
  5268. exp.translate(space.width + padding, diff);
  5269. } else {
  5270. diff = -diff;
  5271. opShape.translate(0, diff);
  5272. sup.translate(0, diff);
  5273. sub.translate(0, diff);
  5274. exp.translate(space.width + padding, 0);
  5275. }
  5276. this.parentExpression.expand(padding, padding * 2);
  5277. this.parentExpression.translateElement(padding, padding);
  5278. },
  5279. getOperatorShape: function() {
  5280. 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;
  5281. opGroup.addShape(opShape);
  5282. group.addShape(opBox);
  5283. group.addShape(opGroup);
  5284. this.addOperatorShape(group);
  5285. for (var i = 1; i < this.opType; i++) {
  5286. tmpShape = new kity.Use(opShape).translate(opShape.getWidth() / 2 * i, 0);
  5287. opGroup.addShape(tmpShape);
  5288. }
  5289. opGroup.scale(1.6);
  5290. tmpShape = null;
  5291. // 为操作符图形创建baseline和meanline方法
  5292. group.getBaseline = function() {
  5293. return opGroup.getFixRenderBox().height;
  5294. };
  5295. group.getMeanline = function() {
  5296. return 10;
  5297. };
  5298. return group;
  5299. }
  5300. });
  5301. }
  5302. };
  5303. /**
  5304. * 操作符抽象类
  5305. * @abstract
  5306. */
  5307. _p[41] = {
  5308. value: function(require) {
  5309. var kity = _p.r(34), GTYPE = _p.r(6);
  5310. return kity.createClass("Operator", {
  5311. base: _p.r(46),
  5312. constructor: function(operatorName) {
  5313. this.callBase();
  5314. this.type = GTYPE.OP;
  5315. // 该操作符所属的表达式
  5316. this.parentExpression = null;
  5317. // 操作符名称
  5318. this.operatorName = operatorName;
  5319. // 操作符图形
  5320. this.operatorShape = new kity.Group();
  5321. this.addShape(this.operatorShape);
  5322. },
  5323. applyOperand: function() {
  5324. throw new Error("applyOperand is abstract");
  5325. },
  5326. setParentExpression: function(exp) {
  5327. this.parentExpression = exp;
  5328. },
  5329. getParentExpression: function() {
  5330. return this.parentExpression;
  5331. },
  5332. clearParentExpression: function() {
  5333. this.parentExpression = null;
  5334. },
  5335. // 提供给具体实现类附加其绘制的操作符图形的接口
  5336. addOperatorShape: function(shpae) {
  5337. return this.operatorShape.addShape(shpae);
  5338. },
  5339. getOperatorShape: function() {
  5340. return this.operatorShape;
  5341. }
  5342. });
  5343. }
  5344. };
  5345. /**
  5346. * 开方操作符
  5347. */
  5348. _p[42] = {
  5349. value: function(require) {
  5350. var kity = _p.r(34), // 符号图形属性
  5351. // 线条宽度
  5352. SHAPE_DATA_WIDTH = 1, // 计算公式
  5353. radians = 2 * Math.PI / 360, sin15 = Math.sin(15 * radians), cos15 = Math.cos(15 * radians), tan15 = Math.tan(15 * radians);
  5354. return kity.createClass("RadicalOperator", {
  5355. base: _p.r(41),
  5356. constructor: function() {
  5357. this.callBase("Radical");
  5358. },
  5359. applyOperand: function(radicand, exponent) {
  5360. generateOperator.call(this, radicand, exponent);
  5361. }
  5362. });
  5363. // 根据给定的操作数生成操作符的pathData
  5364. // radicand 表示被开方数
  5365. // exponent 表示指数
  5366. function generateOperator(radicand, exponent) {
  5367. var decoration = generateDecoration(radicand), vLine = generateVLine(radicand), padding = 5, hLine = generateHLine(radicand);
  5368. this.addOperatorShape(decoration);
  5369. this.addOperatorShape(vLine);
  5370. this.addOperatorShape(hLine);
  5371. adjustmentPosition.call(this, mergeShape(decoration, vLine, hLine), this.operatorShape, radicand, exponent);
  5372. this.parentExpression.expand(0, padding * 2);
  5373. this.parentExpression.translateElement(0, padding);
  5374. }
  5375. // 生成根号中的左边装饰部分
  5376. function generateDecoration(radicand) {
  5377. var shape = new kity.Path(), // 命名为a以便于精简表达式
  5378. a = SHAPE_DATA_WIDTH, h = radicand.getHeight() / 3, drawer = shape.getDrawer();
  5379. // 根号尾部左上角开始
  5380. drawer.moveTo(0, cos15 * a * 6);
  5381. drawer.lineBy(sin15 * a, cos15 * a);
  5382. drawer.lineBy(cos15 * a * 3, -sin15 * a * 3);
  5383. drawer.lineBy(tan15 * h, h);
  5384. drawer.lineBy(sin15 * a * 3, -cos15 * a * 3);
  5385. drawer.lineBy(-sin15 * h, -h);
  5386. drawer.close();
  5387. return shape.fill("black");
  5388. }
  5389. // 根据操作数生成根号的竖直线部分
  5390. function generateVLine(operand) {
  5391. var shape = new kity.Path(), // * 0.9 是为了在视觉上使斜线部分不至于太高
  5392. h = operand.getHeight() * .9, drawer = shape.getDrawer();
  5393. drawer.moveTo(tan15 * h, 0);
  5394. drawer.lineTo(0, h);
  5395. drawer.lineBy(sin15 * SHAPE_DATA_WIDTH * 3, cos15 * SHAPE_DATA_WIDTH * 3);
  5396. drawer.lineBy(tan15 * h + sin15 * SHAPE_DATA_WIDTH * 3, -(h + 3 * SHAPE_DATA_WIDTH * cos15));
  5397. drawer.close();
  5398. return shape.fill("black");
  5399. }
  5400. // 根据操作数生成根号的水平线部分
  5401. function generateHLine(operand) {
  5402. // 表达式宽度
  5403. var w = operand.getWidth() + 2 * SHAPE_DATA_WIDTH;
  5404. return new kity.Rect(w, 2 * SHAPE_DATA_WIDTH).fill("black");
  5405. }
  5406. // 合并根号的各个部分, 并返回根号的关键点位置数据
  5407. function mergeShape(decoration, vLine, hLine) {
  5408. var decoBox = decoration.getFixRenderBox(), vLineBox = vLine.getFixRenderBox();
  5409. vLine.translate(decoBox.width - sin15 * SHAPE_DATA_WIDTH * 3, 0);
  5410. decoration.translate(0, vLineBox.height - decoBox.height);
  5411. vLineBox = vLine.getFixRenderBox();
  5412. hLine.translate(vLineBox.x + vLineBox.width - SHAPE_DATA_WIDTH / cos15, 0);
  5413. // 返回关键点数据
  5414. return {
  5415. x: vLineBox.x + vLineBox.width - SHAPE_DATA_WIDTH / cos15,
  5416. y: 0
  5417. };
  5418. }
  5419. // 调整整个根号表达式的各个部分: 位置、操作符、被开方数、指数
  5420. function adjustmentPosition(position, operator, radicand, exponent) {
  5421. var exponentBox = null, opOffset = {
  5422. x: 0,
  5423. y: 0
  5424. }, opBox = operator.getFixRenderBox();
  5425. exponent.scale(.66);
  5426. exponentBox = exponent.getFixRenderBox();
  5427. if (exponentBox.width > 0 && exponentBox.height > 0) {
  5428. opOffset.y = exponentBox.height - opBox.height / 2;
  5429. // 指数不超出根号, 则移动指数
  5430. if (opOffset.y < 0) {
  5431. exponent.translate(0, -opOffset.y);
  5432. opOffset.y = 0;
  5433. }
  5434. opOffset.x = exponentBox.width + opBox.height / 2 * tan15 - position.x;
  5435. }
  5436. operator.translate(opOffset.x, opOffset.y);
  5437. radicand.translate(opOffset.x + position.x + SHAPE_DATA_WIDTH, opOffset.y + 2 * SHAPE_DATA_WIDTH);
  5438. }
  5439. }
  5440. };
  5441. /**
  5442. * 上下标操作符
  5443. */
  5444. _p[43] = {
  5445. value: function(require) {
  5446. var kity = _p.r(34), ScriptController = _p.r(37);
  5447. return kity.createClass("ScriptOperator", {
  5448. base: _p.r(41),
  5449. constructor: function(operatorName) {
  5450. this.callBase(operatorName || "Script");
  5451. },
  5452. applyOperand: function(operand, sup, sub) {
  5453. var padding = 1, parent = this.parentExpression, space = new ScriptController(this, operand, sup, sub).applySide();
  5454. this.getOperatorShape();
  5455. space && parent.setOffset(space.top, space.bottom);
  5456. parent.expand(4, padding * 2);
  5457. parent.translateElement(2, padding);
  5458. }
  5459. });
  5460. }
  5461. };
  5462. /**
  5463. * 求和操作符:∑
  5464. */
  5465. _p[44] = {
  5466. value: function(require) {
  5467. var kity = _p.r(34), ScriptController = _p.r(37);
  5468. return kity.createClass("SummationOperator", {
  5469. base: _p.r(41),
  5470. constructor: function() {
  5471. this.callBase("Summation");
  5472. this.displayType = "equation";
  5473. },
  5474. applyOperand: function(expr, sup, sub) {
  5475. 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;
  5476. if (diff >= 0) {
  5477. expr.translate(space.width + padding, diff + space.bottom);
  5478. } else {
  5479. diff = -diff;
  5480. opShape.translate(0, diff);
  5481. sup.translate(0, diff);
  5482. sub.translate(0, diff);
  5483. expr.translate(space.width + padding, space.bottom);
  5484. }
  5485. this.parentExpression.setOffset(space.top, space.bottom);
  5486. this.parentExpression.expand(padding, padding * 2);
  5487. this.parentExpression.translateElement(padding, padding);
  5488. },
  5489. getOperatorShape: function() {
  5490. 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;
  5491. group.addShape(opBgShape);
  5492. group.addShape(operatorShape);
  5493. operatorShape.scale(1.6);
  5494. this.addOperatorShape(group);
  5495. opRenderBox = operatorShape.getFixRenderBox();
  5496. if (this.displayType === "inline") {
  5497. operatorShape.translate(5, 15);
  5498. opBgShape.setSize(opRenderBox.width + 10, opRenderBox.height + 25);
  5499. } else {
  5500. operatorShape.translate(2, 5);
  5501. opBgShape.setSize(opRenderBox.width + 4, opRenderBox.height + 8);
  5502. }
  5503. return group;
  5504. }
  5505. });
  5506. }
  5507. };
  5508. /*!
  5509. * 资源管理器
  5510. * 负责管理资源的加载,并在资源ready之后提供Formula构造器
  5511. */
  5512. _p[45] = {
  5513. value: function(require) {
  5514. var kity = _p.r(34), cbList = [], RES_CONF = _p.r(47).resource, FontInstall = _p.r(24), Formula = _p.r(31), // 资源管理器就绪状态
  5515. __readyState = false, // 资源管理器是否已启动
  5516. inited = false;
  5517. return {
  5518. // 初始化
  5519. ready: function(cb, options) {
  5520. if (!inited) {
  5521. inited = true;
  5522. init(options);
  5523. }
  5524. if (__readyState) {
  5525. window.setTimeout(function() {
  5526. cb(Formula);
  5527. }, 0);
  5528. } else {
  5529. cbList.push(cb);
  5530. }
  5531. }
  5532. };
  5533. /**
  5534. * 资源初始化
  5535. */
  5536. function init(options) {
  5537. options = kity.Utils.extend({}, RES_CONF, options);
  5538. if (!/^(https?:)?\/\//.test(options.path)) {
  5539. options.path = getFullPath(options.path);
  5540. }
  5541. new FontInstall(document, options.path).mount(complete);
  5542. }
  5543. function complete() {
  5544. kity.Utils.each(cbList, function(cb) {
  5545. cb(Formula);
  5546. });
  5547. }
  5548. function getFullPath(path) {
  5549. var pathname = location.pathname.split("/"), pathPart;
  5550. pathname.length -= 1;
  5551. pathname = pathname.join("/") + "/";
  5552. pathPart = [ location.protocol, "//", location.host, pathname, path.replace(/^\//, "") ];
  5553. return pathPart.join("");
  5554. }
  5555. }
  5556. };
  5557. /*!
  5558. * 所有符号的基类
  5559. * @abstract
  5560. */
  5561. _p[46] = {
  5562. value: function(require) {
  5563. var kity = _p.r(34), GTYPE = _p.r(6);
  5564. return kity.createClass("SignGroup", {
  5565. base: kity.Group,
  5566. constructor: function() {
  5567. this.callBase();
  5568. this.box = new kity.Rect(0, 0, 0, 0);
  5569. this.type = GTYPE.UNKNOWN;
  5570. this.addShape(this.box);
  5571. this.zoom = 1;
  5572. },
  5573. setZoom: function(zoom) {
  5574. this.zoom = zoom;
  5575. },
  5576. getZoom: function() {
  5577. return this.zoom;
  5578. },
  5579. setBoxSize: function(w, h) {
  5580. return this.box.setSize(w, h);
  5581. },
  5582. setBoxWidth: function(w) {
  5583. return this.box.setWidth(w);
  5584. },
  5585. setBoxHeight: function(h) {
  5586. return this.box.setHeight(h);
  5587. },
  5588. getType: function() {
  5589. return this.type;
  5590. },
  5591. getBaseHeight: function() {
  5592. return this.getHeight();
  5593. },
  5594. getBaseWidth: function() {
  5595. return this.getWidth();
  5596. },
  5597. addedCall: function() {}
  5598. });
  5599. }
  5600. };
  5601. /*!
  5602. * 系统项目配置文件.
  5603. */
  5604. _p[47] = {
  5605. value: function(require) {
  5606. return {
  5607. zoom: .66,
  5608. font: {
  5609. meanline: Math.round(380 / 1e3 * 50),
  5610. baseline: Math.round(800 / 1e3 * 50),
  5611. baseHeight: 50,
  5612. // 系统字体列表
  5613. list: [ _p.r(29), _p.r(27), _p.r(28), _p.r(26), _p.r(30) ]
  5614. },
  5615. /*------------------------- 资源配置*/
  5616. resource: {
  5617. path: "src/resource/"
  5618. },
  5619. // 函数相关配置
  5620. func: {
  5621. // 上下标在函数名上下两侧的函数列表
  5622. "ud-script": {
  5623. lim: true
  5624. }
  5625. }
  5626. };
  5627. }
  5628. };
  5629. /*!
  5630. * 启动代码
  5631. */
  5632. _p[48] = {
  5633. value: function(require) {
  5634. window.kf = {
  5635. // base
  5636. ResourceManager: _p.r(45),
  5637. Operator: _p.r(41),
  5638. // expression
  5639. Expression: _p.r(21),
  5640. CompoundExpression: _p.r(19),
  5641. TextExpression: _p.r(22),
  5642. EmptyExpression: _p.r(20),
  5643. CombinationExpression: _p.r(12),
  5644. FunctionExpression: _p.r(14),
  5645. FractionExpression: _p.r(13),
  5646. IntegrationExpression: _p.r(15),
  5647. RadicalExpression: _p.r(16),
  5648. ScriptExpression: _p.r(17),
  5649. SuperscriptExpression: _p.r(9),
  5650. SubscriptExpression: _p.r(8),
  5651. SummationExpression: _p.r(18),
  5652. // Brackets expressoin
  5653. BracketsExpression: _p.r(11)
  5654. };
  5655. }
  5656. };
  5657. var moduleMapping = {
  5658. "kf.start": 48
  5659. };
  5660. function use(name) {
  5661. _p.r([ moduleMapping[name] ]);
  5662. }
  5663. /**
  5664. * 模块暴露
  5665. */
  5666. ( function ( global ) {
  5667. var oldGetRenderBox = kity.Shape.getRenderBox;
  5668. kity.extendClass(kity.Shape, {
  5669. getFixRenderBox: function () {
  5670. return this.getRenderBox( this.container.container );
  5671. },
  5672. getTranslate: function () {
  5673. return this.transform.translate;
  5674. }
  5675. });
  5676. // build环境中才含有use
  5677. try {
  5678. use( 'kf.start' );
  5679. } catch ( e ) {
  5680. }
  5681. } )( this );
  5682. })();