1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053 |
- var fabric = fabric || { version: '2.3.3' };
- if (typeof exports !== 'undefined') {
- exports.fabric = fabric;
- }
- else if (typeof define === 'function' && define.amd) {
- define([], function() { return fabric; });
- }
- if (typeof document !== 'undefined' && typeof window !== 'undefined') {
- fabric.document = document;
- fabric.window = window;
- }
- else {
-
- fabric.document = require('jsdom')
- .jsdom(
- decodeURIComponent('%3C!DOCTYPE%20html%3E%3Chtml%3E%3Chead%3E%3C%2Fhead%3E%3Cbody%3E%3C%2Fbody%3E%3C%2Fhtml%3E'),
- { features: {
- FetchExternalResources: ['img']
- }
- });
- fabric.jsdomImplForWrapper = require('jsdom/lib/jsdom/living/generated/utils').implForWrapper;
- fabric.nodeCanvas = require('jsdom/lib/jsdom/utils').Canvas;
- fabric.window = fabric.document.defaultView;
- DOMParser = require('xmldom').DOMParser;
- }
- fabric.isTouchSupported = 'ontouchstart' in fabric.window;
- fabric.isLikelyNode = typeof Buffer !== 'undefined' &&
- typeof window === 'undefined';
- fabric.DPI = 96;
- fabric.reNum = '(?:[-+]?(?:\\d+|\\d*\\.\\d+)(?:e[-+]?\\d+)?)';
- fabric.fontPaths = { };
- fabric.iMatrix = [1, 0, 0, 1, 0, 0];
- fabric.canvasModule = 'canvas';
- fabric.perfLimitSizeTotal = 2097152;
- fabric.maxCacheSideLimit = 4096;
- fabric.minCacheSideLimit = 256;
- fabric.charWidthsCache = { };
- fabric.textureSize = 2048;
- fabric.enableGLFiltering = true;
- fabric.devicePixelRatio = fabric.window.devicePixelRatio ||
- fabric.window.webkitDevicePixelRatio ||
- fabric.window.mozDevicePixelRatio ||
- 1;
- fabric.browserShadowBlurConstant = 1;
- fabric.initFilterBackend = function() {
- if (fabric.enableGLFiltering && fabric.isWebglSupported && fabric.isWebglSupported(fabric.textureSize)) {
- console.log('max texture size: ' + fabric.maxTextureSize);
- return (new fabric.WebglFilterBackend({ tileSize: fabric.textureSize }));
- }
- else if (fabric.Canvas2dFilterBackend) {
- return (new fabric.Canvas2dFilterBackend());
- }
- };
- (function() {
-
- function _removeEventListener(eventName, handler) {
- if (!this.__eventListeners[eventName]) {
- return;
- }
- var eventListener = this.__eventListeners[eventName];
- if (handler) {
- eventListener[eventListener.indexOf(handler)] = false;
- }
- else {
- fabric.util.array.fill(eventListener, false);
- }
- }
-
- function observe(eventName, handler) {
- if (!this.__eventListeners) {
- this.__eventListeners = { };
- }
-
- if (arguments.length === 1) {
- for (var prop in eventName) {
- this.on(prop, eventName[prop]);
- }
- }
- else {
- if (!this.__eventListeners[eventName]) {
- this.__eventListeners[eventName] = [];
- }
- this.__eventListeners[eventName].push(handler);
- }
- return this;
- }
-
- function stopObserving(eventName, handler) {
- if (!this.__eventListeners) {
- return;
- }
-
- if (arguments.length === 0) {
- for (eventName in this.__eventListeners) {
- _removeEventListener.call(this, eventName);
- }
- }
-
- else if (arguments.length === 1 && typeof arguments[0] === 'object') {
- for (var prop in eventName) {
- _removeEventListener.call(this, prop, eventName[prop]);
- }
- }
- else {
- _removeEventListener.call(this, eventName, handler);
- }
- return this;
- }
-
- function fire(eventName, options) {
- if (!this.__eventListeners) {
- return;
- }
- var listenersForEvent = this.__eventListeners[eventName];
- if (!listenersForEvent) {
- return;
- }
- for (var i = 0, len = listenersForEvent.length; i < len; i++) {
- listenersForEvent[i] && listenersForEvent[i].call(this, options || { });
- }
- this.__eventListeners[eventName] = listenersForEvent.filter(function(value) {
- return value !== false;
- });
- return this;
- }
-
- fabric.Observable = {
- observe: observe,
- stopObserving: stopObserving,
- fire: fire,
- on: observe,
- off: stopObserving,
- trigger: fire
- };
- })();
- fabric.Collection = {
- _objects: [],
-
- add: function () {
- this._objects.push.apply(this._objects, arguments);
- if (this._onObjectAdded) {
- for (var i = 0, length = arguments.length; i < length; i++) {
- this._onObjectAdded(arguments[i]);
- }
- }
- this.renderOnAddRemove && this.requestRenderAll();
- return this;
- },
-
- insertAt: function (object, index, nonSplicing) {
- var objects = this.getObjects();
- if (nonSplicing) {
- objects[index] = object;
- }
- else {
- objects.splice(index, 0, object);
- }
- this._onObjectAdded && this._onObjectAdded(object);
- this.renderOnAddRemove && this.requestRenderAll();
- return this;
- },
-
- remove: function() {
- var objects = this.getObjects(),
- index, somethingRemoved = false;
- for (var i = 0, length = arguments.length; i < length; i++) {
- index = objects.indexOf(arguments[i]);
-
- if (index !== -1) {
- somethingRemoved = true;
- objects.splice(index, 1);
- this._onObjectRemoved && this._onObjectRemoved(arguments[i]);
- }
- }
- this.renderOnAddRemove && somethingRemoved && this.requestRenderAll();
- return this;
- },
-
- forEachObject: function(callback, context) {
- var objects = this.getObjects();
- for (var i = 0, len = objects.length; i < len; i++) {
- callback.call(context, objects[i], i, objects);
- }
- return this;
- },
-
- getObjects: function(type) {
- if (typeof type === 'undefined') {
- return this._objects;
- }
- return this._objects.filter(function(o) {
- return o.type === type;
- });
- },
-
- item: function (index) {
- return this.getObjects()[index];
- },
-
- isEmpty: function () {
- return this.getObjects().length === 0;
- },
-
- size: function() {
- return this.getObjects().length;
- },
-
- contains: function(object) {
- return this.getObjects().indexOf(object) > -1;
- },
-
- complexity: function () {
- return this.getObjects().reduce(function (memo, current) {
- memo += current.complexity ? current.complexity() : 0;
- return memo;
- }, 0);
- }
- };
- fabric.CommonMethods = {
-
- _setOptions: function(options) {
- for (var prop in options) {
- this.set(prop, options[prop]);
- }
- },
-
- _initGradient: function(filler, property) {
- if (filler && filler.colorStops && !(filler instanceof fabric.Gradient)) {
- this.set(property, new fabric.Gradient(filler));
- }
- },
-
- _initPattern: function(filler, property, callback) {
- if (filler && filler.source && !(filler instanceof fabric.Pattern)) {
- this.set(property, new fabric.Pattern(filler, callback));
- }
- else {
- callback && callback();
- }
- },
-
- _initClipping: function(options) {
- if (!options.clipTo || typeof options.clipTo !== 'string') {
- return;
- }
- var functionBody = fabric.util.getFunctionBody(options.clipTo);
- if (typeof functionBody !== 'undefined') {
- this.clipTo = new Function('ctx', functionBody);
- }
- },
-
- _setObject: function(obj) {
- for (var prop in obj) {
- this._set(prop, obj[prop]);
- }
- },
-
- set: function(key, value) {
- if (typeof key === 'object') {
- this._setObject(key);
- }
- else {
- if (typeof value === 'function' && key !== 'clipTo') {
- this._set(key, value(this.get(key)));
- }
- else {
- this._set(key, value);
- }
- }
- return this;
- },
- _set: function(key, value) {
- this[key] = value;
- },
-
- toggle: function(property) {
- var value = this.get(property);
- if (typeof value === 'boolean') {
- this.set(property, !value);
- }
- return this;
- },
-
- get: function(property) {
- return this[property];
- }
- };
- (function(global) {
- var sqrt = Math.sqrt,
- atan2 = Math.atan2,
- pow = Math.pow,
- abs = Math.abs,
- PiBy180 = Math.PI / 180,
- PiBy2 = Math.PI / 2;
-
- fabric.util = {
-
- cos: function(angle) {
- if (angle === 0) { return 1; }
- if (angle < 0) {
-
- angle = -angle;
- }
- var angleSlice = angle / PiBy2;
- switch (angleSlice) {
- case 1: case 3: return 0;
- case 2: return -1;
- }
- return Math.cos(angle);
- },
-
- sin: function(angle) {
- if (angle === 0) { return 0; }
- var angleSlice = angle / PiBy2, sign = 1;
- if (angle < 0) {
-
- sign = -1;
- }
- switch (angleSlice) {
- case 1: return sign;
- case 2: return 0;
- case 3: return -sign;
- }
- return Math.sin(angle);
- },
-
- removeFromArray: function(array, value) {
- var idx = array.indexOf(value);
- if (idx !== -1) {
- array.splice(idx, 1);
- }
- return array;
- },
-
- getRandomInt: function(min, max) {
- return Math.floor(Math.random() * (max - min + 1)) + min;
- },
-
- degreesToRadians: function(degrees) {
- return degrees * PiBy180;
- },
-
- radiansToDegrees: function(radians) {
- return radians / PiBy180;
- },
-
- rotatePoint: function(point, origin, radians) {
- point.subtractEquals(origin);
- var v = fabric.util.rotateVector(point, radians);
- return new fabric.Point(v.x, v.y).addEquals(origin);
- },
-
- rotateVector: function(vector, radians) {
- var sin = fabric.util.sin(radians),
- cos = fabric.util.cos(radians),
- rx = vector.x * cos - vector.y * sin,
- ry = vector.x * sin + vector.y * cos;
- return {
- x: rx,
- y: ry
- };
- },
-
- transformPoint: function(p, t, ignoreOffset) {
- if (ignoreOffset) {
- return new fabric.Point(
- t[0] * p.x + t[2] * p.y,
- t[1] * p.x + t[3] * p.y
- );
- }
- return new fabric.Point(
- t[0] * p.x + t[2] * p.y + t[4],
- t[1] * p.x + t[3] * p.y + t[5]
- );
- },
-
- makeBoundingBoxFromPoints: function(points) {
- var xPoints = [points[0].x, points[1].x, points[2].x, points[3].x],
- minX = fabric.util.array.min(xPoints),
- maxX = fabric.util.array.max(xPoints),
- width = maxX - minX,
- yPoints = [points[0].y, points[1].y, points[2].y, points[3].y],
- minY = fabric.util.array.min(yPoints),
- maxY = fabric.util.array.max(yPoints),
- height = maxY - minY;
- return {
- left: minX,
- top: minY,
- width: width,
- height: height
- };
- },
-
- invertTransform: function(t) {
- var a = 1 / (t[0] * t[3] - t[1] * t[2]),
- r = [a * t[3], -a * t[1], -a * t[2], a * t[0]],
- o = fabric.util.transformPoint({ x: t[4], y: t[5] }, r, true);
- r[4] = -o.x;
- r[5] = -o.y;
- return r;
- },
-
- toFixed: function(number, fractionDigits) {
- return parseFloat(Number(number).toFixed(fractionDigits));
- },
-
- parseUnit: function(value, fontSize) {
- var unit = /\D{0,2}$/.exec(value),
- number = parseFloat(value);
- if (!fontSize) {
- fontSize = fabric.Text.DEFAULT_SVG_FONT_SIZE;
- }
- switch (unit[0]) {
- case 'mm':
- return number * fabric.DPI / 25.4;
- case 'cm':
- return number * fabric.DPI / 2.54;
- case 'in':
- return number * fabric.DPI;
- case 'pt':
- return number * fabric.DPI / 72;
- case 'pc':
- return number * fabric.DPI / 72 * 12;
- case 'em':
- return number * fontSize;
- default:
- return number;
- }
- },
-
- falseFunction: function() {
- return false;
- },
-
- getKlass: function(type, namespace) {
-
- type = fabric.util.string.camelize(type.charAt(0).toUpperCase() + type.slice(1));
- return fabric.util.resolveNamespace(namespace)[type];
- },
-
- getSvgAttributes: function(type) {
- var attributes = [
- 'instantiated_by_use',
- 'style',
- 'id',
- 'class'
- ];
- switch (type) {
- case 'linearGradient':
- attributes = attributes.concat(['x1', 'y1', 'x2', 'y2', 'gradientUnits', 'gradientTransform']);
- break;
- case 'radialGradient':
- attributes = attributes.concat(['gradientUnits', 'gradientTransform', 'cx', 'cy', 'r', 'fx', 'fy', 'fr']);
- break;
- case 'stop':
- attributes = attributes.concat(['offset', 'stop-color', 'stop-opacity']);
- break;
- }
- return attributes;
- },
-
- resolveNamespace: function(namespace) {
- if (!namespace) {
- return fabric;
- }
- var parts = namespace.split('.'),
- len = parts.length, i,
- obj = global || fabric.window;
- for (i = 0; i < len; ++i) {
- obj = obj[parts[i]];
- }
- return obj;
- },
-
- loadImage: function(url, callback, context, crossOrigin) {
- if (!url) {
- callback && callback.call(context, url);
- return;
- }
- var img = fabric.util.createImage();
-
- var onLoadCallback = function () {
- callback && callback.call(context, img);
- img = img.onload = img.onerror = null;
- };
- img.onload = onLoadCallback;
-
- img.onerror = function() {
- fabric.log('Error loading ' + img.src);
- callback && callback.call(context, null, true);
- img = img.onload = img.onerror = null;
- };
-
-
-
-
- if (url.indexOf('data') !== 0 && crossOrigin) {
- img.crossOrigin = crossOrigin;
- }
-
-
-
- if (url.substring(0,14) === 'data:c_image/svg') {
- img.onload = null;
- fabric.util.loadImageInDom(img, onLoadCallback);
- }
- img.src = url;
- },
-
- loadImageInDom: function(img, onLoadCallback) {
- var div = fabric.document.createElement('div');
- div.style.width = div.style.height = '1px';
- div.style.left = div.style.top = '-100%';
- div.style.position = 'absolute';
- div.appendChild(img);
- fabric.document.querySelector('body').appendChild(div);
-
- img.onload = function () {
- onLoadCallback();
- div.parentNode.removeChild(div);
- div = null;
- };
- },
-
- enlivenObjects: function(objects, callback, namespace, reviver) {
- objects = objects || [];
- function onLoaded() {
- if (++numLoadedObjects === numTotalObjects) {
- callback && callback(enlivenedObjects);
- }
- }
- var enlivenedObjects = [],
- numLoadedObjects = 0,
- numTotalObjects = objects.length;
- if (!numTotalObjects) {
- callback && callback(enlivenedObjects);
- return;
- }
- objects.forEach(function (o, index) {
-
- if (!o || !o.type) {
- onLoaded();
- return;
- }
- var klass = fabric.util.getKlass(o.type, namespace);
- klass.fromObject(o, function (obj, error) {
- error || (enlivenedObjects[index] = obj);
- reviver && reviver(o, obj, error);
- onLoaded();
- });
- });
- },
-
- enlivenPatterns: function(patterns, callback) {
- patterns = patterns || [];
- function onLoaded() {
- if (++numLoadedPatterns === numPatterns) {
- callback && callback(enlivenedPatterns);
- }
- }
- var enlivenedPatterns = [],
- numLoadedPatterns = 0,
- numPatterns = patterns.length;
- if (!numPatterns) {
- callback && callback(enlivenedPatterns);
- return;
- }
- patterns.forEach(function (p, index) {
- if (p && p.source) {
- new fabric.Pattern(p, function(pattern) {
- enlivenedPatterns[index] = pattern;
- onLoaded();
- });
- }
- else {
- enlivenedPatterns[index] = p;
- onLoaded();
- }
- });
- },
-
- groupSVGElements: function(elements, options, path) {
- var object;
- if (elements.length === 1) {
- return elements[0];
- }
- if (options) {
- if (options.width && options.height) {
- options.centerPoint = {
- x: options.width / 2,
- y: options.height / 2
- };
- }
- else {
- delete options.width;
- delete options.height;
- }
- }
- object = new fabric.Group(elements, options);
- if (typeof path !== 'undefined') {
- object.sourcePath = path;
- }
- return object;
- },
-
- populateWithProperties: function(source, destination, properties) {
- if (properties && Object.prototype.toString.call(properties) === '[object Array]') {
- for (var i = 0, len = properties.length; i < len; i++) {
- if (properties[i] in source) {
- destination[properties[i]] = source[properties[i]];
- }
- }
- }
- },
-
- drawDashedLine: function(ctx, x, y, x2, y2, da) {
- var dx = x2 - x,
- dy = y2 - y,
- len = sqrt(dx * dx + dy * dy),
- rot = atan2(dy, dx),
- dc = da.length,
- di = 0,
- draw = true;
- ctx.save();
- ctx.translate(x, y);
- ctx.moveTo(0, 0);
- ctx.rotate(rot);
- x = 0;
- while (len > x) {
- x += da[di++ % dc];
- if (x > len) {
- x = len;
- }
- ctx[draw ? 'lineTo' : 'moveTo'](x, 0);
- draw = !draw;
- }
- ctx.restore();
- },
-
- createCanvasElement: function() {
- return fabric.document.createElement('canvas');
- },
-
- createImage: function() {
- return fabric.document.createElement('img');
- },
-
- clipContext: function(receiver, ctx) {
- ctx.save();
- ctx.beginPath();
- receiver.clipTo(ctx);
- ctx.clip();
- },
-
- multiplyTransformMatrices: function(a, b, is2x2) {
-
- return [
- a[0] * b[0] + a[2] * b[1],
- a[1] * b[0] + a[3] * b[1],
- a[0] * b[2] + a[2] * b[3],
- a[1] * b[2] + a[3] * b[3],
- is2x2 ? 0 : a[0] * b[4] + a[2] * b[5] + a[4],
- is2x2 ? 0 : a[1] * b[4] + a[3] * b[5] + a[5]
- ];
- },
-
- qrDecompose: function(a) {
- var angle = atan2(a[1], a[0]),
- denom = pow(a[0], 2) + pow(a[1], 2),
- scaleX = sqrt(denom),
- scaleY = (a[0] * a[3] - a[2] * a [1]) / scaleX,
- skewX = atan2(a[0] * a[2] + a[1] * a [3], denom);
- return {
- angle: angle / PiBy180,
- scaleX: scaleX,
- scaleY: scaleY,
- skewX: skewX / PiBy180,
- skewY: 0,
- translateX: a[4],
- translateY: a[5]
- };
- },
- customTransformMatrix: function(scaleX, scaleY, skewX) {
- var skewMatrixX = [1, 0, abs(Math.tan(skewX * PiBy180)), 1],
- scaleMatrix = [abs(scaleX), 0, 0, abs(scaleY)];
- return fabric.util.multiplyTransformMatrices(scaleMatrix, skewMatrixX, true);
- },
- resetObjectTransform: function (target) {
- target.scaleX = 1;
- target.scaleY = 1;
- target.skewX = 0;
- target.skewY = 0;
- target.flipX = false;
- target.flipY = false;
- target.rotate(0);
- },
-
- getFunctionBody: function(fn) {
- return (String(fn).match(/function[^{]*\{([\s\S]*)\}/) || {})[1];
- },
-
- isTransparent: function(ctx, x, y, tolerance) {
-
-
- if (tolerance > 0) {
- if (x > tolerance) {
- x -= tolerance;
- }
- else {
- x = 0;
- }
- if (y > tolerance) {
- y -= tolerance;
- }
- else {
- y = 0;
- }
- }
- var _isTransparent = true, i, temp,
- imageData = ctx.getImageData(x, y, (tolerance * 2) || 1, (tolerance * 2) || 1),
- l = imageData.data.length;
-
- for (i = 3; i < l; i += 4) {
- temp = imageData.data[i];
- _isTransparent = temp <= 0;
- if (_isTransparent === false) {
- break;
- }
- }
- imageData = null;
- return _isTransparent;
- },
-
- parsePreserveAspectRatioAttribute: function(attribute) {
- var meetOrSlice = 'meet', alignX = 'Mid', alignY = 'Mid',
- aspectRatioAttrs = attribute.split(' '), align;
- if (aspectRatioAttrs && aspectRatioAttrs.length) {
- meetOrSlice = aspectRatioAttrs.pop();
- if (meetOrSlice !== 'meet' && meetOrSlice !== 'slice') {
- align = meetOrSlice;
- meetOrSlice = 'meet';
- }
- else if (aspectRatioAttrs.length) {
- align = aspectRatioAttrs.pop();
- }
- }
-
- alignX = align !== 'none' ? align.slice(1, 4) : 'none';
- alignY = align !== 'none' ? align.slice(5, 8) : 'none';
- return {
- meetOrSlice: meetOrSlice,
- alignX: alignX,
- alignY: alignY
- };
- },
-
- clearFabricFontCache: function(fontFamily) {
- fontFamily = (fontFamily || '').toLowerCase();
- if (!fontFamily) {
- fabric.charWidthsCache = { };
- }
- else if (fabric.charWidthsCache[fontFamily]) {
- delete fabric.charWidthsCache[fontFamily];
- }
- },
-
- limitDimsByArea: function(ar, maximumArea) {
- var roughWidth = Math.sqrt(maximumArea * ar),
- perfLimitSizeY = Math.floor(maximumArea / roughWidth);
- return { x: Math.floor(roughWidth), y: perfLimitSizeY };
- },
- capValue: function(min, value, max) {
- return Math.max(min, Math.min(value, max));
- },
- findScaleToFit: function(source, destination) {
- return Math.min(destination.width / source.width, destination.height / source.height);
- },
- findScaleToCover: function(source, destination) {
- return Math.max(destination.width / source.width, destination.height / source.height);
- }
- };
- })(typeof exports !== 'undefined' ? exports : this);
- (function() {
- var arcToSegmentsCache = { },
- segmentToBezierCache = { },
- boundsOfCurveCache = { },
- _join = Array.prototype.join;
-
- function arcToSegments(toX, toY, rx, ry, large, sweep, rotateX) {
- var argsString = _join.call(arguments);
- if (arcToSegmentsCache[argsString]) {
- return arcToSegmentsCache[argsString];
- }
- var PI = Math.PI, th = rotateX * PI / 180,
- sinTh = fabric.util.sin(th),
- cosTh = fabric.util.cos(th),
- fromX = 0, fromY = 0;
- rx = Math.abs(rx);
- ry = Math.abs(ry);
- var px = -cosTh * toX * 0.5 - sinTh * toY * 0.5,
- py = -cosTh * toY * 0.5 + sinTh * toX * 0.5,
- rx2 = rx * rx, ry2 = ry * ry, py2 = py * py, px2 = px * px,
- pl = rx2 * ry2 - rx2 * py2 - ry2 * px2,
- root = 0;
- if (pl < 0) {
- var s = Math.sqrt(1 - pl / (rx2 * ry2));
- rx *= s;
- ry *= s;
- }
- else {
- root = (large === sweep ? -1.0 : 1.0) *
- Math.sqrt( pl / (rx2 * py2 + ry2 * px2));
- }
- var cx = root * rx * py / ry,
- cy = -root * ry * px / rx,
- cx1 = cosTh * cx - sinTh * cy + toX * 0.5,
- cy1 = sinTh * cx + cosTh * cy + toY * 0.5,
- mTheta = calcVectorAngle(1, 0, (px - cx) / rx, (py - cy) / ry),
- dtheta = calcVectorAngle((px - cx) / rx, (py - cy) / ry, (-px - cx) / rx, (-py - cy) / ry);
- if (sweep === 0 && dtheta > 0) {
- dtheta -= 2 * PI;
- }
- else if (sweep === 1 && dtheta < 0) {
- dtheta += 2 * PI;
- }
-
- var segments = Math.ceil(Math.abs(dtheta / PI * 2)),
- result = [], mDelta = dtheta / segments,
- mT = 8 / 3 * Math.sin(mDelta / 4) * Math.sin(mDelta / 4) / Math.sin(mDelta / 2),
- th3 = mTheta + mDelta;
- for (var i = 0; i < segments; i++) {
- result[i] = segmentToBezier(mTheta, th3, cosTh, sinTh, rx, ry, cx1, cy1, mT, fromX, fromY);
- fromX = result[i][4];
- fromY = result[i][5];
- mTheta = th3;
- th3 += mDelta;
- }
- arcToSegmentsCache[argsString] = result;
- return result;
- }
- function segmentToBezier(th2, th3, cosTh, sinTh, rx, ry, cx1, cy1, mT, fromX, fromY) {
- var argsString2 = _join.call(arguments);
- if (segmentToBezierCache[argsString2]) {
- return segmentToBezierCache[argsString2];
- }
- var costh2 = fabric.util.cos(th2),
- sinth2 = fabric.util.sin(th2),
- costh3 = fabric.util.cos(th3),
- sinth3 = fabric.util.sin(th3),
- toX = cosTh * rx * costh3 - sinTh * ry * sinth3 + cx1,
- toY = sinTh * rx * costh3 + cosTh * ry * sinth3 + cy1,
- cp1X = fromX + mT * ( -cosTh * rx * sinth2 - sinTh * ry * costh2),
- cp1Y = fromY + mT * ( -sinTh * rx * sinth2 + cosTh * ry * costh2),
- cp2X = toX + mT * ( cosTh * rx * sinth3 + sinTh * ry * costh3),
- cp2Y = toY + mT * ( sinTh * rx * sinth3 - cosTh * ry * costh3);
- segmentToBezierCache[argsString2] = [
- cp1X, cp1Y,
- cp2X, cp2Y,
- toX, toY
- ];
- return segmentToBezierCache[argsString2];
- }
-
- function calcVectorAngle(ux, uy, vx, vy) {
- var ta = Math.atan2(uy, ux),
- tb = Math.atan2(vy, vx);
- if (tb >= ta) {
- return tb - ta;
- }
- else {
- return 2 * Math.PI - (ta - tb);
- }
- }
-
- fabric.util.drawArc = function(ctx, fx, fy, coords) {
- var rx = coords[0],
- ry = coords[1],
- rot = coords[2],
- large = coords[3],
- sweep = coords[4],
- tx = coords[5],
- ty = coords[6],
- segs = [[], [], [], []],
- segsNorm = arcToSegments(tx - fx, ty - fy, rx, ry, large, sweep, rot);
- for (var i = 0, len = segsNorm.length; i < len; i++) {
- segs[i][0] = segsNorm[i][0] + fx;
- segs[i][1] = segsNorm[i][1] + fy;
- segs[i][2] = segsNorm[i][2] + fx;
- segs[i][3] = segsNorm[i][3] + fy;
- segs[i][4] = segsNorm[i][4] + fx;
- segs[i][5] = segsNorm[i][5] + fy;
- ctx.bezierCurveTo.apply(ctx, segs[i]);
- }
- };
-
- fabric.util.getBoundsOfArc = function(fx, fy, rx, ry, rot, large, sweep, tx, ty) {
- var fromX = 0, fromY = 0, bound, bounds = [],
- segs = arcToSegments(tx - fx, ty - fy, rx, ry, large, sweep, rot);
- for (var i = 0, len = segs.length; i < len; i++) {
- bound = getBoundsOfCurve(fromX, fromY, segs[i][0], segs[i][1], segs[i][2], segs[i][3], segs[i][4], segs[i][5]);
- bounds.push({ x: bound[0].x + fx, y: bound[0].y + fy });
- bounds.push({ x: bound[1].x + fx, y: bound[1].y + fy });
- fromX = segs[i][4];
- fromY = segs[i][5];
- }
- return bounds;
- };
-
-
- function getBoundsOfCurve(x0, y0, x1, y1, x2, y2, x3, y3) {
- var argsString = _join.call(arguments);
- if (boundsOfCurveCache[argsString]) {
- return boundsOfCurveCache[argsString];
- }
- var sqrt = Math.sqrt,
- min = Math.min, max = Math.max,
- abs = Math.abs, tvalues = [],
- bounds = [[], []],
- a, b, c, t, t1, t2, b2ac, sqrtb2ac;
- b = 6 * x0 - 12 * x1 + 6 * x2;
- a = -3 * x0 + 9 * x1 - 9 * x2 + 3 * x3;
- c = 3 * x1 - 3 * x0;
- for (var i = 0; i < 2; ++i) {
- if (i > 0) {
- b = 6 * y0 - 12 * y1 + 6 * y2;
- a = -3 * y0 + 9 * y1 - 9 * y2 + 3 * y3;
- c = 3 * y1 - 3 * y0;
- }
- if (abs(a) < 1e-12) {
- if (abs(b) < 1e-12) {
- continue;
- }
- t = -c / b;
- if (0 < t && t < 1) {
- tvalues.push(t);
- }
- continue;
- }
- b2ac = b * b - 4 * c * a;
- if (b2ac < 0) {
- continue;
- }
- sqrtb2ac = sqrt(b2ac);
- t1 = (-b + sqrtb2ac) / (2 * a);
- if (0 < t1 && t1 < 1) {
- tvalues.push(t1);
- }
- t2 = (-b - sqrtb2ac) / (2 * a);
- if (0 < t2 && t2 < 1) {
- tvalues.push(t2);
- }
- }
- var x, y, j = tvalues.length, jlen = j, mt;
- while (j--) {
- t = tvalues[j];
- mt = 1 - t;
- x = (mt * mt * mt * x0) + (3 * mt * mt * t * x1) + (3 * mt * t * t * x2) + (t * t * t * x3);
- bounds[0][j] = x;
- y = (mt * mt * mt * y0) + (3 * mt * mt * t * y1) + (3 * mt * t * t * y2) + (t * t * t * y3);
- bounds[1][j] = y;
- }
- bounds[0][jlen] = x0;
- bounds[1][jlen] = y0;
- bounds[0][jlen + 1] = x3;
- bounds[1][jlen + 1] = y3;
- var result = [
- {
- x: min.apply(null, bounds[0]),
- y: min.apply(null, bounds[1])
- },
- {
- x: max.apply(null, bounds[0]),
- y: max.apply(null, bounds[1])
- }
- ];
- boundsOfCurveCache[argsString] = result;
- return result;
- }
- fabric.util.getBoundsOfCurve = getBoundsOfCurve;
- })();
- (function() {
- var slice = Array.prototype.slice;
-
- function invoke(array, method) {
- var args = slice.call(arguments, 2), result = [];
- for (var i = 0, len = array.length; i < len; i++) {
- result[i] = args.length ? array[i][method].apply(array[i], args) : array[i][method].call(array[i]);
- }
- return result;
- }
-
- function max(array, byProperty) {
- return find(array, byProperty, function(value1, value2) {
- return value1 >= value2;
- });
- }
-
- function min(array, byProperty) {
- return find(array, byProperty, function(value1, value2) {
- return value1 < value2;
- });
- }
-
- function fill(array, value) {
- var k = array.length;
- while (k--) {
- array[k] = value;
- }
- return array;
- }
-
- function find(array, byProperty, condition) {
- if (!array || array.length === 0) {
- return;
- }
- var i = array.length - 1,
- result = byProperty ? array[i][byProperty] : array[i];
- if (byProperty) {
- while (i--) {
- if (condition(array[i][byProperty], result)) {
- result = array[i][byProperty];
- }
- }
- }
- else {
- while (i--) {
- if (condition(array[i], result)) {
- result = array[i];
- }
- }
- }
- return result;
- }
-
- fabric.util.array = {
- fill: fill,
- invoke: invoke,
- min: min,
- max: max
- };
- })();
- (function() {
-
- function extend(destination, source, deep) {
-
-
-
- if (deep) {
- if (!fabric.isLikelyNode && source instanceof Element) {
-
- destination = source;
- }
- else if (source instanceof Array) {
- destination = [];
- for (var i = 0, len = source.length; i < len; i++) {
- destination[i] = extend({ }, source[i], deep);
- }
- }
- else if (source && typeof source === 'object') {
- for (var property in source) {
- if (source.hasOwnProperty(property)) {
- destination[property] = extend({ }, source[property], deep);
- }
- }
- }
- else {
-
- destination = source;
- }
- }
- else {
- for (var property in source) {
- destination[property] = source[property];
- }
- }
- return destination;
- }
-
- function clone(object, deep) {
- return extend({ }, object, deep);
- }
-
- fabric.util.object = {
- extend: extend,
- clone: clone
- };
- fabric.util.object.extend(fabric.util, fabric.Observable);
- })();
- (function() {
-
- function camelize(string) {
- return string.replace(/-+(.)?/g, function(match, character) {
- return character ? character.toUpperCase() : '';
- });
- }
-
- function capitalize(string, firstLetterOnly) {
- return string.charAt(0).toUpperCase() +
- (firstLetterOnly ? string.slice(1) : string.slice(1).toLowerCase());
- }
-
- function escapeXml(string) {
- return string.replace(/&/g, '&')
- .replace(/"/g, '"')
- .replace(/'/g, ''')
- .replace(/</g, '<')
- .replace(/>/g, '>');
- }
-
- function graphemeSplit(textstring) {
- var i = 0, chr, graphemes = [];
- for (i = 0, chr; i < textstring.length; i++) {
- if ((chr = getWholeChar(textstring, i)) === false) {
- continue;
- }
- graphemes.push(chr);
- }
- return graphemes;
- }
-
- function getWholeChar(str, i) {
- var code = str.charCodeAt(i);
- if (isNaN(code)) {
- return '';
- }
- if (code < 0xD800 || code > 0xDFFF) {
- return str.charAt(i);
- }
-
-
- if (0xD800 <= code && code <= 0xDBFF) {
- if (str.length <= (i + 1)) {
- throw 'High surrogate without following low surrogate';
- }
- var next = str.charCodeAt(i + 1);
- if (0xDC00 > next || next > 0xDFFF) {
- throw 'High surrogate without following low surrogate';
- }
- return str.charAt(i) + str.charAt(i + 1);
- }
-
- if (i === 0) {
- throw 'Low surrogate without preceding high surrogate';
- }
- var prev = str.charCodeAt(i - 1);
-
-
- if (0xD800 > prev || prev > 0xDBFF) {
- throw 'Low surrogate without preceding high surrogate';
- }
-
-
- return false;
- }
-
- fabric.util.string = {
- camelize: camelize,
- capitalize: capitalize,
- escapeXml: escapeXml,
- graphemeSplit: graphemeSplit
- };
- })();
- (function() {
- var slice = Array.prototype.slice, emptyFunction = function() { },
- IS_DONTENUM_BUGGY = (function() {
- for (var p in { toString: 1 }) {
- if (p === 'toString') {
- return false;
- }
- }
- return true;
- })(),
-
- addMethods = function(klass, source, parent) {
- for (var property in source) {
- if (property in klass.prototype &&
- typeof klass.prototype[property] === 'function' &&
- (source[property] + '').indexOf('callSuper') > -1) {
- klass.prototype[property] = (function(property) {
- return function() {
- var superclass = this.constructor.superclass;
- this.constructor.superclass = parent;
- var returnValue = source[property].apply(this, arguments);
- this.constructor.superclass = superclass;
- if (property !== 'initialize') {
- return returnValue;
- }
- };
- })(property);
- }
- else {
- klass.prototype[property] = source[property];
- }
- if (IS_DONTENUM_BUGGY) {
- if (source.toString !== Object.prototype.toString) {
- klass.prototype.toString = source.toString;
- }
- if (source.valueOf !== Object.prototype.valueOf) {
- klass.prototype.valueOf = source.valueOf;
- }
- }
- }
- };
- function Subclass() { }
- function callSuper(methodName) {
- var parentMethod = null,
- _this = this;
-
- while (_this.constructor.superclass) {
- var superClassMethod = _this.constructor.superclass.prototype[methodName];
- if (_this[methodName] !== superClassMethod) {
- parentMethod = superClassMethod;
- break;
- }
-
- _this = _this.constructor.superclass.prototype;
- }
- if (!parentMethod) {
- return console.log('tried to callSuper ' + methodName + ', method not found in prototype chain', this);
- }
- return (arguments.length > 1)
- ? parentMethod.apply(this, slice.call(arguments, 1))
- : parentMethod.call(this);
- }
-
- function createClass() {
- var parent = null,
- properties = slice.call(arguments, 0);
- if (typeof properties[0] === 'function') {
- parent = properties.shift();
- }
- function klass() {
- this.initialize.apply(this, arguments);
- }
- klass.superclass = parent;
- klass.subclasses = [];
- if (parent) {
- Subclass.prototype = parent.prototype;
- klass.prototype = new Subclass();
- parent.subclasses.push(klass);
- }
- for (var i = 0, length = properties.length; i < length; i++) {
- addMethods(klass, properties[i], parent);
- }
- if (!klass.prototype.initialize) {
- klass.prototype.initialize = emptyFunction;
- }
- klass.prototype.constructor = klass;
- klass.prototype.callSuper = callSuper;
- return klass;
- }
- fabric.util.createClass = createClass;
- })();
- (function () {
-
- function setStyle(element, styles) {
- var elementStyle = element.style;
- if (!elementStyle) {
- return element;
- }
- if (typeof styles === 'string') {
- element.style.cssText += ';' + styles;
- return styles.indexOf('opacity') > -1
- ? setOpacity(element, styles.match(/opacity:\s*(\d?\.?\d*)/)[1])
- : element;
- }
- for (var property in styles) {
- if (property === 'opacity') {
- setOpacity(element, styles[property]);
- }
- else {
- var normalizedProperty = (property === 'float' || property === 'cssFloat')
- ? (typeof elementStyle.styleFloat === 'undefined' ? 'cssFloat' : 'styleFloat')
- : property;
- elementStyle[normalizedProperty] = styles[property];
- }
- }
- return element;
- }
- var parseEl = fabric.document.createElement('div'),
- supportsOpacity = typeof parseEl.style.opacity === 'string',
- supportsFilters = typeof parseEl.style.filter === 'string',
- reOpacity = /alpha\s*\(\s*opacity\s*=\s*([^\)]+)\)/,
-
- setOpacity = function (element) { return element; };
- if (supportsOpacity) {
-
- setOpacity = function(element, value) {
- element.style.opacity = value;
- return element;
- };
- }
- else if (supportsFilters) {
-
- setOpacity = function(element, value) {
- var es = element.style;
- if (element.currentStyle && !element.currentStyle.hasLayout) {
- es.zoom = 1;
- }
- if (reOpacity.test(es.filter)) {
- value = value >= 0.9999 ? '' : ('alpha(opacity=' + (value * 100) + ')');
- es.filter = es.filter.replace(reOpacity, value);
- }
- else {
- es.filter += ' alpha(opacity=' + (value * 100) + ')';
- }
- return element;
- };
- }
- fabric.util.setStyle = setStyle;
- })();
- (function() {
- var _slice = Array.prototype.slice;
-
- function getById(id) {
- return typeof id === 'string' ? fabric.document.getElementById(id) : id;
- }
- var sliceCanConvertNodelists,
-
- toArray = function(arrayLike) {
- return _slice.call(arrayLike, 0);
- };
- try {
- sliceCanConvertNodelists = toArray(fabric.document.childNodes) instanceof Array;
- }
- catch (err) { }
- if (!sliceCanConvertNodelists) {
- toArray = function(arrayLike) {
- var arr = new Array(arrayLike.length), i = arrayLike.length;
- while (i--) {
- arr[i] = arrayLike[i];
- }
- return arr;
- };
- }
-
- function makeElement(tagName, attributes) {
- var el = fabric.document.createElement(tagName);
- for (var prop in attributes) {
- if (prop === 'class') {
- el.className = attributes[prop];
- }
- else if (prop === 'for') {
- el.htmlFor = attributes[prop];
- }
- else {
- el.setAttribute(prop, attributes[prop]);
- }
- }
- return el;
- }
-
- function addClass(element, className) {
- if (element && (' ' + element.className + ' ').indexOf(' ' + className + ' ') === -1) {
- element.className += (element.className ? ' ' : '') + className;
- }
- }
-
- function wrapElement(element, wrapper, attributes) {
- if (typeof wrapper === 'string') {
- wrapper = makeElement(wrapper, attributes);
- }
- if (element.parentNode) {
- element.parentNode.replaceChild(wrapper, element);
- }
- wrapper.appendChild(element);
- return wrapper;
- }
-
- function getScrollLeftTop(element) {
- var left = 0,
- top = 0,
- docElement = fabric.document.documentElement,
- body = fabric.document.body || {
- scrollLeft: 0, scrollTop: 0
- };
-
-
-
-
- while (element && (element.parentNode || element.host)) {
-
- element = element.parentNode || element.host;
- if (element === fabric.document) {
- left = body.scrollLeft || docElement.scrollLeft || 0;
- top = body.scrollTop || docElement.scrollTop || 0;
- }
- else {
- left += element.scrollLeft || 0;
- top += element.scrollTop || 0;
- }
- if (element.nodeType === 1 && element.style.position === 'fixed') {
- break;
- }
- }
- return { left: left, top: top };
- }
-
- function getElementOffset(element) {
- var docElem,
- doc = element && element.ownerDocument,
- box = { left: 0, top: 0 },
- offset = { left: 0, top: 0 },
- scrollLeftTop,
- offsetAttributes = {
- borderLeftWidth: 'left',
- borderTopWidth: 'top',
- paddingLeft: 'left',
- paddingTop: 'top'
- };
- if (!doc) {
- return offset;
- }
- for (var attr in offsetAttributes) {
- offset[offsetAttributes[attr]] += parseInt(getElementStyle(element, attr), 10) || 0;
- }
- docElem = doc.documentElement;
- if ( typeof element.getBoundingClientRect !== 'undefined' ) {
- box = element.getBoundingClientRect();
- }
- scrollLeftTop = getScrollLeftTop(element);
- return {
- left: box.left + scrollLeftTop.left - (docElem.clientLeft || 0) + offset.left,
- top: box.top + scrollLeftTop.top - (docElem.clientTop || 0) + offset.top
- };
- }
-
- var getElementStyle;
- if (fabric.document.defaultView && fabric.document.defaultView.getComputedStyle) {
- getElementStyle = function(element, attr) {
- var style = fabric.document.defaultView.getComputedStyle(element, null);
- return style ? style[attr] : undefined;
- };
- }
- else {
- getElementStyle = function(element, attr) {
- var value = element.style[attr];
- if (!value && element.currentStyle) {
- value = element.currentStyle[attr];
- }
- return value;
- };
- }
- (function () {
- var style = fabric.document.documentElement.style,
- selectProp = 'userSelect' in style
- ? 'userSelect'
- : 'MozUserSelect' in style
- ? 'MozUserSelect'
- : 'WebkitUserSelect' in style
- ? 'WebkitUserSelect'
- : 'KhtmlUserSelect' in style
- ? 'KhtmlUserSelect'
- : '';
-
- function makeElementUnselectable(element) {
- if (typeof element.onselectstart !== 'undefined') {
- element.onselectstart = fabric.util.falseFunction;
- }
- if (selectProp) {
- element.style[selectProp] = 'none';
- }
- else if (typeof element.unselectable === 'string') {
- element.unselectable = 'on';
- }
- return element;
- }
-
- function makeElementSelectable(element) {
- if (typeof element.onselectstart !== 'undefined') {
- element.onselectstart = null;
- }
- if (selectProp) {
- element.style[selectProp] = '';
- }
- else if (typeof element.unselectable === 'string') {
- element.unselectable = '';
- }
- return element;
- }
- fabric.util.makeElementUnselectable = makeElementUnselectable;
- fabric.util.makeElementSelectable = makeElementSelectable;
- })();
- (function() {
-
- function getScript(url, callback) {
- var headEl = fabric.document.getElementsByTagName('head')[0],
- scriptEl = fabric.document.createElement('script'),
- loading = true;
-
- scriptEl.onload = scriptEl.onreadystatechange = function(e) {
- if (loading) {
- if (typeof this.readyState === 'string' &&
- this.readyState !== 'loaded' &&
- this.readyState !== 'complete') {
- return;
- }
- loading = false;
- callback(e || fabric.window.event);
- scriptEl = scriptEl.onload = scriptEl.onreadystatechange = null;
- }
- };
- scriptEl.src = url;
- headEl.appendChild(scriptEl);
-
-
- }
- fabric.util.getScript = getScript;
- })();
- function getNodeCanvas(element) {
- var impl = fabric.jsdomImplForWrapper(element);
- return impl._canvas || impl._image;
- };
- fabric.util.getById = getById;
- fabric.util.toArray = toArray;
- fabric.util.makeElement = makeElement;
- fabric.util.addClass = addClass;
- fabric.util.wrapElement = wrapElement;
- fabric.util.getScrollLeftTop = getScrollLeftTop;
- fabric.util.getElementOffset = getElementOffset;
- fabric.util.getElementStyle = getElementStyle;
- fabric.util.getNodeCanvas = getNodeCanvas;
- })();
- (function() {
- function addParamToUrl(url, param) {
- return url + (/\?/.test(url) ? '&' : '?') + param;
- }
- var makeXHR = (function() {
- var factories = [
- function() { return new ActiveXObject('Microsoft.XMLHTTP'); },
- function() { return new ActiveXObject('Msxml2.XMLHTTP'); },
- function() { return new ActiveXObject('Msxml2.XMLHTTP.3.0'); },
- function() { return new XMLHttpRequest(); }
- ];
- for (var i = factories.length; i--; ) {
- try {
- var req = factories[i]();
- if (req) {
- return factories[i];
- }
- }
- catch (err) { }
- }
- })();
- function emptyFn() { }
-
- function request(url, options) {
- options || (options = { });
- var method = options.method ? options.method.toUpperCase() : 'GET',
- onComplete = options.onComplete || function() { },
- xhr = makeXHR(),
- body = options.body || options.parameters;
-
- xhr.onreadystatechange = function() {
- if (xhr.readyState === 4) {
- onComplete(xhr);
- xhr.onreadystatechange = emptyFn;
- }
- };
- if (method === 'GET') {
- body = null;
- if (typeof options.parameters === 'string') {
- url = addParamToUrl(url, options.parameters);
- }
- }
- xhr.open(method, url, true);
- if (method === 'POST' || method === 'PUT') {
- xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
- }
- xhr.send(body);
- return xhr;
- }
- fabric.util.request = request;
- })();
- fabric.log = function() { };
- fabric.warn = function() { };
- if (typeof console !== 'undefined') {
- ['log', 'warn'].forEach(function(methodName) {
- if (typeof console[methodName] !== 'undefined' &&
- typeof console[methodName].apply === 'function') {
- fabric[methodName] = function() {
- return console[methodName].apply(console, arguments);
- };
- }
- });
- }
- (function(global) {
- 'use strict';
-
- var fabric = global.fabric || (global.fabric = { });
- if (fabric.Point) {
- fabric.warn('fabric.Point is already defined');
- return;
- }
- fabric.Point = Point;
-
- function Point(x, y) {
- this.x = x;
- this.y = y;
- }
- Point.prototype = {
- type: 'point',
- constructor: Point,
- /**
- * Adds another point to this one and returns another one
- * @param {fabric.Point} that
- * @return {fabric.Point} new Point instance with added values
- */
- add: function (that) {
- return new Point(this.x + that.x, this.y + that.y);
- },
- /**
- * Adds another point to this one
- * @param {fabric.Point} that
- * @return {fabric.Point} thisArg
- * @chainable
- */
- addEquals: function (that) {
- this.x += that.x;
- this.y += that.y;
- return this;
- },
- /**
- * Adds value to this point and returns a new one
- * @param {Number} scalar
- * @return {fabric.Point} new Point with added value
- */
- scalarAdd: function (scalar) {
- return new Point(this.x + scalar, this.y + scalar);
- },
- /**
- * Adds value to this point
- * @param {Number} scalar
- * @return {fabric.Point} thisArg
- * @chainable
- */
- scalarAddEquals: function (scalar) {
- this.x += scalar;
- this.y += scalar;
- return this;
- },
- /**
- * Subtracts another point from this point and returns a new one
- * @param {fabric.Point} that
- * @return {fabric.Point} new Point object with subtracted values
- */
- subtract: function (that) {
- return new Point(this.x - that.x, this.y - that.y);
- },
- /**
- * Subtracts another point from this point
- * @param {fabric.Point} that
- * @return {fabric.Point} thisArg
- * @chainable
- */
- subtractEquals: function (that) {
- this.x -= that.x;
- this.y -= that.y;
- return this;
- },
- /**
- * Subtracts value from this point and returns a new one
- * @param {Number} scalar
- * @return {fabric.Point}
- */
- scalarSubtract: function (scalar) {
- return new Point(this.x - scalar, this.y - scalar);
- },
- /**
- * Subtracts value from this point
- * @param {Number} scalar
- * @return {fabric.Point} thisArg
- * @chainable
- */
- scalarSubtractEquals: function (scalar) {
- this.x -= scalar;
- this.y -= scalar;
- return this;
- },
- /**
- * Multiplies this point by a value and returns a new one
- * TODO: rename in scalarMultiply in 2.0
- * @param {Number} scalar
- * @return {fabric.Point}
- */
- multiply: function (scalar) {
- return new Point(this.x * scalar, this.y * scalar);
- },
- /**
- * Multiplies this point by a value
- * TODO: rename in scalarMultiplyEquals in 2.0
- * @param {Number} scalar
- * @return {fabric.Point} thisArg
- * @chainable
- */
- multiplyEquals: function (scalar) {
- this.x *= scalar;
- this.y *= scalar;
- return this;
- },
- /**
- * Divides this point by a value and returns a new one
- * TODO: rename in scalarDivide in 2.0
- * @param {Number} scalar
- * @return {fabric.Point}
- */
- divide: function (scalar) {
- return new Point(this.x / scalar, this.y / scalar);
- },
-
- divideEquals: function (scalar) {
- this.x /= scalar;
- this.y /= scalar;
- return this;
- },
-
- eq: function (that) {
- return (this.x === that.x && this.y === that.y);
- },
-
- lt: function (that) {
- return (this.x < that.x && this.y < that.y);
- },
-
- lte: function (that) {
- return (this.x <= that.x && this.y <= that.y);
- },
-
- gt: function (that) {
- return (this.x > that.x && this.y > that.y);
- },
-
- gte: function (that) {
- return (this.x >= that.x && this.y >= that.y);
- },
-
- lerp: function (that, t) {
- if (typeof t === 'undefined') {
- t = 0.5;
- }
- t = Math.max(Math.min(1, t), 0);
- return new Point(this.x + (that.x - this.x) * t, this.y + (that.y - this.y) * t);
- },
-
- distanceFrom: function (that) {
- var dx = this.x - that.x,
- dy = this.y - that.y;
- return Math.sqrt(dx * dx + dy * dy);
- },
-
- midPointFrom: function (that) {
- return this.lerp(that);
- },
-
- min: function (that) {
- return new Point(Math.min(this.x, that.x), Math.min(this.y, that.y));
- },
-
- max: function (that) {
- return new Point(Math.max(this.x, that.x), Math.max(this.y, that.y));
- },
-
- toString: function () {
- return this.x + ',' + this.y;
- },
-
- setXY: function (x, y) {
- this.x = x;
- this.y = y;
- return this;
- },
-
- setX: function (x) {
- this.x = x;
- return this;
- },
-
- setY: function (y) {
- this.y = y;
- return this;
- },
-
- setFromPoint: function (that) {
- this.x = that.x;
- this.y = that.y;
- return this;
- },
-
- swap: function (that) {
- var x = this.x,
- y = this.y;
- this.x = that.x;
- this.y = that.y;
- that.x = x;
- that.y = y;
- },
-
- clone: function () {
- return new Point(this.x, this.y);
- }
- };
- })(typeof exports !== 'undefined' ? exports : this);
- (function(global) {
- 'use strict';
-
- var fabric = global.fabric || (global.fabric = { });
- if (fabric.Intersection) {
- fabric.warn('fabric.Intersection is already defined');
- return;
- }
-
- function Intersection(status) {
- this.status = status;
- this.points = [];
- }
- fabric.Intersection = Intersection;
- fabric.Intersection.prototype = {
- constructor: Intersection,
- /**
- * Appends a point to intersection
- * @param {fabric.Point} point
- * @return {fabric.Intersection} thisArg
- * @chainable
- */
- appendPoint: function (point) {
- this.points.push(point);
- return this;
- },
- /**
- * Appends points to intersection
- * @param {Array} points
- * @return {fabric.Intersection} thisArg
- * @chainable
- */
- appendPoints: function (points) {
- this.points = this.points.concat(points);
- return this;
- }
- };
- /**
- * Checks if one line intersects another
- * TODO: rename in intersectSegmentSegment
- * @static
- * @param {fabric.Point} a1
- * @param {fabric.Point} a2
- * @param {fabric.Point} b1
- * @param {fabric.Point} b2
- * @return {fabric.Intersection}
- */
- fabric.Intersection.intersectLineLine = function (a1, a2, b1, b2) {
- var result,
- uaT = (b2.x - b1.x) * (a1.y - b1.y) - (b2.y - b1.y) * (a1.x - b1.x),
- ubT = (a2.x - a1.x) * (a1.y - b1.y) - (a2.y - a1.y) * (a1.x - b1.x),
- uB = (b2.y - b1.y) * (a2.x - a1.x) - (b2.x - b1.x) * (a2.y - a1.y);
- if (uB !== 0) {
- var ua = uaT / uB,
- ub = ubT / uB;
- if (0 <= ua && ua <= 1 && 0 <= ub && ub <= 1) {
- result = new Intersection('Intersection');
- result.appendPoint(new fabric.Point(a1.x + ua * (a2.x - a1.x), a1.y + ua * (a2.y - a1.y)));
- }
- else {
- result = new Intersection();
- }
- }
- else {
- if (uaT === 0 || ubT === 0) {
- result = new Intersection('Coincident');
- }
- else {
- result = new Intersection('Parallel');
- }
- }
- return result;
- };
-
- fabric.Intersection.intersectLinePolygon = function(a1, a2, points) {
- var result = new Intersection(),
- length = points.length,
- b1, b2, inter, i;
- for (i = 0; i < length; i++) {
- b1 = points[i];
- b2 = points[(i + 1) % length];
- inter = Intersection.intersectLineLine(a1, a2, b1, b2);
- result.appendPoints(inter.points);
- }
- if (result.points.length > 0) {
- result.status = 'Intersection';
- }
- return result;
- };
-
- fabric.Intersection.intersectPolygonPolygon = function (points1, points2) {
- var result = new Intersection(),
- length = points1.length, i;
- for (i = 0; i < length; i++) {
- var a1 = points1[i],
- a2 = points1[(i + 1) % length],
- inter = Intersection.intersectLinePolygon(a1, a2, points2);
- result.appendPoints(inter.points);
- }
- if (result.points.length > 0) {
- result.status = 'Intersection';
- }
- return result;
- };
-
- fabric.Intersection.intersectPolygonRectangle = function (points, r1, r2) {
- var min = r1.min(r2),
- max = r1.max(r2),
- topRight = new fabric.Point(max.x, min.y),
- bottomLeft = new fabric.Point(min.x, max.y),
- inter1 = Intersection.intersectLinePolygon(min, topRight, points),
- inter2 = Intersection.intersectLinePolygon(topRight, max, points),
- inter3 = Intersection.intersectLinePolygon(max, bottomLeft, points),
- inter4 = Intersection.intersectLinePolygon(bottomLeft, min, points),
- result = new Intersection();
- result.appendPoints(inter1.points);
- result.appendPoints(inter2.points);
- result.appendPoints(inter3.points);
- result.appendPoints(inter4.points);
- if (result.points.length > 0) {
- result.status = 'Intersection';
- }
- return result;
- };
- })(typeof exports !== 'undefined' ? exports : this);
- (function(global) {
- 'use strict';
- var fabric = global.fabric || (global.fabric = { });
- if (fabric.Color) {
- fabric.warn('fabric.Color is already defined.');
- return;
- }
-
- function Color(color) {
- if (!color) {
- this.setSource([0, 0, 0, 1]);
- }
- else {
- this._tryParsingColor(color);
- }
- }
- fabric.Color = Color;
- fabric.Color.prototype = {
-
- _tryParsingColor: function(color) {
- var source;
- if (color in Color.colorNameMap) {
- color = Color.colorNameMap[color];
- }
- if (color === 'transparent') {
- source = [255, 255, 255, 0];
- }
- if (!source) {
- source = Color.sourceFromHex(color);
- }
- if (!source) {
- source = Color.sourceFromRgb(color);
- }
- if (!source) {
- source = Color.sourceFromHsl(color);
- }
- if (!source) {
-
- source = [0, 0, 0, 1];
- }
- if (source) {
- this.setSource(source);
- }
- },
-
- _rgbToHsl: function(r, g, b) {
- r /= 255; g /= 255; b /= 255;
- var h, s, l,
- max = fabric.util.array.max([r, g, b]),
- min = fabric.util.array.min([r, g, b]);
- l = (max + min) / 2;
- if (max === min) {
- h = s = 0;
- }
- else {
- var d = max - min;
- s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
- switch (max) {
- case r:
- h = (g - b) / d + (g < b ? 6 : 0);
- break;
- case g:
- h = (b - r) / d + 2;
- break;
- case b:
- h = (r - g) / d + 4;
- break;
- }
- h /= 6;
- }
- return [
- Math.round(h * 360),
- Math.round(s * 100),
- Math.round(l * 100)
- ];
- },
-
- getSource: function() {
- return this._source;
- },
-
- setSource: function(source) {
- this._source = source;
- },
-
- toRgb: function() {
- var source = this.getSource();
- return 'rgb(' + source[0] + ',' + source[1] + ',' + source[2] + ')';
- },
-
- toRgba: function() {
- var source = this.getSource();
- return 'rgba(' + source[0] + ',' + source[1] + ',' + source[2] + ',' + source[3] + ')';
- },
-
- toHsl: function() {
- var source = this.getSource(),
- hsl = this._rgbToHsl(source[0], source[1], source[2]);
- return 'hsl(' + hsl[0] + ',' + hsl[1] + '%,' + hsl[2] + '%)';
- },
-
- toHsla: function() {
- var source = this.getSource(),
- hsl = this._rgbToHsl(source[0], source[1], source[2]);
- return 'hsla(' + hsl[0] + ',' + hsl[1] + '%,' + hsl[2] + '%,' + source[3] + ')';
- },
-
- toHex: function() {
- var source = this.getSource(), r, g, b;
- r = source[0].toString(16);
- r = (r.length === 1) ? ('0' + r) : r;
- g = source[1].toString(16);
- g = (g.length === 1) ? ('0' + g) : g;
- b = source[2].toString(16);
- b = (b.length === 1) ? ('0' + b) : b;
- return r.toUpperCase() + g.toUpperCase() + b.toUpperCase();
- },
-
- toHexa: function() {
- var source = this.getSource(), a;
- a = Math.round(source[3] * 255);
- a = a.toString(16);
- a = (a.length === 1) ? ('0' + a) : a;
- return this.toHex() + a.toUpperCase();
- },
-
- getAlpha: function() {
- return this.getSource()[3];
- },
-
- setAlpha: function(alpha) {
- var source = this.getSource();
- source[3] = alpha;
- this.setSource(source);
- return this;
- },
-
- toGrayscale: function() {
- var source = this.getSource(),
- average = parseInt((source[0] * 0.3 + source[1] * 0.59 + source[2] * 0.11).toFixed(0), 10),
- currentAlpha = source[3];
- this.setSource([average, average, average, currentAlpha]);
- return this;
- },
-
- toBlackWhite: function(threshold) {
- var source = this.getSource(),
- average = (source[0] * 0.3 + source[1] * 0.59 + source[2] * 0.11).toFixed(0),
- currentAlpha = source[3];
- threshold = threshold || 127;
- average = (Number(average) < Number(threshold)) ? 0 : 255;
- this.setSource([average, average, average, currentAlpha]);
- return this;
- },
-
- overlayWith: function(otherColor) {
- if (!(otherColor instanceof Color)) {
- otherColor = new Color(otherColor);
- }
- var result = [],
- alpha = this.getAlpha(),
- otherAlpha = 0.5,
- source = this.getSource(),
- otherSource = otherColor.getSource(), i;
- for (i = 0; i < 3; i++) {
- result.push(Math.round((source[i] * (1 - otherAlpha)) + (otherSource[i] * otherAlpha)));
- }
- result[3] = alpha;
- this.setSource(result);
- return this;
- }
- };
-
-
- fabric.Color.reRGBa = /^rgba?\(\s*(\d{1,3}(?:\.\d+)?\%?)\s*,\s*(\d{1,3}(?:\.\d+)?\%?)\s*,\s*(\d{1,3}(?:\.\d+)?\%?)\s*(?:\s*,\s*((?:\d*\.?\d+)?)\s*)?\)$/i;
-
- fabric.Color.reHSLa = /^hsla?\(\s*(\d{1,3})\s*,\s*(\d{1,3}\%)\s*,\s*(\d{1,3}\%)\s*(?:\s*,\s*(\d+(?:\.\d+)?)\s*)?\)$/i;
-
- fabric.Color.reHex = /^#?([0-9a-f]{8}|[0-9a-f]{6}|[0-9a-f]{4}|[0-9a-f]{3})$/i;
-
- fabric.Color.colorNameMap = {
- aliceblue: '#F0F8FF',
- antiquewhite: '#FAEBD7',
- aqua: '#00FFFF',
- aquamarine: '#7FFFD4',
- azure: '#F0FFFF',
- beige: '#F5F5DC',
- bisque: '#FFE4C4',
- black: '#000000',
- blanchedalmond: '#FFEBCD',
- blue: '#0000FF',
- blueviolet: '#8A2BE2',
- brown: '#A52A2A',
- burlywood: '#DEB887',
- cadetblue: '#5F9EA0',
- chartreuse: '#7FFF00',
- chocolate: '#D2691E',
- coral: '#FF7F50',
- cornflowerblue: '#6495ED',
- cornsilk: '#FFF8DC',
- crimson: '#DC143C',
- cyan: '#00FFFF',
- darkblue: '#00008B',
- darkcyan: '#008B8B',
- darkgoldenrod: '#B8860B',
- darkgray: '#A9A9A9',
- darkgrey: '#A9A9A9',
- darkgreen: '#006400',
- darkkhaki: '#BDB76B',
- darkmagenta: '#8B008B',
- darkolivegreen: '#556B2F',
- darkorange: '#FF8C00',
- darkorchid: '#9932CC',
- darkred: '#8B0000',
- darksalmon: '#E9967A',
- darkseagreen: '#8FBC8F',
- darkslateblue: '#483D8B',
- darkslategray: '#2F4F4F',
- darkslategrey: '#2F4F4F',
- darkturquoise: '#00CED1',
- darkviolet: '#9400D3',
- deeppink: '#FF1493',
- deepskyblue: '#00BFFF',
- dimgray: '#696969',
- dimgrey: '#696969',
- dodgerblue: '#1E90FF',
- firebrick: '#B22222',
- floralwhite: '#FFFAF0',
- forestgreen: '#228B22',
- fuchsia: '#FF00FF',
- gainsboro: '#DCDCDC',
- ghostwhite: '#F8F8FF',
- gold: '#FFD700',
- goldenrod: '#DAA520',
- gray: '#808080',
- grey: '#808080',
- green: '#008000',
- greenyellow: '#ADFF2F',
- honeydew: '#F0FFF0',
- hotpink: '#FF69B4',
- indianred: '#CD5C5C',
- indigo: '#4B0082',
- ivory: '#FFFFF0',
- khaki: '#F0E68C',
- lavender: '#E6E6FA',
- lavenderblush: '#FFF0F5',
- lawngreen: '#7CFC00',
- lemonchiffon: '#FFFACD',
- lightblue: '#ADD8E6',
- lightcoral: '#F08080',
- lightcyan: '#E0FFFF',
- lightgoldenrodyellow: '#FAFAD2',
- lightgray: '#D3D3D3',
- lightgrey: '#D3D3D3',
- lightgreen: '#90EE90',
- lightpink: '#FFB6C1',
- lightsalmon: '#FFA07A',
- lightseagreen: '#20B2AA',
- lightskyblue: '#87CEFA',
- lightslategray: '#778899',
- lightslategrey: '#778899',
- lightsteelblue: '#B0C4DE',
- lightyellow: '#FFFFE0',
- lime: '#00FF00',
- limegreen: '#32CD32',
- linen: '#FAF0E6',
- magenta: '#FF00FF',
- maroon: '#800000',
- mediumaquamarine: '#66CDAA',
- mediumblue: '#0000CD',
- mediumorchid: '#BA55D3',
- mediumpurple: '#9370DB',
- mediumseagreen: '#3CB371',
- mediumslateblue: '#7B68EE',
- mediumspringgreen: '#00FA9A',
- mediumturquoise: '#48D1CC',
- mediumvioletred: '#C71585',
- midnightblue: '#191970',
- mintcream: '#F5FFFA',
- mistyrose: '#FFE4E1',
- moccasin: '#FFE4B5',
- navajowhite: '#FFDEAD',
- navy: '#000080',
- oldlace: '#FDF5E6',
- olive: '#808000',
- olivedrab: '#6B8E23',
- orange: '#FFA500',
- orangered: '#FF4500',
- orchid: '#DA70D6',
- palegoldenrod: '#EEE8AA',
- palegreen: '#98FB98',
- paleturquoise: '#AFEEEE',
- palevioletred: '#DB7093',
- papayawhip: '#FFEFD5',
- peachpuff: '#FFDAB9',
- peru: '#CD853F',
- pink: '#FFC0CB',
- plum: '#DDA0DD',
- powderblue: '#B0E0E6',
- purple: '#800080',
- rebeccapurple: '#663399',
- red: '#FF0000',
- rosybrown: '#BC8F8F',
- royalblue: '#4169E1',
- saddlebrown: '#8B4513',
- salmon: '#FA8072',
- sandybrown: '#F4A460',
- seagreen: '#2E8B57',
- seashell: '#FFF5EE',
- sienna: '#A0522D',
- silver: '#C0C0C0',
- skyblue: '#87CEEB',
- slateblue: '#6A5ACD',
- slategray: '#708090',
- slategrey: '#708090',
- snow: '#FFFAFA',
- springgreen: '#00FF7F',
- steelblue: '#4682B4',
- tan: '#D2B48C',
- teal: '#008080',
- thistle: '#D8BFD8',
- tomato: '#FF6347',
- turquoise: '#40E0D0',
- violet: '#EE82EE',
- wheat: '#F5DEB3',
- white: '#FFFFFF',
- whitesmoke: '#F5F5F5',
- yellow: '#FFFF00',
- yellowgreen: '#9ACD32'
- };
-
- function hue2rgb(p, q, t) {
- if (t < 0) {
- t += 1;
- }
- if (t > 1) {
- t -= 1;
- }
- if (t < 1 / 6) {
- return p + (q - p) * 6 * t;
- }
- if (t < 1 / 2) {
- return q;
- }
- if (t < 2 / 3) {
- return p + (q - p) * (2 / 3 - t) * 6;
- }
- return p;
- }
-
- fabric.Color.fromRgb = function(color) {
- return Color.fromSource(Color.sourceFromRgb(color));
- };
-
- fabric.Color.sourceFromRgb = function(color) {
- var match = color.match(Color.reRGBa);
- if (match) {
- var r = parseInt(match[1], 10) / (/%$/.test(match[1]) ? 100 : 1) * (/%$/.test(match[1]) ? 255 : 1),
- g = parseInt(match[2], 10) / (/%$/.test(match[2]) ? 100 : 1) * (/%$/.test(match[2]) ? 255 : 1),
- b = parseInt(match[3], 10) / (/%$/.test(match[3]) ? 100 : 1) * (/%$/.test(match[3]) ? 255 : 1);
- return [
- parseInt(r, 10),
- parseInt(g, 10),
- parseInt(b, 10),
- match[4] ? parseFloat(match[4]) : 1
- ];
- }
- };
-
- fabric.Color.fromRgba = Color.fromRgb;
-
- fabric.Color.fromHsl = function(color) {
- return Color.fromSource(Color.sourceFromHsl(color));
- };
-
- fabric.Color.sourceFromHsl = function(color) {
- var match = color.match(Color.reHSLa);
- if (!match) {
- return;
- }
- var h = (((parseFloat(match[1]) % 360) + 360) % 360) / 360,
- s = parseFloat(match[2]) / (/%$/.test(match[2]) ? 100 : 1),
- l = parseFloat(match[3]) / (/%$/.test(match[3]) ? 100 : 1),
- r, g, b;
- if (s === 0) {
- r = g = b = l;
- }
- else {
- var q = l <= 0.5 ? l * (s + 1) : l + s - l * s,
- p = l * 2 - q;
- r = hue2rgb(p, q, h + 1 / 3);
- g = hue2rgb(p, q, h);
- b = hue2rgb(p, q, h - 1 / 3);
- }
- return [
- Math.round(r * 255),
- Math.round(g * 255),
- Math.round(b * 255),
- match[4] ? parseFloat(match[4]) : 1
- ];
- };
-
- fabric.Color.fromHsla = Color.fromHsl;
-
- fabric.Color.fromHex = function(color) {
- return Color.fromSource(Color.sourceFromHex(color));
- };
-
- fabric.Color.sourceFromHex = function(color) {
- if (color.match(Color.reHex)) {
- var value = color.slice(color.indexOf('#') + 1),
- isShortNotation = (value.length === 3 || value.length === 4),
- isRGBa = (value.length === 8 || value.length === 4),
- r = isShortNotation ? (value.charAt(0) + value.charAt(0)) : value.substring(0, 2),
- g = isShortNotation ? (value.charAt(1) + value.charAt(1)) : value.substring(2, 4),
- b = isShortNotation ? (value.charAt(2) + value.charAt(2)) : value.substring(4, 6),
- a = isRGBa ? (isShortNotation ? (value.charAt(3) + value.charAt(3)) : value.substring(6, 8)) : 'FF';
- return [
- parseInt(r, 16),
- parseInt(g, 16),
- parseInt(b, 16),
- parseFloat((parseInt(a, 16) / 255).toFixed(2))
- ];
- }
- };
-
- fabric.Color.fromSource = function(source) {
- var oColor = new Color();
- oColor.setSource(source);
- return oColor;
- };
- })(typeof exports !== 'undefined' ? exports : this);
- (function () {
- 'use strict';
- if (fabric.StaticCanvas) {
- fabric.warn('fabric.StaticCanvas is already defined.');
- return;
- }
-
- var extend = fabric.util.object.extend,
- getElementOffset = fabric.util.getElementOffset,
- removeFromArray = fabric.util.removeFromArray,
- toFixed = fabric.util.toFixed,
- transformPoint = fabric.util.transformPoint,
- invertTransform = fabric.util.invertTransform,
- CANVAS_INIT_ERROR = new Error('Could not initialize `canvas` element');
-
- fabric.StaticCanvas = fabric.util.createClass(fabric.CommonMethods, {
-
- initialize: function(el, options) {
- options || (options = { });
- this.renderAndResetBound = this.renderAndReset.bind(this);
- this.requestRenderAllBound = this.requestRenderAll.bind(this);
- this._initStatic(el, options);
- },
-
- backgroundColor: '',
-
- backgroundImage: null,
-
- overlayColor: '',
-
- overlayImage: null,
-
- includeDefaultValues: true,
-
- stateful: false,
-
- renderOnAddRemove: true,
-
- clipTo: null,
-
- controlsAboveOverlay: false,
-
- allowTouchScrolling: false,
-
- imageSmoothingEnabled: true,
-
- viewportTransform: fabric.iMatrix.concat(),
-
- backgroundVpt: true,
-
- overlayVpt: true,
-
- onBeforeScaleRotate: function () {
-
- },
-
- enableRetinaScaling: true,
-
- vptCoords: { },
-
- skipOffscreen: true,
-
- _initStatic: function(el, options) {
- var cb = this.requestRenderAllBound;
- this._objects = [];
- this._createLowerCanvas(el);
- this._initOptions(options);
- this._setImageSmoothing();
-
- if (!this.interactive) {
- this._initRetinaScaling();
- }
- if (options.overlayImage) {
- this.setOverlayImage(options.overlayImage, cb);
- }
- if (options.backgroundImage) {
- this.setBackgroundImage(options.backgroundImage, cb);
- }
- if (options.backgroundColor) {
- this.setBackgroundColor(options.backgroundColor, cb);
- }
- if (options.overlayColor) {
- this.setOverlayColor(options.overlayColor, cb);
- }
- this.calcOffset();
- },
-
- _isRetinaScaling: function() {
- return (fabric.devicePixelRatio !== 1 && this.enableRetinaScaling);
- },
-
- getRetinaScaling: function() {
- return this._isRetinaScaling() ? fabric.devicePixelRatio : 1;
- },
-
- _initRetinaScaling: function() {
- if (!this._isRetinaScaling()) {
- return;
- }
- this.lowerCanvasEl.setAttribute('width', this.width * fabric.devicePixelRatio);
- this.lowerCanvasEl.setAttribute('height', this.height * fabric.devicePixelRatio);
- this.contextContainer.scale(fabric.devicePixelRatio, fabric.devicePixelRatio);
- },
-
- calcOffset: function () {
- this._offset = getElementOffset(this.lowerCanvasEl);
- return this;
- },
-
- setOverlayImage: function (image, callback, options) {
- return this.__setBgOverlayImage('overlayImage', image, callback, options);
- },
-
- setBackgroundImage: function (image, callback, options) {
- return this.__setBgOverlayImage('backgroundImage', image, callback, options);
- },
-
- setOverlayColor: function(overlayColor, callback) {
- return this.__setBgOverlayColor('overlayColor', overlayColor, callback);
- },
-
- setBackgroundColor: function(backgroundColor, callback) {
- return this.__setBgOverlayColor('backgroundColor', backgroundColor, callback);
- },
-
- _setImageSmoothing: function() {
- var ctx = this.getContext();
- ctx.imageSmoothingEnabled = ctx.imageSmoothingEnabled || ctx.webkitImageSmoothingEnabled
- || ctx.mozImageSmoothingEnabled || ctx.msImageSmoothingEnabled || ctx.oImageSmoothingEnabled;
- ctx.imageSmoothingEnabled = this.imageSmoothingEnabled;
- },
-
- __setBgOverlayImage: function(property, image, callback, options) {
- if (typeof image === 'string') {
- fabric.util.loadImage(image, function(img) {
- img && (this[property] = new fabric.Image(img, options));
- callback && callback(img);
- }, this, options && options.crossOrigin);
- }
- else {
- options && image.setOptions(options);
- this[property] = image;
- callback && callback(image);
- }
- return this;
- },
-
- __setBgOverlayColor: function(property, color, callback) {
- this[property] = color;
- this._initGradient(color, property);
- this._initPattern(color, property, callback);
- return this;
- },
-
- _createCanvasElement: function() {
- var element = fabric.util.createCanvasElement();
- if (!element) {
- throw CANVAS_INIT_ERROR;
- }
- if (!element.style) {
- element.style = { };
- }
- if (typeof element.getContext === 'undefined') {
- throw CANVAS_INIT_ERROR;
- }
- return element;
- },
-
- _initOptions: function (options) {
- this._setOptions(options);
- this.width = this.width || parseInt(this.lowerCanvasEl.width, 10) || 0;
- this.height = this.height || parseInt(this.lowerCanvasEl.height, 10) || 0;
- if (!this.lowerCanvasEl.style) {
- return;
- }
- this.lowerCanvasEl.width = this.width;
- this.lowerCanvasEl.height = this.height;
- this.lowerCanvasEl.style.width = this.width + 'px';
- this.lowerCanvasEl.style.height = this.height + 'px';
- this.viewportTransform = this.viewportTransform.slice();
- },
-
- _createLowerCanvas: function (canvasEl) {
-
- if (canvasEl && canvasEl.getContext) {
- this.lowerCanvasEl = canvasEl;
- }
- else {
- this.lowerCanvasEl = fabric.util.getById(canvasEl) || this._createCanvasElement();
- }
- fabric.util.addClass(this.lowerCanvasEl, 'lower-canvas');
- if (this.interactive) {
- this._applyCanvasStyle(this.lowerCanvasEl);
- }
- this.contextContainer = this.lowerCanvasEl.getContext('2d');
- },
-
- getWidth: function () {
- return this.width;
- },
-
- getHeight: function () {
- return this.height;
- },
-
- setWidth: function (value, options) {
- return this.setDimensions({ width: value }, options);
- },
-
- setHeight: function (value, options) {
- return this.setDimensions({ height: value }, options);
- },
-
- setDimensions: function (dimensions, options) {
- var cssValue;
- options = options || {};
- for (var prop in dimensions) {
- cssValue = dimensions[prop];
- if (!options.cssOnly) {
- this._setBackstoreDimension(prop, dimensions[prop]);
- cssValue += 'px';
- this.hasLostContext = true;
- }
- if (!options.backstoreOnly) {
- this._setCssDimension(prop, cssValue);
- }
- }
- if (this._isCurrentlyDrawing) {
- this.freeDrawingBrush && this.freeDrawingBrush._setBrushStyles();
- }
- this._initRetinaScaling();
- this._setImageSmoothing();
- this.calcOffset();
- if (!options.cssOnly) {
- this.requestRenderAll();
- }
- return this;
- },
-
- _setBackstoreDimension: function (prop, value) {
- this.lowerCanvasEl[prop] = value;
- if (this.upperCanvasEl) {
- this.upperCanvasEl[prop] = value;
- }
- if (this.cacheCanvasEl) {
- this.cacheCanvasEl[prop] = value;
- }
- this[prop] = value;
- return this;
- },
-
- _setCssDimension: function (prop, value) {
- this.lowerCanvasEl.style[prop] = value;
- if (this.upperCanvasEl) {
- this.upperCanvasEl.style[prop] = value;
- }
- if (this.wrapperEl) {
- this.wrapperEl.style[prop] = value;
- }
- return this;
- },
-
- getZoom: function () {
- return this.viewportTransform[0];
- },
-
- setViewportTransform: function (vpt) {
- var activeObject = this._activeObject, object, ignoreVpt = false, skipAbsolute = true, i, len;
- this.viewportTransform = vpt;
- for (i = 0, len = this._objects.length; i < len; i++) {
- object = this._objects[i];
- object.group || object.setCoords(ignoreVpt, skipAbsolute);
- }
- if (activeObject && activeObject.type === 'activeSelection') {
- activeObject.setCoords(ignoreVpt, skipAbsolute);
- }
- this.calcViewportBoundaries();
- this.renderOnAddRemove && this.requestRenderAll();
- return this;
- },
-
- zoomToPoint: function (point, value) {
-
- var before = point, vpt = this.viewportTransform.slice(0);
- point = transformPoint(point, invertTransform(this.viewportTransform));
- vpt[0] = value;
- vpt[3] = value;
- var after = transformPoint(point, vpt);
- vpt[4] += before.x - after.x;
- vpt[5] += before.y - after.y;
- return this.setViewportTransform(vpt);
- },
-
- setZoom: function (value) {
- this.zoomToPoint(new fabric.Point(0, 0), value);
- return this;
- },
-
- absolutePan: function (point) {
- var vpt = this.viewportTransform.slice(0);
- vpt[4] = -point.x;
- vpt[5] = -point.y;
- return this.setViewportTransform(vpt);
- },
-
- relativePan: function (point) {
- return this.absolutePan(new fabric.Point(
- -point.x - this.viewportTransform[4],
- -point.y - this.viewportTransform[5]
- ));
- },
-
- getElement: function () {
- return this.lowerCanvasEl;
- },
-
- _onObjectAdded: function(obj) {
- this.stateful && obj.setupState();
- obj._set('canvas', this);
- obj.setCoords();
- this.fire('object:added', { target: obj });
- obj.fire('added');
- },
-
- _onObjectRemoved: function(obj) {
- this.fire('object:removed', { target: obj });
- obj.fire('removed');
- delete obj.canvas;
- },
-
- clearContext: function(ctx) {
- ctx.clearRect(0, 0, this.width, this.height);
- return this;
- },
-
- getContext: function () {
- return this.contextContainer;
- },
-
- clear: function () {
- this._objects.length = 0;
- this.backgroundImage = null;
- this.overlayImage = null;
- this.backgroundColor = '';
- this.overlayColor = '';
- if (this._hasITextHandlers) {
- this.off('mouse:up', this._mouseUpITextHandler);
- this._iTextInstances = null;
- this._hasITextHandlers = false;
- }
- this.clearContext(this.contextContainer);
- this.fire('canvas:cleared');
- this.renderOnAddRemove && this.requestRenderAll();
- return this;
- },
-
- renderAll: function () {
- var canvasToDrawOn = this.contextContainer;
- this.renderCanvas(canvasToDrawOn, this._objects);
- return this;
- },
-
- renderAndReset: function() {
- this.isRendering = 0;
- this.renderAll();
- },
-
- requestRenderAll: function () {
- if (!this.isRendering) {
- this.isRendering = fabric.util.requestAnimFrame(this.renderAndResetBound);
- }
- return this;
- },
-
- calcViewportBoundaries: function() {
- var points = { }, width = this.width, height = this.height,
- iVpt = invertTransform(this.viewportTransform);
- points.tl = transformPoint({ x: 0, y: 0 }, iVpt);
- points.br = transformPoint({ x: width, y: height }, iVpt);
- points.tr = new fabric.Point(points.br.x, points.tl.y);
- points.bl = new fabric.Point(points.tl.x, points.br.y);
- this.vptCoords = points;
- return points;
- },
-
- renderCanvas: function(ctx, objects) {
- var v = this.viewportTransform;
- if (this.isRendering) {
- fabric.util.cancelAnimFrame(this.isRendering);
- this.isRendering = 0;
- }
- this.calcViewportBoundaries();
- this.clearContext(ctx);
- this.fire('before:render');
- if (this.clipTo) {
- fabric.util.clipContext(this, ctx);
- }
- this._renderBackground(ctx);
- ctx.save();
-
- ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);
- this._renderObjects(ctx, objects);
- ctx.restore();
- if (!this.controlsAboveOverlay && this.interactive) {
- this.drawControls(ctx);
- }
- if (this.clipTo) {
- ctx.restore();
- }
- this._renderOverlay(ctx);
- if (this.controlsAboveOverlay && this.interactive) {
- this.drawControls(ctx);
- }
- this.fire('after:render');
- },
-
- _renderObjects: function(ctx, objects) {
- var i, len;
- for (i = 0, len = objects.length; i < len; ++i) {
- objects[i] && objects[i].render(ctx);
- }
- },
-
- _renderBackgroundOrOverlay: function(ctx, property) {
- var object = this[property + 'Color'], v;
- if (object) {
- ctx.fillStyle = object.toLive
- ? object.toLive(ctx, this)
- : object;
- ctx.fillRect(
- object.offsetX || 0,
- object.offsetY || 0,
- this.width,
- this.height);
- }
- object = this[property + 'Image'];
- if (object) {
- if (this[property + 'Vpt']) {
- v = this.viewportTransform;
- ctx.save();
- ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);
- }
- object.render(ctx);
- this[property + 'Vpt'] && ctx.restore();
- }
- },
-
- _renderBackground: function(ctx) {
- this._renderBackgroundOrOverlay(ctx, 'background');
- },
-
- _renderOverlay: function(ctx) {
- this._renderBackgroundOrOverlay(ctx, 'overlay');
- },
-
- getCenter: function () {
- return {
- top: this.height / 2,
- left: this.width / 2
- };
- },
-
- centerObjectH: function (object) {
- return this._centerObject(object, new fabric.Point(this.getCenter().left, object.getCenterPoint().y));
- },
-
- centerObjectV: function (object) {
- return this._centerObject(object, new fabric.Point(object.getCenterPoint().x, this.getCenter().top));
- },
-
- centerObject: function(object) {
- var center = this.getCenter();
- return this._centerObject(object, new fabric.Point(center.left, center.top));
- },
-
- viewportCenterObject: function(object) {
- var vpCenter = this.getVpCenter();
- return this._centerObject(object, vpCenter);
- },
-
- viewportCenterObjectH: function(object) {
- var vpCenter = this.getVpCenter();
- this._centerObject(object, new fabric.Point(vpCenter.x, object.getCenterPoint().y));
- return this;
- },
-
- viewportCenterObjectV: function(object) {
- var vpCenter = this.getVpCenter();
- return this._centerObject(object, new fabric.Point(object.getCenterPoint().x, vpCenter.y));
- },
-
- getVpCenter: function() {
- var center = this.getCenter(),
- iVpt = invertTransform(this.viewportTransform);
- return transformPoint({ x: center.left, y: center.top }, iVpt);
- },
-
- _centerObject: function(object, center) {
- object.setPositionByOrigin(center, 'center', 'center');
- object.setCoords();
- this.renderOnAddRemove && this.requestRenderAll();
- return this;
- },
-
- toDatalessJSON: function (propertiesToInclude) {
- return this.toDatalessObject(propertiesToInclude);
- },
-
- toObject: function (propertiesToInclude) {
- return this._toObjectMethod('toObject', propertiesToInclude);
- },
-
- toDatalessObject: function (propertiesToInclude) {
- return this._toObjectMethod('toDatalessObject', propertiesToInclude);
- },
-
- _toObjectMethod: function (methodName, propertiesToInclude) {
- var data = {
- version: fabric.version,
- objects: this._toObjects(methodName, propertiesToInclude)
- };
- extend(data, this.__serializeBgOverlay(methodName, propertiesToInclude));
- fabric.util.populateWithProperties(this, data, propertiesToInclude);
- return data;
- },
-
- _toObjects: function(methodName, propertiesToInclude) {
- return this.getObjects().filter(function(object) {
- return !object.excludeFromExport;
- }).map(function(instance) {
- return this._toObject(instance, methodName, propertiesToInclude);
- }, this);
- },
-
- _toObject: function(instance, methodName, propertiesToInclude) {
- var originalValue;
- if (!this.includeDefaultValues) {
- originalValue = instance.includeDefaultValues;
- instance.includeDefaultValues = false;
- }
- var object = instance[methodName](propertiesToInclude);
- if (!this.includeDefaultValues) {
- instance.includeDefaultValues = originalValue;
- }
- return object;
- },
-
- __serializeBgOverlay: function(methodName, propertiesToInclude) {
- var data = { }, bgImage = this.backgroundImage, overlay = this.overlayImage;
- if (this.backgroundColor) {
- data.background = this.backgroundColor.toObject
- ? this.backgroundColor.toObject(propertiesToInclude)
- : this.backgroundColor;
- }
- if (this.overlayColor) {
- data.overlay = this.overlayColor.toObject
- ? this.overlayColor.toObject(propertiesToInclude)
- : this.overlayColor;
- }
- if (bgImage && !bgImage.excludeFromExport) {
- data.backgroundImage = this._toObject(bgImage, methodName, propertiesToInclude);
- }
- if (overlay && !overlay.excludeFromExport) {
- data.overlayImage = this._toObject(overlay, methodName, propertiesToInclude);
- }
- return data;
- },
-
-
- svgViewportTransformation: true,
-
- toSVG: function(options, reviver) {
- options || (options = { });
- var markup = [];
- this._setSVGPreamble(markup, options);
- this._setSVGHeader(markup, options);
- this._setSVGBgOverlayColor(markup, 'backgroundColor');
- this._setSVGBgOverlayImage(markup, 'backgroundImage', reviver);
- this._setSVGObjects(markup, reviver);
- this._setSVGBgOverlayColor(markup, 'overlayColor');
- this._setSVGBgOverlayImage(markup, 'overlayImage', reviver);
- markup.push('</svg>');
- return markup.join('');
- },
-
- _setSVGPreamble: function(markup, options) {
- if (options.suppressPreamble) {
- return;
- }
- markup.push(
- '<?xml version="1.0" encoding="', (options.encoding || 'UTF-8'), '" standalone="no" ?>\n',
- '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" ',
- '"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n'
- );
- },
-
- _setSVGHeader: function(markup, options) {
- var width = options.width || this.width,
- height = options.height || this.height,
- vpt, viewBox = 'viewBox="0 0 ' + this.width + ' ' + this.height + '" ',
- NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS;
- if (options.viewBox) {
- viewBox = 'viewBox="' +
- options.viewBox.x + ' ' +
- options.viewBox.y + ' ' +
- options.viewBox.width + ' ' +
- options.viewBox.height + '" ';
- }
- else {
- if (this.svgViewportTransformation) {
- vpt = this.viewportTransform;
- viewBox = 'viewBox="' +
- toFixed(-vpt[4] / vpt[0], NUM_FRACTION_DIGITS) + ' ' +
- toFixed(-vpt[5] / vpt[3], NUM_FRACTION_DIGITS) + ' ' +
- toFixed(this.width / vpt[0], NUM_FRACTION_DIGITS) + ' ' +
- toFixed(this.height / vpt[3], NUM_FRACTION_DIGITS) + '" ';
- }
- }
- markup.push(
- '<svg ',
- 'xmlns="http://www.w3.org/2000/svg" ',
- 'xmlns:xlink="http://www.w3.org/1999/xlink" ',
- 'version="1.1" ',
- 'width="', width, '" ',
- 'height="', height, '" ',
- viewBox,
- 'xml:space="preserve">\n',
- '<desc>Created with Fabric.js ', fabric.version, '</desc>\n',
- '<defs>\n',
- this.createSVGFontFacesMarkup(),
- this.createSVGRefElementsMarkup(),
- '</defs>\n'
- );
- },
-
- createSVGRefElementsMarkup: function() {
- var _this = this,
- markup = ['backgroundColor', 'overlayColor'].map(function(prop) {
- var fill = _this[prop];
- if (fill && fill.toLive) {
- return fill.toSVG(_this, false);
- }
- });
- return markup.join('');
- },
-
- createSVGFontFacesMarkup: function() {
- var markup = '', fontList = { }, obj, fontFamily,
- style, row, rowIndex, _char, charIndex, i, len,
- fontPaths = fabric.fontPaths, objects = this.getObjects();
- for (i = 0, len = objects.length; i < len; i++) {
- obj = objects[i];
- fontFamily = obj.fontFamily;
- if (obj.type.indexOf('text') === -1 || fontList[fontFamily] || !fontPaths[fontFamily]) {
- continue;
- }
- fontList[fontFamily] = true;
- if (!obj.styles) {
- continue;
- }
- style = obj.styles;
- for (rowIndex in style) {
- row = style[rowIndex];
- for (charIndex in row) {
- _char = row[charIndex];
- fontFamily = _char.fontFamily;
- if (!fontList[fontFamily] && fontPaths[fontFamily]) {
- fontList[fontFamily] = true;
- }
- }
- }
- }
- for (var j in fontList) {
- markup += [
- '\t\t@font-face {\n',
- '\t\t\tfont-family: \'', j, '\';\n',
- '\t\t\tsrc: url(\'', fontPaths[j], '\');\n',
- '\t\t}\n'
- ].join('');
- }
- if (markup) {
- markup = [
- '\t<c_style type="text/c_style">',
- '<![CDATA[\n',
- markup,
- ']]>',
- '</c_style>\n'
- ].join('');
- }
- return markup;
- },
-
- _setSVGObjects: function(markup, reviver) {
- var instance, i, len, objects = this.getObjects();
- for (i = 0, len = objects.length; i < len; i++) {
- instance = objects[i];
- if (instance.excludeFromExport) {
- continue;
- }
- this._setSVGObject(markup, instance, reviver);
- }
- },
-
- _setSVGObject: function(markup, instance, reviver) {
- markup.push(instance.toSVG(reviver));
- },
-
- _setSVGBgOverlayImage: function(markup, property, reviver) {
- if (this[property] && this[property].toSVG) {
- markup.push(this[property].toSVG(reviver));
- }
- },
-
- _setSVGBgOverlayColor: function(markup, property) {
- var filler = this[property], vpt = this.viewportTransform, finalWidth = this.width / vpt[0],
- finalHeight = this.height / vpt[3];
- if (!filler) {
- return;
- }
- if (filler.toLive) {
- var repeat = filler.repeat;
- markup.push(
- '<rect transform="translate(', finalWidth / 2, ',', finalHeight / 2, ')"',
- ' x="', filler.offsetX - finalWidth / 2, '" y="', filler.offsetY - finalHeight / 2, '" ',
- 'width="',
- (repeat === 'repeat-y' || repeat === 'no-repeat'
- ? filler.source.width
- : finalWidth ),
- '" height="',
- (repeat === 'repeat-x' || repeat === 'no-repeat'
- ? filler.source.height
- : finalHeight),
- '" fill="url(#SVGID_' + filler.id + ')"',
- '></rect>\n'
- );
- }
- else {
- markup.push(
- '<rect x="0" y="0" width="100%" height="100%" ',
- 'fill="', this[property], '"',
- '></rect>\n'
- );
- }
- },
-
-
- sendToBack: function (object) {
- if (!object) {
- return this;
- }
- var activeSelection = this._activeObject,
- i, obj, objs;
- if (object === activeSelection && object.type === 'activeSelection') {
- objs = activeSelection._objects;
- for (i = objs.length; i--;) {
- obj = objs[i];
- removeFromArray(this._objects, obj);
- this._objects.unshift(obj);
- }
- }
- else {
- removeFromArray(this._objects, object);
- this._objects.unshift(object);
- }
- this.renderOnAddRemove && this.requestRenderAll();
- return this;
- },
-
- bringToFront: function (object) {
- if (!object) {
- return this;
- }
- var activeSelection = this._activeObject,
- i, obj, objs;
- if (object === activeSelection && object.type === 'activeSelection') {
- objs = activeSelection._objects;
- for (i = 0; i < objs.length; i++) {
- obj = objs[i];
- removeFromArray(this._objects, obj);
- this._objects.push(obj);
- }
- }
- else {
- removeFromArray(this._objects, object);
- this._objects.push(object);
- }
- this.renderOnAddRemove && this.requestRenderAll();
- return this;
- },
-
- sendBackwards: function (object, intersecting) {
- if (!object) {
- return this;
- }
- var activeSelection = this._activeObject,
- i, obj, idx, newIdx, objs, objsMoved = 0;
- if (object === activeSelection && object.type === 'activeSelection') {
- objs = activeSelection._objects;
- for (i = 0; i < objs.length; i++) {
- obj = objs[i];
- idx = this._objects.indexOf(obj);
- if (idx > 0 + objsMoved) {
- newIdx = idx - 1;
- removeFromArray(this._objects, obj);
- this._objects.splice(newIdx, 0, obj);
- }
- objsMoved++;
- }
- }
- else {
- idx = this._objects.indexOf(object);
- if (idx !== 0) {
-
- newIdx = this._findNewLowerIndex(object, idx, intersecting);
- removeFromArray(this._objects, object);
- this._objects.splice(newIdx, 0, object);
- }
- }
- this.renderOnAddRemove && this.requestRenderAll();
- return this;
- },
-
- _findNewLowerIndex: function(object, idx, intersecting) {
- var newIdx, i;
- if (intersecting) {
- newIdx = idx;
-
- for (i = idx - 1; i >= 0; --i) {
- var isIntersecting = object.intersectsWithObject(this._objects[i]) ||
- object.isContainedWithinObject(this._objects[i]) ||
- this._objects[i].isContainedWithinObject(object);
- if (isIntersecting) {
- newIdx = i;
- break;
- }
- }
- }
- else {
- newIdx = idx - 1;
- }
- return newIdx;
- },
-
- bringForward: function (object, intersecting) {
- if (!object) {
- return this;
- }
- var activeSelection = this._activeObject,
- i, obj, idx, newIdx, objs, objsMoved = 0;
- if (object === activeSelection && object.type === 'activeSelection') {
- objs = activeSelection._objects;
- for (i = objs.length; i--;) {
- obj = objs[i];
- idx = this._objects.indexOf(obj);
- if (idx < this._objects.length - 1 - objsMoved) {
- newIdx = idx + 1;
- removeFromArray(this._objects, obj);
- this._objects.splice(newIdx, 0, obj);
- }
- objsMoved++;
- }
- }
- else {
- idx = this._objects.indexOf(object);
- if (idx !== this._objects.length - 1) {
-
- newIdx = this._findNewUpperIndex(object, idx, intersecting);
- removeFromArray(this._objects, object);
- this._objects.splice(newIdx, 0, object);
- }
- }
- this.renderOnAddRemove && this.requestRenderAll();
- return this;
- },
-
- _findNewUpperIndex: function(object, idx, intersecting) {
- var newIdx, i, len;
- if (intersecting) {
- newIdx = idx;
-
- for (i = idx + 1, len = this._objects.length; i < len; ++i) {
- var isIntersecting = object.intersectsWithObject(this._objects[i]) ||
- object.isContainedWithinObject(this._objects[i]) ||
- this._objects[i].isContainedWithinObject(object);
- if (isIntersecting) {
- newIdx = i;
- break;
- }
- }
- }
- else {
- newIdx = idx + 1;
- }
- return newIdx;
- },
-
- moveTo: function (object, index) {
- removeFromArray(this._objects, object);
- this._objects.splice(index, 0, object);
- return this.renderOnAddRemove && this.requestRenderAll();
- },
-
- dispose: function () {
-
- if (this.isRendering) {
- fabric.util.cancelAnimFrame(this.isRendering);
- this.isRendering = 0;
- }
- this.forEachObject(function(object) {
- object.dispose && object.dispose();
- });
- this._objects = [];
- this.backgroundImage = null;
- this.overlayImage = null;
- this._iTextInstances = null;
- this.lowerCanvasEl = null;
- this.contextContainer = null;
- return this;
- },
-
- toString: function () {
- return '#<fabric.Canvas (' + this.complexity() + '): ' +
- '{ objects: ' + this.getObjects().length + ' }>';
- }
- });
- extend(fabric.StaticCanvas.prototype, fabric.Observable);
- extend(fabric.StaticCanvas.prototype, fabric.Collection);
- extend(fabric.StaticCanvas.prototype, fabric.DataURLExporter);
- extend(fabric.StaticCanvas, {
-
- EMPTY_JSON: '{"objects": [], "background": "white"}',
-
- supports: function (methodName) {
- var el = fabric.util.createCanvasElement();
- if (!el || !el.getContext) {
- return null;
- }
- var ctx = el.getContext('2d');
- if (!ctx) {
- return null;
- }
- switch (methodName) {
- case 'getImageData':
- return typeof ctx.getImageData !== 'undefined';
- case 'setLineDash':
- return typeof ctx.setLineDash !== 'undefined';
- case 'toDataURL':
- return typeof el.toDataURL !== 'undefined';
- case 'toDataURLWithQuality':
- try {
- el.toDataURL('c_image/jpeg', 0);
- return true;
- }
- catch (e) { }
- return false;
- default:
- return null;
- }
- }
- });
-
- fabric.StaticCanvas.prototype.toJSON = fabric.StaticCanvas.prototype.toObject;
- if (fabric.isLikelyNode) {
- fabric.StaticCanvas.prototype.createPNGStream = function() {
- var impl = fabric.util.getNodeCanvas(this.lowerCanvasEl);
- return impl && impl.createPNGStream();
- };
- fabric.StaticCanvas.prototype.createJPEGStream = function(opts) {
- var impl = fabric.util.getNodeCanvas(this.lowerCanvasEl);
- return impl && impl.createJPEGStream(opts);
- };
- }
- })();
- (function () {
- var supportQuality = fabric.StaticCanvas.supports('toDataURLWithQuality');
- fabric.util.object.extend(fabric.StaticCanvas.prototype, {
-
- toDataURL: function (options) {
- options || (options = { });
- var format = options.format || 'png',
- quality = options.quality || 1,
- multiplier = (options.multiplier || 1) * (options.enableRetinaScaling ? 1 : 1 / this.getRetinaScaling()),
- cropping = {
- left: options.left || 0,
- top: options.top || 0,
- width: options.width || 0,
- height: options.height || 0,
- };
- return this.__toDataURLWithMultiplier(format, quality, cropping, multiplier);
- },
-
- __toDataURLWithMultiplier: function(format, quality, cropping, multiplier) {
- var origWidth = this.width,
- origHeight = this.height,
- scaledWidth = (cropping.width || this.width) * multiplier,
- scaledHeight = (cropping.height || this.height) * multiplier,
- zoom = this.getZoom(),
- newZoom = zoom * multiplier,
- vp = this.viewportTransform,
- translateX = (vp[4] - cropping.left) * multiplier,
- translateY = (vp[5] - cropping.top) * multiplier,
- newVp = [newZoom, 0, 0, newZoom, translateX, translateY],
- originalInteractive = this.interactive,
- originalSkipOffScreen = this.skipOffscreen,
- needsResize = origWidth !== scaledWidth || origHeight !== scaledHeight;
- this.viewportTransform = newVp;
- this.skipOffscreen = false;
-
- this.interactive = false;
- if (needsResize) {
- this.setDimensions({ width: scaledWidth, height: scaledHeight }, { backstoreOnly: true });
- }
-
-
- this.renderAll();
- var data = this.__toDataURL(format, quality, cropping);
- this.interactive = originalInteractive;
- this.skipOffscreen = originalSkipOffScreen;
- this.viewportTransform = vp;
-
-
- if (needsResize) {
- this.setDimensions({ width: origWidth, height: origHeight }, { backstoreOnly: true });
- }
- this.renderAll();
- return data;
- },
-
- __toDataURL: function(format, quality) {
- var canvasEl = this.contextContainer.canvas;
-
- if (format === 'jpg') {
- format = 'jpeg';
- }
- var data = supportQuality
- ? canvasEl.toDataURL('c_image/' + format, quality)
- : canvasEl.toDataURL('c_image/' + format);
- return data;
- },
- });
- })();
- (function(global) {
- 'use strict';
- var fabric = global.fabric || (global.fabric = { }),
- extend = fabric.util.object.extend,
- clone = fabric.util.object.clone,
- toFixed = fabric.util.toFixed,
- capitalize = fabric.util.string.capitalize,
- degreesToRadians = fabric.util.degreesToRadians,
- supportsLineDash = fabric.StaticCanvas.supports('setLineDash'),
- objectCaching = !fabric.isLikelyNode,
- ALIASING_LIMIT = 2;
- if (fabric.Object) {
- return;
- }
-
- fabric.Object = fabric.util.createClass(fabric.CommonMethods, {
-
- type: 'object',
-
- originX: 'left',
-
- originY: 'top',
-
- top: 0,
-
- left: 0,
-
- width: 0,
-
- height: 0,
-
- scaleX: 1,
-
- scaleY: 1,
-
- flipX: false,
-
- flipY: false,
-
- opacity: 1,
-
- angle: 0,
-
- skewX: 0,
-
- skewY: 0,
-
- cornerSize: 13,
-
- transparentCorners: true,
-
- hoverCursor: null,
-
- moveCursor: null,
-
- padding: 0,
-
- borderColor: 'rgba(102,153,255,0.75)',
-
- borderDashArray: null,
-
- cornerColor: 'rgba(102,153,255,0.5)',
-
- cornerStrokeColor: null,
-
- cornerStyle: 'rect',
-
- cornerDashArray: null,
-
- centeredScaling: false,
-
- centeredRotation: true,
-
- fill: 'rgb(0,0,0)',
-
- fillRule: 'nonzero',
-
- globalCompositeOperation: 'source-over',
-
- backgroundColor: '',
-
- selectionBackgroundColor: '',
-
- stroke: null,
-
- strokeWidth: 1,
-
- strokeDashArray: null,
-
- strokeLineCap: 'butt',
-
- strokeLineJoin: 'miter',
-
- strokeMiterLimit: 4,
-
- shadow: null,
-
- borderOpacityWhenMoving: 0.4,
-
- borderScaleFactor: 1,
-
- transformMatrix: null,
-
- minScaleLimit: 0,
-
- selectable: true,
-
- evented: true,
-
- visible: true,
-
- hasControls: true,
-
- hasBorders: true,
-
- hasRotatingPoint: true,
-
- rotatingPointOffset: 40,
-
- perPixelTargetFind: false,
-
- includeDefaultValues: true,
-
- clipTo: null,
-
- lockMovementX: false,
-
- lockMovementY: false,
-
- lockRotation: false,
-
- lockScalingX: false,
-
- lockScalingY: false,
-
- lockUniScaling: false,
-
- lockSkewingX: false,
-
- lockSkewingY: false,
-
- lockScalingFlip: false,
-
- excludeFromExport: false,
-
- objectCaching: objectCaching,
-
- statefullCache: false,
-
- noScaleCache: true,
-
- dirty: true,
-
- __corner: 0,
-
- paintFirst: 'fill',
-
- stateProperties: (
- 'top left width height scaleX scaleY flipX flipY originX originY transformMatrix ' +
- 'stroke strokeWidth strokeDashArray strokeLineCap strokeLineJoin strokeMiterLimit ' +
- 'angle opacity fill globalCompositeOperation shadow clipTo visible backgroundColor ' +
- 'skewX skewY fillRule paintFirst'
- ).split(' '),
-
- cacheProperties: (
- 'fill stroke strokeWidth strokeDashArray width height paintFirst' +
- ' strokeLineCap strokeLineJoin strokeMiterLimit backgroundColor'
- ).split(' '),
-
- initialize: function(options) {
- if (options) {
- this.setOptions(options);
- }
- },
-
- _createCacheCanvas: function() {
- this._cacheProperties = {};
- this._cacheCanvas = fabric.document.createElement('canvas');
- this._cacheContext = this._cacheCanvas.getContext('2d');
- this._updateCacheCanvas();
-
- this.dirty = true;
- },
-
- _limitCacheSize: function(dims) {
- var perfLimitSizeTotal = fabric.perfLimitSizeTotal,
- width = dims.width, height = dims.height,
- max = fabric.maxCacheSideLimit, min = fabric.minCacheSideLimit;
- if (width <= max && height <= max && width * height <= perfLimitSizeTotal) {
- if (width < min) {
- dims.width = min;
- }
- if (height < min) {
- dims.height = min;
- }
- return dims;
- }
- var ar = width / height, limitedDims = fabric.util.limitDimsByArea(ar, perfLimitSizeTotal),
- capValue = fabric.util.capValue,
- x = capValue(min, limitedDims.x, max),
- y = capValue(min, limitedDims.y, max);
- if (width > x) {
- dims.zoomX /= width / x;
- dims.width = x;
- dims.capped = true;
- }
- if (height > y) {
- dims.zoomY /= height / y;
- dims.height = y;
- dims.capped = true;
- }
- return dims;
- },
-
- _getCacheCanvasDimensions: function() {
- var zoom = this.canvas && this.canvas.getZoom() || 1,
- objectScale = this.getObjectScaling(),
- retina = this.canvas && this.canvas._isRetinaScaling() ? fabric.devicePixelRatio : 1,
- dim = this._getNonTransformedDimensions(),
- zoomX = objectScale.scaleX * zoom * retina,
- zoomY = objectScale.scaleY * zoom * retina,
- width = dim.x * zoomX,
- height = dim.y * zoomY;
- return {
-
-
- width: width + ALIASING_LIMIT,
- height: height + ALIASING_LIMIT,
- zoomX: zoomX,
- zoomY: zoomY,
- x: dim.x,
- y: dim.y
- };
- },
-
- _updateCacheCanvas: function() {
- if (this.noScaleCache && this.canvas && this.canvas._currentTransform) {
- var target = this.canvas._currentTransform.target,
- action = this.canvas._currentTransform.action;
- if (this === target && action.slice && action.slice(0, 5) === 'scale') {
- return false;
- }
- }
- var canvas = this._cacheCanvas,
- dims = this._limitCacheSize(this._getCacheCanvasDimensions()),
- minCacheSize = fabric.minCacheSideLimit,
- width = dims.width, height = dims.height, drawingWidth, drawingHeight,
- zoomX = dims.zoomX, zoomY = dims.zoomY,
- dimensionsChanged = width !== this.cacheWidth || height !== this.cacheHeight,
- zoomChanged = this.zoomX !== zoomX || this.zoomY !== zoomY,
- shouldRedraw = dimensionsChanged || zoomChanged,
- additionalWidth = 0, additionalHeight = 0, shouldResizeCanvas = false;
- if (dimensionsChanged) {
- var canvasWidth = this._cacheCanvas.width,
- canvasHeight = this._cacheCanvas.height,
- sizeGrowing = width > canvasWidth || height > canvasHeight,
- sizeShrinking = (width < canvasWidth * 0.9 || height < canvasHeight * 0.9) &&
- canvasWidth > minCacheSize && canvasHeight > minCacheSize;
- shouldResizeCanvas = sizeGrowing || sizeShrinking;
- if (sizeGrowing && !dims.capped && (width > minCacheSize || height > minCacheSize)) {
- additionalWidth = width * 0.1;
- additionalHeight = height * 0.1;
- }
- }
- if (shouldRedraw) {
- if (shouldResizeCanvas) {
- canvas.width = Math.ceil(width + additionalWidth);
- canvas.height = Math.ceil(height + additionalHeight);
- }
- else {
- this._cacheContext.setTransform(1, 0, 0, 1, 0, 0);
- this._cacheContext.clearRect(0, 0, canvas.width, canvas.height);
- }
- drawingWidth = dims.x * zoomX / 2;
- drawingHeight = dims.y * zoomY / 2;
- this.cacheTranslationX = Math.round(canvas.width / 2 - drawingWidth) + drawingWidth;
- this.cacheTranslationY = Math.round(canvas.height / 2 - drawingHeight) + drawingHeight;
- this.cacheWidth = width;
- this.cacheHeight = height;
- this._cacheContext.translate(this.cacheTranslationX, this.cacheTranslationY);
- this._cacheContext.scale(zoomX, zoomY);
- this.zoomX = zoomX;
- this.zoomY = zoomY;
- return true;
- }
- return false;
- },
-
- setOptions: function(options) {
- this._setOptions(options);
- this._initGradient(options.fill, 'fill');
- this._initGradient(options.stroke, 'stroke');
- this._initClipping(options);
- this._initPattern(options.fill, 'fill');
- this._initPattern(options.stroke, 'stroke');
- },
-
- transform: function(ctx) {
- var m;
- if (this.group && !this.group._transformDone) {
- m = this.calcTransformMatrix();
- }
- else {
- m = this.calcOwnMatrix();
- }
- ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]);
- },
-
- toObject: function(propertiesToInclude) {
- var NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS,
- object = {
- type: this.type,
- version: fabric.version,
- originX: this.originX,
- originY: this.originY,
- left: toFixed(this.left, NUM_FRACTION_DIGITS),
- top: toFixed(this.top, NUM_FRACTION_DIGITS),
- width: toFixed(this.width, NUM_FRACTION_DIGITS),
- height: toFixed(this.height, NUM_FRACTION_DIGITS),
- fill: (this.fill && this.fill.toObject) ? this.fill.toObject() : this.fill,
- stroke: (this.stroke && this.stroke.toObject) ? this.stroke.toObject() : this.stroke,
- strokeWidth: toFixed(this.strokeWidth, NUM_FRACTION_DIGITS),
- strokeDashArray: this.strokeDashArray ? this.strokeDashArray.concat() : this.strokeDashArray,
- strokeLineCap: this.strokeLineCap,
- strokeLineJoin: this.strokeLineJoin,
- strokeMiterLimit: toFixed(this.strokeMiterLimit, NUM_FRACTION_DIGITS),
- scaleX: toFixed(this.scaleX, NUM_FRACTION_DIGITS),
- scaleY: toFixed(this.scaleY, NUM_FRACTION_DIGITS),
- angle: toFixed(this.angle, NUM_FRACTION_DIGITS),
- flipX: this.flipX,
- flipY: this.flipY,
- opacity: toFixed(this.opacity, NUM_FRACTION_DIGITS),
- shadow: (this.shadow && this.shadow.toObject) ? this.shadow.toObject() : this.shadow,
- visible: this.visible,
- clipTo: this.clipTo && String(this.clipTo),
- backgroundColor: this.backgroundColor,
- fillRule: this.fillRule,
- paintFirst: this.paintFirst,
- globalCompositeOperation: this.globalCompositeOperation,
- transformMatrix: this.transformMatrix ? this.transformMatrix.concat() : null,
- skewX: toFixed(this.skewX, NUM_FRACTION_DIGITS),
- skewY: toFixed(this.skewY, NUM_FRACTION_DIGITS)
- };
- fabric.util.populateWithProperties(this, object, propertiesToInclude);
- if (!this.includeDefaultValues) {
- object = this._removeDefaultValues(object);
- }
- return object;
- },
-
- toDatalessObject: function(propertiesToInclude) {
-
- return this.toObject(propertiesToInclude);
- },
-
- _removeDefaultValues: function(object) {
- var prototype = fabric.util.getKlass(object.type).prototype,
- stateProperties = prototype.stateProperties;
- stateProperties.forEach(function(prop) {
- if (object[prop] === prototype[prop]) {
- delete object[prop];
- }
- var isArray = Object.prototype.toString.call(object[prop]) === '[object Array]' &&
- Object.prototype.toString.call(prototype[prop]) === '[object Array]';
-
- if (isArray && object[prop].length === 0 && prototype[prop].length === 0) {
- delete object[prop];
- }
- });
- return object;
- },
-
- toString: function() {
- return '#<fabric.' + capitalize(this.type) + '>';
- },
-
- getObjectScaling: function() {
- var scaleX = this.scaleX, scaleY = this.scaleY;
- if (this.group) {
- var scaling = this.group.getObjectScaling();
- scaleX *= scaling.scaleX;
- scaleY *= scaling.scaleY;
- }
- return { scaleX: scaleX, scaleY: scaleY };
- },
-
- getObjectOpacity: function() {
- var opacity = this.opacity;
- if (this.group) {
- opacity *= this.group.getObjectOpacity();
- }
- return opacity;
- },
-
- _set: function(key, value) {
- var shouldConstrainValue = (key === 'scaleX' || key === 'scaleY'),
- isChanged = this[key] !== value, groupNeedsUpdate = false;
- if (shouldConstrainValue) {
- value = this._constrainScale(value);
- }
- if (key === 'scaleX' && value < 0) {
- this.flipX = !this.flipX;
- value *= -1;
- }
- else if (key === 'scaleY' && value < 0) {
- this.flipY = !this.flipY;
- value *= -1;
- }
- else if (key === 'shadow' && value && !(value instanceof fabric.Shadow)) {
- value = new fabric.Shadow(value);
- }
- else if (key === 'dirty' && this.group) {
- this.group.set('dirty', value);
- }
- this[key] = value;
- if (isChanged) {
- groupNeedsUpdate = this.group && this.group.isOnACache();
- if (this.cacheProperties.indexOf(key) > -1) {
- this.dirty = true;
- groupNeedsUpdate && this.group.set('dirty', true);
- }
- else if (groupNeedsUpdate && this.stateProperties.indexOf(key) > -1) {
- this.group.set('dirty', true);
- }
- }
- return this;
- },
-
- setOnGroup: function() {
-
- },
-
- getViewportTransform: function() {
- if (this.canvas && this.canvas.viewportTransform) {
- return this.canvas.viewportTransform;
- }
- return fabric.iMatrix.concat();
- },
-
- isNotVisible: function() {
- return this.opacity === 0 || (this.width === 0 && this.height === 0) || !this.visible;
- },
-
- render: function(ctx) {
-
- if (this.isNotVisible()) {
- return;
- }
- if (this.canvas && this.canvas.skipOffscreen && !this.group && !this.isOnScreen()) {
- return;
- }
- ctx.save();
- this._setupCompositeOperation(ctx);
- this.drawSelectionBackground(ctx);
- this.transform(ctx);
- this._setOpacity(ctx);
- this._setShadow(ctx, this);
- if (this.transformMatrix) {
- ctx.transform.apply(ctx, this.transformMatrix);
- }
- this.clipTo && fabric.util.clipContext(this, ctx);
- if (this.shouldCache()) {
- if (!this._cacheCanvas) {
- this._createCacheCanvas();
- }
- if (this.isCacheDirty()) {
- this.statefullCache && this.saveState({ propertySet: 'cacheProperties' });
- this.drawObject(this._cacheContext);
- this.dirty = false;
- }
- this.drawCacheOnCanvas(ctx);
- }
- else {
- this._removeCacheCanvas();
- this.dirty = false;
- this.drawObject(ctx);
- if (this.objectCaching && this.statefullCache) {
- this.saveState({ propertySet: 'cacheProperties' });
- }
- }
- this.clipTo && ctx.restore();
- ctx.restore();
- },
-
- _removeCacheCanvas: function() {
- this._cacheCanvas = null;
- this.cacheWidth = 0;
- this.cacheHeight = 0;
- },
-
- needsItsOwnCache: function() {
- if (this.paintFirst === 'stroke' && typeof this.shadow === 'object') {
- return true;
- }
- return false;
- },
-
- shouldCache: function() {
- this.ownCaching = this.objectCaching &&
- (!this.group || this.needsItsOwnCache() || !this.group.isOnACache());
- return this.ownCaching;
- },
-
- willDrawShadow: function() {
- return !!this.shadow && (this.shadow.offsetX !== 0 || this.shadow.offsetY !== 0);
- },
-
- drawObject: function(ctx) {
- this._renderBackground(ctx);
- this._setStrokeStyles(ctx, this);
- this._setFillStyles(ctx, this);
- this._render(ctx);
- },
-
- drawCacheOnCanvas: function(ctx) {
- ctx.scale(1 / this.zoomX, 1 / this.zoomY);
- ctx.drawImage(this._cacheCanvas, -this.cacheTranslationX, -this.cacheTranslationY);
- },
-
- isCacheDirty: function(skipCanvas) {
- if (this.isNotVisible()) {
- return false;
- }
- if (this._cacheCanvas && !skipCanvas && this._updateCacheCanvas()) {
-
- return true;
- }
- else {
- if (this.dirty || (this.statefullCache && this.hasStateChanged('cacheProperties'))) {
- if (this._cacheCanvas && !skipCanvas) {
- var width = this.cacheWidth / this.zoomX;
- var height = this.cacheHeight / this.zoomY;
- this._cacheContext.clearRect(-width / 2, -height / 2, width, height);
- }
- return true;
- }
- }
- return false;
- },
-
- _renderBackground: function(ctx) {
- if (!this.backgroundColor) {
- return;
- }
- var dim = this._getNonTransformedDimensions();
- ctx.fillStyle = this.backgroundColor;
- ctx.fillRect(
- -dim.x / 2,
- -dim.y / 2,
- dim.x,
- dim.y
- );
-
-
- this._removeShadow(ctx);
- },
-
- _setOpacity: function(ctx) {
- if (this.group && !this.group._transformDone) {
- ctx.globalAlpha = this.getObjectOpacity();
- }
- else {
- ctx.globalAlpha *= this.opacity;
- }
- },
- _setStrokeStyles: function(ctx, decl) {
- if (decl.stroke) {
- ctx.lineWidth = decl.strokeWidth;
- ctx.lineCap = decl.strokeLineCap;
- ctx.lineJoin = decl.strokeLineJoin;
- ctx.miterLimit = decl.strokeMiterLimit;
- ctx.strokeStyle = decl.stroke.toLive
- ? decl.stroke.toLive(ctx, this)
- : decl.stroke;
- }
- },
- _setFillStyles: function(ctx, decl) {
- if (decl.fill) {
- ctx.fillStyle = decl.fill.toLive
- ? decl.fill.toLive(ctx, this)
- : decl.fill;
- }
- },
-
- _setLineDash: function(ctx, dashArray, alternative) {
- if (!dashArray) {
- return;
- }
-
- if (1 & dashArray.length) {
- dashArray.push.apply(dashArray, dashArray);
- }
- if (supportsLineDash) {
- ctx.setLineDash(dashArray);
- }
- else {
- alternative && alternative(ctx);
- }
- },
-
- _renderControls: function(ctx, styleOverride) {
- var vpt = this.getViewportTransform(),
- matrix = this.calcTransformMatrix(),
- options, drawBorders, drawControls;
- styleOverride = styleOverride || { };
- drawBorders = typeof styleOverride.hasBorders !== 'undefined' ? styleOverride.hasBorders : this.hasBorders;
- drawControls = typeof styleOverride.hasControls !== 'undefined' ? styleOverride.hasControls : this.hasControls;
- matrix = fabric.util.multiplyTransformMatrices(vpt, matrix);
- options = fabric.util.qrDecompose(matrix);
- ctx.save();
- ctx.translate(options.translateX, options.translateY);
- ctx.lineWidth = 1 * this.borderScaleFactor;
- if (!this.group) {
- ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1;
- }
- if (styleOverride.forActiveSelection) {
- ctx.rotate(degreesToRadians(options.angle));
- drawBorders && this.drawBordersInGroup(ctx, options, styleOverride);
- }
- else {
- ctx.rotate(degreesToRadians(this.angle));
- drawBorders && this.drawBorders(ctx, styleOverride);
- }
- drawControls && this.drawControls(ctx, styleOverride);
- ctx.restore();
- },
-
- _setShadow: function(ctx) {
- if (!this.shadow) {
- return;
- }
- var multX = (this.canvas && this.canvas.viewportTransform[0]) || 1,
- multY = (this.canvas && this.canvas.viewportTransform[3]) || 1,
- scaling = this.getObjectScaling();
- if (this.canvas && this.canvas._isRetinaScaling()) {
- multX *= fabric.devicePixelRatio;
- multY *= fabric.devicePixelRatio;
- }
- ctx.shadowColor = this.shadow.color;
- ctx.shadowBlur = this.shadow.blur * fabric.browserShadowBlurConstant *
- (multX + multY) * (scaling.scaleX + scaling.scaleY) / 4;
- ctx.shadowOffsetX = this.shadow.offsetX * multX * scaling.scaleX;
- ctx.shadowOffsetY = this.shadow.offsetY * multY * scaling.scaleY;
- },
-
- _removeShadow: function(ctx) {
- if (!this.shadow) {
- return;
- }
- ctx.shadowColor = '';
- ctx.shadowBlur = ctx.shadowOffsetX = ctx.shadowOffsetY = 0;
- },
-
- _applyPatternGradientTransform: function(ctx, filler) {
- if (!filler || !filler.toLive) {
- return { offsetX: 0, offsetY: 0 };
- }
- var t = filler.gradientTransform || filler.patternTransform;
- var offsetX = -this.width / 2 + filler.offsetX || 0,
- offsetY = -this.height / 2 + filler.offsetY || 0;
- ctx.translate(offsetX, offsetY);
- if (t) {
- ctx.transform(t[0], t[1], t[2], t[3], t[4], t[5]);
- }
- return { offsetX: offsetX, offsetY: offsetY };
- },
-
- _renderPaintInOrder: function(ctx) {
- if (this.paintFirst === 'stroke') {
- this._renderStroke(ctx);
- this._renderFill(ctx);
- }
- else {
- this._renderFill(ctx);
- this._renderStroke(ctx);
- }
- },
-
- _renderFill: function(ctx) {
- if (!this.fill) {
- return;
- }
- ctx.save();
- this._applyPatternGradientTransform(ctx, this.fill);
- if (this.fillRule === 'evenodd') {
- ctx.fill('evenodd');
- }
- else {
- ctx.fill();
- }
- ctx.restore();
- },
- _renderStroke: function(ctx) {
- if (!this.stroke || this.strokeWidth === 0) {
- return;
- }
- if (this.shadow && !this.shadow.affectStroke) {
- this._removeShadow(ctx);
- }
- ctx.save();
- this._setLineDash(ctx, this.strokeDashArray, this._renderDashedStroke);
- this._applyPatternGradientTransform(ctx, this.stroke);
- ctx.stroke();
- ctx.restore();
- },
-
- _findCenterFromElement: function() {
- return { x: this.left + this.width / 2, y: this.top + this.height / 2 };
- },
-
- _assignTransformMatrixProps: function() {
- if (this.transformMatrix) {
- var options = fabric.util.qrDecompose(this.transformMatrix);
- this.flipX = false;
- this.flipY = false;
- this.set('scaleX', options.scaleX);
- this.set('scaleY', options.scaleY);
- this.angle = options.angle;
- this.skewX = options.skewX;
- this.skewY = 0;
- }
- },
-
- _removeTransformMatrix: function(preserveAspectRatioOptions) {
- var center = this._findCenterFromElement();
- if (this.transformMatrix) {
- this._assignTransformMatrixProps();
- center = fabric.util.transformPoint(center, this.transformMatrix);
- }
- this.transformMatrix = null;
- if (preserveAspectRatioOptions) {
- this.scaleX *= preserveAspectRatioOptions.scaleX;
- this.scaleY *= preserveAspectRatioOptions.scaleY;
- this.cropX = preserveAspectRatioOptions.cropX;
- this.cropY = preserveAspectRatioOptions.cropY;
- center.x += preserveAspectRatioOptions.offsetLeft;
- center.y += preserveAspectRatioOptions.offsetTop;
- this.width = preserveAspectRatioOptions.width;
- this.height = preserveAspectRatioOptions.height;
- }
- this.setPositionByOrigin(center, 'center', 'center');
- },
-
- clone: function(callback, propertiesToInclude) {
- var objectForm = this.toObject(propertiesToInclude);
- if (this.constructor.fromObject) {
- this.constructor.fromObject(objectForm, callback);
- }
- else {
- fabric.Object._fromObject('Object', objectForm, callback);
- }
- },
-
- cloneAsImage: function(callback, options) {
- var dataUrl = this.toDataURL(options);
- fabric.util.loadImage(dataUrl, function(img) {
- if (callback) {
- callback(new fabric.Image(img));
- }
- });
- return this;
- },
-
- toDataURL: function(options) {
- options || (options = { });
- var el = fabric.util.createCanvasElement(),
- boundingRect = this.getBoundingRect();
- el.width = boundingRect.width;
- el.height = boundingRect.height;
- fabric.util.wrapElement(el, 'div');
- var canvas = new fabric.StaticCanvas(el, {
- enableRetinaScaling: options.enableRetinaScaling,
- renderOnAddRemove: false,
- skipOffscreen: false,
- });
-
- if (options.format === 'jpg') {
- options.format = 'jpeg';
- }
- if (options.format === 'jpeg') {
- canvas.backgroundColor = '#fff';
- }
- var origParams = {
- left: this.left,
- top: this.top
- };
- this.setPositionByOrigin(new fabric.Point(canvas.width / 2, canvas.height / 2), 'center', 'center');
- var originalCanvas = this.canvas;
- canvas.add(this);
- var data = canvas.toDataURL(options);
- this.set(origParams).setCoords();
- this.canvas = originalCanvas;
-
-
-
- canvas._objects = [];
- canvas.dispose();
- canvas = null;
- return data;
- },
-
- isType: function(type) {
- return this.type === type;
- },
-
- complexity: function() {
- return 1;
- },
-
- toJSON: function(propertiesToInclude) {
-
- return this.toObject(propertiesToInclude);
- },
-
- setGradient: function(property, options) {
- options || (options = { });
- var gradient = { colorStops: [] };
- gradient.type = options.type || (options.r1 || options.r2 ? 'radial' : 'linear');
- gradient.coords = {
- x1: options.x1,
- y1: options.y1,
- x2: options.x2,
- y2: options.y2
- };
- if (options.r1 || options.r2) {
- gradient.coords.r1 = options.r1;
- gradient.coords.r2 = options.r2;
- }
- gradient.gradientTransform = options.gradientTransform;
- fabric.Gradient.prototype.addColorStop.call(gradient, options.colorStops);
- return this.set(property, fabric.Gradient.forObject(this, gradient));
- },
-
- setPatternFill: function(options) {
- return this.set('fill', new fabric.Pattern(options));
- },
-
- setShadow: function(options) {
- return this.set('shadow', options ? new fabric.Shadow(options) : null);
- },
-
- setColor: function(color) {
- this.set('fill', color);
- return this;
- },
-
- rotate: function(angle) {
- var shouldCenterOrigin = (this.originX !== 'center' || this.originY !== 'center') && this.centeredRotation;
- if (shouldCenterOrigin) {
- this._setOriginToCenter();
- }
- this.set('angle', angle);
- if (shouldCenterOrigin) {
- this._resetOrigin();
- }
- return this;
- },
-
- centerH: function () {
- this.canvas && this.canvas.centerObjectH(this);
- return this;
- },
-
- viewportCenterH: function () {
- this.canvas && this.canvas.viewportCenterObjectH(this);
- return this;
- },
-
- centerV: function () {
- this.canvas && this.canvas.centerObjectV(this);
- return this;
- },
-
- viewportCenterV: function () {
- this.canvas && this.canvas.viewportCenterObjectV(this);
- return this;
- },
-
- center: function () {
- this.canvas && this.canvas.centerObject(this);
- return this;
- },
-
- viewportCenter: function () {
- this.canvas && this.canvas.viewportCenterObject(this);
- return this;
- },
-
- getLocalPointer: function(e, pointer) {
- pointer = pointer || this.canvas.getPointer(e);
- var pClicked = new fabric.Point(pointer.x, pointer.y),
- objectLeftTop = this._getLeftTopCoords();
- if (this.angle) {
- pClicked = fabric.util.rotatePoint(
- pClicked, objectLeftTop, degreesToRadians(-this.angle));
- }
- return {
- x: pClicked.x - objectLeftTop.x,
- y: pClicked.y - objectLeftTop.y
- };
- },
-
- _setupCompositeOperation: function (ctx) {
- if (this.globalCompositeOperation) {
- ctx.globalCompositeOperation = this.globalCompositeOperation;
- }
- }
- });
- fabric.util.createAccessors && fabric.util.createAccessors(fabric.Object);
- extend(fabric.Object.prototype, fabric.Observable);
-
- fabric.Object.NUM_FRACTION_DIGITS = 2;
- fabric.Object._fromObject = function(className, object, callback, extraParam) {
- var klass = fabric[className];
- object = clone(object, true);
- fabric.util.enlivenPatterns([object.fill, object.stroke], function(patterns) {
- if (typeof patterns[0] !== 'undefined') {
- object.fill = patterns[0];
- }
- if (typeof patterns[1] !== 'undefined') {
- object.stroke = patterns[1];
- }
- var instance = extraParam ? new klass(object[extraParam], object) : new klass(object);
- callback && callback(instance);
- });
- };
-
- fabric.Object.__uid = 0;
- })(typeof exports !== 'undefined' ? exports : this);
- (function() {
- var degreesToRadians = fabric.util.degreesToRadians,
- originXOffset = {
- left: -0.5,
- center: 0,
- right: 0.5
- },
- originYOffset = {
- top: -0.5,
- center: 0,
- bottom: 0.5
- };
- fabric.util.object.extend(fabric.Object.prototype, {
-
- translateToGivenOrigin: function(point, fromOriginX, fromOriginY, toOriginX, toOriginY) {
- var x = point.x,
- y = point.y,
- offsetX, offsetY, dim;
- if (typeof fromOriginX === 'string') {
- fromOriginX = originXOffset[fromOriginX];
- }
- else {
- fromOriginX -= 0.5;
- }
- if (typeof toOriginX === 'string') {
- toOriginX = originXOffset[toOriginX];
- }
- else {
- toOriginX -= 0.5;
- }
- offsetX = toOriginX - fromOriginX;
- if (typeof fromOriginY === 'string') {
- fromOriginY = originYOffset[fromOriginY];
- }
- else {
- fromOriginY -= 0.5;
- }
- if (typeof toOriginY === 'string') {
- toOriginY = originYOffset[toOriginY];
- }
- else {
- toOriginY -= 0.5;
- }
- offsetY = toOriginY - fromOriginY;
- if (offsetX || offsetY) {
- dim = this._getTransformedDimensions();
- x = point.x + offsetX * dim.x;
- y = point.y + offsetY * dim.y;
- }
- return new fabric.Point(x, y);
- },
-
- translateToCenterPoint: function(point, originX, originY) {
- var p = this.translateToGivenOrigin(point, originX, originY, 'center', 'center');
- if (this.angle) {
- return fabric.util.rotatePoint(p, point, degreesToRadians(this.angle));
- }
- return p;
- },
-
- translateToOriginPoint: function(center, originX, originY) {
- var p = this.translateToGivenOrigin(center, 'center', 'center', originX, originY);
- if (this.angle) {
- return fabric.util.rotatePoint(p, center, degreesToRadians(this.angle));
- }
- return p;
- },
-
- getCenterPoint: function() {
- var leftTop = new fabric.Point(this.left, this.top);
- return this.translateToCenterPoint(leftTop, this.originX, this.originY);
- },
-
-
-
-
-
- getPointByOrigin: function(originX, originY) {
- var center = this.getCenterPoint();
- return this.translateToOriginPoint(center, originX, originY);
- },
-
- toLocalPoint: function(point, originX, originY) {
- var center = this.getCenterPoint(),
- p, p2;
- if (typeof originX !== 'undefined' && typeof originY !== 'undefined' ) {
- p = this.translateToGivenOrigin(center, 'center', 'center', originX, originY);
- }
- else {
- p = new fabric.Point(this.left, this.top);
- }
- p2 = new fabric.Point(point.x, point.y);
- if (this.angle) {
- p2 = fabric.util.rotatePoint(p2, center, -degreesToRadians(this.angle));
- }
- return p2.subtractEquals(p);
- },
-
-
-
-
-
- setPositionByOrigin: function(pos, originX, originY) {
- var center = this.translateToCenterPoint(pos, originX, originY),
- position = this.translateToOriginPoint(center, this.originX, this.originY);
- this.set('left', position.x);
- this.set('top', position.y);
- },
-
- adjustPosition: function(to) {
- var angle = degreesToRadians(this.angle),
- hypotFull = this.getScaledWidth(),
- xFull = fabric.util.cos(angle) * hypotFull,
- yFull = fabric.util.sin(angle) * hypotFull,
- offsetFrom, offsetTo;
-
- if (typeof this.originX === 'string') {
- offsetFrom = originXOffset[this.originX];
- }
- else {
- offsetFrom = this.originX - 0.5;
- }
- if (typeof to === 'string') {
- offsetTo = originXOffset[to];
- }
- else {
- offsetTo = to - 0.5;
- }
- this.left += xFull * (offsetTo - offsetFrom);
- this.top += yFull * (offsetTo - offsetFrom);
- this.setCoords();
- this.originX = to;
- },
-
- _setOriginToCenter: function() {
- this._originalOriginX = this.originX;
- this._originalOriginY = this.originY;
- var center = this.getCenterPoint();
- this.originX = 'center';
- this.originY = 'center';
- this.left = center.x;
- this.top = center.y;
- },
-
- _resetOrigin: function() {
- var originPoint = this.translateToOriginPoint(
- this.getCenterPoint(),
- this._originalOriginX,
- this._originalOriginY);
- this.originX = this._originalOriginX;
- this.originY = this._originalOriginY;
- this.left = originPoint.x;
- this.top = originPoint.y;
- this._originalOriginX = null;
- this._originalOriginY = null;
- },
-
- _getLeftTopCoords: function() {
- return this.translateToOriginPoint(this.getCenterPoint(), 'left', 'top');
- },
- });
- })();
- (function() {
- function getCoords(coords) {
- return [
- new fabric.Point(coords.tl.x, coords.tl.y),
- new fabric.Point(coords.tr.x, coords.tr.y),
- new fabric.Point(coords.br.x, coords.br.y),
- new fabric.Point(coords.bl.x, coords.bl.y)
- ];
- }
- var degreesToRadians = fabric.util.degreesToRadians,
- multiplyMatrices = fabric.util.multiplyTransformMatrices,
- transformPoint = fabric.util.transformPoint;
- fabric.util.object.extend(fabric.Object.prototype, {
-
- oCoords: null,
-
- aCoords: null,
-
- ownMatrixCache: null,
-
- matrixCache: null,
-
- getCoords: function(absolute, calculate) {
- if (!this.oCoords) {
- this.setCoords();
- }
- var coords = absolute ? this.aCoords : this.oCoords;
- return getCoords(calculate ? this.calcCoords(absolute) : coords);
- },
-
- intersectsWithRect: function(pointTL, pointBR, absolute, calculate) {
- var coords = this.getCoords(absolute, calculate),
- intersection = fabric.Intersection.intersectPolygonRectangle(
- coords,
- pointTL,
- pointBR
- );
- return intersection.status === 'Intersection';
- },
-
- intersectsWithObject: function(other, absolute, calculate) {
- var intersection = fabric.Intersection.intersectPolygonPolygon(
- this.getCoords(absolute, calculate),
- other.getCoords(absolute, calculate)
- );
- return intersection.status === 'Intersection'
- || other.isContainedWithinObject(this, absolute, calculate)
- || this.isContainedWithinObject(other, absolute, calculate);
- },
-
- isContainedWithinObject: function(other, absolute, calculate) {
- var points = this.getCoords(absolute, calculate),
- i = 0, lines = other._getImageLines(
- calculate ? other.calcCoords(absolute) : absolute ? other.aCoords : other.oCoords
- );
- for (; i < 4; i++) {
- if (!other.containsPoint(points[i], lines)) {
- return false;
- }
- }
- return true;
- },
-
- isContainedWithinRect: function(pointTL, pointBR, absolute, calculate) {
- var boundingRect = this.getBoundingRect(absolute, calculate);
- return (
- boundingRect.left >= pointTL.x &&
- boundingRect.left + boundingRect.width <= pointBR.x &&
- boundingRect.top >= pointTL.y &&
- boundingRect.top + boundingRect.height <= pointBR.y
- );
- },
-
- containsPoint: function(point, lines, absolute, calculate) {
- var lines = lines || this._getImageLines(
- calculate ? this.calcCoords(absolute) : absolute ? this.aCoords : this.oCoords
- ),
- xPoints = this._findCrossPoints(point, lines);
-
- return (xPoints !== 0 && xPoints % 2 === 1);
- },
-
- isOnScreen: function(calculate) {
- if (!this.canvas) {
- return false;
- }
- var pointTL = this.canvas.vptCoords.tl, pointBR = this.canvas.vptCoords.br;
- var points = this.getCoords(true, calculate), point;
- for (var i = 0; i < 4; i++) {
- point = points[i];
- if (point.x <= pointBR.x && point.x >= pointTL.x && point.y <= pointBR.y && point.y >= pointTL.y) {
- return true;
- }
- }
-
- if (this.intersectsWithRect(pointTL, pointBR, true, calculate)) {
- return true;
- }
- return this._containsCenterOfCanvas(pointTL, pointBR, calculate);
- },
-
- _containsCenterOfCanvas: function(pointTL, pointBR, calculate) {
-
- var centerPoint = { x: (pointTL.x + pointBR.x) / 2, y: (pointTL.y + pointBR.y) / 2 };
- if (this.containsPoint(centerPoint, null, true, calculate)) {
- return true;
- }
- return false;
- },
-
- isPartiallyOnScreen: function(calculate) {
- if (!this.canvas) {
- return false;
- }
- var pointTL = this.canvas.vptCoords.tl, pointBR = this.canvas.vptCoords.br;
- if (this.intersectsWithRect(pointTL, pointBR, true, calculate)) {
- return true;
- }
- return this._containsCenterOfCanvas(pointTL, pointBR, calculate);
- },
-
- _getImageLines: function(oCoords) {
- return {
- topline: {
- o: oCoords.tl,
- d: oCoords.tr
- },
- rightline: {
- o: oCoords.tr,
- d: oCoords.br
- },
- bottomline: {
- o: oCoords.br,
- d: oCoords.bl
- },
- leftline: {
- o: oCoords.bl,
- d: oCoords.tl
- }
- };
- },
-
-
- _findCrossPoints: function(point, lines) {
- var b1, b2, a1, a2, xi,
- xcount = 0,
- iLine;
- for (var lineKey in lines) {
- iLine = lines[lineKey];
-
- if ((iLine.o.y < point.y) && (iLine.d.y < point.y)) {
- continue;
- }
-
- if ((iLine.o.y >= point.y) && (iLine.d.y >= point.y)) {
- continue;
- }
-
- if ((iLine.o.x === iLine.d.x) && (iLine.o.x >= point.x)) {
- xi = iLine.o.x;
-
- }
-
- else {
- b1 = 0;
- b2 = (iLine.d.y - iLine.o.y) / (iLine.d.x - iLine.o.x);
- a1 = point.y - b1 * point.x;
- a2 = iLine.o.y - b2 * iLine.o.x;
- xi = -(a1 - a2) / (b1 - b2);
-
- }
-
- if (xi >= point.x) {
- xcount += 1;
- }
-
- if (xcount === 2) {
- break;
- }
- }
- return xcount;
- },
-
- getBoundingRect: function(absolute, calculate) {
- var coords = this.getCoords(absolute, calculate);
- return fabric.util.makeBoundingBoxFromPoints(coords);
- },
-
- getScaledWidth: function() {
- return this._getTransformedDimensions().x;
- },
-
- getScaledHeight: function() {
- return this._getTransformedDimensions().y;
- },
-
- _constrainScale: function(value) {
- if (Math.abs(value) < this.minScaleLimit) {
- if (value < 0) {
- return -this.minScaleLimit;
- }
- else {
- return this.minScaleLimit;
- }
- }
- else if (value === 0) {
- return 0.0001;
- }
- return value;
- },
-
- scale: function(value) {
- this._set('scaleX', value);
- this._set('scaleY', value);
- return this.setCoords();
- },
-
- scaleToWidth: function(value, absolute) {
-
- var boundingRectFactor = this.getBoundingRect(absolute).width / this.getScaledWidth();
- return this.scale(value / this.width / boundingRectFactor);
- },
-
- scaleToHeight: function(value, absolute) {
-
- var boundingRectFactor = this.getBoundingRect(absolute).height / this.getScaledHeight();
- return this.scale(value / this.height / boundingRectFactor);
- },
-
- calcCoords: function(absolute) {
- var rotateMatrix = this._calcRotateMatrix(),
- translateMatrix = this._calcTranslateMatrix(),
- startMatrix = multiplyMatrices(translateMatrix, rotateMatrix),
- vpt = this.getViewportTransform(),
- finalMatrix = absolute ? startMatrix : multiplyMatrices(vpt, startMatrix),
- dim = this._getTransformedDimensions(),
- w = dim.x / 2, h = dim.y / 2,
- tl = transformPoint({ x: -w, y: -h }, finalMatrix),
- tr = transformPoint({ x: w, y: -h }, finalMatrix),
- bl = transformPoint({ x: -w, y: h }, finalMatrix),
- br = transformPoint({ x: w, y: h }, finalMatrix);
- if (!absolute) {
- var padding = this.padding, angle = degreesToRadians(this.angle),
- cos = fabric.util.cos(angle), sin = fabric.util.sin(angle),
- cosP = cos * padding, sinP = sin * padding, cosPSinP = cosP + sinP,
- cosPMinusSinP = cosP - sinP;
- if (padding) {
- tl.x -= cosPMinusSinP;
- tl.y -= cosPSinP;
- tr.x += cosPSinP;
- tr.y -= cosPMinusSinP;
- bl.x -= cosPSinP;
- bl.y += cosPMinusSinP;
- br.x += cosPMinusSinP;
- br.y += cosPSinP;
- }
- var ml = new fabric.Point((tl.x + bl.x) / 2, (tl.y + bl.y) / 2),
- mt = new fabric.Point((tr.x + tl.x) / 2, (tr.y + tl.y) / 2),
- mr = new fabric.Point((br.x + tr.x) / 2, (br.y + tr.y) / 2),
- mb = new fabric.Point((br.x + bl.x) / 2, (br.y + bl.y) / 2),
- mtr = new fabric.Point(mt.x + sin * this.rotatingPointOffset, mt.y - cos * this.rotatingPointOffset);
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- var coords = {
-
- tl: tl, tr: tr, br: br, bl: bl,
- };
- if (!absolute) {
-
- coords.ml = ml;
- coords.mt = mt;
- coords.mr = mr;
- coords.mb = mb;
-
- coords.mtr = mtr;
- }
- return coords;
- },
-
- setCoords: function(ignoreZoom, skipAbsolute) {
- this.oCoords = this.calcCoords(ignoreZoom);
- if (!skipAbsolute) {
- this.aCoords = this.calcCoords(true);
- }
-
- ignoreZoom || (this._setCornerCoords && this._setCornerCoords());
- return this;
- },
-
- _calcRotateMatrix: function() {
- if (this.angle) {
- var theta = degreesToRadians(this.angle), cos = fabric.util.cos(theta), sin = fabric.util.sin(theta);
- return [cos, sin, -sin, cos, 0, 0];
- }
- return fabric.iMatrix.concat();
- },
-
- _calcTranslateMatrix: function() {
- var center = this.getCenterPoint();
- return [1, 0, 0, 1, center.x, center.y];
- },
- transformMatrixKey: function(skipGroup) {
- var sep = '_', prefix = '';
- if (!skipGroup && this.group) {
- prefix = this.group.transformMatrixKey(skipGroup) + sep;
- };
- return prefix + this.top + sep + this.left + sep + this.scaleX + sep + this.scaleY +
- sep + this.skewX + sep + this.skewY + sep + this.angle + sep + this.originX + sep + this.originY +
- sep + this.width + sep + this.height + sep + this.strokeWidth + this.flipX + this.flipY;
- },
-
- calcTransformMatrix: function(skipGroup) {
- if (skipGroup) {
- return this.calcOwnMatrix();
- }
- var key = this.transformMatrixKey(), cache = this.matrixCache || (this.matrixCache = {});
- if (cache.key === key) {
- return cache.value;
- }
- var matrix = this.calcOwnMatrix();
- if (this.group) {
- matrix = multiplyMatrices(this.group.calcTransformMatrix(), matrix);
- }
- cache.key = key;
- cache.value = matrix;
- return matrix;
- },
- calcOwnMatrix: function() {
- var key = this.transformMatrixKey(true), cache = this.ownMatrixCache || (this.ownMatrixCache = {});
- if (cache.key === key) {
- return cache.value;
- }
- var matrix = this._calcTranslateMatrix(),
- rotateMatrix,
- dimensionMatrix = this._calcDimensionsTransformMatrix(this.skewX, this.skewY, true);
- if (this.angle) {
- rotateMatrix = this._calcRotateMatrix();
- matrix = multiplyMatrices(matrix, rotateMatrix);
- }
- matrix = multiplyMatrices(matrix, dimensionMatrix);
- cache.key = key;
- cache.value = matrix;
- return matrix;
- },
- _calcDimensionsTransformMatrix: function(skewX, skewY, flipping) {
- var skewMatrix,
- scaleX = this.scaleX * (flipping && this.flipX ? -1 : 1),
- scaleY = this.scaleY * (flipping && this.flipY ? -1 : 1),
- scaleMatrix = [scaleX, 0, 0, scaleY, 0, 0];
- if (skewX) {
- skewMatrix = [1, 0, Math.tan(degreesToRadians(skewX)), 1];
- scaleMatrix = multiplyMatrices(scaleMatrix, skewMatrix, true);
- }
- if (skewY) {
- skewMatrix = [1, Math.tan(degreesToRadians(skewY)), 0, 1];
- scaleMatrix = multiplyMatrices(scaleMatrix, skewMatrix, true);
- }
- return scaleMatrix;
- },
-
- _getNonTransformedDimensions: function() {
- var strokeWidth = this.strokeWidth,
- w = this.width + strokeWidth,
- h = this.height + strokeWidth;
- return { x: w, y: h };
- },
-
- _getTransformedDimensions: function(skewX, skewY) {
- if (typeof skewX === 'undefined') {
- skewX = this.skewX;
- }
- if (typeof skewY === 'undefined') {
- skewY = this.skewY;
- }
- var dimensions = this._getNonTransformedDimensions();
- if (skewX === 0 && skewY === 0) {
- return { x: dimensions.x * this.scaleX, y: dimensions.y * this.scaleY };
- }
- var dimX = dimensions.x / 2, dimY = dimensions.y / 2,
- points = [
- {
- x: -dimX,
- y: -dimY
- },
- {
- x: dimX,
- y: -dimY
- },
- {
- x: -dimX,
- y: dimY
- },
- {
- x: dimX,
- y: dimY
- }],
- i, transformMatrix = this._calcDimensionsTransformMatrix(skewX, skewY, false),
- bbox;
- for (i = 0; i < points.length; i++) {
- points[i] = fabric.util.transformPoint(points[i], transformMatrix);
- }
- bbox = fabric.util.makeBoundingBoxFromPoints(points);
- return { x: bbox.width, y: bbox.height };
- },
-
- _calculateCurrentDimensions: function() {
- var vpt = this.getViewportTransform(),
- dim = this._getTransformedDimensions(),
- p = fabric.util.transformPoint(dim, vpt, true);
- return p.scalarAdd(2 * this.padding);
- },
- });
- })();
- fabric.util.object.extend(fabric.Object.prototype, {
-
- sendToBack: function() {
- if (this.group) {
- fabric.StaticCanvas.prototype.sendToBack.call(this.group, this);
- }
- else {
- this.canvas.sendToBack(this);
- }
- return this;
- },
-
- bringToFront: function() {
- if (this.group) {
- fabric.StaticCanvas.prototype.bringToFront.call(this.group, this);
- }
- else {
- this.canvas.bringToFront(this);
- }
- return this;
- },
-
- sendBackwards: function(intersecting) {
- if (this.group) {
- fabric.StaticCanvas.prototype.sendBackwards.call(this.group, this, intersecting);
- }
- else {
- this.canvas.sendBackwards(this, intersecting);
- }
- return this;
- },
-
- bringForward: function(intersecting) {
- if (this.group) {
- fabric.StaticCanvas.prototype.bringForward.call(this.group, this, intersecting);
- }
- else {
- this.canvas.bringForward(this, intersecting);
- }
- return this;
- },
-
- moveTo: function(index) {
- if (this.group && this.group.type !== 'activeSelection') {
- fabric.StaticCanvas.prototype.moveTo.call(this.group, this, index);
- }
- else {
- this.canvas.moveTo(this, index);
- }
- return this;
- }
- });
- (function() {
- function getSvgColorString(prop, value) {
- if (!value) {
- return prop + ': none; ';
- }
- else if (value.toLive) {
- return prop + ': url(#SVGID_' + value.id + '); ';
- }
- else {
- var color = new fabric.Color(value),
- str = prop + ': ' + color.toRgb() + '; ',
- opacity = color.getAlpha();
- if (opacity !== 1) {
-
- str += prop + '-opacity: ' + opacity.toString() + '; ';
- }
- return str;
- }
- }
- var toFixed = fabric.util.toFixed;
- fabric.util.object.extend(fabric.Object.prototype, {
-
- getSvgStyles: function(skipShadow) {
- var fillRule = this.fillRule,
- strokeWidth = this.strokeWidth ? this.strokeWidth : '0',
- strokeDashArray = this.strokeDashArray ? this.strokeDashArray.join(' ') : 'none',
- strokeLineCap = this.strokeLineCap ? this.strokeLineCap : 'butt',
- strokeLineJoin = this.strokeLineJoin ? this.strokeLineJoin : 'miter',
- strokeMiterLimit = this.strokeMiterLimit ? this.strokeMiterLimit : '4',
- opacity = typeof this.opacity !== 'undefined' ? this.opacity : '1',
- visibility = this.visible ? '' : ' visibility: hidden;',
- filter = skipShadow ? '' : this.getSvgFilter(),
- fill = getSvgColorString('fill', this.fill),
- stroke = getSvgColorString('stroke', this.stroke);
- return [
- stroke,
- 'stroke-width: ', strokeWidth, '; ',
- 'stroke-dasharray: ', strokeDashArray, '; ',
- 'stroke-linecap: ', strokeLineCap, '; ',
- 'stroke-linejoin: ', strokeLineJoin, '; ',
- 'stroke-miterlimit: ', strokeMiterLimit, '; ',
- fill,
- 'fill-rule: ', fillRule, '; ',
- 'opacity: ', opacity, ';',
- filter,
- visibility
- ].join('');
- },
-
- getSvgSpanStyles: function(style, useWhiteSpace) {
- var term = '; ';
- var fontFamily = style.fontFamily ?
- 'font-family: ' + (((style.fontFamily.indexOf('\'') === -1 && style.fontFamily.indexOf('"') === -1) ?
- '\'' + style.fontFamily + '\'' : style.fontFamily)) + term : '';
- var strokeWidth = style.strokeWidth ? 'stroke-width: ' + style.strokeWidth + term : '',
- fontFamily = fontFamily,
- fontSize = style.fontSize ? 'font-size: ' + style.fontSize + 'px' + term : '',
- fontStyle = style.fontStyle ? 'font-c_style: ' + style.fontStyle + term : '',
- fontWeight = style.fontWeight ? 'font-weight: ' + style.fontWeight + term : '',
- fill = style.fill ? getSvgColorString('fill', style.fill) : '',
- stroke = style.stroke ? getSvgColorString('stroke', style.stroke) : '',
- textDecoration = this.getSvgTextDecoration(style),
- deltaY = style.deltaY ? 'baseline-shift: ' + (-style.deltaY) + '; ' : '';
- if (textDecoration) {
- textDecoration = 'text-decoration: ' + textDecoration + term;
- }
- return [
- stroke,
- strokeWidth,
- fontFamily,
- fontSize,
- fontStyle,
- fontWeight,
- textDecoration,
- fill,
- deltaY,
- useWhiteSpace ? 'white-space: pre; ' : ''
- ].join('');
- },
-
- getSvgTextDecoration: function(style) {
- if ('overline' in style || 'underline' in style || 'linethrough' in style) {
- return (style.overline ? 'overline ' : '') +
- (style.underline ? 'underline ' : '') + (style.linethrough ? 'line-through ' : '');
- }
- return '';
- },
-
- getSvgFilter: function() {
- return this.shadow ? 'filter: url(#SVGID_' + this.shadow.id + ');' : '';
- },
-
- getSvgId: function() {
- return this.id ? 'id="' + this.id + '" ' : '';
- },
-
- getSvgTransform: function() {
- var angle = this.angle,
- skewX = (this.skewX % 360),
- skewY = (this.skewY % 360),
- center = this.getCenterPoint(),
- NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS,
- translatePart = 'translate(' +
- toFixed(center.x, NUM_FRACTION_DIGITS) +
- ' ' +
- toFixed(center.y, NUM_FRACTION_DIGITS) +
- ')',
- anglePart = angle !== 0
- ? (' rotate(' + toFixed(angle, NUM_FRACTION_DIGITS) + ')')
- : '',
- scalePart = (this.scaleX === 1 && this.scaleY === 1)
- ? '' :
- (' scale(' +
- toFixed(this.scaleX, NUM_FRACTION_DIGITS) +
- ' ' +
- toFixed(this.scaleY, NUM_FRACTION_DIGITS) +
- ')'),
- skewXPart = skewX !== 0 ? ' skewX(' + toFixed(skewX, NUM_FRACTION_DIGITS) + ')' : '',
- skewYPart = skewY !== 0 ? ' skewY(' + toFixed(skewY, NUM_FRACTION_DIGITS) + ')' : '',
- flipXPart = this.flipX ? ' matrix(-1 0 0 1 0 0) ' : '',
- flipYPart = this.flipY ? ' matrix(1 0 0 -1 0 0)' : '';
- return [
- translatePart, anglePart, scalePart, flipXPart, flipYPart, skewXPart, skewYPart
- ].join('');
- },
-
- getSvgTransformMatrix: function() {
- return this.transformMatrix ? ' matrix(' + this.transformMatrix.join(' ') + ') ' : '';
- },
- _setSVGBg: function(textBgRects) {
- if (this.backgroundColor) {
- var NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS;
- textBgRects.push(
- '\t\t<rect ',
- this._getFillAttributes(this.backgroundColor),
- ' x="',
- toFixed(-this.width / 2, NUM_FRACTION_DIGITS),
- '" y="',
- toFixed(-this.height / 2, NUM_FRACTION_DIGITS),
- '" width="',
- toFixed(this.width, NUM_FRACTION_DIGITS),
- '" height="',
- toFixed(this.height, NUM_FRACTION_DIGITS),
- '"></rect>\n');
- }
- },
-
- _createBaseSVGMarkup: function() {
- var markup = [];
- if (this.fill && this.fill.toLive) {
- markup.push(this.fill.toSVG(this, false));
- }
- if (this.stroke && this.stroke.toLive) {
- markup.push(this.stroke.toSVG(this, false));
- }
- if (this.shadow) {
- markup.push(this.shadow.toSVG(this));
- }
- return markup;
- },
- addPaintOrder: function() {
- return this.paintFirst !== 'fill' ? ' paint-order="' + this.paintFirst + '" ' : '';
- }
- });
- })();
- (function() {
- var extend = fabric.util.object.extend,
- originalSet = 'stateProperties';
-
- function saveProps(origin, destination, props) {
- var tmpObj = { }, deep = true;
- props.forEach(function(prop) {
- tmpObj[prop] = origin[prop];
- });
- extend(origin[destination], tmpObj, deep);
- }
- function _isEqual(origValue, currentValue, firstPass) {
- if (origValue === currentValue) {
-
- return true;
- }
- else if (Array.isArray(origValue)) {
- if (!Array.isArray(currentValue) || origValue.length !== currentValue.length) {
- return false;
- }
- for (var i = 0, len = origValue.length; i < len; i++) {
- if (!_isEqual(origValue[i], currentValue[i])) {
- return false;
- }
- }
- return true;
- }
- else if (origValue && typeof origValue === 'object') {
- var keys = Object.keys(origValue), key;
- if (!currentValue ||
- typeof currentValue !== 'object' ||
- (!firstPass && keys.length !== Object.keys(currentValue).length)
- ) {
- return false;
- }
- for (var i = 0, len = keys.length; i < len; i++) {
- key = keys[i];
- if (!_isEqual(origValue[key], currentValue[key])) {
- return false;
- }
- }
- return true;
- }
- }
- fabric.util.object.extend(fabric.Object.prototype, {
-
- hasStateChanged: function(propertySet) {
- propertySet = propertySet || originalSet;
- var dashedPropertySet = '_' + propertySet;
- if (Object.keys(this[dashedPropertySet]).length < this[propertySet].length) {
- return true;
- }
- return !_isEqual(this[dashedPropertySet], this, true);
- },
-
- saveState: function(options) {
- var propertySet = options && options.propertySet || originalSet,
- destination = '_' + propertySet;
- if (!this[destination]) {
- return this.setupState(options);
- }
- saveProps(this, destination, this[propertySet]);
- if (options && options.stateProperties) {
- saveProps(this, destination, options.stateProperties);
- }
- return this;
- },
-
- setupState: function(options) {
- options = options || { };
- var propertySet = options.propertySet || originalSet;
- options.propertySet = propertySet;
- this['_' + propertySet] = { };
- this.saveState(options);
- return this;
- }
- });
- })();
- (function(global) {
- 'use strict';
- var fabric = global.fabric || (global.fabric = { }),
- extend = fabric.util.object.extend,
- clone = fabric.util.object.clone,
- coordProps = { x1: 1, x2: 1, y1: 1, y2: 1 },
- supportsLineDash = fabric.StaticCanvas.supports('setLineDash');
- if (fabric.Line) {
- fabric.warn('fabric.Line is already defined');
- return;
- }
-
- fabric.Line = fabric.util.createClass(fabric.Object, {
-
- type: 'line',
-
- x1: 0,
-
- y1: 0,
-
- x2: 0,
-
- y2: 0,
- cacheProperties: fabric.Object.prototype.cacheProperties.concat('x1', 'x2', 'y1', 'y2'),
-
- initialize: function(points, options) {
- if (!points) {
- points = [0, 0, 0, 0];
- }
- this.callSuper('initialize', options);
- this.set('x1', points[0]);
- this.set('y1', points[1]);
- this.set('x2', points[2]);
- this.set('y2', points[3]);
- this._setWidthHeight(options);
- },
-
- _setWidthHeight: function(options) {
- options || (options = { });
- this.width = Math.abs(this.x2 - this.x1);
- this.height = Math.abs(this.y2 - this.y1);
- this.left = 'left' in options
- ? options.left
- : this._getLeftToOriginX();
- this.top = 'top' in options
- ? options.top
- : this._getTopToOriginY();
- },
-
- _set: function(key, value) {
- this.callSuper('_set', key, value);
- if (typeof coordProps[key] !== 'undefined') {
- this._setWidthHeight();
- }
- return this;
- },
-
- _getLeftToOriginX: makeEdgeToOriginGetter(
- {
- origin: 'originX',
- axis1: 'x1',
- axis2: 'x2',
- dimension: 'width'
- },
- {
- nearest: 'left',
- center: 'center',
- farthest: 'right'
- }
- ),
-
- _getTopToOriginY: makeEdgeToOriginGetter(
- {
- origin: 'originY',
- axis1: 'y1',
- axis2: 'y2',
- dimension: 'height'
- },
- {
- nearest: 'top',
- center: 'center',
- farthest: 'bottom'
- }
- ),
-
- _render: function(ctx) {
- ctx.beginPath();
- if (!this.strokeDashArray || this.strokeDashArray && supportsLineDash) {
-
-
- var p = this.calcLinePoints();
- ctx.moveTo(p.x1, p.y1);
- ctx.lineTo(p.x2, p.y2);
- }
- ctx.lineWidth = this.strokeWidth;
-
-
-
- var origStrokeStyle = ctx.strokeStyle;
- ctx.strokeStyle = this.stroke || ctx.fillStyle;
- this.stroke && this._renderStroke(ctx);
- ctx.strokeStyle = origStrokeStyle;
- },
-
- _renderDashedStroke: function(ctx) {
- var p = this.calcLinePoints();
- ctx.beginPath();
- fabric.util.drawDashedLine(ctx, p.x1, p.y1, p.x2, p.y2, this.strokeDashArray);
- ctx.closePath();
- },
-
- _findCenterFromElement: function() {
- return {
- x: (this.x1 + this.x2) / 2,
- y: (this.y1 + this.y2) / 2,
- };
- },
-
- toObject: function(propertiesToInclude) {
- return extend(this.callSuper('toObject', propertiesToInclude), this.calcLinePoints());
- },
-
- _getNonTransformedDimensions: function() {
- var dim = this.callSuper('_getNonTransformedDimensions');
- if (this.strokeLineCap === 'butt') {
- if (this.width === 0) {
- dim.y -= this.strokeWidth;
- }
- if (this.height === 0) {
- dim.x -= this.strokeWidth;
- }
- }
- return dim;
- },
-
- calcLinePoints: function() {
- var xMult = this.x1 <= this.x2 ? -1 : 1,
- yMult = this.y1 <= this.y2 ? -1 : 1,
- x1 = (xMult * this.width * 0.5),
- y1 = (yMult * this.height * 0.5),
- x2 = (xMult * this.width * -0.5),
- y2 = (yMult * this.height * -0.5);
- return {
- x1: x1,
- x2: x2,
- y1: y1,
- y2: y2
- };
- },
-
-
- toSVG: function(reviver) {
- var markup = this._createBaseSVGMarkup(),
- p = this.calcLinePoints();
- markup.push(
- '<line ', this.getSvgId(),
- 'x1="', p.x1,
- '" y1="', p.y1,
- '" x2="', p.x2,
- '" y2="', p.y2,
- '" c_style="', this.getSvgStyles(),
- '" transform="', this.getSvgTransform(),
- this.getSvgTransformMatrix(),
- '"/>\n'
- );
- return reviver ? reviver(markup.join('')) : markup.join('');
- },
-
- });
-
- fabric.Line.fromObject = function(object, callback) {
- function _callback(instance) {
- delete instance.points;
- callback && callback(instance);
- };
- var options = clone(object, true);
- options.points = [object.x1, object.y1, object.x2, object.y2];
- fabric.Object._fromObject('Line', options, _callback, 'points');
- };
-
- function makeEdgeToOriginGetter(propertyNames, originValues) {
- var origin = propertyNames.origin,
- axis1 = propertyNames.axis1,
- axis2 = propertyNames.axis2,
- dimension = propertyNames.dimension,
- nearest = originValues.nearest,
- center = originValues.center,
- farthest = originValues.farthest;
- return function() {
- switch (this.get(origin)) {
- case nearest:
- return Math.min(this.get(axis1), this.get(axis2));
- case center:
- return Math.min(this.get(axis1), this.get(axis2)) + (0.5 * this.get(dimension));
- case farthest:
- return Math.max(this.get(axis1), this.get(axis2));
- }
- };
- }
- })(typeof exports !== 'undefined' ? exports : this);
- (function(global) {
- 'use strict';
- var fabric = global.fabric || (global.fabric = { }),
- pi = Math.PI;
- if (fabric.Circle) {
- fabric.warn('fabric.Circle is already defined.');
- return;
- }
-
- fabric.Circle = fabric.util.createClass(fabric.Object, {
-
- type: 'circle',
-
- radius: 0,
-
- startAngle: 0,
-
- endAngle: pi * 2,
- cacheProperties: fabric.Object.prototype.cacheProperties.concat('radius', 'startAngle', 'endAngle'),
-
- _set: function(key, value) {
- this.callSuper('_set', key, value);
- if (key === 'radius') {
- this.setRadius(value);
- }
- return this;
- },
-
- toObject: function(propertiesToInclude) {
- return this.callSuper('toObject', ['radius', 'startAngle', 'endAngle'].concat(propertiesToInclude));
- },
-
-
- toSVG: function(reviver) {
- var markup = this._createBaseSVGMarkup(), x = 0, y = 0,
- angle = (this.endAngle - this.startAngle) % ( 2 * pi);
- if (angle === 0) {
- markup.push(
- '<circle ', this.getSvgId(),
- 'cx="' + x + '" cy="' + y + '" ',
- 'r="', this.radius,
- '" c_style="', this.getSvgStyles(),
- '" transform="', this.getSvgTransform(),
- ' ', this.getSvgTransformMatrix(), '"',
- this.addPaintOrder(),
- '/>\n'
- );
- }
- else {
- var startX = fabric.util.cos(this.startAngle) * this.radius,
- startY = fabric.util.sin(this.startAngle) * this.radius,
- endX = fabric.util.cos(this.endAngle) * this.radius,
- endY = fabric.util.sin(this.endAngle) * this.radius,
- largeFlag = angle > pi ? '1' : '0';
- markup.push(
- '<path d="M ' + startX + ' ' + startY,
- ' A ' + this.radius + ' ' + this.radius,
- ' 0 ', +largeFlag + ' 1', ' ' + endX + ' ' + endY,
- '" c_style="', this.getSvgStyles(),
- '" transform="', this.getSvgTransform(),
- ' ', this.getSvgTransformMatrix(), '"',
- this.addPaintOrder(),
- '"/>\n'
- );
- }
- return reviver ? reviver(markup.join('')) : markup.join('');
- },
-
-
- _render: function(ctx) {
- ctx.beginPath();
- ctx.arc(
- 0,
- 0,
- this.radius,
- this.startAngle,
- this.endAngle, false);
- this._renderPaintInOrder(ctx);
- },
-
- getRadiusX: function() {
- return this.get('radius') * this.get('scaleX');
- },
-
- getRadiusY: function() {
- return this.get('radius') * this.get('scaleY');
- },
-
- setRadius: function(value) {
- this.radius = value;
- return this.set('width', value * 2).set('height', value * 2);
- },
- });
-
- fabric.Circle.fromObject = function(object, callback) {
- return fabric.Object._fromObject('Circle', object, callback);
- };
- })(typeof exports !== 'undefined' ? exports : this);
- (function(global) {
- 'use strict';
- var fabric = global.fabric || (global.fabric = { });
- if (fabric.Triangle) {
- fabric.warn('fabric.Triangle is already defined');
- return;
- }
-
- fabric.Triangle = fabric.util.createClass(fabric.Object, {
-
- type: 'triangle',
-
- width: 100,
-
- height: 100,
-
- _render: function(ctx) {
- var widthBy2 = this.width / 2,
- heightBy2 = this.height / 2;
- ctx.beginPath();
- ctx.moveTo(-widthBy2, heightBy2);
- ctx.lineTo(0, -heightBy2);
- ctx.lineTo(widthBy2, heightBy2);
- ctx.closePath();
- this._renderPaintInOrder(ctx);
- },
-
- _renderDashedStroke: function(ctx) {
- var widthBy2 = this.width / 2,
- heightBy2 = this.height / 2;
- ctx.beginPath();
- fabric.util.drawDashedLine(ctx, -widthBy2, heightBy2, 0, -heightBy2, this.strokeDashArray);
- fabric.util.drawDashedLine(ctx, 0, -heightBy2, widthBy2, heightBy2, this.strokeDashArray);
- fabric.util.drawDashedLine(ctx, widthBy2, heightBy2, -widthBy2, heightBy2, this.strokeDashArray);
- ctx.closePath();
- },
-
-
- toSVG: function(reviver) {
- var markup = this._createBaseSVGMarkup(),
- widthBy2 = this.width / 2,
- heightBy2 = this.height / 2,
- points = [
- -widthBy2 + ' ' + heightBy2,
- '0 ' + -heightBy2,
- widthBy2 + ' ' + heightBy2
- ]
- .join(',');
- markup.push(
- '<polygon ', this.getSvgId(),
- 'points="', points,
- '" c_style="', this.getSvgStyles(),
- '" transform="', this.getSvgTransform(), '"',
- this.addPaintOrder(),
- '/>'
- );
- return reviver ? reviver(markup.join('')) : markup.join('');
- },
-
- });
-
- fabric.Triangle.fromObject = function(object, callback) {
- return fabric.Object._fromObject('Triangle', object, callback);
- };
- })(typeof exports !== 'undefined' ? exports : this);
- (function(global) {
- 'use strict';
- var fabric = global.fabric || (global.fabric = { }),
- piBy2 = Math.PI * 2;
- if (fabric.Ellipse) {
- fabric.warn('fabric.Ellipse is already defined.');
- return;
- }
-
- fabric.Ellipse = fabric.util.createClass(fabric.Object, {
-
- type: 'ellipse',
-
- rx: 0,
-
- ry: 0,
- cacheProperties: fabric.Object.prototype.cacheProperties.concat('rx', 'ry'),
-
- initialize: function(options) {
- this.callSuper('initialize', options);
- this.set('rx', options && options.rx || 0);
- this.set('ry', options && options.ry || 0);
- },
-
- _set: function(key, value) {
- this.callSuper('_set', key, value);
- switch (key) {
- case 'rx':
- this.rx = value;
- this.set('width', value * 2);
- break;
- case 'ry':
- this.ry = value;
- this.set('height', value * 2);
- break;
- }
- return this;
- },
-
- getRx: function() {
- return this.get('rx') * this.get('scaleX');
- },
-
- getRy: function() {
- return this.get('ry') * this.get('scaleY');
- },
-
- toObject: function(propertiesToInclude) {
- return this.callSuper('toObject', ['rx', 'ry'].concat(propertiesToInclude));
- },
-
-
- toSVG: function(reviver) {
- var markup = this._createBaseSVGMarkup();
- markup.push(
- '<ellipse ', this.getSvgId(),
- 'cx="0" cy="0" ',
- 'rx="', this.rx,
- '" ry="', this.ry,
- '" c_style="', this.getSvgStyles(),
- '" transform="', this.getSvgTransform(),
- this.getSvgTransformMatrix(), '"',
- this.addPaintOrder(),
- '/>\n'
- );
- return reviver ? reviver(markup.join('')) : markup.join('');
- },
-
-
- _render: function(ctx) {
- ctx.beginPath();
- ctx.save();
- ctx.transform(1, 0, 0, this.ry / this.rx, 0, 0);
- ctx.arc(
- 0,
- 0,
- this.rx,
- 0,
- piBy2,
- false);
- ctx.restore();
- this._renderPaintInOrder(ctx);
- },
- });
-
- fabric.Ellipse.fromObject = function(object, callback) {
- return fabric.Object._fromObject('Ellipse', object, callback);
- };
- })(typeof exports !== 'undefined' ? exports : this);
- (function(global) {
- 'use strict';
- var fabric = global.fabric || (global.fabric = { }),
- extend = fabric.util.object.extend;
- if (fabric.Rect) {
- fabric.warn('fabric.Rect is already defined');
- return;
- }
-
- fabric.Rect = fabric.util.createClass(fabric.Object, {
-
- stateProperties: fabric.Object.prototype.stateProperties.concat('rx', 'ry'),
-
- type: 'rect',
-
- rx: 0,
-
- ry: 0,
- cacheProperties: fabric.Object.prototype.cacheProperties.concat('rx', 'ry'),
-
- initialize: function(options) {
- this.callSuper('initialize', options);
- this._initRxRy();
- },
-
- _initRxRy: function() {
- if (this.rx && !this.ry) {
- this.ry = this.rx;
- }
- else if (this.ry && !this.rx) {
- this.rx = this.ry;
- }
- },
-
- _render: function(ctx) {
-
- if (this.width === 1 && this.height === 1) {
- ctx.fillRect(-0.5, -0.5, 1, 1);
- return;
- }
- var rx = this.rx ? Math.min(this.rx, this.width / 2) : 0,
- ry = this.ry ? Math.min(this.ry, this.height / 2) : 0,
- w = this.width,
- h = this.height,
- x = -this.width / 2,
- y = -this.height / 2,
- isRounded = rx !== 0 || ry !== 0,
-
- k = 1 - 0.5522847498;
- ctx.beginPath();
- ctx.moveTo(x + rx, y);
- ctx.lineTo(x + w - rx, y);
- isRounded && ctx.bezierCurveTo(x + w - k * rx, y, x + w, y + k * ry, x + w, y + ry);
- ctx.lineTo(x + w, y + h - ry);
- isRounded && ctx.bezierCurveTo(x + w, y + h - k * ry, x + w - k * rx, y + h, x + w - rx, y + h);
- ctx.lineTo(x + rx, y + h);
- isRounded && ctx.bezierCurveTo(x + k * rx, y + h, x, y + h - k * ry, x, y + h - ry);
- ctx.lineTo(x, y + ry);
- isRounded && ctx.bezierCurveTo(x, y + k * ry, x + k * rx, y, x + rx, y);
- ctx.closePath();
- this._renderPaintInOrder(ctx);
- },
-
- _renderDashedStroke: function(ctx) {
- var x = -this.width / 2,
- y = -this.height / 2,
- w = this.width,
- h = this.height;
- ctx.beginPath();
- fabric.util.drawDashedLine(ctx, x, y, x + w, y, this.strokeDashArray);
- fabric.util.drawDashedLine(ctx, x + w, y, x + w, y + h, this.strokeDashArray);
- fabric.util.drawDashedLine(ctx, x + w, y + h, x, y + h, this.strokeDashArray);
- fabric.util.drawDashedLine(ctx, x, y + h, x, y, this.strokeDashArray);
- ctx.closePath();
- },
-
- toObject: function(propertiesToInclude) {
- return this.callSuper('toObject', ['rx', 'ry'].concat(propertiesToInclude));
- },
-
-
- toSVG: function(reviver) {
- var markup = this._createBaseSVGMarkup(), x = -this.width / 2, y = -this.height / 2;
- markup.push(
- '<rect ', this.getSvgId(),
- 'x="', x, '" y="', y,
- '" rx="', this.get('rx'), '" ry="', this.get('ry'),
- '" width="', this.width, '" height="', this.height,
- '" c_style="', this.getSvgStyles(),
- '" transform="', this.getSvgTransform(),
- this.getSvgTransformMatrix(), '"',
- this.addPaintOrder(),
- '/>\n');
- return reviver ? reviver(markup.join('')) : markup.join('');
- },
-
- });
-
- fabric.Rect.fromObject = function(object, callback) {
- return fabric.Object._fromObject('Rect', object, callback);
- };
- })(typeof exports !== 'undefined' ? exports : this);
- (function(global) {
- 'use strict';
- var fabric = global.fabric || (global.fabric = { }),
- extend = fabric.util.object.extend,
- min = fabric.util.array.min,
- max = fabric.util.array.max,
- toFixed = fabric.util.toFixed;
- if (fabric.Polyline) {
- fabric.warn('fabric.Polyline is already defined');
- return;
- }
-
- fabric.Polyline = fabric.util.createClass(fabric.Object, {
-
- type: 'polyline',
-
- points: null,
- cacheProperties: fabric.Object.prototype.cacheProperties.concat('points'),
-
- initialize: function(points, options) {
- options = options || {};
- this.points = points || [];
- this.callSuper('initialize', options);
- var calcDim = this._calcDimensions();
- if (typeof options.left === 'undefined') {
- this.left = calcDim.left;
- }
- if (typeof options.top === 'undefined') {
- this.top = calcDim.top;
- }
- this.width = calcDim.width;
- this.height = calcDim.height;
- this.pathOffset = {
- x: calcDim.left + this.width / 2,
- y: calcDim.top + this.height / 2
- };
- },
-
- _calcDimensions: function() {
- var points = this.points,
- minX = min(points, 'x') || 0,
- minY = min(points, 'y') || 0,
- maxX = max(points, 'x') || 0,
- maxY = max(points, 'y') || 0,
- width = (maxX - minX),
- height = (maxY - minY);
- return {
- left: minX,
- top: minY,
- width: width,
- height: height
- };
- },
-
- toObject: function(propertiesToInclude) {
- return extend(this.callSuper('toObject', propertiesToInclude), {
- points: this.points.concat()
- });
- },
-
-
- toSVG: function(reviver) {
- var points = [], diffX = this.pathOffset.x, diffY = this.pathOffset.y,
- markup = this._createBaseSVGMarkup(),
- NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS;
- for (var i = 0, len = this.points.length; i < len; i++) {
- points.push(
- toFixed(this.points[i].x - diffX, NUM_FRACTION_DIGITS), ',',
- toFixed(this.points[i].y - diffY, NUM_FRACTION_DIGITS), ' '
- );
- }
- markup.push(
- '<', this.type, ' ', this.getSvgId(),
- 'points="', points.join(''),
- '" c_style="', this.getSvgStyles(),
- '" transform="', this.getSvgTransform(),
- ' ', this.getSvgTransformMatrix(), '"',
- this.addPaintOrder(),
- '/>\n'
- );
- return reviver ? reviver(markup.join('')) : markup.join('');
- },
-
-
- commonRender: function(ctx) {
- var point, len = this.points.length,
- x = this.pathOffset.x,
- y = this.pathOffset.y;
- if (!len || isNaN(this.points[len - 1].y)) {
-
-
- return false;
- }
- ctx.beginPath();
- ctx.moveTo(this.points[0].x - x, this.points[0].y - y);
- for (var i = 0; i < len; i++) {
- point = this.points[i];
- ctx.lineTo(point.x - x, point.y - y);
- }
- return true;
- },
-
- _render: function(ctx) {
- if (!this.commonRender(ctx)) {
- return;
- }
- this._renderPaintInOrder(ctx);
- },
-
- _renderDashedStroke: function(ctx) {
- var p1, p2;
- ctx.beginPath();
- for (var i = 0, len = this.points.length; i < len; i++) {
- p1 = this.points[i];
- p2 = this.points[i + 1] || p1;
- fabric.util.drawDashedLine(ctx, p1.x, p1.y, p2.x, p2.y, this.strokeDashArray);
- }
- },
-
- complexity: function() {
- return this.get('points').length;
- }
- });
-
- fabric.Polyline.fromObject = function(object, callback) {
- return fabric.Object._fromObject('Polyline', object, callback, 'points');
- };
- })(typeof exports !== 'undefined' ? exports : this);
- (function(global) {
- 'use strict';
- var fabric = global.fabric || (global.fabric = { }),
- extend = fabric.util.object.extend;
- if (fabric.Polygon) {
- fabric.warn('fabric.Polygon is already defined');
- return;
- }
-
- fabric.Polygon = fabric.util.createClass(fabric.Polyline, {
-
- type: 'polygon',
-
- _render: function(ctx) {
- if (!this.commonRender(ctx)) {
- return;
- }
- ctx.closePath();
- this._renderPaintInOrder(ctx);
- },
-
- _renderDashedStroke: function(ctx) {
- this.callSuper('_renderDashedStroke', ctx);
- ctx.closePath();
- },
- });
-
- fabric.Polygon.fromObject = function(object, callback) {
- return fabric.Object._fromObject('Polygon', object, callback, 'points');
- };
- })(typeof exports !== 'undefined' ? exports : this);
- (function(global) {
- 'use strict';
- var fabric = global.fabric || (global.fabric = { }),
- min = fabric.util.array.min,
- max = fabric.util.array.max,
- extend = fabric.util.object.extend,
- _toString = Object.prototype.toString,
- drawArc = fabric.util.drawArc,
- commandLengths = {
- m: 2,
- l: 2,
- h: 1,
- v: 1,
- c: 6,
- s: 4,
- q: 4,
- t: 2,
- a: 7
- },
- repeatedCommands = {
- m: 'l',
- M: 'L'
- };
- if (fabric.Path) {
- fabric.warn('fabric.Path is already defined');
- return;
- }
-
- fabric.Path = fabric.util.createClass(fabric.Object, {
-
- type: 'path',
-
- path: null,
- cacheProperties: fabric.Object.prototype.cacheProperties.concat('path', 'fillRule'),
- stateProperties: fabric.Object.prototype.stateProperties.concat('path'),
-
- initialize: function(path, options) {
- options = options || { };
- this.callSuper('initialize', options);
- if (!path) {
- path = [];
- }
- var fromArray = _toString.call(path) === '[object Array]';
- this.path = fromArray
- ? path
-
- : path.match && path.match(/[mzlhvcsqta][^mzlhvcsqta]*/gi);
- if (!this.path) {
- return;
- }
- if (!fromArray) {
- this.path = this._parsePath();
- }
- this._setPositionDimensions(options);
- },
-
- _setPositionDimensions: function(options) {
- var calcDim = this._parseDimensions();
- this.width = calcDim.width;
- this.height = calcDim.height;
- if (typeof options.left === 'undefined') {
- this.left = calcDim.left;
- }
- if (typeof options.top === 'undefined') {
- this.top = calcDim.top;
- }
- this.pathOffset = this.pathOffset || {
- x: calcDim.left + this.width / 2,
- y: calcDim.top + this.height / 2
- };
- },
-
- _renderPathCommands: function(ctx) {
- var current,
- previous = null,
- subpathStartX = 0,
- subpathStartY = 0,
- x = 0,
- y = 0,
- controlX = 0,
- controlY = 0,
- tempX,
- tempY,
- l = -this.pathOffset.x,
- t = -this.pathOffset.y;
- ctx.beginPath();
- for (var i = 0, len = this.path.length; i < len; ++i) {
- current = this.path[i];
- switch (current[0]) {
- case 'l':
- x += current[1];
- y += current[2];
- ctx.lineTo(x + l, y + t);
- break;
- case 'L':
- x = current[1];
- y = current[2];
- ctx.lineTo(x + l, y + t);
- break;
- case 'h':
- x += current[1];
- ctx.lineTo(x + l, y + t);
- break;
- case 'H':
- x = current[1];
- ctx.lineTo(x + l, y + t);
- break;
- case 'v':
- y += current[1];
- ctx.lineTo(x + l, y + t);
- break;
- case 'V':
- y = current[1];
- ctx.lineTo(x + l, y + t);
- break;
- case 'm':
- x += current[1];
- y += current[2];
- subpathStartX = x;
- subpathStartY = y;
- ctx.moveTo(x + l, y + t);
- break;
- case 'M':
- x = current[1];
- y = current[2];
- subpathStartX = x;
- subpathStartY = y;
- ctx.moveTo(x + l, y + t);
- break;
- case 'c':
- tempX = x + current[5];
- tempY = y + current[6];
- controlX = x + current[3];
- controlY = y + current[4];
- ctx.bezierCurveTo(
- x + current[1] + l,
- y + current[2] + t,
- controlX + l,
- controlY + t,
- tempX + l,
- tempY + t
- );
- x = tempX;
- y = tempY;
- break;
- case 'C':
- x = current[5];
- y = current[6];
- controlX = current[3];
- controlY = current[4];
- ctx.bezierCurveTo(
- current[1] + l,
- current[2] + t,
- controlX + l,
- controlY + t,
- x + l,
- y + t
- );
- break;
- case 's':
-
- tempX = x + current[3];
- tempY = y + current[4];
- if (previous[0].match(/[CcSs]/) === null) {
-
-
- controlX = x;
- controlY = y;
- }
- else {
-
- controlX = 2 * x - controlX;
- controlY = 2 * y - controlY;
- }
- ctx.bezierCurveTo(
- controlX + l,
- controlY + t,
- x + current[1] + l,
- y + current[2] + t,
- tempX + l,
- tempY + t
- );
-
-
-
-
- controlX = x + current[1];
- controlY = y + current[2];
- x = tempX;
- y = tempY;
- break;
- case 'S':
- tempX = current[3];
- tempY = current[4];
- if (previous[0].match(/[CcSs]/) === null) {
-
-
- controlX = x;
- controlY = y;
- }
- else {
-
- controlX = 2 * x - controlX;
- controlY = 2 * y - controlY;
- }
- ctx.bezierCurveTo(
- controlX + l,
- controlY + t,
- current[1] + l,
- current[2] + t,
- tempX + l,
- tempY + t
- );
- x = tempX;
- y = tempY;
-
-
-
-
- controlX = current[1];
- controlY = current[2];
- break;
- case 'q':
-
- tempX = x + current[3];
- tempY = y + current[4];
- controlX = x + current[1];
- controlY = y + current[2];
- ctx.quadraticCurveTo(
- controlX + l,
- controlY + t,
- tempX + l,
- tempY + t
- );
- x = tempX;
- y = tempY;
- break;
- case 'Q':
- tempX = current[3];
- tempY = current[4];
- ctx.quadraticCurveTo(
- current[1] + l,
- current[2] + t,
- tempX + l,
- tempY + t
- );
- x = tempX;
- y = tempY;
- controlX = current[1];
- controlY = current[2];
- break;
- case 't':
-
- tempX = x + current[1];
- tempY = y + current[2];
- if (previous[0].match(/[QqTt]/) === null) {
-
-
- controlX = x;
- controlY = y;
- }
- else {
-
- controlX = 2 * x - controlX;
- controlY = 2 * y - controlY;
- }
- ctx.quadraticCurveTo(
- controlX + l,
- controlY + t,
- tempX + l,
- tempY + t
- );
- x = tempX;
- y = tempY;
- break;
- case 'T':
- tempX = current[1];
- tempY = current[2];
- if (previous[0].match(/[QqTt]/) === null) {
-
-
- controlX = x;
- controlY = y;
- }
- else {
-
- controlX = 2 * x - controlX;
- controlY = 2 * y - controlY;
- }
- ctx.quadraticCurveTo(
- controlX + l,
- controlY + t,
- tempX + l,
- tempY + t
- );
- x = tempX;
- y = tempY;
- break;
- case 'a':
-
- drawArc(ctx, x + l, y + t, [
- current[1],
- current[2],
- current[3],
- current[4],
- current[5],
- current[6] + x + l,
- current[7] + y + t
- ]);
- x += current[6];
- y += current[7];
- break;
- case 'A':
-
- drawArc(ctx, x + l, y + t, [
- current[1],
- current[2],
- current[3],
- current[4],
- current[5],
- current[6] + l,
- current[7] + t
- ]);
- x = current[6];
- y = current[7];
- break;
- case 'z':
- case 'Z':
- x = subpathStartX;
- y = subpathStartY;
- ctx.closePath();
- break;
- }
- previous = current;
- }
- },
-
- _render: function(ctx) {
- this._renderPathCommands(ctx);
- this._renderPaintInOrder(ctx);
- },
-
- toString: function() {
- return '#<fabric.Path (' + this.complexity() +
- '): { "top": ' + this.top + ', "left": ' + this.left + ' }>';
- },
-
- toObject: function(propertiesToInclude) {
- var o = extend(this.callSuper('toObject', propertiesToInclude), {
- path: this.path.map(function(item) { return item.slice(); }),
- top: this.top,
- left: this.left,
- });
- return o;
- },
-
- toDatalessObject: function(propertiesToInclude) {
- var o = this.toObject(['sourcePath'].concat(propertiesToInclude));
- if (o.sourcePath) {
- delete o.path;
- }
- return o;
- },
-
-
- toSVG: function(reviver) {
- var chunks = [],
- markup = this._createBaseSVGMarkup(), addTransform = '';
- for (var i = 0, len = this.path.length; i < len; i++) {
- chunks.push(this.path[i].join(' '));
- }
- var path = chunks.join(' ');
- addTransform = ' translate(' + (-this.pathOffset.x) + ', ' + (-this.pathOffset.y) + ') ';
- markup.push(
- '<path ', this.getSvgId(),
- 'd="', path,
- '" c_style="', this.getSvgStyles(),
- '" transform="', this.getSvgTransform(), addTransform,
- this.getSvgTransformMatrix(), '" stroke-linecap="round" ',
- this.addPaintOrder(),
- '/>\n'
- );
- return reviver ? reviver(markup.join('')) : markup.join('');
- },
-
-
- complexity: function() {
- return this.path.length;
- },
-
- _parsePath: function() {
- var result = [],
- coords = [],
- currentPath,
- parsed,
- re = /([-+]?((\d+\.\d+)|((\d+)|(\.\d+)))(?:e[-+]?\d+)?)/ig,
- match,
- coordsStr;
- for (var i = 0, coordsParsed, len = this.path.length; i < len; i++) {
- currentPath = this.path[i];
- coordsStr = currentPath.slice(1).trim();
- coords.length = 0;
- while ((match = re.exec(coordsStr))) {
- coords.push(match[0]);
- }
- coordsParsed = [currentPath.charAt(0)];
- for (var j = 0, jlen = coords.length; j < jlen; j++) {
- parsed = parseFloat(coords[j]);
- if (!isNaN(parsed)) {
- coordsParsed.push(parsed);
- }
- }
- var command = coordsParsed[0],
- commandLength = commandLengths[command.toLowerCase()],
- repeatedCommand = repeatedCommands[command] || command;
- if (coordsParsed.length - 1 > commandLength) {
- for (var k = 1, klen = coordsParsed.length; k < klen; k += commandLength) {
- result.push([command].concat(coordsParsed.slice(k, k + commandLength)));
- command = repeatedCommand;
- }
- }
- else {
- result.push(coordsParsed);
- }
- }
- return result;
- },
-
- _parseDimensions: function() {
- var aX = [],
- aY = [],
- current,
- previous = null,
- subpathStartX = 0,
- subpathStartY = 0,
- x = 0,
- y = 0,
- controlX = 0,
- controlY = 0,
- tempX,
- tempY,
- bounds;
- for (var i = 0, len = this.path.length; i < len; ++i) {
- current = this.path[i];
- switch (current[0]) {
- case 'l':
- x += current[1];
- y += current[2];
- bounds = [];
- break;
- case 'L':
- x = current[1];
- y = current[2];
- bounds = [];
- break;
- case 'h':
- x += current[1];
- bounds = [];
- break;
- case 'H':
- x = current[1];
- bounds = [];
- break;
- case 'v':
- y += current[1];
- bounds = [];
- break;
- case 'V':
- y = current[1];
- bounds = [];
- break;
- case 'm':
- x += current[1];
- y += current[2];
- subpathStartX = x;
- subpathStartY = y;
- bounds = [];
- break;
- case 'M':
- x = current[1];
- y = current[2];
- subpathStartX = x;
- subpathStartY = y;
- bounds = [];
- break;
- case 'c':
- tempX = x + current[5];
- tempY = y + current[6];
- controlX = x + current[3];
- controlY = y + current[4];
- bounds = fabric.util.getBoundsOfCurve(x, y,
- x + current[1],
- y + current[2],
- controlX,
- controlY,
- tempX,
- tempY
- );
- x = tempX;
- y = tempY;
- break;
- case 'C':
- controlX = current[3];
- controlY = current[4];
- bounds = fabric.util.getBoundsOfCurve(x, y,
- current[1],
- current[2],
- controlX,
- controlY,
- current[5],
- current[6]
- );
- x = current[5];
- y = current[6];
- break;
- case 's':
-
- tempX = x + current[3];
- tempY = y + current[4];
- if (previous[0].match(/[CcSs]/) === null) {
-
-
- controlX = x;
- controlY = y;
- }
- else {
-
- controlX = 2 * x - controlX;
- controlY = 2 * y - controlY;
- }
- bounds = fabric.util.getBoundsOfCurve(x, y,
- controlX,
- controlY,
- x + current[1],
- y + current[2],
- tempX,
- tempY
- );
-
-
-
-
- controlX = x + current[1];
- controlY = y + current[2];
- x = tempX;
- y = tempY;
- break;
- case 'S':
- tempX = current[3];
- tempY = current[4];
- if (previous[0].match(/[CcSs]/) === null) {
-
-
- controlX = x;
- controlY = y;
- }
- else {
-
- controlX = 2 * x - controlX;
- controlY = 2 * y - controlY;
- }
- bounds = fabric.util.getBoundsOfCurve(x, y,
- controlX,
- controlY,
- current[1],
- current[2],
- tempX,
- tempY
- );
- x = tempX;
- y = tempY;
-
-
-
-
- controlX = current[1];
- controlY = current[2];
- break;
- case 'q':
-
- tempX = x + current[3];
- tempY = y + current[4];
- controlX = x + current[1];
- controlY = y + current[2];
- bounds = fabric.util.getBoundsOfCurve(x, y,
- controlX,
- controlY,
- controlX,
- controlY,
- tempX,
- tempY
- );
- x = tempX;
- y = tempY;
- break;
- case 'Q':
- controlX = current[1];
- controlY = current[2];
- bounds = fabric.util.getBoundsOfCurve(x, y,
- controlX,
- controlY,
- controlX,
- controlY,
- current[3],
- current[4]
- );
- x = current[3];
- y = current[4];
- break;
- case 't':
-
- tempX = x + current[1];
- tempY = y + current[2];
- if (previous[0].match(/[QqTt]/) === null) {
-
-
- controlX = x;
- controlY = y;
- }
- else {
-
- controlX = 2 * x - controlX;
- controlY = 2 * y - controlY;
- }
- bounds = fabric.util.getBoundsOfCurve(x, y,
- controlX,
- controlY,
- controlX,
- controlY,
- tempX,
- tempY
- );
- x = tempX;
- y = tempY;
- break;
- case 'T':
- tempX = current[1];
- tempY = current[2];
- if (previous[0].match(/[QqTt]/) === null) {
-
-
- controlX = x;
- controlY = y;
- }
- else {
-
- controlX = 2 * x - controlX;
- controlY = 2 * y - controlY;
- }
- bounds = fabric.util.getBoundsOfCurve(x, y,
- controlX,
- controlY,
- controlX,
- controlY,
- tempX,
- tempY
- );
- x = tempX;
- y = tempY;
- break;
- case 'a':
-
- bounds = fabric.util.getBoundsOfArc(x, y,
- current[1],
- current[2],
- current[3],
- current[4],
- current[5],
- current[6] + x,
- current[7] + y
- );
- x += current[6];
- y += current[7];
- break;
- case 'A':
-
- bounds = fabric.util.getBoundsOfArc(x, y,
- current[1],
- current[2],
- current[3],
- current[4],
- current[5],
- current[6],
- current[7]
- );
- x = current[6];
- y = current[7];
- break;
- case 'z':
- case 'Z':
- x = subpathStartX;
- y = subpathStartY;
- break;
- }
- previous = current;
- bounds.forEach(function (point) {
- aX.push(point.x);
- aY.push(point.y);
- });
- aX.push(x);
- aY.push(y);
- }
- var minX = min(aX) || 0,
- minY = min(aY) || 0,
- maxX = max(aX) || 0,
- maxY = max(aY) || 0,
- deltaX = maxX - minX,
- deltaY = maxY - minY,
- o = {
- left: minX,
- top: minY,
- width: deltaX,
- height: deltaY
- };
- return o;
- }
- });
-
- fabric.Path.fromObject = function(object, callback) {
- if (typeof object.sourcePath === 'string') {
- var pathUrl = object.sourcePath;
- fabric.loadSVGFromURL(pathUrl, function (elements) {
- var path = elements[0];
- path.setOptions(object);
- callback && callback(path);
- });
- }
- else {
- fabric.Object._fromObject('Path', object, callback, 'path');
- }
- };
- })(typeof exports !== 'undefined' ? exports : this);
- (function(global) {
- 'use strict';
- var fabric = global.fabric || (global.fabric = { }),
- extend = fabric.util.object.extend,
- min = fabric.util.array.min,
- max = fabric.util.array.max;
- if (fabric.Group) {
- return;
- }
-
- fabric.Group = fabric.util.createClass(fabric.Object, fabric.Collection, {
-
- type: 'group',
-
- strokeWidth: 0,
-
- subTargetCheck: false,
-
- cacheProperties: [],
-
- useSetOnGroup: false,
-
- initialize: function(objects, options, isAlreadyGrouped) {
- options = options || {};
- this._objects = [];
-
-
-
- isAlreadyGrouped && this.callSuper('initialize', options);
- this._objects = objects || [];
- for (var i = this._objects.length; i--; ) {
- this._objects[i].group = this;
- }
- if (options.originX) {
- this.originX = options.originX;
- }
- if (options.originY) {
- this.originY = options.originY;
- }
- if (!isAlreadyGrouped) {
- var center = options && options.centerPoint;
-
-
- center || this._calcBounds();
- this._updateObjectsCoords(center);
- delete options.centerPoint;
- this.callSuper('initialize', options);
- }
- else {
- this._updateObjectsACoords();
- }
- this.setCoords();
- },
-
- _updateObjectsACoords: function() {
- var ignoreZoom = true, skipAbsolute = true;
- for (var i = this._objects.length; i--; ){
- this._objects[i].setCoords(ignoreZoom, skipAbsolute);
- }
- },
-
- _updateObjectsCoords: function(center) {
- var center = center || this.getCenterPoint();
- for (var i = this._objects.length; i--; ){
- this._updateObjectCoords(this._objects[i], center);
- }
- },
-
- _updateObjectCoords: function(object, center) {
- var objectLeft = object.left,
- objectTop = object.top,
- ignoreZoom = true, skipAbsolute = true;
- object.set({
- left: objectLeft - center.x,
- top: objectTop - center.y
- });
- object.group = this;
- object.setCoords(ignoreZoom, skipAbsolute);
- },
-
- toString: function() {
- return '#<fabric.Group: (' + this.complexity() + ')>';
- },
-
- addWithUpdate: function(object) {
- this._restoreObjectsState();
- fabric.util.resetObjectTransform(this);
- if (object) {
- this._objects.push(object);
- object.group = this;
- object._set('canvas', this.canvas);
- }
- this._calcBounds();
- this._updateObjectsCoords();
- this.setCoords();
- this.dirty = true;
- return this;
- },
-
- removeWithUpdate: function(object) {
- this._restoreObjectsState();
- fabric.util.resetObjectTransform(this);
- this.remove(object);
- this._calcBounds();
- this._updateObjectsCoords();
- this.setCoords();
- this.dirty = true;
- return this;
- },
-
- _onObjectAdded: function(object) {
- this.dirty = true;
- object.group = this;
- object._set('canvas', this.canvas);
- },
-
- _onObjectRemoved: function(object) {
- this.dirty = true;
- delete object.group;
- },
-
- _set: function(key, value) {
- var i = this._objects.length;
- if (this.useSetOnGroup) {
- while (i--) {
- this._objects[i].setOnGroup(key, value);
- }
- }
- if (key === 'canvas') {
- i = this._objects.length;
- while (i--) {
- this._objects[i]._set(key, value);
- }
- }
- this.callSuper('_set', key, value);
- },
-
- toObject: function(propertiesToInclude) {
- var objsToObject = this.getObjects().map(function(obj) {
- var originalDefaults = obj.includeDefaultValues;
- obj.includeDefaultValues = obj.group.includeDefaultValues;
- var _obj = obj.toObject(propertiesToInclude);
- obj.includeDefaultValues = originalDefaults;
- return _obj;
- });
- return extend(this.callSuper('toObject', propertiesToInclude), {
- objects: objsToObject
- });
- },
-
- toDatalessObject: function(propertiesToInclude) {
- var objsToObject, sourcePath = this.sourcePath;
- if (sourcePath) {
- objsToObject = sourcePath;
- }
- else {
- objsToObject = this.getObjects().map(function(obj) {
- var originalDefaults = obj.includeDefaultValues;
- obj.includeDefaultValues = obj.group.includeDefaultValues;
- var _obj = obj.toDatalessObject(propertiesToInclude);
- obj.includeDefaultValues = originalDefaults;
- return _obj;
- });
- }
- return extend(this.callSuper('toDatalessObject', propertiesToInclude), {
- objects: objsToObject
- });
- },
-
- render: function(ctx) {
- this._transformDone = true;
- this.callSuper('render', ctx);
- this._transformDone = false;
- },
-
- shouldCache: function() {
- var ownCache = this.objectCaching && (!this.group || this.needsItsOwnCache() || !this.group.isOnACache());
- this.ownCaching = ownCache;
- if (ownCache) {
- for (var i = 0, len = this._objects.length; i < len; i++) {
- if (this._objects[i].willDrawShadow()) {
- this.ownCaching = false;
- return false;
- }
- }
- }
- return ownCache;
- },
-
- willDrawShadow: function() {
- if (this.shadow) {
- return this.callSuper('willDrawShadow');
- }
- for (var i = 0, len = this._objects.length; i < len; i++) {
- if (this._objects[i].willDrawShadow()) {
- return true;
- }
- }
- return false;
- },
-
- isOnACache: function() {
- return this.ownCaching || (this.group && this.group.isOnACache());
- },
-
- drawObject: function(ctx) {
- for (var i = 0, len = this._objects.length; i < len; i++) {
- this._objects[i].render(ctx);
- }
- },
-
- isCacheDirty: function() {
- if (this.callSuper('isCacheDirty')) {
- return true;
- }
- if (!this.statefullCache) {
- return false;
- }
- for (var i = 0, len = this._objects.length; i < len; i++) {
- if (this._objects[i].isCacheDirty(true)) {
- if (this._cacheCanvas) {
-
- var x = this.cacheWidth / this.zoomX, y = this.cacheHeight / this.zoomY;
- this._cacheContext.clearRect(-x / 2, -y / 2, x, y);
- }
- return true;
- }
- }
- return false;
- },
-
- _restoreObjectsState: function() {
- this._objects.forEach(this._restoreObjectState, this);
- return this;
- },
-
- realizeTransform: function(object) {
- var matrix = object.calcTransformMatrix(),
- options = fabric.util.qrDecompose(matrix),
- center = new fabric.Point(options.translateX, options.translateY);
- object.flipX = false;
- object.flipY = false;
- object.set('scaleX', options.scaleX);
- object.set('scaleY', options.scaleY);
- object.skewX = options.skewX;
- object.skewY = options.skewY;
- object.angle = options.angle;
- object.setPositionByOrigin(center, 'center', 'center');
- return object;
- },
-
- _restoreObjectState: function(object) {
- this.realizeTransform(object);
- object.setCoords();
- delete object.group;
- return this;
- },
-
- destroy: function() {
-
-
- this._objects.forEach(function(object) {
- object.set('dirty', true);
- });
- return this._restoreObjectsState();
- },
-
- toActiveSelection: function() {
- if (!this.canvas) {
- return;
- }
- var objects = this._objects, canvas = this.canvas;
- this._objects = [];
- var options = this.toObject();
- delete options.objects;
- var activeSelection = new fabric.ActiveSelection([]);
- activeSelection.set(options);
- activeSelection.type = 'activeSelection';
- canvas.remove(this);
- objects.forEach(function(object) {
- object.group = activeSelection;
- object.dirty = true;
- canvas.add(object);
- });
- activeSelection.canvas = canvas;
- activeSelection._objects = objects;
- canvas._activeObject = activeSelection;
- activeSelection.setCoords();
- return activeSelection;
- },
-
- ungroupOnCanvas: function() {
- return this._restoreObjectsState();
- },
-
- setObjectsCoords: function() {
- var ignoreZoom = true, skipAbsolute = true;
- this.forEachObject(function(object) {
- object.setCoords(ignoreZoom, skipAbsolute);
- });
- return this;
- },
-
- _calcBounds: function(onlyWidthHeight) {
- var aX = [],
- aY = [],
- o, prop,
- props = ['tr', 'br', 'bl', 'tl'],
- i = 0, iLen = this._objects.length,
- j, jLen = props.length,
- ignoreZoom = true;
- for ( ; i < iLen; ++i) {
- o = this._objects[i];
- o.setCoords(ignoreZoom);
- for (j = 0; j < jLen; j++) {
- prop = props[j];
- aX.push(o.oCoords[prop].x);
- aY.push(o.oCoords[prop].y);
- }
- }
- this.set(this._getBounds(aX, aY, onlyWidthHeight));
- },
-
- _getBounds: function(aX, aY, onlyWidthHeight) {
- var minXY = new fabric.Point(min(aX), min(aY)),
- maxXY = new fabric.Point(max(aX), max(aY)),
- obj = {
- width: (maxXY.x - minXY.x) || 0,
- height: (maxXY.y - minXY.y) || 0
- };
- if (!onlyWidthHeight) {
- obj.left = minXY.x || 0;
- obj.top = minXY.y || 0;
- if (this.originX === 'center') {
- obj.left += obj.width / 2;
- }
- if (this.originX === 'right') {
- obj.left += obj.width;
- }
- if (this.originY === 'center') {
- obj.top += obj.height / 2;
- }
- if (this.originY === 'bottom') {
- obj.top += obj.height;
- }
- }
- return obj;
- },
-
-
- toSVG: function(reviver) {
- var markup = this._createBaseSVGMarkup();
- markup.push(
- '<g ', this.getSvgId(), 'transform="',
-
- this.getSvgTransform(),
- this.getSvgTransformMatrix(),
- '" c_style="',
- this.getSvgFilter(),
- '">\n'
- );
- for (var i = 0, len = this._objects.length; i < len; i++) {
- markup.push('\t', this._objects[i].toSVG(reviver));
- }
- markup.push('</g>\n');
- return reviver ? reviver(markup.join('')) : markup.join('');
- },
-
- });
-
- fabric.Group.fromObject = function(object, callback) {
- fabric.util.enlivenObjects(object.objects, function(enlivenedObjects) {
- var options = fabric.util.object.clone(object, true);
- delete options.objects;
- callback && callback(new fabric.Group(enlivenedObjects, options, true));
- });
- };
- })(typeof exports !== 'undefined' ? exports : this);
- (function(global) {
- 'use strict';
- var extend = fabric.util.object.extend;
- if (!global.fabric) {
- global.fabric = { };
- }
- if (global.fabric.Image) {
- fabric.warn('fabric.Image is already defined.');
- return;
- }
-
- fabric.Image = fabric.util.createClass(fabric.Object, {
-
- type: 'image',
-
- crossOrigin: '',
-
- strokeWidth: 0,
-
- _lastScaleX: 1,
-
- _lastScaleY: 1,
-
- _filterScalingX: 1,
-
- _filterScalingY: 1,
-
- minimumScaleTrigger: 0.5,
-
- stateProperties: fabric.Object.prototype.stateProperties.concat('cropX', 'cropY'),
-
- objectCaching: false,
-
- cacheKey: '',
-
- cropX: 0,
-
- cropY: 0,
-
- initialize: function(element, options) {
- options || (options = { });
- this.filters = [];
- this.cacheKey = 'texture' + fabric.Object.__uid++;
- this.callSuper('initialize', options);
- this._initElement(element, options);
- },
-
- getElement: function() {
- return this._element;
- },
-
- setElement: function(element, options) {
- var backend = fabric.filterBackend;
- if (backend && backend.evictCachesForKey) {
- backend.evictCachesForKey(this.cacheKey);
- backend.evictCachesForKey(this.cacheKey + '_filtered');
- }
- this._element = element;
- this._originalElement = element;
- this._initConfig(options);
- if (this.resizeFilter) {
- this.applyResizeFilters();
- }
- if (this.filters.length !== 0) {
- this.applyFilters();
- }
- return this;
- },
-
- dispose: function() {
- var backend = fabric.filterBackend;
- if (backend && backend.evictCachesForKey) {
- backend.evictCachesForKey(this.cacheKey);
- backend.evictCachesForKey(this.cacheKey + '_filtered');
- }
- this._originalElement = undefined;
- this._element = undefined;
- this._filteredEl = undefined;
- },
-
- setCrossOrigin: function(value) {
- this.crossOrigin = value;
- this._element.crossOrigin = value;
- return this;
- },
-
- getOriginalSize: function() {
- var element = this.getElement();
- return {
- width: element.width,
- height: element.height
- };
- },
-
- _stroke: function(ctx) {
- if (!this.stroke || this.strokeWidth === 0) {
- return;
- }
- var w = this.width / 2, h = this.height / 2;
- ctx.beginPath();
- ctx.moveTo(-w, -h);
- ctx.lineTo(w, -h);
- ctx.lineTo(w, h);
- ctx.lineTo(-w, h);
- ctx.lineTo(-w, -h);
- ctx.closePath();
- },
-
- _renderDashedStroke: function(ctx) {
- var x = -this.width / 2,
- y = -this.height / 2,
- w = this.width,
- h = this.height;
- ctx.save();
- this._setStrokeStyles(ctx, this);
- ctx.beginPath();
- fabric.util.drawDashedLine(ctx, x, y, x + w, y, this.strokeDashArray);
- fabric.util.drawDashedLine(ctx, x + w, y, x + w, y + h, this.strokeDashArray);
- fabric.util.drawDashedLine(ctx, x + w, y + h, x, y + h, this.strokeDashArray);
- fabric.util.drawDashedLine(ctx, x, y + h, x, y, this.strokeDashArray);
- ctx.closePath();
- ctx.restore();
- },
-
- toObject: function(propertiesToInclude) {
- var filters = [];
- this.filters.forEach(function(filterObj) {
- if (filterObj) {
- filters.push(filterObj.toObject());
- }
- });
- var object = extend(
- this.callSuper(
- 'toObject',
- ['crossOrigin', 'cropX', 'cropY'].concat(propertiesToInclude)
- ), {
- src: this.getSrc(),
- filters: filters,
- });
- if (this.resizeFilter) {
- object.resizeFilter = this.resizeFilter.toObject();
- }
- return object;
- },
-
- hasCrop: function() {
- return this.cropX || this.cropY || this.width < this._element.width || this.height < this._element.height;
- },
-
-
- toSVG: function(reviver) {
- var markup = this._createBaseSVGMarkup(), x = -this.width / 2, y = -this.height / 2, clipPath = '';
- if (this.hasCrop()) {
- var clipPathId = fabric.Object.__uid++;
- markup.push(
- '<clipPath id="imageCrop_' + clipPathId + '">\n',
- '\t<rect x="' + x + '" y="' + y + '" width="' + this.width + '" height="' + this.height + '" />\n',
- '</clipPath>\n'
- );
- clipPath = ' clip-path="url(#imageCrop_' + clipPathId + ')" ';
- }
- markup.push('<g transform="', this.getSvgTransform(), this.getSvgTransformMatrix(), '">\n');
- var imageMarkup = ['\t<c_image ', this.getSvgId(), 'xlink:href="', this.getSvgSrc(true),
- '" x="', x - this.cropX, '" y="', y - this.cropY,
- '" c_style="', this.getSvgStyles(),
-
-
-
- '" width="', this._element.width || this._element.naturalWidth,
- '" height="', this._element.height || this._element.height,
- '"', clipPath,
- '></c_image>\n'];
- if (this.paintFirst === 'fill') {
- Array.prototype.push.apply(markup, imageMarkup);
- }
- if (this.stroke || this.strokeDashArray) {
- var origFill = this.fill;
- this.fill = null;
- markup.push(
- '\t<rect ',
- 'x="', x, '" y="', y,
- '" width="', this.width, '" height="', this.height,
- '" c_style="', this.getSvgStyles(),
- '"/>\n'
- );
- this.fill = origFill;
- }
- if (this.paintFirst !== 'fill') {
- Array.prototype.push.apply(markup, imageMarkup);
- }
- markup.push('</g>\n');
- return reviver ? reviver(markup.join('')) : markup.join('');
- },
-
-
- getSrc: function(filtered) {
- var element = filtered ? this._element : this._originalElement;
- if (element) {
- if (element.toDataURL) {
- return element.toDataURL();
- }
- return element.src;
- }
- else {
- return this.src || '';
- }
- },
-
- setSrc: function(src, callback, options) {
- fabric.util.loadImage(src, function(img) {
- this.setElement(img, options);
- this._setWidthHeight();
- callback(this);
- }, this, options && options.crossOrigin);
- return this;
- },
-
- toString: function() {
- return '#<fabric.Image: { src: "' + this.getSrc() + '" }>';
- },
- applyResizeFilters: function() {
- var filter = this.resizeFilter,
- retinaScaling = this.canvas ? this.canvas.getRetinaScaling() : 1,
- minimumScale = this.minimumScaleTrigger,
- scaleX = this.scaleX * retinaScaling,
- scaleY = this.scaleY * retinaScaling,
- elementToFilter = this._filteredEl || this._originalElement;
- if (this.group) {
- this.set('dirty', true);
- }
- if (!filter || (scaleX > minimumScale && scaleY > minimumScale)) {
- this._element = elementToFilter;
- this._filterScalingX = 1;
- this._filterScalingY = 1;
- return;
- }
- if (!fabric.filterBackend) {
- fabric.filterBackend = fabric.initFilterBackend();
- }
- var canvasEl = fabric.util.createCanvasElement(),
- cacheKey = this._filteredEl ? this.cacheKey : (this.cacheKey + '_filtered'),
- sourceWidth = elementToFilter.width, sourceHeight = elementToFilter.height;
- canvasEl.width = sourceWidth;
- canvasEl.height = sourceHeight;
- this._element = canvasEl;
- filter.scaleX = scaleX;
- filter.scaleY = scaleY;
- fabric.filterBackend.applyFilters(
- [filter], elementToFilter, sourceWidth, sourceHeight, this._element, cacheKey);
- this._filterScalingX = canvasEl.width / this._originalElement.width;
- this._filterScalingY = canvasEl.height / this._originalElement.height;
- },
-
- applyFilters: function(filters) {
- filters = filters || this.filters || [];
- filters = filters.filter(function(filter) { return filter; });
- if (this.group) {
- this.set('dirty', true);
- }
- if (filters.length === 0) {
- this._element = this._originalElement;
- this._filteredEl = null;
- this._filterScalingX = 1;
- this._filterScalingY = 1;
- return this;
- }
- var imgElement = this._originalElement,
- sourceWidth = imgElement.naturalWidth || imgElement.width,
- sourceHeight = imgElement.naturalHeight || imgElement.height;
- if (this._element === this._originalElement) {
-
- var canvasEl = fabric.util.createCanvasElement();
- canvasEl.width = sourceWidth;
- canvasEl.height = sourceHeight;
- this._element = canvasEl;
- this._filteredEl = canvasEl;
- }
- else {
-
- this._element.getContext('2d').clearRect(0, 0, sourceWidth, sourceHeight);
- }
- if (!fabric.filterBackend) {
- fabric.filterBackend = fabric.initFilterBackend();
- }
- fabric.filterBackend.applyFilters(
- filters, this._originalElement, sourceWidth, sourceHeight, this._element, this.cacheKey);
- if (this._originalElement.width !== this._element.width ||
- this._originalElement.height !== this._element.height) {
- this._filterScalingX = this._element.width / this._originalElement.width;
- this._filterScalingY = this._element.height / this._originalElement.height;
- }
- return this;
- },
-
- _render: function(ctx) {
- if (this.isMoving === false && this.resizeFilter && this._needsResize()) {
- this._lastScaleX = this.scaleX;
- this._lastScaleY = this.scaleY;
- this.applyResizeFilters();
- }
- this._stroke(ctx);
- this._renderPaintInOrder(ctx);
- },
- _renderFill: function(ctx) {
- var w = this.width, h = this.height, sW = w * this._filterScalingX, sH = h * this._filterScalingY,
- x = -w / 2, y = -h / 2, elementToDraw = this._element;
- elementToDraw && ctx.drawImage(elementToDraw,
- this.cropX * this._filterScalingX,
- this.cropY * this._filterScalingY,
- sW,
- sH,
- x, y, w, h);
- },
-
- _needsResize: function() {
- return (this.scaleX !== this._lastScaleX || this.scaleY !== this._lastScaleY);
- },
-
- _resetWidthHeight: function() {
- var element = this.getElement();
- this.set('width', element.width);
- this.set('height', element.height);
- },
-
- _initElement: function(element, options) {
- this.setElement(fabric.util.getById(element), options);
- fabric.util.addClass(this.getElement(), fabric.Image.CSS_CANVAS);
- },
-
- _initConfig: function(options) {
- options || (options = { });
- this.setOptions(options);
- this._setWidthHeight(options);
- if (this._element && this.crossOrigin) {
- this._element.crossOrigin = this.crossOrigin;
- }
- },
-
- _initFilters: function(filters, callback) {
- if (filters && filters.length) {
- fabric.util.enlivenObjects(filters, function(enlivenedObjects) {
- callback && callback(enlivenedObjects);
- }, 'fabric.Image.filters');
- }
- else {
- callback && callback();
- }
- },
-
- _setWidthHeight: function(options) {
- this.width = options && ('width' in options)
- ? options.width
- : (this.getElement()
- ? this.getElement().width || 0
- : 0);
- this.height = options && ('height' in options)
- ? options.height
- : (this.getElement()
- ? this.getElement().height || 0
- : 0);
- },
-
- parsePreserveAspectRatioAttribute: function() {
- var pAR = fabric.util.parsePreserveAspectRatioAttribute(this.preserveAspectRatio || ''),
- rWidth = this._element.width, rHeight = this._element.height,
- scaleX = 1, scaleY = 1, offsetLeft = 0, offsetTop = 0, cropX = 0, cropY = 0,
- offset, pWidth = this.width, pHeight = this.height, parsedAttributes = { width: pWidth, height: pHeight };
- if (pAR && (pAR.alignX !== 'none' || pAR.alignY !== 'none')) {
- if (pAR.meetOrSlice === 'meet') {
- scaleX = scaleY = fabric.util.findScaleToFit(this._element, parsedAttributes);
- offset = (pWidth - rWidth * scaleX) / 2;
- if (pAR.alignX === 'Min') {
- offsetLeft = -offset;
- }
- if (pAR.alignX === 'Max') {
- offsetLeft = offset;
- }
- offset = (pHeight - rHeight * scaleY) / 2;
- if (pAR.alignY === 'Min') {
- offsetTop = -offset;
- }
- if (pAR.alignY === 'Max') {
- offsetTop = offset;
- }
- }
- if (pAR.meetOrSlice === 'slice') {
- scaleX = scaleY = fabric.util.findScaleToCover(this._element, parsedAttributes);
- offset = rWidth - pWidth / scaleX;
- if (pAR.alignX === 'Mid') {
- cropX = offset / 2;
- }
- if (pAR.alignX === 'Max') {
- cropX = offset;
- }
- offset = rHeight - pHeight / scaleY;
- if (pAR.alignY === 'Mid') {
- cropY = offset / 2;
- }
- if (pAR.alignY === 'Max') {
- cropY = offset;
- }
- rWidth = pWidth / scaleX;
- rHeight = pHeight / scaleY;
- }
- }
- else {
- scaleX = pWidth / rWidth;
- scaleY = pHeight / rHeight;
- }
- return {
- width: rWidth,
- height: rHeight,
- scaleX: scaleX,
- scaleY: scaleY,
- offsetLeft: offsetLeft,
- offsetTop: offsetTop,
- cropX: cropX,
- cropY: cropY
- };
- }
- });
-
- fabric.Image.CSS_CANVAS = 'canvas-img';
-
- fabric.Image.prototype.getSvgSrc = fabric.Image.prototype.getSrc;
-
- fabric.Image.fromObject = function(_object, callback) {
- var object = fabric.util.object.clone(_object);
- fabric.util.loadImage(object.src, function(img, error) {
- if (error) {
- callback && callback(null, error);
- return;
- }
- fabric.Image.prototype._initFilters.call(object, object.filters, function(filters) {
- object.filters = filters || [];
- fabric.Image.prototype._initFilters.call(object, [object.resizeFilter], function(resizeFilters) {
- object.resizeFilter = resizeFilters[0];
- var image = new fabric.Image(img, object);
- callback(image);
- });
- });
- }, null, object.crossOrigin);
- };
-
- fabric.Image.fromURL = function(url, callback, imgOptions) {
- fabric.util.loadImage(url, function(img) {
- callback && callback(new fabric.Image(img, imgOptions));
- }, null, imgOptions && imgOptions.crossOrigin);
- };
- })(typeof exports !== 'undefined' ? exports : this);
|