jspdf.src.js 749 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195151961519715198151991520015201152021520315204152051520615207152081520915210152111521215213152141521515216152171521815219152201522115222152231522415225152261522715228152291523015231152321523315234152351523615237152381523915240152411524215243152441524515246152471524815249152501525115252152531525415255152561525715258152591526015261152621526315264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532315324153251532615327153281532915330153311533215333153341533515336153371533815339153401534115342153431534415345153461534715348153491535015351153521535315354153551535615357153581535915360153611536215363153641536515366153671536815369153701537115372153731537415375153761537715378153791538015381153821538315384153851538615387153881538915390153911539215393153941539515396153971539815399154001540115402154031540415405154061540715408154091541015411154121541315414154151541615417154181541915420154211542215423154241542515426154271542815429154301543115432154331543415435154361543715438154391544015441154421544315444154451544615447154481544915450154511545215453154541545515456154571545815459154601546115462154631546415465154661546715468154691547015471154721547315474154751547615477154781547915480154811548215483154841548515486154871548815489154901549115492154931549415495154961549715498154991550015501155021550315504155051550615507155081550915510155111551215513155141551515516155171551815519155201552115522155231552415525155261552715528155291553015531155321553315534155351553615537155381553915540155411554215543155441554515546155471554815549155501555115552155531555415555155561555715558155591556015561155621556315564155651556615567155681556915570155711557215573155741557515576155771557815579155801558115582155831558415585155861558715588155891559015591155921559315594155951559615597155981559915600156011560215603156041560515606156071560815609156101561115612156131561415615156161561715618156191562015621156221562315624156251562615627156281562915630156311563215633156341563515636156371563815639156401564115642156431564415645156461564715648156491565015651156521565315654156551565615657156581565915660156611566215663156641566515666156671566815669156701567115672156731567415675156761567715678156791568015681156821568315684156851568615687156881568915690156911569215693156941569515696156971569815699157001570115702157031570415705157061570715708157091571015711157121571315714157151571615717157181571915720157211572215723157241572515726157271572815729157301573115732157331573415735157361573715738157391574015741157421574315744157451574615747157481574915750157511575215753157541575515756157571575815759157601576115762157631576415765157661576715768157691577015771157721577315774157751577615777157781577915780157811578215783157841578515786157871578815789157901579115792157931579415795157961579715798157991580015801158021580315804158051580615807158081580915810158111581215813158141581515816158171581815819158201582115822158231582415825158261582715828158291583015831158321583315834158351583615837158381583915840158411584215843158441584515846158471584815849158501585115852158531585415855158561585715858158591586015861158621586315864158651586615867158681586915870158711587215873158741587515876158771587815879158801588115882158831588415885158861588715888158891589015891158921589315894158951589615897158981589915900159011590215903159041590515906159071590815909159101591115912159131591415915159161591715918159191592015921159221592315924159251592615927159281592915930159311593215933159341593515936159371593815939159401594115942159431594415945159461594715948159491595015951159521595315954159551595615957159581595915960159611596215963159641596515966159671596815969159701597115972159731597415975159761597715978159791598015981159821598315984159851598615987159881598915990159911599215993159941599515996159971599815999160001600116002160031600416005160061600716008160091601016011160121601316014160151601616017160181601916020160211602216023160241602516026160271602816029160301603116032160331603416035160361603716038160391604016041160421604316044160451604616047160481604916050160511605216053160541605516056160571605816059160601606116062160631606416065160661606716068160691607016071160721607316074160751607616077160781607916080160811608216083160841608516086160871608816089160901609116092160931609416095160961609716098160991610016101161021610316104161051610616107161081610916110161111611216113161141611516116161171611816119161201612116122161231612416125161261612716128161291613016131161321613316134161351613616137161381613916140161411614216143161441614516146161471614816149161501615116152161531615416155161561615716158161591616016161161621616316164161651616616167161681616916170161711617216173161741617516176161771617816179161801618116182161831618416185161861618716188161891619016191161921619316194161951619616197161981619916200162011620216203162041620516206162071620816209162101621116212162131621416215162161621716218162191622016221162221622316224162251622616227162281622916230162311623216233162341623516236162371623816239162401624116242162431624416245162461624716248162491625016251162521625316254162551625616257162581625916260162611626216263162641626516266162671626816269162701627116272162731627416275162761627716278162791628016281162821628316284162851628616287162881628916290162911629216293162941629516296162971629816299163001630116302163031630416305163061630716308163091631016311163121631316314163151631616317163181631916320163211632216323163241632516326163271632816329163301633116332163331633416335163361633716338163391634016341163421634316344163451634616347163481634916350163511635216353163541635516356163571635816359163601636116362163631636416365163661636716368163691637016371163721637316374163751637616377163781637916380163811638216383163841638516386163871638816389163901639116392163931639416395163961639716398163991640016401164021640316404164051640616407164081640916410164111641216413164141641516416164171641816419164201642116422164231642416425164261642716428164291643016431164321643316434164351643616437164381643916440164411644216443164441644516446164471644816449164501645116452164531645416455164561645716458164591646016461164621646316464164651646616467164681646916470164711647216473164741647516476164771647816479164801648116482164831648416485164861648716488164891649016491164921649316494164951649616497164981649916500165011650216503165041650516506165071650816509165101651116512165131651416515165161651716518165191652016521165221652316524165251652616527165281652916530165311653216533165341653516536165371653816539165401654116542165431654416545165461654716548165491655016551165521655316554165551655616557165581655916560165611656216563165641656516566165671656816569165701657116572165731657416575165761657716578165791658016581165821658316584165851658616587165881658916590165911659216593165941659516596165971659816599166001660116602166031660416605166061660716608166091661016611166121661316614166151661616617166181661916620166211662216623166241662516626166271662816629166301663116632166331663416635166361663716638166391664016641166421664316644166451664616647166481664916650166511665216653166541665516656166571665816659166601666116662166631666416665166661666716668166691667016671166721667316674166751667616677166781667916680166811668216683166841668516686166871668816689166901669116692166931669416695166961669716698166991670016701167021670316704167051670616707167081670916710167111671216713167141671516716167171671816719167201672116722167231672416725167261672716728167291673016731167321673316734167351673616737167381673916740167411674216743167441674516746167471674816749167501675116752167531675416755167561675716758167591676016761167621676316764167651676616767167681676916770167711677216773167741677516776167771677816779167801678116782167831678416785167861678716788167891679016791167921679316794167951679616797167981679916800168011680216803168041680516806168071680816809168101681116812168131681416815168161681716818168191682016821168221682316824168251682616827168281682916830168311683216833168341683516836168371683816839168401684116842168431684416845168461684716848168491685016851168521685316854168551685616857168581685916860168611686216863168641686516866168671686816869168701687116872168731687416875168761687716878168791688016881168821688316884168851688616887168881688916890168911689216893168941689516896168971689816899169001690116902169031690416905169061690716908169091691016911169121691316914169151691616917169181691916920169211692216923169241692516926169271692816929169301693116932169331693416935169361693716938169391694016941169421694316944169451694616947169481694916950169511695216953169541695516956169571695816959169601696116962169631696416965169661696716968169691697016971169721697316974169751697616977169781697916980169811698216983169841698516986169871698816989169901699116992169931699416995169961699716998169991700017001170021700317004170051700617007170081700917010170111701217013170141701517016170171701817019170201702117022170231702417025170261702717028170291703017031170321703317034170351703617037170381703917040170411704217043170441704517046170471704817049170501705117052170531705417055170561705717058170591706017061170621706317064170651706617067170681706917070170711707217073170741707517076170771707817079170801708117082170831708417085170861708717088170891709017091170921709317094170951709617097170981709917100171011710217103171041710517106171071710817109171101711117112171131711417115171161711717118171191712017121171221712317124171251712617127171281712917130171311713217133171341713517136171371713817139171401714117142171431714417145171461714717148171491715017151171521715317154171551715617157171581715917160171611716217163171641716517166171671716817169171701717117172171731717417175171761717717178171791718017181171821718317184171851718617187171881718917190171911719217193171941719517196171971719817199172001720117202172031720417205172061720717208172091721017211172121721317214172151721617217172181721917220172211722217223172241722517226172271722817229172301723117232172331723417235172361723717238172391724017241172421724317244172451724617247172481724917250172511725217253172541725517256172571725817259172601726117262172631726417265172661726717268172691727017271172721727317274172751727617277172781727917280172811728217283172841728517286172871728817289172901729117292172931729417295172961729717298172991730017301173021730317304173051730617307173081730917310173111731217313173141731517316173171731817319173201732117322173231732417325173261732717328173291733017331173321733317334173351733617337173381733917340173411734217343173441734517346173471734817349173501735117352173531735417355173561735717358173591736017361173621736317364173651736617367173681736917370173711737217373173741737517376173771737817379173801738117382173831738417385173861738717388173891739017391173921739317394173951739617397173981739917400174011740217403174041740517406174071740817409174101741117412174131741417415174161741717418174191742017421174221742317424174251742617427174281742917430174311743217433174341743517436174371743817439174401744117442174431744417445174461744717448174491745017451174521745317454174551745617457174581745917460174611746217463174641746517466174671746817469174701747117472174731747417475174761747717478174791748017481174821748317484174851748617487174881748917490174911749217493174941749517496174971749817499175001750117502175031750417505175061750717508175091751017511175121751317514175151751617517175181751917520175211752217523175241752517526175271752817529175301753117532175331753417535175361753717538175391754017541175421754317544175451754617547175481754917550175511755217553175541755517556175571755817559175601756117562175631756417565175661756717568175691757017571175721757317574175751757617577175781757917580175811758217583175841758517586175871758817589175901759117592175931759417595175961759717598175991760017601176021760317604176051760617607176081760917610176111761217613176141761517616176171761817619176201762117622176231762417625176261762717628176291763017631176321763317634176351763617637176381763917640176411764217643176441764517646176471764817649176501765117652176531765417655176561765717658176591766017661176621766317664176651766617667176681766917670176711767217673176741767517676176771767817679176801768117682176831768417685176861768717688176891769017691176921769317694176951769617697176981769917700177011770217703177041770517706177071770817709177101771117712177131771417715177161771717718177191772017721177221772317724177251772617727177281772917730177311773217733177341773517736177371773817739177401774117742177431774417745177461774717748177491775017751177521775317754177551775617757177581775917760177611776217763177641776517766177671776817769177701777117772177731777417775177761777717778177791778017781177821778317784177851778617787177881778917790177911779217793177941779517796177971779817799178001780117802178031780417805178061780717808178091781017811178121781317814178151781617817178181781917820178211782217823178241782517826178271782817829178301783117832178331783417835178361783717838178391784017841178421784317844178451784617847178481784917850178511785217853178541785517856178571785817859178601786117862178631786417865178661786717868178691787017871178721787317874178751787617877178781787917880178811788217883178841788517886178871788817889178901789117892178931789417895178961789717898178991790017901179021790317904179051790617907179081790917910179111791217913179141791517916179171791817919179201792117922179231792417925179261792717928179291793017931179321793317934179351793617937179381793917940179411794217943179441794517946179471794817949179501795117952179531795417955179561795717958179591796017961179621796317964179651796617967179681796917970179711797217973179741797517976179771797817979179801798117982179831798417985179861798717988179891799017991179921799317994179951799617997179981799918000180011800218003180041800518006180071800818009180101801118012180131801418015180161801718018180191802018021180221802318024180251802618027180281802918030180311803218033180341803518036180371803818039180401804118042180431804418045180461804718048180491805018051180521805318054180551805618057180581805918060180611806218063180641806518066180671806818069180701807118072180731807418075180761807718078180791808018081180821808318084180851808618087180881808918090180911809218093180941809518096180971809818099181001810118102181031810418105181061810718108181091811018111181121811318114181151811618117181181811918120181211812218123181241812518126181271812818129181301813118132181331813418135181361813718138181391814018141181421814318144181451814618147181481814918150181511815218153181541815518156181571815818159181601816118162181631816418165181661816718168181691817018171181721817318174181751817618177181781817918180181811818218183181841818518186181871818818189181901819118192181931819418195181961819718198181991820018201182021820318204182051820618207182081820918210182111821218213182141821518216182171821818219182201822118222182231822418225182261822718228182291823018231182321823318234182351823618237182381823918240182411824218243182441824518246182471824818249182501825118252182531825418255182561825718258182591826018261182621826318264182651826618267182681826918270182711827218273182741827518276182771827818279182801828118282182831828418285182861828718288182891829018291182921829318294182951829618297182981829918300183011830218303183041830518306183071830818309183101831118312183131831418315183161831718318183191832018321183221832318324183251832618327183281832918330183311833218333183341833518336183371833818339183401834118342183431834418345183461834718348183491835018351183521835318354183551835618357183581835918360183611836218363183641836518366183671836818369183701837118372183731837418375183761837718378183791838018381183821838318384183851838618387183881838918390183911839218393183941839518396183971839818399184001840118402184031840418405184061840718408184091841018411184121841318414184151841618417184181841918420184211842218423184241842518426184271842818429184301843118432184331843418435184361843718438184391844018441184421844318444184451844618447184481844918450184511845218453184541845518456184571845818459184601846118462184631846418465184661846718468184691847018471184721847318474184751847618477184781847918480184811848218483184841848518486184871848818489184901849118492184931849418495184961849718498184991850018501185021850318504185051850618507185081850918510185111851218513185141851518516185171851818519185201852118522185231852418525185261852718528185291853018531185321853318534185351853618537185381853918540185411854218543185441854518546185471854818549185501855118552185531855418555185561855718558185591856018561185621856318564185651856618567185681856918570185711857218573185741857518576185771857818579185801858118582185831858418585185861858718588185891859018591185921859318594185951859618597185981859918600186011860218603186041860518606186071860818609186101861118612186131861418615186161861718618186191862018621186221862318624186251862618627186281862918630186311863218633186341863518636186371863818639186401864118642186431864418645186461864718648186491865018651186521865318654186551865618657186581865918660186611866218663186641866518666186671866818669186701867118672186731867418675186761867718678186791868018681186821868318684186851868618687186881868918690186911869218693186941869518696186971869818699187001870118702187031870418705187061870718708187091871018711187121871318714187151871618717187181871918720187211872218723187241872518726187271872818729187301873118732187331873418735187361873718738187391874018741187421874318744187451874618747187481874918750187511875218753187541875518756187571875818759187601876118762187631876418765187661876718768187691877018771187721877318774187751877618777187781877918780187811878218783187841878518786187871878818789187901879118792187931879418795187961879718798187991880018801188021880318804188051880618807188081880918810188111881218813188141881518816188171881818819188201882118822188231882418825188261882718828188291883018831188321883318834188351883618837188381883918840188411884218843188441884518846188471884818849188501885118852188531885418855188561885718858188591886018861188621886318864188651886618867188681886918870188711887218873188741887518876188771887818879188801888118882188831888418885188861888718888188891889018891188921889318894188951889618897188981889918900189011890218903189041890518906189071890818909189101891118912189131891418915189161891718918189191892018921189221892318924189251892618927189281892918930189311893218933189341893518936189371893818939189401894118942189431894418945189461894718948189491895018951189521895318954189551895618957189581895918960189611896218963189641896518966189671896818969189701897118972189731897418975189761897718978189791898018981189821898318984189851898618987189881898918990189911899218993189941899518996189971899818999190001900119002190031900419005190061900719008190091901019011190121901319014190151901619017190181901919020190211902219023190241902519026190271902819029190301903119032190331903419035190361903719038190391904019041190421904319044190451904619047190481904919050190511905219053190541905519056190571905819059190601906119062190631906419065190661906719068190691907019071190721907319074190751907619077190781907919080190811908219083190841908519086190871908819089190901909119092190931909419095190961909719098190991910019101191021910319104191051910619107191081910919110191111911219113191141911519116191171911819119191201912119122191231912419125191261912719128191291913019131191321913319134191351913619137191381913919140191411914219143191441914519146191471914819149191501915119152191531915419155191561915719158191591916019161191621916319164191651916619167191681916919170191711917219173191741917519176191771917819179191801918119182191831918419185191861918719188191891919019191191921919319194191951919619197191981919919200192011920219203192041920519206192071920819209192101921119212192131921419215192161921719218192191922019221192221922319224192251922619227192281922919230192311923219233192341923519236192371923819239192401924119242192431924419245192461924719248192491925019251192521925319254192551925619257192581925919260192611926219263192641926519266192671926819269192701927119272192731927419275192761927719278192791928019281192821928319284192851928619287192881928919290192911929219293192941929519296192971929819299193001930119302193031930419305193061930719308193091931019311193121931319314193151931619317193181931919320193211932219323193241932519326193271932819329193301933119332193331933419335193361933719338193391934019341193421934319344193451934619347193481934919350193511935219353193541935519356193571935819359193601936119362193631936419365193661936719368193691937019371193721937319374193751937619377193781937919380193811938219383193841938519386193871938819389193901939119392193931939419395193961939719398193991940019401194021940319404194051940619407194081940919410194111941219413194141941519416194171941819419194201942119422194231942419425194261942719428194291943019431194321943319434194351943619437194381943919440194411944219443194441944519446194471944819449194501945119452194531945419455194561945719458194591946019461194621946319464194651946619467194681946919470194711947219473194741947519476194771947819479194801948119482194831948419485194861948719488194891949019491194921949319494194951949619497194981949919500195011950219503195041950519506195071950819509195101951119512195131951419515195161951719518195191952019521195221952319524195251952619527195281952919530195311953219533195341953519536195371953819539195401954119542195431954419545195461954719548195491955019551195521955319554195551955619557195581955919560195611956219563195641956519566195671956819569195701957119572195731957419575195761957719578195791958019581195821958319584195851958619587195881958919590195911959219593195941959519596195971959819599196001960119602196031960419605196061960719608196091961019611196121961319614196151961619617196181961919620196211962219623196241962519626196271962819629196301963119632196331963419635196361963719638196391964019641196421964319644196451964619647196481964919650196511965219653196541965519656196571965819659196601966119662196631966419665196661966719668196691967019671196721967319674196751967619677196781967919680196811968219683196841968519686196871968819689196901969119692196931969419695196961969719698196991970019701197021970319704197051970619707197081970919710197111971219713197141971519716197171971819719197201972119722197231972419725197261972719728197291973019731197321973319734197351973619737197381973919740197411974219743197441974519746197471974819749197501975119752197531975419755197561975719758197591976019761197621976319764197651976619767197681976919770197711977219773197741977519776197771977819779197801978119782197831978419785197861978719788197891979019791197921979319794197951979619797197981979919800198011980219803198041980519806198071980819809198101981119812198131981419815198161981719818198191982019821198221982319824198251982619827198281982919830198311983219833198341983519836198371983819839198401984119842198431984419845198461984719848198491985019851198521985319854198551985619857198581985919860198611986219863198641986519866198671986819869198701987119872198731987419875198761987719878198791988019881198821988319884198851988619887198881988919890198911989219893198941989519896198971989819899199001990119902199031990419905199061990719908199091991019911199121991319914199151991619917199181991919920199211992219923199241992519926199271992819929199301993119932199331993419935199361993719938199391994019941199421994319944199451994619947199481994919950199511995219953199541995519956199571995819959199601996119962199631996419965199661996719968199691997019971199721997319974199751997619977199781997919980199811998219983199841998519986199871998819989199901999119992199931999419995199961999719998199992000020001200022000320004200052000620007200082000920010200112001220013200142001520016200172001820019200202002120022200232002420025200262002720028200292003020031200322003320034200352003620037200382003920040200412004220043200442004520046200472004820049200502005120052200532005420055200562005720058200592006020061200622006320064200652006620067200682006920070200712007220073200742007520076200772007820079200802008120082200832008420085200862008720088200892009020091200922009320094200952009620097200982009920100201012010220103201042010520106201072010820109201102011120112201132011420115201162011720118201192012020121201222012320124201252012620127201282012920130201312013220133201342013520136201372013820139201402014120142201432014420145201462014720148201492015020151201522015320154201552015620157201582015920160201612016220163201642016520166201672016820169201702017120172201732017420175201762017720178201792018020181201822018320184201852018620187201882018920190201912019220193201942019520196201972019820199202002020120202202032020420205202062020720208202092021020211202122021320214202152021620217202182021920220202212022220223202242022520226202272022820229202302023120232202332023420235202362023720238202392024020241202422024320244202452024620247202482024920250202512025220253202542025520256202572025820259202602026120262202632026420265202662026720268202692027020271202722027320274202752027620277202782027920280202812028220283202842028520286202872028820289202902029120292202932029420295202962029720298202992030020301203022030320304203052030620307203082030920310203112031220313203142031520316203172031820319203202032120322203232032420325203262032720328203292033020331203322033320334203352033620337203382033920340203412034220343203442034520346203472034820349203502035120352203532035420355203562035720358203592036020361203622036320364203652036620367203682036920370203712037220373203742037520376203772037820379203802038120382203832038420385203862038720388203892039020391203922039320394203952039620397203982039920400204012040220403204042040520406204072040820409204102041120412204132041420415204162041720418204192042020421204222042320424204252042620427204282042920430204312043220433204342043520436204372043820439204402044120442204432044420445204462044720448204492045020451204522045320454204552045620457204582045920460204612046220463204642046520466204672046820469204702047120472204732047420475204762047720478204792048020481204822048320484204852048620487204882048920490204912049220493204942049520496204972049820499205002050120502205032050420505205062050720508205092051020511205122051320514205152051620517205182051920520205212052220523205242052520526205272052820529205302053120532205332053420535205362053720538205392054020541205422054320544205452054620547205482054920550205512055220553205542055520556205572055820559205602056120562205632056420565205662056720568205692057020571205722057320574205752057620577205782057920580205812058220583205842058520586205872058820589205902059120592205932059420595205962059720598205992060020601206022060320604206052060620607206082060920610206112061220613206142061520616206172061820619206202062120622206232062420625206262062720628206292063020631206322063320634206352063620637206382063920640206412064220643206442064520646206472064820649206502065120652206532065420655206562065720658206592066020661206622066320664206652066620667206682066920670206712067220673206742067520676206772067820679206802068120682206832068420685206862068720688206892069020691206922069320694206952069620697206982069920700207012070220703207042070520706207072070820709207102071120712207132071420715207162071720718207192072020721207222072320724207252072620727207282072920730207312073220733207342073520736207372073820739207402074120742207432074420745207462074720748207492075020751207522075320754207552075620757207582075920760207612076220763207642076520766207672076820769207702077120772207732077420775207762077720778207792078020781207822078320784207852078620787207882078920790207912079220793207942079520796207972079820799208002080120802208032080420805208062080720808208092081020811208122081320814208152081620817208182081920820208212082220823208242082520826208272082820829208302083120832208332083420835208362083720838208392084020841208422084320844208452084620847208482084920850208512085220853208542085520856208572085820859208602086120862208632086420865208662086720868208692087020871208722087320874208752087620877208782087920880208812088220883208842088520886208872088820889208902089120892208932089420895208962089720898208992090020901209022090320904209052090620907209082090920910209112091220913209142091520916209172091820919209202092120922209232092420925209262092720928209292093020931209322093320934209352093620937209382093920940209412094220943209442094520946209472094820949209502095120952209532095420955209562095720958209592096020961209622096320964209652096620967209682096920970209712097220973209742097520976209772097820979209802098120982209832098420985209862098720988209892099020991209922099320994209952099620997209982099921000210012100221003210042100521006210072100821009210102101121012210132101421015210162101721018210192102021021210222102321024210252102621027210282102921030210312103221033210342103521036210372103821039210402104121042210432104421045210462104721048210492105021051210522105321054210552105621057210582105921060210612106221063210642106521066210672106821069210702107121072210732107421075210762107721078210792108021081210822108321084210852108621087210882108921090210912109221093210942109521096210972109821099211002110121102211032110421105211062110721108211092111021111211122111321114211152111621117211182111921120211212112221123211242112521126211272112821129211302113121132211332113421135211362113721138211392114021141211422114321144211452114621147211482114921150211512115221153211542115521156211572115821159211602116121162211632116421165211662116721168211692117021171211722117321174211752117621177211782117921180211812118221183211842118521186211872118821189211902119121192211932119421195211962119721198211992120021201212022120321204212052120621207212082120921210212112121221213212142121521216212172121821219212202122121222212232122421225212262122721228212292123021231212322123321234212352123621237212382123921240212412124221243212442124521246212472124821249212502125121252212532125421255212562125721258212592126021261212622126321264212652126621267212682126921270212712127221273212742127521276212772127821279212802128121282212832128421285212862128721288212892129021291212922129321294212952129621297212982129921300213012130221303213042130521306213072130821309213102131121312213132131421315213162131721318213192132021321213222132321324213252132621327213282132921330213312133221333213342133521336213372133821339213402134121342213432134421345213462134721348213492135021351213522135321354213552135621357213582135921360213612136221363213642136521366213672136821369213702137121372213732137421375213762137721378213792138021381213822138321384213852138621387213882138921390213912139221393213942139521396213972139821399214002140121402214032140421405214062140721408214092141021411214122141321414214152141621417214182141921420214212142221423214242142521426214272142821429214302143121432214332143421435214362143721438214392144021441214422144321444214452144621447214482144921450214512145221453214542145521456214572145821459214602146121462214632146421465214662146721468214692147021471214722147321474214752147621477214782147921480214812148221483214842148521486214872148821489214902149121492214932149421495214962149721498214992150021501215022150321504215052150621507215082150921510215112151221513215142151521516215172151821519215202152121522215232152421525215262152721528215292153021531215322153321534215352153621537215382153921540215412154221543215442154521546215472154821549215502155121552215532155421555215562155721558215592156021561215622156321564215652156621567215682156921570215712157221573215742157521576215772157821579215802158121582215832158421585215862158721588215892159021591215922159321594215952159621597215982159921600216012160221603216042160521606216072160821609216102161121612216132161421615216162161721618216192162021621216222162321624216252162621627216282162921630216312163221633216342163521636216372163821639216402164121642216432164421645216462164721648216492165021651216522165321654216552165621657216582165921660216612166221663216642166521666216672166821669216702167121672216732167421675216762167721678216792168021681216822168321684216852168621687216882168921690216912169221693216942169521696216972169821699217002170121702217032170421705217062170721708217092171021711217122171321714217152171621717217182171921720217212172221723217242172521726217272172821729217302173121732217332173421735217362173721738217392174021741217422174321744217452174621747217482174921750217512175221753217542175521756217572175821759217602176121762217632176421765217662176721768217692177021771217722177321774217752177621777217782177921780217812178221783217842178521786217872178821789217902179121792217932179421795217962179721798217992180021801218022180321804218052180621807218082180921810218112181221813218142181521816218172181821819218202182121822218232182421825218262182721828218292183021831218322183321834218352183621837218382183921840218412184221843218442184521846218472184821849218502185121852218532185421855218562185721858218592186021861218622186321864218652186621867218682186921870218712187221873218742187521876218772187821879218802188121882218832188421885218862188721888218892189021891218922189321894218952189621897218982189921900219012190221903219042190521906219072190821909219102191121912219132191421915219162191721918219192192021921219222192321924219252192621927219282192921930219312193221933219342193521936219372193821939219402194121942219432194421945219462194721948219492195021951219522195321954219552195621957219582195921960219612196221963219642196521966219672196821969219702197121972219732197421975219762197721978219792198021981219822198321984219852198621987219882198921990219912199221993219942199521996219972199821999220002200122002220032200422005220062200722008220092201022011220122201322014220152201622017220182201922020220212202222023220242202522026220272202822029220302203122032220332203422035220362203722038220392204022041220422204322044220452204622047220482204922050220512205222053220542205522056220572205822059220602206122062220632206422065220662206722068220692207022071220722207322074220752207622077220782207922080220812208222083220842208522086220872208822089220902209122092220932209422095220962209722098220992210022101221022210322104221052210622107221082210922110221112211222113221142211522116221172211822119221202212122122221232212422125221262212722128221292213022131221322213322134221352213622137221382213922140221412214222143221442214522146221472214822149221502215122152221532215422155221562215722158221592216022161221622216322164221652216622167221682216922170221712217222173221742217522176221772217822179221802218122182221832218422185221862218722188221892219022191221922219322194221952219622197221982219922200222012220222203222042220522206222072220822209222102221122212222132221422215222162221722218222192222022221222222222322224222252222622227222282222922230222312223222233222342223522236222372223822239222402224122242222432224422245222462224722248222492225022251222522225322254222552225622257222582225922260222612226222263222642226522266222672226822269222702227122272222732227422275222762227722278222792228022281222822228322284222852228622287222882228922290222912229222293222942229522296222972229822299223002230122302223032230422305223062230722308223092231022311223122231322314223152231622317223182231922320223212232222323223242232522326223272232822329223302233122332223332233422335223362233722338223392234022341223422234322344223452234622347223482234922350223512235222353223542235522356223572235822359223602236122362223632236422365223662236722368223692237022371223722237322374223752237622377223782237922380223812238222383223842238522386223872238822389223902239122392223932239422395223962239722398223992240022401224022240322404224052240622407224082240922410224112241222413224142241522416224172241822419224202242122422224232242422425224262242722428224292243022431224322243322434224352243622437224382243922440224412244222443224442244522446224472244822449224502245122452224532245422455224562245722458224592246022461224622246322464224652246622467224682246922470224712247222473224742247522476224772247822479224802248122482224832248422485224862248722488224892249022491224922249322494224952249622497224982249922500225012250222503225042250522506225072250822509225102251122512225132251422515225162251722518225192252022521225222252322524225252252622527225282252922530225312253222533225342253522536225372253822539225402254122542225432254422545225462254722548225492255022551225522255322554225552255622557
  1. (function (global, factory) {
  2. typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
  3. typeof define === 'function' && define.amd ? define(['exports'], factory) :
  4. (factory((global.jsPDF = {})));
  5. }(this, (function (exports) { 'use strict';
  6. /**
  7. * JavaScript Polyfill functions for jsPDF
  8. * Collected from public resources by
  9. * https://github.com/diegocr
  10. */
  11. (function (global) {
  12. if (typeof global.console !== "object") {
  13. // Console-polyfill. MIT license.
  14. // https://github.com/paulmillr/console-polyfill
  15. // Make it safe to do console.log() always.
  16. global.console = {};
  17. var con = global.console;
  18. var prop, method;
  19. var dummy = function () {};
  20. var properties = ["memory"];
  21. var methods = ("assert,clear,count,debug,dir,dirxml,error,exception,group," + "groupCollapsed,groupEnd,info,log,markTimeline,profile,profiles,profileEnd," + "show,table,time,timeEnd,timeline,timelineEnd,timeStamp,trace,warn").split(",");
  22. while (prop = properties.pop()) if (!con[prop]) con[prop] = {};
  23. while (method = methods.pop()) if (!con[method]) con[method] = dummy;
  24. }
  25. var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
  26. if (typeof global.btoa === "undefined") {
  27. global.btoa = function (data) {
  28. // discuss at: http://phpjs.org/functions/base64_encode/
  29. // original by: Tyler Akins (http://rumkin.com)
  30. // improved by: Bayron Guevara
  31. // improved by: Thunder.m
  32. // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  33. // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  34. // improved by: Rafal Kukawski (http://kukawski.pl)
  35. // bugfixed by: Pellentesque Malesuada
  36. // example 1: base64_encode('Kevin van Zonneveld');
  37. // returns 1: 'S2V2aW4gdmFuIFpvbm5ldmVsZA=='
  38. var o1,
  39. o2,
  40. o3,
  41. h1,
  42. h2,
  43. h3,
  44. h4,
  45. bits,
  46. i = 0,
  47. ac = 0,
  48. enc = "",
  49. tmp_arr = [];
  50. if (!data) {
  51. return data;
  52. }
  53. do {
  54. // pack three octets into four hexets
  55. o1 = data.charCodeAt(i++);
  56. o2 = data.charCodeAt(i++);
  57. o3 = data.charCodeAt(i++);
  58. bits = o1 << 16 | o2 << 8 | o3;
  59. h1 = bits >> 18 & 0x3f;
  60. h2 = bits >> 12 & 0x3f;
  61. h3 = bits >> 6 & 0x3f;
  62. h4 = bits & 0x3f; // use hexets to index into b64, and append result to encoded string
  63. tmp_arr[ac++] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4);
  64. } while (i < data.length);
  65. enc = tmp_arr.join("");
  66. var r = data.length % 3;
  67. return (r ? enc.slice(0, r - 3) : enc) + "===".slice(r || 3);
  68. };
  69. }
  70. if (typeof global.atob === "undefined") {
  71. global.atob = function (data) {
  72. // discuss at: http://phpjs.org/functions/base64_decode/
  73. // original by: Tyler Akins (http://rumkin.com)
  74. // improved by: Thunder.m
  75. // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  76. // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  77. // input by: Aman Gupta
  78. // input by: Brett Zamir (http://brett-zamir.me)
  79. // bugfixed by: Onno Marsman
  80. // bugfixed by: Pellentesque Malesuada
  81. // bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  82. // example 1: base64_decode('S2V2aW4gdmFuIFpvbm5ldmVsZA==');
  83. // returns 1: 'Kevin van Zonneveld'
  84. var o1,
  85. o2,
  86. o3,
  87. h1,
  88. h2,
  89. h3,
  90. h4,
  91. bits,
  92. i = 0,
  93. ac = 0,
  94. dec = "",
  95. tmp_arr = [];
  96. if (!data) {
  97. return data;
  98. }
  99. data += "";
  100. do {
  101. // unpack four hexets into three octets using index points in b64
  102. h1 = b64.indexOf(data.charAt(i++));
  103. h2 = b64.indexOf(data.charAt(i++));
  104. h3 = b64.indexOf(data.charAt(i++));
  105. h4 = b64.indexOf(data.charAt(i++));
  106. bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;
  107. o1 = bits >> 16 & 0xff;
  108. o2 = bits >> 8 & 0xff;
  109. o3 = bits & 0xff;
  110. if (h3 == 64) {
  111. tmp_arr[ac++] = String.fromCharCode(o1);
  112. } else if (h4 == 64) {
  113. tmp_arr[ac++] = String.fromCharCode(o1, o2);
  114. } else {
  115. tmp_arr[ac++] = String.fromCharCode(o1, o2, o3);
  116. }
  117. } while (i < data.length);
  118. dec = tmp_arr.join("");
  119. return dec;
  120. };
  121. }
  122. if (!Array.prototype.map) {
  123. Array.prototype.map = function (fun
  124. /*, thisArg */
  125. ) {
  126. if (this === void 0 || this === null || typeof fun !== "function") throw new TypeError();
  127. var t = Object(this),
  128. len = t.length >>> 0,
  129. res = new Array(len);
  130. var thisArg = arguments.length > 1 ? arguments[1] : void 0;
  131. for (var i = 0; i < len; i++) {
  132. // NOTE: Absolute correctness would demand Object.defineProperty
  133. // be used. But this method is fairly new, and failure is
  134. // possible only if Object.prototype or Array.prototype
  135. // has a property |i| (very unlikely), so use a less-correct
  136. // but more portable alternative.
  137. if (i in t) res[i] = fun.call(thisArg, t[i], i, t);
  138. }
  139. return res;
  140. };
  141. }
  142. if (!Array.isArray) {
  143. Array.isArray = function (arg) {
  144. return Object.prototype.toString.call(arg) === "[object Array]";
  145. };
  146. }
  147. if (!Array.prototype.forEach) {
  148. Array.prototype.forEach = function (fun, thisArg) {
  149. if (this === void 0 || this === null || typeof fun !== "function") throw new TypeError();
  150. var t = Object(this),
  151. len = t.length >>> 0;
  152. for (var i = 0; i < len; i++) {
  153. if (i in t) fun.call(thisArg, t[i], i, t);
  154. }
  155. };
  156. }
  157. if (!Object.keys) {
  158. Object.keys = function () {
  159. var hasOwnProperty = Object.prototype.hasOwnProperty,
  160. hasDontEnumBug = !{
  161. toString: null
  162. }.propertyIsEnumerable("toString"),
  163. dontEnums = ["toString", "toLocaleString", "valueOf", "hasOwnProperty", "isPrototypeOf", "propertyIsEnumerable", "constructor"],
  164. dontEnumsLength = dontEnums.length;
  165. return function (obj) {
  166. if (typeof obj !== "object" && (typeof obj !== "function" || obj === null)) {
  167. throw new TypeError();
  168. }
  169. var result = [],
  170. prop,
  171. i;
  172. for (prop in obj) {
  173. if (hasOwnProperty.call(obj, prop)) {
  174. result.push(prop);
  175. }
  176. }
  177. if (hasDontEnumBug) {
  178. for (i = 0; i < dontEnumsLength; i++) {
  179. if (hasOwnProperty.call(obj, dontEnums[i])) {
  180. result.push(dontEnums[i]);
  181. }
  182. }
  183. }
  184. return result;
  185. };
  186. }();
  187. }
  188. if (typeof Object.assign != "function") {
  189. Object.assign = function (target) {
  190. if (target == null) {
  191. throw new TypeError("Cannot convert undefined or null to object");
  192. }
  193. target = Object(target);
  194. for (var index = 1; index < arguments.length; index++) {
  195. var source = arguments[index];
  196. if (source != null) {
  197. for (var key in source) {
  198. if (Object.prototype.hasOwnProperty.call(source, key)) {
  199. target[key] = source[key];
  200. }
  201. }
  202. }
  203. }
  204. return target;
  205. };
  206. }
  207. if (!String.prototype.trim) {
  208. String.prototype.trim = function () {
  209. return this.replace(/^\s+|\s+$/g, "");
  210. };
  211. }
  212. if (!String.prototype.trimLeft) {
  213. String.prototype.trimLeft = function () {
  214. return this.replace(/^\s+/g, "");
  215. };
  216. }
  217. if (!String.prototype.trimRight) {
  218. String.prototype.trimRight = function () {
  219. return this.replace(/\s+$/g, "");
  220. };
  221. }
  222. })(typeof self !== "undefined" && self || typeof window !== "undefined" && window || typeof global !== "undefined" && global || Function('return typeof this === "object" && this.content')() || Function("return this")()); // `self` is undefined in Firefox for Android content script context
  223. // while `this` is nsIContentFrameMessageManager
  224. // with an attribute `content` that corresponds to the window
  225. (function (global, factory) {
  226. typeof exports === 'object' && typeof module !== 'undefined' ? factory() : typeof define === 'function' && define.amd ? define(factory) : factory();
  227. })(window, function () {
  228. /**
  229. * @this {Promise}
  230. */
  231. function finallyConstructor(callback) {
  232. var constructor = this.constructor;
  233. return this.then(function (value) {
  234. return constructor.resolve(callback()).then(function () {
  235. return value;
  236. });
  237. }, function (reason) {
  238. return constructor.resolve(callback()).then(function () {
  239. return constructor.reject(reason);
  240. });
  241. });
  242. } // Store setTimeout reference so promise-polyfill will be unaffected by
  243. // other code modifying setTimeout (like sinon.useFakeTimers())
  244. var setTimeoutFunc = setTimeout;
  245. function noop() {} // Polyfill for Function.prototype.bind
  246. function bind(fn, thisArg) {
  247. return function () {
  248. fn.apply(thisArg, arguments);
  249. };
  250. }
  251. /**
  252. * @constructor
  253. * @param {Function} fn
  254. */
  255. function Promise(fn) {
  256. if (!(this instanceof Promise)) throw new TypeError('Promises must be constructed via new');
  257. if (typeof fn !== 'function') throw new TypeError('not a function');
  258. /** @type {!number} */
  259. this._state = 0;
  260. /** @type {!boolean} */
  261. this._handled = false;
  262. /** @type {Promise|undefined} */
  263. this._value = undefined;
  264. /** @type {!Array<!Function>} */
  265. this._deferreds = [];
  266. doResolve(fn, this);
  267. }
  268. function handle(self, deferred) {
  269. while (self._state === 3) {
  270. self = self._value;
  271. }
  272. if (self._state === 0) {
  273. self._deferreds.push(deferred);
  274. return;
  275. }
  276. self._handled = true;
  277. Promise._immediateFn(function () {
  278. var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected;
  279. if (cb === null) {
  280. (self._state === 1 ? resolve : reject)(deferred.promise, self._value);
  281. return;
  282. }
  283. var ret;
  284. try {
  285. ret = cb(self._value);
  286. } catch (e) {
  287. reject(deferred.promise, e);
  288. return;
  289. }
  290. resolve(deferred.promise, ret);
  291. });
  292. }
  293. function resolve(self, newValue) {
  294. try {
  295. // Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
  296. if (newValue === self) throw new TypeError('A promise cannot be resolved with itself.');
  297. if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
  298. var then = newValue.then;
  299. if (newValue instanceof Promise) {
  300. self._state = 3;
  301. self._value = newValue;
  302. finale(self);
  303. return;
  304. } else if (typeof then === 'function') {
  305. doResolve(bind(then, newValue), self);
  306. return;
  307. }
  308. }
  309. self._state = 1;
  310. self._value = newValue;
  311. finale(self);
  312. } catch (e) {
  313. reject(self, e);
  314. }
  315. }
  316. function reject(self, newValue) {
  317. self._state = 2;
  318. self._value = newValue;
  319. finale(self);
  320. }
  321. function finale(self) {
  322. if (self._state === 2 && self._deferreds.length === 0) {
  323. Promise._immediateFn(function () {
  324. if (!self._handled) {
  325. Promise._unhandledRejectionFn(self._value);
  326. }
  327. });
  328. }
  329. for (var i = 0, len = self._deferreds.length; i < len; i++) {
  330. handle(self, self._deferreds[i]);
  331. }
  332. self._deferreds = null;
  333. }
  334. /**
  335. * @constructor
  336. */
  337. function Handler(onFulfilled, onRejected, promise) {
  338. this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
  339. this.onRejected = typeof onRejected === 'function' ? onRejected : null;
  340. this.promise = promise;
  341. }
  342. /**
  343. * Take a potentially misbehaving resolver function and make sure
  344. * onFulfilled and onRejected are only called once.
  345. *
  346. * Makes no guarantees about asynchrony.
  347. */
  348. function doResolve(fn, self) {
  349. var done = false;
  350. try {
  351. fn(function (value) {
  352. if (done) return;
  353. done = true;
  354. resolve(self, value);
  355. }, function (reason) {
  356. if (done) return;
  357. done = true;
  358. reject(self, reason);
  359. });
  360. } catch (ex) {
  361. if (done) return;
  362. done = true;
  363. reject(self, ex);
  364. }
  365. }
  366. Promise.prototype['catch'] = function (onRejected) {
  367. return this.then(null, onRejected);
  368. };
  369. Promise.prototype.then = function (onFulfilled, onRejected) {
  370. // @ts-ignore
  371. var prom = new this.constructor(noop);
  372. handle(this, new Handler(onFulfilled, onRejected, prom));
  373. return prom;
  374. };
  375. Promise.prototype['finally'] = finallyConstructor;
  376. Promise.all = function (arr) {
  377. return new Promise(function (resolve, reject) {
  378. if (!arr || typeof arr.length === 'undefined') throw new TypeError('Promise.all accepts an array');
  379. var args = Array.prototype.slice.call(arr);
  380. if (args.length === 0) return resolve([]);
  381. var remaining = args.length;
  382. function res(i, val) {
  383. try {
  384. if (val && (typeof val === 'object' || typeof val === 'function')) {
  385. var then = val.then;
  386. if (typeof then === 'function') {
  387. then.call(val, function (val) {
  388. res(i, val);
  389. }, reject);
  390. return;
  391. }
  392. }
  393. args[i] = val;
  394. if (--remaining === 0) {
  395. resolve(args);
  396. }
  397. } catch (ex) {
  398. reject(ex);
  399. }
  400. }
  401. for (var i = 0; i < args.length; i++) {
  402. res(i, args[i]);
  403. }
  404. });
  405. };
  406. Promise.resolve = function (value) {
  407. if (value && typeof value === 'object' && value.constructor === Promise) {
  408. return value;
  409. }
  410. return new Promise(function (resolve) {
  411. resolve(value);
  412. });
  413. };
  414. Promise.reject = function (value) {
  415. return new Promise(function (resolve, reject) {
  416. reject(value);
  417. });
  418. };
  419. Promise.race = function (values) {
  420. return new Promise(function (resolve, reject) {
  421. for (var i = 0, len = values.length; i < len; i++) {
  422. values[i].then(resolve, reject);
  423. }
  424. });
  425. }; // Use polyfill for setImmediate for performance gains
  426. Promise._immediateFn = typeof setImmediate === 'function' && function (fn) {
  427. setImmediate(fn);
  428. } || function (fn) {
  429. setTimeoutFunc(fn, 0);
  430. };
  431. Promise._unhandledRejectionFn = function _unhandledRejectionFn(err) {
  432. if (typeof console !== 'undefined' && console) {
  433. console.warn('Possible Unhandled Promise Rejection:', err); // eslint-disable-line no-console
  434. }
  435. };
  436. /** @suppress {undefinedVars} */
  437. var globalNS = function () {
  438. // the only reliable means to get the global object is
  439. // `Function('return this')()`
  440. // However, this causes CSP violations in Chrome apps.
  441. if (typeof self !== 'undefined') {
  442. return self;
  443. }
  444. if (typeof window !== 'undefined') {
  445. return window;
  446. }
  447. if (typeof global !== 'undefined') {
  448. return global;
  449. }
  450. throw new Error('unable to locate global object');
  451. }();
  452. if (!('Promise' in globalNS)) {
  453. globalNS['Promise'] = Promise;
  454. } else if (!globalNS.Promise.prototype['finally']) {
  455. globalNS.Promise.prototype['finally'] = finallyConstructor;
  456. }
  457. });
  458. function _typeof(obj) {
  459. if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
  460. _typeof = function (obj) {
  461. return typeof obj;
  462. };
  463. } else {
  464. _typeof = function (obj) {
  465. return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
  466. };
  467. }
  468. return _typeof(obj);
  469. }
  470. /** @license
  471. * jsPDF - PDF Document creation from JavaScript
  472. * Version 2.0.0 Built on 2018-10-01T11:18:29.385Z
  473. * CommitID a19d4618f6
  474. *
  475. * Copyright (c) 2015-2018 yWorks GmbH, http://www.yworks.com
  476. * 2015-2018 Lukas Holländer <lukas.hollaender@yworks.com>, https://github.com/HackbrettXXX
  477. * 2010-2016 James Hall <james@parall.ax>, https://github.com/MrRio/jsPDF
  478. * 2010 Aaron Spike, https://github.com/acspike
  479. * 2012 Willow Systems Corporation, willow-systems.com
  480. * 2012 Pablo Hess, https://github.com/pablohess
  481. * 2012 Florian Jenett, https://github.com/fjenett
  482. * 2013 Warren Weckesser, https://github.com/warrenweckesser
  483. * 2013 Youssef Beddad, https://github.com/lifof
  484. * 2013 Lee Driscoll, https://github.com/lsdriscoll
  485. * 2013 Stefan Slonevskiy, https://github.com/stefslon
  486. * 2013 Jeremy Morel, https://github.com/jmorel
  487. * 2013 Christoph Hartmann, https://github.com/chris-rock
  488. * 2014 Juan Pablo Gaviria, https://github.com/juanpgaviria
  489. * 2014 James Makes, https://github.com/dollaruw
  490. * 2014 Diego Casorran, https://github.com/diegocr
  491. * 2014 Steven Spungin, https://github.com/Flamenco
  492. * 2014 Kenneth Glassey, https://github.com/Gavvers
  493. *
  494. * Licensed under the MIT License
  495. *
  496. * Contributor(s):
  497. * siefkenj, ahwolf, rickygu, Midnith, saintclair, eaparango,
  498. * kim3er, mfo, alnorth, Flamenco
  499. */
  500. /**
  501. * Creates new jsPDF document object instance.
  502. * @name jsPDF
  503. * @class
  504. * @param orientation {string/Object} Orientation of the first page. Possible values are "portrait" or "landscape" (or shortcuts "p" (Default), "l") <br />
  505. * Can also be an options object.
  506. * @param unit {string} Measurement unit to be used when coordinates are specified.<br />
  507. * Possible values are "pt" (points), "mm" (Default), "cm", "in" or "px".
  508. * @param format {string/Array} The format of the first page. Can be <ul><li>a0 - a10</li><li>b0 - b10</li><li>c0 - c10</li><li>c0 - c10</li><li>dl</li><li>letter</li><li>government-letter</li><li>legal</li><li>junior-legal</li><li>ledger</li><li>tabloid</li><li>credit-card</li></ul><br />
  509. * Default is "a4". If you want to use your own format just pass instead of one of the above predefined formats the size as an number-array , e.g. [595.28, 841.89]
  510. * @returns {jsPDF} jsPDF-instance
  511. * @description
  512. * If the first parameter (orientation) is an object, it will be interpreted as an object of named parameters
  513. * ```
  514. * {
  515. * orientation: 'p',
  516. * unit: 'mm',
  517. * format: 'a4',
  518. * hotfixes: [] // an array of hotfix strings to enable
  519. * }
  520. * ```
  521. */
  522. var jsPDF = function (global) {
  523. var pdfVersion = "1.3",
  524. pageFormats = {
  525. // Size in pt of various paper formats
  526. a0: [2383.94, 3370.39],
  527. a1: [1683.78, 2383.94],
  528. a2: [1190.55, 1683.78],
  529. a3: [841.89, 1190.55],
  530. a4: [595.28, 841.89],
  531. a5: [419.53, 595.28],
  532. a6: [297.64, 419.53],
  533. a7: [209.76, 297.64],
  534. a8: [147.4, 209.76],
  535. a9: [104.88, 147.4],
  536. a10: [73.7, 104.88],
  537. b0: [2834.65, 4008.19],
  538. b1: [2004.09, 2834.65],
  539. b2: [1417.32, 2004.09],
  540. b3: [1000.63, 1417.32],
  541. b4: [708.66, 1000.63],
  542. b5: [498.9, 708.66],
  543. b6: [354.33, 498.9],
  544. b7: [249.45, 354.33],
  545. b8: [175.75, 249.45],
  546. b9: [124.72, 175.75],
  547. b10: [87.87, 124.72],
  548. c0: [2599.37, 3676.54],
  549. c1: [1836.85, 2599.37],
  550. c2: [1298.27, 1836.85],
  551. c3: [918.43, 1298.27],
  552. c4: [649.13, 918.43],
  553. c5: [459.21, 649.13],
  554. c6: [323.15, 459.21],
  555. c7: [229.61, 323.15],
  556. c8: [161.57, 229.61],
  557. c9: [113.39, 161.57],
  558. c10: [79.37, 113.39],
  559. dl: [311.81, 623.62],
  560. letter: [612, 792],
  561. "government-letter": [576, 756],
  562. legal: [612, 1008],
  563. "junior-legal": [576, 360],
  564. ledger: [1224, 792],
  565. tabloid: [792, 1224],
  566. "credit-card": [153, 243]
  567. };
  568. /**
  569. * jsPDF's Internal PubSub Implementation.
  570. * Backward compatible rewritten on 2014 by
  571. * Diego Casorran, https://github.com/diegocr
  572. *
  573. * @class
  574. * @name PubSub
  575. * @ignore
  576. */
  577. function PubSub(context) {
  578. var topics = {};
  579. this.subscribe = function (topic, callback, once) {
  580. if (typeof callback !== "function") {
  581. return false;
  582. }
  583. if (!topics.hasOwnProperty(topic)) {
  584. topics[topic] = {};
  585. }
  586. var id = Math.random().toString(35);
  587. topics[topic][id] = [callback, !!once];
  588. return id;
  589. };
  590. this.unsubscribe = function (token) {
  591. for (var topic in topics) {
  592. if (topics[topic][token]) {
  593. delete topics[topic][token];
  594. return true;
  595. }
  596. }
  597. return false;
  598. };
  599. this.publish = function (topic) {
  600. if (topics.hasOwnProperty(topic)) {
  601. var args = Array.prototype.slice.call(arguments, 1),
  602. idr = [];
  603. for (var id in topics[topic]) {
  604. var sub = topics[topic][id];
  605. try {
  606. sub[0].apply(context, args);
  607. } catch (ex) {
  608. if (global.console) {
  609. console.error("jsPDF PubSub Error", ex.message, ex);
  610. }
  611. }
  612. if (sub[1]) idr.push(id);
  613. }
  614. if (idr.length) idr.forEach(this.unsubscribe);
  615. }
  616. };
  617. }
  618. /**
  619. * @constructor
  620. * @private
  621. */
  622. function jsPDF(orientation, unit, format, compressPdf) {
  623. var options = {};
  624. if (_typeof(orientation) === "object") {
  625. options = orientation;
  626. orientation = options.orientation;
  627. unit = options.unit || unit;
  628. format = options.format || format;
  629. compressPdf = options.compress || options.compressPdf || compressPdf;
  630. } // Default options
  631. unit = unit || "mm";
  632. format = format || "a4";
  633. orientation = ("" + (orientation || "P")).toLowerCase();
  634. var format_as_string = ("" + format).toLowerCase(),
  635. compress = !!compressPdf && typeof Uint8Array === "function",
  636. textColor = options.textColor || "0 g",
  637. drawColor = options.drawColor || "0 G",
  638. activeFontSize = options.fontSize || 16,
  639. activeCharSpace = options.charSpace || 0,
  640. R2L = options.R2L || false,
  641. lineHeightProportion = options.lineHeight || 1.15,
  642. lineWidth = options.lineWidth || 0.200025,
  643. // 2mm
  644. fileId = "00000000000000000000000000000000",
  645. objectNumber = 2,
  646. // 'n' Current object number
  647. outToPages = !1,
  648. // switches where out() prints. outToPages true = push to pages obj. outToPages false = doc builder content
  649. offsets = [],
  650. // List of offsets. Activated and reset by buildDocument(). Pupulated by various calls buildDocument makes.
  651. fonts = {},
  652. // collection of font objects, where key is fontKey - a dynamically created label for a given font.
  653. fontmap = {},
  654. // mapping structure fontName > fontStyle > font key - performance layer. See addFont()
  655. activeFontKey,
  656. // will be string representing the KEY of the font as combination of fontName + fontStyle
  657. fontStateStack = [],
  658. //
  659. patterns = {},
  660. // collection of pattern objects
  661. patternMap = {},
  662. // see fonts
  663. gStates = {},
  664. // collection of graphic state objects
  665. gStatesMap = {},
  666. // see fonts
  667. activeGState = null,
  668. k,
  669. // Scale factor
  670. tmp,
  671. page = 0,
  672. currentPage,
  673. pages = [],
  674. pagesContext = [],
  675. // same index as pages and pagedim
  676. pagedim = [],
  677. content = [],
  678. additionalObjects = [],
  679. lineCapID = 0,
  680. lineJoinID = 0,
  681. content_length = 0,
  682. renderTargets = {},
  683. renderTargetMap = {},
  684. renderTargetStack = [],
  685. pageX,
  686. pageY,
  687. pageMatrix,
  688. // only used for FormObjects
  689. pageWidth,
  690. pageHeight,
  691. pageMode,
  692. zoomMode,
  693. layoutMode,
  694. creationDate,
  695. documentProperties = {
  696. title: "",
  697. subject: "",
  698. author: "",
  699. keywords: "",
  700. creator: ""
  701. },
  702. API = {},
  703. ApiMode = {
  704. COMPAT: "compat",
  705. ADVANCED: "advanced"
  706. },
  707. apiMode = ApiMode.COMPAT,
  708. events = new PubSub(API),
  709. hotfixes = options.hotfixes || [],
  710. /////////////////////
  711. // Private functions
  712. /////////////////////
  713. generateColorString = function generateColorString(options) {
  714. var color;
  715. var ch1 = options.ch1;
  716. var ch2 = options.ch2;
  717. var ch3 = options.ch3;
  718. var ch4 = options.ch4;
  719. var precision = options.precision;
  720. var letterArray = options.pdfColorType === "draw" ? ["G", "RG", "K"] : ["g", "rg", "k"];
  721. if (typeof ch1 === "string" && ch1.charAt(0) !== "#") {
  722. var rgbColor = new RGBColor(ch1);
  723. if (rgbColor.ok) {
  724. ch1 = rgbColor.toHex();
  725. }
  726. } //convert short rgb to long form
  727. if (typeof ch1 === "string" && /^#[0-9A-Fa-f]{3}$/.test(ch1)) {
  728. ch1 = "#" + ch1[1] + ch1[1] + ch1[2] + ch1[2] + ch1[3] + ch1[3];
  729. }
  730. if (typeof ch1 === "string" && /^#[0-9A-Fa-f]{6}$/.test(ch1)) {
  731. var hex = parseInt(ch1.substr(1), 16);
  732. ch1 = hex >> 16 & 255;
  733. ch2 = hex >> 8 & 255;
  734. ch3 = hex & 255;
  735. }
  736. if (typeof ch2 === "undefined" || typeof ch4 === "undefined" && ch1 === ch2 && ch2 === ch3) {
  737. // Gray color space.
  738. if (typeof ch1 === "string") {
  739. color = ch1 + " " + letterArray[0];
  740. } else {
  741. switch (options.precision) {
  742. case 2:
  743. color = f2(ch1 / 255) + " " + letterArray[0];
  744. break;
  745. case 3:
  746. default:
  747. color = f3(ch1 / 255) + " " + letterArray[0];
  748. }
  749. }
  750. } else if (typeof ch4 === "undefined" || _typeof(ch4) === "object") {
  751. // assume RGB
  752. if (typeof ch1 === "string") {
  753. color = [ch1, ch2, ch3, letterArray[1]].join(" ");
  754. } else {
  755. switch (options.precision) {
  756. case 2:
  757. color = [f2(ch1 / 255), f2(ch2 / 255), f2(ch3 / 255), letterArray[1]].join(" ");
  758. break;
  759. default:
  760. case 3:
  761. color = [f3(ch1 / 255), f3(ch2 / 255), f3(ch3 / 255), letterArray[1]].join(" ");
  762. }
  763. } // assume RGBA
  764. if (ch4 && ch4.a === 0) {
  765. //TODO Implement transparency.
  766. //WORKAROUND use white for now
  767. color = ["255", "255", "255", letterArray[1]].join(" ");
  768. }
  769. } else {
  770. // assume CMYK
  771. if (typeof ch1 === "string") {
  772. color = [ch1, ch2, ch3, ch4, letterArray[2]].join(" ");
  773. } else {
  774. switch (options.precision) {
  775. case 2:
  776. color = [f2(ch1), f2(ch2), f2(ch3), f2(ch4), letterArray[2]].join(" ");
  777. break;
  778. case 3:
  779. default:
  780. color = [f3(ch1), f3(ch2), f3(ch3), f3(ch4), letterArray[2]].join(" ");
  781. }
  782. }
  783. }
  784. return color;
  785. },
  786. convertDateToPDFDate = function convertDateToPDFDate(parmDate) {
  787. var padd2 = function padd2(number) {
  788. return ("0" + parseInt(number)).slice(-2);
  789. };
  790. var result = "";
  791. var tzoffset = parmDate.getTimezoneOffset(),
  792. tzsign = tzoffset < 0 ? "+" : "-",
  793. tzhour = Math.floor(Math.abs(tzoffset / 60)),
  794. tzmin = Math.abs(tzoffset % 60),
  795. timeZoneString = [tzsign, padd2(tzhour), "'", padd2(tzmin), "'"].join("");
  796. result = ["D:", parmDate.getFullYear(), padd2(parmDate.getMonth() + 1), padd2(parmDate.getDate()), padd2(parmDate.getHours()), padd2(parmDate.getMinutes()), padd2(parmDate.getSeconds()), timeZoneString].join("");
  797. return result;
  798. },
  799. convertPDFDateToDate = function convertPDFDateToDate(parmPDFDate) {
  800. var year = parseInt(parmPDFDate.substr(2, 4), 10);
  801. var month = parseInt(parmPDFDate.substr(6, 2), 10) - 1;
  802. var date = parseInt(parmPDFDate.substr(8, 2), 10);
  803. var hour = parseInt(parmPDFDate.substr(10, 2), 10);
  804. var minutes = parseInt(parmPDFDate.substr(12, 2), 10);
  805. var seconds = parseInt(parmPDFDate.substr(14, 2), 10);
  806. var timeZoneHour = parseInt(parmPDFDate.substr(16, 2), 10);
  807. var timeZoneMinutes = parseInt(parmPDFDate.substr(20, 2), 10);
  808. var resultingDate = new Date(year, month, date, hour, minutes, seconds, 0);
  809. return resultingDate;
  810. },
  811. setCreationDate = function setCreationDate(date) {
  812. var tmpCreationDateString;
  813. var regexPDFCreationDate = /^D:(20[0-2][0-9]|203[0-7]|19[7-9][0-9])(0[0-9]|1[0-2])([0-2][0-9]|3[0-1])(0[0-9]|1[0-9]|2[0-3])(0[0-9]|[1-5][0-9])(0[0-9]|[1-5][0-9])(\+0[0-9]|\+1[0-4]|\-0[0-9]|\-1[0-1])\'(0[0-9]|[1-5][0-9])\'?$/;
  814. if (_typeof(date) === undefined) {
  815. date = new Date();
  816. }
  817. if (_typeof(date) === "object" && Object.prototype.toString.call(date) === "[object Date]") {
  818. tmpCreationDateString = convertDateToPDFDate(date);
  819. } else if (regexPDFCreationDate.test(date)) {
  820. tmpCreationDateString = date;
  821. } else {
  822. tmpCreationDateString = convertDateToPDFDate(new Date());
  823. }
  824. creationDate = tmpCreationDateString;
  825. return creationDate;
  826. },
  827. getCreationDate = function getCreationDate(type) {
  828. var result = creationDate;
  829. if (type === "jsDate") {
  830. result = convertPDFDateToDate(creationDate);
  831. }
  832. return result;
  833. },
  834. setFileId = function setFileId(value) {
  835. value = value || "12345678901234567890123456789012".split("").map(function () {
  836. return "ABCDEF0123456789".charAt(Math.floor(Math.random() * 16));
  837. }).join("");
  838. fileId = value;
  839. return fileId;
  840. },
  841. getFileId = function getFileId() {
  842. return fileId;
  843. },
  844. f2 = function f2(number) {
  845. return number.toFixed(2); // Ie, %.2f
  846. },
  847. f3 = function f3(number) {
  848. return number.toFixed(3); // Ie, %.3f
  849. },
  850. // high precision float
  851. hpf = function hpf(number) {
  852. return number.toFixed(16).replace(/0+$/, "");
  853. },
  854. scaleByK = function scaleByK(coordinate) {
  855. if (apiMode === ApiMode.COMPAT) {
  856. return coordinate * k;
  857. } else if (apiMode === ApiMode.ADVANCED) {
  858. return coordinate;
  859. }
  860. },
  861. transformY = function transformY(y) {
  862. if (apiMode === ApiMode.COMPAT) {
  863. return pageHeight - y;
  864. } else if (apiMode === ApiMode.ADVANCED) {
  865. return y;
  866. }
  867. },
  868. transformScaleY = function transformScaleY(y) {
  869. return scaleByK(transformY(y));
  870. },
  871. padd2Hex = function padd2Hex(hexString) {
  872. var s = "00" + hexString;
  873. return s.substr(s.length - 2);
  874. },
  875. advancedApiModeTrap = function advancedApiModeTrap(methodName) {
  876. if (apiMode !== ApiMode.ADVANCED) {
  877. throw new Error(methodName + " is only available in 'advanced' API mode. " + "You need to call advancedAPI() first.");
  878. }
  879. },
  880. out = function out(string) {
  881. string = typeof string === "string" ? string : string.toString();
  882. if (outToPages) {
  883. /* set by beginPage */
  884. pages[currentPage].push(string);
  885. } else {
  886. // +1 for '\n' that will be used to join 'content'
  887. content_length += string.length + 1;
  888. content.push(string);
  889. }
  890. },
  891. newObject = function newObject() {
  892. // Begin a new object
  893. objectNumber++;
  894. offsets[objectNumber] = content_length;
  895. out(objectNumber + " 0 obj");
  896. return objectNumber;
  897. },
  898. // Does not output the object until after the pages have been output.
  899. // Returns an object containing the objectId and content.
  900. // All pages have been added so the object ID can be estimated to start right after.
  901. // This does not modify the current objectNumber; It must be updated after the newObjects are output.
  902. newAdditionalObject = function newAdditionalObject() {
  903. var objId = pages.length * 2 + 1;
  904. objId += additionalObjects.length;
  905. var obj = {
  906. objId: objId,
  907. content: ""
  908. };
  909. additionalObjects.push(obj);
  910. return obj;
  911. },
  912. // Does not output the object. The caller must call newObjectDeferredBegin(oid) before outputing any data
  913. newObjectDeferred = function newObjectDeferred() {
  914. objectNumber++;
  915. offsets[objectNumber] = function () {
  916. return content_length;
  917. };
  918. return objectNumber;
  919. },
  920. newObjectDeferredBegin = function newObjectDeferredBegin(oid) {
  921. offsets[oid] = content_length;
  922. },
  923. putStream = function putStream(str) {
  924. out("stream");
  925. out(str);
  926. out("endstream");
  927. },
  928. putPages = function putPages() {
  929. var n,
  930. p,
  931. arr,
  932. i,
  933. deflater,
  934. adler32,
  935. adler32cs,
  936. wPt,
  937. hPt,
  938. pageObjectNumbers = [];
  939. adler32cs = global.adler32cs || jsPDF.API.adler32cs;
  940. if (compress && typeof adler32cs === "undefined") {
  941. compress = false;
  942. } // outToPages = false as set in endDocument(). out() writes to content.
  943. for (n = 1; n <= page; n++) {
  944. pageObjectNumbers.push(newObject());
  945. wPt = (pageWidth = pagedim[n].width) * k;
  946. hPt = (pageHeight = pagedim[n].height) * k;
  947. out("<</Type /Page");
  948. out("/Parent 1 0 R");
  949. out("/Resources 2 0 R");
  950. out("/MediaBox [0 0 " + hpf(wPt) + " " + hpf(hPt) + "]"); // Added for annotation plugin
  951. events.publish("putPage", {
  952. pageNumber: n,
  953. page: pages[n]
  954. });
  955. out("/Contents " + (objectNumber + 1) + " 0 R");
  956. out(">>");
  957. out("endobj"); // Page content
  958. p = pages[n].join("\n");
  959. if (apiMode === ApiMode.ADVANCED) {
  960. // if the user forgot to switch back to COMPAT mode, we must balance the graphics stack again
  961. p += "\nQ";
  962. }
  963. newObject();
  964. if (compress) {
  965. arr = [];
  966. i = p.length;
  967. while (i--) {
  968. arr[i] = p.charCodeAt(i);
  969. }
  970. adler32 = adler32cs.from(p);
  971. deflater = new Deflater(6);
  972. deflater.append(new Uint8Array(arr));
  973. p = deflater.flush();
  974. arr = new Uint8Array(p.length + 6);
  975. arr.set(new Uint8Array([120, 156]));
  976. arr.set(p, 2);
  977. arr.set(new Uint8Array([adler32 & 0xff, adler32 >> 8 & 0xff, adler32 >> 16 & 0xff, adler32 >> 24 & 0xff]), p.length + 2);
  978. p = String.fromCharCode.apply(null, arr);
  979. out("<</Length " + p.length + " /Filter [/FlateDecode]>>");
  980. } else {
  981. out("<</Length " + p.length + ">>");
  982. }
  983. putStream(p);
  984. out("endobj");
  985. }
  986. offsets[1] = content_length;
  987. out("1 0 obj");
  988. out("<</Type /Pages");
  989. var kids = "/Kids [";
  990. for (i = 0; i < page; i++) {
  991. kids += pageObjectNumbers[i] + " 0 R ";
  992. }
  993. out(kids + "]");
  994. out("/Count " + page);
  995. out(">>");
  996. out("endobj");
  997. events.publish("postPutPages");
  998. },
  999. putFont = function putFont(font) {
  1000. events.publish("putFont", {
  1001. font: font,
  1002. out: out,
  1003. newObject: newObject
  1004. });
  1005. if (font.isAlreadyPutted !== true) {
  1006. font.objectNumber = newObject();
  1007. out("<<");
  1008. out("/Type /Font");
  1009. out("/BaseFont /" + font.postScriptName);
  1010. out("/Subtype /Type1");
  1011. if (typeof font.encoding === "string") {
  1012. out("/Encoding /" + font.encoding);
  1013. }
  1014. out("/FirstChar 32");
  1015. out("/LastChar 255");
  1016. out(">>");
  1017. out("endobj");
  1018. }
  1019. },
  1020. putFonts = function putFonts() {
  1021. for (var fontKey in fonts) {
  1022. if (fonts.hasOwnProperty(fontKey)) {
  1023. putFont(fonts[fontKey]);
  1024. }
  1025. }
  1026. },
  1027. putXObject = function putXObject(xObject) {
  1028. xObject.objectNumber = newObject();
  1029. out("<<");
  1030. out("/Type /XObject");
  1031. out("/Subtype /Form");
  1032. out("/BBox [" + [hpf(xObject.x), hpf(xObject.y), hpf(xObject.x + xObject.width), hpf(xObject.y + xObject.height)].join(" ") + "]");
  1033. out("/Matrix [" + xObject.matrix.toString() + "]"); // TODO: /Resources
  1034. var p = xObject.pages[1].join("\n");
  1035. out("/Length " + p.length);
  1036. out(">>");
  1037. putStream(p);
  1038. out("endobj");
  1039. },
  1040. putXObjects = function putXObjects() {
  1041. for (var xObjectKey in renderTargets) {
  1042. if (renderTargets.hasOwnProperty(xObjectKey)) {
  1043. putXObject(renderTargets[xObjectKey]);
  1044. }
  1045. }
  1046. },
  1047. interpolateAndEncodeRGBStream = function interpolateAndEncodeRGBStream(colors, numberSamples) {
  1048. var tValues = [];
  1049. var t;
  1050. var dT = 1.0 / (numberSamples - 1);
  1051. for (t = 0.0; t < 1.0; t += dT) {
  1052. tValues.push(t);
  1053. }
  1054. tValues.push(1.0); // add first and last control point if not present
  1055. if (colors[0].offset != 0.0) {
  1056. var c0 = {
  1057. offset: 0.0,
  1058. color: colors[0].color
  1059. };
  1060. colors.unshift(c0);
  1061. }
  1062. if (colors[colors.length - 1].offset != 1.0) {
  1063. var c1 = {
  1064. offset: 1.0,
  1065. color: colors[colors.length - 1].color
  1066. };
  1067. colors.push(c1);
  1068. }
  1069. var out = "";
  1070. var index = 0;
  1071. for (var i = 0; i < tValues.length; i++) {
  1072. t = tValues[i];
  1073. while (t > colors[index + 1].offset) {
  1074. index++;
  1075. }
  1076. var a = colors[index].offset;
  1077. var b = colors[index + 1].offset;
  1078. var d = (t - a) / (b - a);
  1079. var aColor = colors[index].color;
  1080. var bColor = colors[index + 1].color;
  1081. out += padd2Hex(Math.round((1 - d) * aColor[0] + d * bColor[0]).toString(16)) + padd2Hex(Math.round((1 - d) * aColor[1] + d * bColor[1]).toString(16)) + padd2Hex(Math.round((1 - d) * aColor[2] + d * bColor[2]).toString(16));
  1082. }
  1083. return out.trim();
  1084. },
  1085. putShadingPattern = function putShadingPattern(pattern, numberSamples) {
  1086. /*
  1087. Axial patterns shade between the two points specified in coords, radial patterns between the inner
  1088. and outer circle.
  1089. The user can specify an array (colors) that maps t-Values in [0, 1] to RGB colors. These are now
  1090. interpolated to equidistant samples and written to pdf as a sample (type 0) function.
  1091. */
  1092. // The number of color samples that should be used to describe the shading.
  1093. // The higher, the more accurate the gradient will be.
  1094. numberSamples || (numberSamples = 21);
  1095. var funcObjectNumber = newObject();
  1096. var stream = interpolateAndEncodeRGBStream(pattern.colors, numberSamples);
  1097. out("<< /FunctionType 0");
  1098. out("/Domain [0.0 1.0]");
  1099. out("/Size [" + numberSamples + "]");
  1100. out("/BitsPerSample 8");
  1101. out("/Range [0.0 1.0 0.0 1.0 0.0 1.0]");
  1102. out("/Decode [0.0 1.0 0.0 1.0 0.0 1.0]");
  1103. out("/Length " + stream.length); // The stream is Hex encoded
  1104. out("/Filter /ASCIIHexDecode");
  1105. out(">>");
  1106. putStream(stream);
  1107. out("endobj");
  1108. pattern.objectNumber = newObject();
  1109. out("<< /ShadingType " + pattern.type);
  1110. out("/ColorSpace /DeviceRGB");
  1111. var coords = "/Coords [" + hpf(parseFloat(pattern.coords[0])) + " " + // x1
  1112. hpf(parseFloat(pattern.coords[1])) + " "; // y1
  1113. if (pattern.type === 2) {
  1114. // axial
  1115. coords += hpf(parseFloat(pattern.coords[2])) + " " + // x2
  1116. hpf(parseFloat(pattern.coords[3])); // y2
  1117. } else {
  1118. // radial
  1119. coords += hpf(parseFloat(pattern.coords[2])) + " " + // r1
  1120. hpf(parseFloat(pattern.coords[3])) + " " + // x2
  1121. hpf(parseFloat(pattern.coords[4])) + " " + // y2
  1122. hpf(parseFloat(pattern.coords[5])); // r2
  1123. }
  1124. coords += "]";
  1125. out(coords);
  1126. if (pattern.matrix) {
  1127. out("/Matrix [" + pattern.matrix.toString() + "]");
  1128. }
  1129. out("/Function " + funcObjectNumber + " 0 R");
  1130. out("/Extend [true true]");
  1131. out(">>");
  1132. out("endobj");
  1133. },
  1134. putTilingPattern = function putTilingPattern(pattern) {
  1135. var resourcesObjectNumber = newObject();
  1136. out("<<");
  1137. putResourceDictionary();
  1138. out(">>");
  1139. out("endobj");
  1140. pattern.objectNumber = newObject();
  1141. out("<< /Type /Pattern");
  1142. out("/PatternType 1"); // tiling pattern
  1143. out("/PaintType 1"); // colored tiling pattern
  1144. out("/TilingType 1"); // constant spacing
  1145. out("/BBox [" + pattern.boundingBox.map(hpf).join(" ") + "]");
  1146. out("/XStep " + hpf(pattern.xStep));
  1147. out("/YStep " + hpf(pattern.yStep));
  1148. out("/Length " + pattern.stream.length);
  1149. out("/Resources " + resourcesObjectNumber + " 0 R"); // TODO: resources
  1150. pattern.matrix && out("/Matrix [" + pattern.matrix.toString() + "]");
  1151. out(">>");
  1152. putStream(pattern.stream);
  1153. out("endobj");
  1154. },
  1155. putPatterns = function putPatterns() {
  1156. var patternKey;
  1157. for (patternKey in patterns) {
  1158. if (patterns.hasOwnProperty(patternKey)) {
  1159. if (patterns[patternKey] instanceof API.ShadingPattern) {
  1160. putShadingPattern(patterns[patternKey]);
  1161. } else if (patterns[patternKey] instanceof API.TilingPattern) {
  1162. putTilingPattern(patterns[patternKey]);
  1163. }
  1164. }
  1165. }
  1166. },
  1167. putGState = function putGState(gState) {
  1168. gState.objectNumber = newObject();
  1169. out("<<");
  1170. for (var p in gState) {
  1171. switch (p) {
  1172. case "opacity":
  1173. out("/ca " + f2(gState[p]));
  1174. break;
  1175. case "stroke-opacity":
  1176. out("/CA " + f2(gState[p]));
  1177. break;
  1178. }
  1179. }
  1180. out(">>");
  1181. out("endobj");
  1182. },
  1183. putGStates = function putGStates() {
  1184. var gStateKey;
  1185. for (gStateKey in gStates) {
  1186. if (gStates.hasOwnProperty(gStateKey)) {
  1187. putGState(gStates[gStateKey]);
  1188. }
  1189. }
  1190. },
  1191. putXobjectDict = function putXobjectDict() {
  1192. for (var xObjectKey in renderTargets) {
  1193. if (renderTargets.hasOwnProperty(xObjectKey) && renderTargets[xObjectKey].objectNumber >= 0) {
  1194. out("/" + xObjectKey + " " + renderTargets[xObjectKey].objectNumber + " 0 R");
  1195. }
  1196. }
  1197. events.publish("putXobjectDict");
  1198. },
  1199. putShadingPatternDict = function putShadingPatternDict() {
  1200. for (var patternKey in patterns) {
  1201. if (patterns.hasOwnProperty(patternKey) && patterns[patternKey] instanceof API.ShadingPattern && patterns[patternKey].objectNumber >= 0) {
  1202. out("/" + patternKey + " " + patterns[patternKey].objectNumber + " 0 R");
  1203. }
  1204. }
  1205. events.publish("putShadingPatternDict");
  1206. },
  1207. putTilingPatternDict = function putTilingPatternDict() {
  1208. for (var patternKey in patterns) {
  1209. if (patterns.hasOwnProperty(patternKey) && patterns[patternKey] instanceof API.TilingPattern && patterns[patternKey].objectNumber >= 0) {
  1210. out("/" + patternKey + " " + patterns[patternKey].objectNumber + " 0 R");
  1211. }
  1212. }
  1213. events.publish("putTilingPatternDict");
  1214. },
  1215. putGStatesDict = function putGStatesDict() {
  1216. var gStateKey;
  1217. for (gStateKey in gStates) {
  1218. if (gStates.hasOwnProperty(gStateKey) && gStates[gStateKey].objectNumber >= 0) {
  1219. out("/" + gStateKey + " " + gStates[gStateKey].objectNumber + " 0 R");
  1220. }
  1221. }
  1222. events.publish("putGStateDict");
  1223. },
  1224. putResourceDictionary = function putResourceDictionary() {
  1225. out("/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]");
  1226. out("/Font <<"); // Do this for each font, the '1' bit is the index of the font
  1227. for (var fontKey in fonts) {
  1228. if (fonts.hasOwnProperty(fontKey)) {
  1229. out("/" + fontKey + " " + fonts[fontKey].objectNumber + " 0 R");
  1230. }
  1231. }
  1232. out(">>");
  1233. out("/Shading <<");
  1234. putShadingPatternDict();
  1235. out(">>");
  1236. out("/Pattern <<");
  1237. putTilingPatternDict();
  1238. out(">>");
  1239. out("/ExtGState <<");
  1240. putGStatesDict();
  1241. out(">>");
  1242. out("/XObject <<");
  1243. putXobjectDict();
  1244. out(">>");
  1245. },
  1246. putResources = function putResources() {
  1247. putFonts();
  1248. putGStates();
  1249. putXObjects();
  1250. putPatterns();
  1251. events.publish("putResources"); // Resource dictionary
  1252. offsets[2] = content_length;
  1253. out("2 0 obj");
  1254. out("<<");
  1255. putResourceDictionary();
  1256. out(">>");
  1257. out("endobj");
  1258. events.publish("postPutResources");
  1259. },
  1260. putAdditionalObjects = function putAdditionalObjects() {
  1261. events.publish("putAdditionalObjects");
  1262. for (var i = 0; i < additionalObjects.length; i++) {
  1263. var obj = additionalObjects[i];
  1264. offsets[obj.objId] = content_length;
  1265. out(obj.objId + " 0 obj");
  1266. out(obj.content);
  1267. out("endobj");
  1268. }
  1269. objectNumber += additionalObjects.length;
  1270. events.publish("postPutAdditionalObjects");
  1271. },
  1272. addToFontDictionary = function addToFontDictionary(fontKey, fontName, fontStyle) {
  1273. // this is mapping structure for quick font key lookup.
  1274. // returns the KEY of the font (ex: "F1") for a given
  1275. // pair of font name and type (ex: "Arial". "Italic")
  1276. if (!fontmap.hasOwnProperty(fontName)) {
  1277. fontmap[fontName] = {};
  1278. }
  1279. fontmap[fontName][fontStyle] = fontKey;
  1280. },
  1281. addFont = function addFont(postScriptName, fontName, fontStyle, encoding) {
  1282. var fontKey = "F" + (Object.keys(fonts).length + 1).toString(10),
  1283. // This is FontObject
  1284. font = fonts[fontKey] = {
  1285. id: fontKey,
  1286. postScriptName: postScriptName,
  1287. fontName: fontName,
  1288. fontStyle: fontStyle,
  1289. encoding: encoding,
  1290. metadata: {}
  1291. };
  1292. addToFontDictionary(fontKey, fontName, fontStyle);
  1293. events.publish("addFont", font);
  1294. return fontKey;
  1295. },
  1296. addFonts = function addFonts() {
  1297. var HELVETICA = "helvetica",
  1298. TIMES = "times",
  1299. COURIER = "courier",
  1300. NORMAL = "normal",
  1301. BOLD = "bold",
  1302. ITALIC = "italic",
  1303. BOLD_ITALIC = "bolditalic",
  1304. ZAPF = "zapfdingbats",
  1305. SYMBOL = "symbol",
  1306. standardFonts = [["Helvetica", HELVETICA, NORMAL, "WinAnsiEncoding"], ["Helvetica-Bold", HELVETICA, BOLD, "WinAnsiEncoding"], ["Helvetica-Oblique", HELVETICA, ITALIC, "WinAnsiEncoding"], ["Helvetica-BoldOblique", HELVETICA, BOLD_ITALIC, "WinAnsiEncoding"], ["Courier", COURIER, NORMAL, "WinAnsiEncoding"], ["Courier-Bold", COURIER, BOLD, "WinAnsiEncoding"], ["Courier-Oblique", COURIER, ITALIC, "WinAnsiEncoding"], ["Courier-BoldOblique", COURIER, BOLD_ITALIC, "WinAnsiEncoding"], ["Times-Roman", TIMES, NORMAL, "WinAnsiEncoding"], ["Times-Bold", TIMES, BOLD, "WinAnsiEncoding"], ["Times-Italic", TIMES, ITALIC, "WinAnsiEncoding"], ["Times-BoldItalic", TIMES, BOLD_ITALIC, "WinAnsiEncoding"], ["ZapfDingbats", ZAPF, NORMAL, null], ["Symbol", SYMBOL, NORMAL, null]];
  1307. for (var i = 0, l = standardFonts.length; i < l; i++) {
  1308. var fontKey = addFont(standardFonts[i][0], standardFonts[i][1], standardFonts[i][2], standardFonts[i][3]); // adding aliases for standard fonts, this time matching the capitalization
  1309. var parts = standardFonts[i][0].split("-");
  1310. addToFontDictionary(fontKey, parts[0], parts[1] || "");
  1311. }
  1312. events.publish("addFonts", {
  1313. fonts: fonts,
  1314. dictionary: fontmap
  1315. });
  1316. },
  1317. matrixMult = function matrixMult(m1, m2) {
  1318. return new Matrix(m1.a * m2.a + m1.b * m2.c, m1.a * m2.b + m1.b * m2.d, m1.c * m2.a + m1.d * m2.c, m1.c * m2.b + m1.d * m2.d, m1.e * m2.a + m1.f * m2.c + m2.e, m1.e * m2.b + m1.f * m2.d + m2.f);
  1319. },
  1320. Matrix = function Matrix(a, b, c, d, e, f) {
  1321. this.a = a;
  1322. this.b = b;
  1323. this.c = c;
  1324. this.d = d;
  1325. this.e = e;
  1326. this.f = f;
  1327. };
  1328. Matrix.prototype = {
  1329. toString: function toString() {
  1330. return [hpf(this.a), hpf(this.b), hpf(this.c), hpf(this.d), hpf(this.e), hpf(this.f)].join(" ");
  1331. },
  1332. inversed: function inversed() {
  1333. var a = this.a,
  1334. b = this.b,
  1335. c = this.c,
  1336. d = this.d,
  1337. e = this.e,
  1338. f = this.f;
  1339. var quot = 1 / (a * d - b * c);
  1340. var aInv = d * quot;
  1341. var bInv = -b * quot;
  1342. var cInv = -c * quot;
  1343. var dInv = a * quot;
  1344. var eInv = -aInv * e - cInv * f;
  1345. var fInv = -bInv * e - dInv * f;
  1346. return new Matrix(aInv, bInv, cInv, dInv, eInv, fInv);
  1347. }
  1348. };
  1349. var unitMatrix = new Matrix(1, 0, 0, 1, 0, 0),
  1350. // Used (1) to save the current stream state to the XObjects stack and (2) to save completed form
  1351. // objects in the xObjects map.
  1352. RenderTarget = function RenderTarget() {
  1353. this.page = page;
  1354. this.currentPage = currentPage;
  1355. this.pages = pages.slice(0);
  1356. this.pagedim = pagedim.slice(0);
  1357. this.pagesContext = pagesContext.slice(0);
  1358. this.x = pageX;
  1359. this.y = pageY;
  1360. this.matrix = pageMatrix;
  1361. this.width = pageWidth;
  1362. this.height = pageHeight;
  1363. this.id = ""; // set by endFormObject()
  1364. this.objectNumber = -1; // will be set by putXObject()
  1365. };
  1366. RenderTarget.prototype = {
  1367. restore: function restore() {
  1368. page = this.page;
  1369. currentPage = this.currentPage;
  1370. pagesContext = this.pagesContext;
  1371. pagedim = this.pagedim;
  1372. pages = this.pages;
  1373. pageX = this.x;
  1374. pageY = this.y;
  1375. pageMatrix = this.matrix;
  1376. pageWidth = this.width;
  1377. pageHeight = this.height;
  1378. }
  1379. };
  1380. var beginNewRenderTarget = function beginNewRenderTarget(x, y, width, height, matrix) {
  1381. // save current state
  1382. renderTargetStack.push(new RenderTarget()); // clear pages
  1383. page = currentPage = 0;
  1384. pages = [];
  1385. pageX = x;
  1386. pageY = y;
  1387. pageMatrix = matrix;
  1388. beginPage(width, height);
  1389. },
  1390. endFormObject = function endFormObject(key) {
  1391. // only add it if it is not already present (the keys provided by the user must be unique!)
  1392. if (renderTargetMap[key]) return; // save the created xObject
  1393. var newXObject = new RenderTarget();
  1394. var xObjectId = "Xo" + (Object.keys(renderTargets).length + 1).toString(10);
  1395. newXObject.id = xObjectId;
  1396. renderTargetMap[key] = xObjectId;
  1397. renderTargets[xObjectId] = newXObject;
  1398. events.publish("addFormObject", newXObject); // restore state from stack
  1399. renderTargetStack.pop().restore();
  1400. },
  1401. /**
  1402. * Adds a new pattern for later use.
  1403. * @param {String} key The key by it can be referenced later. The keys must be unique!
  1404. * @param {API.Pattern} pattern The pattern
  1405. */
  1406. addPattern = function addPattern(key, pattern) {
  1407. // only add it if it is not already present (the keys provided by the user must be unique!)
  1408. if (patternMap[key]) return;
  1409. var prefix = pattern instanceof API.ShadingPattern ? "Sh" : "P";
  1410. var patternKey = prefix + (Object.keys(patterns).length + 1).toString(10);
  1411. pattern.id = patternKey;
  1412. patternMap[key] = patternKey;
  1413. patterns[patternKey] = pattern;
  1414. events.publish("addPattern", pattern);
  1415. },
  1416. /**
  1417. * Adds a new Graphics State. Duplicates are automatically eliminated.
  1418. * @param {String} key Might also be null, if no later reference to this gState is needed
  1419. * @param {Object} gState The gState object
  1420. */
  1421. addGState = function addGState(key, gState) {
  1422. // only add it if it is not already present (the keys provided by the user must be unique!)
  1423. if (key && gStatesMap[key]) return;
  1424. var duplicate = false;
  1425. for (var s in gStates) {
  1426. if (gStates.hasOwnProperty(s)) {
  1427. if (gStates[s].equals(gState)) {
  1428. duplicate = true;
  1429. break;
  1430. }
  1431. }
  1432. }
  1433. if (duplicate) {
  1434. gState = gStates[s];
  1435. } else {
  1436. var gStateKey = "GS" + (Object.keys(gStates).length + 1).toString(10);
  1437. gStates[gStateKey] = gState;
  1438. gState.id = gStateKey;
  1439. } // several user keys may point to the same GState object
  1440. key && (gStatesMap[key] = gState.id);
  1441. events.publish("addGState", gState);
  1442. return gState;
  1443. },
  1444. SAFE = function __safeCall(fn) {
  1445. fn.foo = function __safeCallWrapper() {
  1446. try {
  1447. return fn.apply(this, arguments);
  1448. } catch (e) {
  1449. var stack = e.stack || "";
  1450. if (~stack.indexOf(" at ")) stack = stack.split(" at ")[1];
  1451. var m = "Error in function " + stack.split("\n")[0].split("<")[0] + ": " + e.message;
  1452. if (global.console) {
  1453. global.console.error(m, e);
  1454. if (global.alert) alert(m);
  1455. } else {
  1456. throw new Error(m);
  1457. }
  1458. }
  1459. };
  1460. fn.foo.bar = fn;
  1461. return fn.foo;
  1462. },
  1463. to8bitStream = function to8bitStream(text, flags) {
  1464. /**
  1465. * PDF 1.3 spec:
  1466. * "For text strings encoded in Unicode, the first two bytes must be 254 followed by
  1467. * 255, representing the Unicode byte order marker, U+FEFF. (This sequence conflicts
  1468. * with the PDFDocEncoding character sequence thorn ydieresis, which is unlikely
  1469. * to be a meaningful beginning of a word or phrase.) The remainder of the
  1470. * string consists of Unicode character codes, according to the UTF-16 encoding
  1471. * specified in the Unicode standard, version 2.0. Commonly used Unicode values
  1472. * are represented as 2 bytes per character, with the high-order byte appearing first
  1473. * in the string."
  1474. *
  1475. * In other words, if there are chars in a string with char code above 255, we
  1476. * recode the string to UCS2 BE - string doubles in length and BOM is prepended.
  1477. *
  1478. * HOWEVER!
  1479. * Actual *content* (body) text (as opposed to strings used in document properties etc)
  1480. * does NOT expect BOM. There, it is treated as a literal GID (Glyph ID)
  1481. *
  1482. * Because of Adobe's focus on "you subset your fonts!" you are not supposed to have
  1483. * a font that maps directly Unicode (UCS2 / UTF16BE) code to font GID, but you could
  1484. * fudge it with "Identity-H" encoding and custom CIDtoGID map that mimics Unicode
  1485. * code page. There, however, all characters in the stream are treated as GIDs,
  1486. * including BOM, which is the reason we need to skip BOM in content text (i.e. that
  1487. * that is tied to a font).
  1488. *
  1489. * To signal this "special" PDFEscape / to8bitStream handling mode,
  1490. * API.text() function sets (unless you overwrite it with manual values
  1491. * given to API.text(.., flags) )
  1492. * flags.autoencode = true
  1493. * flags.noBOM = true
  1494. *
  1495. * ===================================================================================
  1496. * `flags` properties relied upon:
  1497. * .sourceEncoding = string with encoding label.
  1498. * "Unicode" by default. = encoding of the incoming text.
  1499. * pass some non-existing encoding name
  1500. * (ex: 'Do not touch my strings! I know what I am doing.')
  1501. * to make encoding code skip the encoding step.
  1502. * .outputEncoding = Either valid PDF encoding name
  1503. * (must be supported by jsPDF font metrics, otherwise no encoding)
  1504. * or a JS object, where key = sourceCharCode, value = outputCharCode
  1505. * missing keys will be treated as: sourceCharCode === outputCharCode
  1506. * .noBOM
  1507. * See comment higher above for explanation for why this is important
  1508. * .autoencode
  1509. * See comment higher above for explanation for why this is important
  1510. */
  1511. var i, l, sourceEncoding, encodingBlock, outputEncoding, newtext, isUnicode, ch, bch;
  1512. flags = flags || {};
  1513. sourceEncoding = flags.sourceEncoding || "Unicode";
  1514. outputEncoding = flags.outputEncoding; // This 'encoding' section relies on font metrics format
  1515. // attached to font objects by, among others,
  1516. // "Willow Systems' standard_font_metrics plugin"
  1517. // see jspdf.plugin.standard_font_metrics.js for format
  1518. // of the font.metadata.encoding Object.
  1519. // It should be something like
  1520. // .encoding = {'codePages':['WinANSI....'], 'WinANSI...':{code:code, ...}}
  1521. // .widths = {0:width, code:width, ..., 'fof':divisor}
  1522. // .kerning = {code:{previous_char_code:shift, ..., 'fof':-divisor},...}
  1523. if ((flags.autoencode || outputEncoding) && fonts[activeFontKey].metadata && fonts[activeFontKey].metadata[sourceEncoding] && fonts[activeFontKey].metadata[sourceEncoding].encoding) {
  1524. encodingBlock = fonts[activeFontKey].metadata[sourceEncoding].encoding; // each font has default encoding. Some have it clearly defined.
  1525. if (!outputEncoding && fonts[activeFontKey].encoding) {
  1526. outputEncoding = fonts[activeFontKey].encoding;
  1527. } // Hmmm, the above did not work? Let's try again, in different place.
  1528. if (!outputEncoding && encodingBlock.codePages) {
  1529. outputEncoding = encodingBlock.codePages[0]; // let's say, first one is the default
  1530. }
  1531. if (typeof outputEncoding === "string") {
  1532. outputEncoding = encodingBlock[outputEncoding];
  1533. } // we want output encoding to be a JS Object, where
  1534. // key = sourceEncoding's character code and
  1535. // value = outputEncoding's character code.
  1536. if (outputEncoding) {
  1537. isUnicode = false;
  1538. newtext = [];
  1539. for (i = 0, l = text.length; i < l; i++) {
  1540. ch = outputEncoding[text.charCodeAt(i)];
  1541. if (ch) {
  1542. newtext.push(String.fromCharCode(ch));
  1543. } else {
  1544. newtext.push(text[i]);
  1545. } // since we are looping over chars anyway, might as well
  1546. // check for residual unicodeness
  1547. if (newtext[i].charCodeAt(0) >> 8) {
  1548. /* more than 255 */
  1549. isUnicode = true;
  1550. }
  1551. }
  1552. text = newtext.join("");
  1553. }
  1554. }
  1555. i = text.length; // isUnicode may be set to false above. Hence the triple-equal to undefined
  1556. while (isUnicode === undefined && i !== 0) {
  1557. if (text.charCodeAt(i - 1) >> 8) {
  1558. /* more than 255 */
  1559. isUnicode = true;
  1560. }
  1561. i--;
  1562. }
  1563. if (!isUnicode) {
  1564. return text;
  1565. }
  1566. newtext = flags.noBOM ? [] : [254, 255];
  1567. for (i = 0, l = text.length; i < l; i++) {
  1568. ch = text.charCodeAt(i);
  1569. bch = ch >> 8; // divide by 256
  1570. if (bch >> 8) {
  1571. /* something left after dividing by 256 second time */
  1572. throw new Error("Character at position " + i + " of string '" + text + "' exceeds 16bits. Cannot be encoded into UCS-2 BE");
  1573. }
  1574. newtext.push(bch);
  1575. newtext.push(ch - (bch << 8));
  1576. }
  1577. return String.fromCharCode.apply(undefined, newtext);
  1578. },
  1579. pdfEscape = function pdfEscape(text, flags) {
  1580. /**
  1581. * Replace '/', '(', and ')' with pdf-safe versions
  1582. *
  1583. * Doing to8bitStream does NOT make this PDF display unicode text. For that
  1584. * we also need to reference a unicode font and embed it - royal pain in the rear.
  1585. *
  1586. * There is still a benefit to to8bitStream - PDF simply cannot handle 16bit chars,
  1587. * which JavaScript Strings are happy to provide. So, while we still cannot display
  1588. * 2-byte characters property, at least CONDITIONALLY converting (entire string containing)
  1589. * 16bit chars to (USC-2-BE) 2-bytes per char + BOM streams we ensure that entire PDF
  1590. * is still parseable.
  1591. * This will allow immediate support for unicode in document properties strings.
  1592. */
  1593. return to8bitStream(text, flags).replace(/\\/g, "\\\\").replace(/\(/g, "\\(").replace(/\)/g, "\\)");
  1594. },
  1595. putInfo = function putInfo() {
  1596. out("/Producer (jsPDF " + jsPDF.version + ")");
  1597. for (var key in documentProperties) {
  1598. if (documentProperties.hasOwnProperty(key) && documentProperties[key]) {
  1599. out("/" + key.substr(0, 1).toUpperCase() + key.substr(1) + " (" + pdfEscape(documentProperties[key]) + ")");
  1600. }
  1601. }
  1602. out("/CreationDate (" + creationDate + ")");
  1603. },
  1604. putCatalog = function putCatalog() {
  1605. out("/Type /Catalog");
  1606. out("/Pages 1 0 R"); // PDF13ref Section 7.2.1
  1607. if (!zoomMode) zoomMode = "fullwidth";
  1608. switch (zoomMode) {
  1609. case "fullwidth":
  1610. out("/OpenAction [3 0 R /FitH null]");
  1611. break;
  1612. case "fullheight":
  1613. out("/OpenAction [3 0 R /FitV null]");
  1614. break;
  1615. case "fullpage":
  1616. out("/OpenAction [3 0 R /Fit]");
  1617. break;
  1618. case "original":
  1619. out("/OpenAction [3 0 R /XYZ null null 1]");
  1620. break;
  1621. default:
  1622. var pcn = "" + zoomMode;
  1623. if (pcn.substr(pcn.length - 1) === "%") zoomMode = parseInt(zoomMode) / 100;
  1624. if (typeof zoomMode === "number") {
  1625. out("/OpenAction [3 0 R /XYZ null null " + f2(zoomMode) + "]");
  1626. }
  1627. }
  1628. if (!layoutMode) layoutMode = "continuous";
  1629. switch (layoutMode) {
  1630. case "continuous":
  1631. out("/PageLayout /OneColumn");
  1632. break;
  1633. case "single":
  1634. out("/PageLayout /SinglePage");
  1635. break;
  1636. case "two":
  1637. case "twoleft":
  1638. out("/PageLayout /TwoColumnLeft");
  1639. break;
  1640. case "tworight":
  1641. out("/PageLayout /TwoColumnRight");
  1642. break;
  1643. }
  1644. if (pageMode) {
  1645. /**
  1646. * A name object specifying how the document should be displayed when opened:
  1647. * UseNone : Neither document outline nor thumbnail images visible -- DEFAULT
  1648. * UseOutlines : Document outline visible
  1649. * UseThumbs : Thumbnail images visible
  1650. * FullScreen : Full-screen mode, with no menu bar, window controls, or any other window visible
  1651. */
  1652. out("/PageMode /" + pageMode);
  1653. }
  1654. events.publish("putCatalog");
  1655. },
  1656. putTrailer = function putTrailer() {
  1657. out("/Size " + (objectNumber + 1));
  1658. out("/Root " + objectNumber + " 0 R");
  1659. out("/Info " + (objectNumber - 1) + " 0 R");
  1660. out("/ID [ <" + fileId + "> <" + fileId + "> ]");
  1661. },
  1662. beginPage = function beginPage(width, height) {
  1663. outToPages = true;
  1664. pages[++page] = [];
  1665. pagedim[page] = {
  1666. width: Number(width) || pageWidth,
  1667. height: Number(height) || pageHeight
  1668. };
  1669. pagesContext[page] = {};
  1670. _setPage(page);
  1671. },
  1672. _addPage = function _addPage(width, height) {
  1673. // Dimensions are stored as user units and converted to points on output
  1674. var orientation = typeof height === "string" && height.toLowerCase();
  1675. if (typeof width === "string") {
  1676. var format = width.toLowerCase();
  1677. if (pageFormats.hasOwnProperty(format)) {
  1678. width = pageFormats[format][0] / k;
  1679. height = pageFormats[format][1] / k;
  1680. }
  1681. }
  1682. if (Array.isArray(width)) {
  1683. height = width[1];
  1684. width = width[0];
  1685. }
  1686. if (orientation) {
  1687. switch (orientation.substr(0, 1)) {
  1688. case "l":
  1689. if (height > width) orientation = "s";
  1690. break;
  1691. case "p":
  1692. if (width > height) orientation = "s";
  1693. break;
  1694. }
  1695. if (orientation === "s") {
  1696. tmp = width;
  1697. width = height;
  1698. height = tmp;
  1699. }
  1700. }
  1701. beginPage(width, height); // Set line width
  1702. out(hpf(lineWidth * k) + " w"); // Set draw color
  1703. out(drawColor); // resurrecting non-default line caps, joins
  1704. if (lineCapID !== 0) {
  1705. out(lineCapID + " J");
  1706. }
  1707. if (lineJoinID !== 0) {
  1708. out(lineJoinID + " j");
  1709. }
  1710. events.publish("addPage", {
  1711. pageNumber: page
  1712. });
  1713. },
  1714. _deletePage = function _deletePage(n) {
  1715. if (n > 0 && n <= page) {
  1716. pages.splice(n, 1);
  1717. pagedim.splice(n, 1);
  1718. page--;
  1719. if (currentPage > page) {
  1720. currentPage = page;
  1721. }
  1722. this.setPage(currentPage);
  1723. }
  1724. },
  1725. _setPage = function _setPage(n) {
  1726. if (n > 0 && n <= page) {
  1727. currentPage = n;
  1728. pageWidth = pagedim[n].width;
  1729. pageHeight = pagedim[n].height;
  1730. }
  1731. },
  1732. /**
  1733. * Returns a document-specific font key - a label assigned to a
  1734. * font name + font type combination at the time the font was added
  1735. * to the font inventory.
  1736. *
  1737. * Font key is used as label for the desired font for a block of text
  1738. * to be added to the PDF document stream.
  1739. * @private
  1740. * @function
  1741. * @param {String} fontName can be undefined on "falthy" to indicate "use current"
  1742. * @param {String} fontStyle can be undefined on "falthy" to indicate "use current"
  1743. * @returns {String} Font key.
  1744. */
  1745. _getFont = function getFont(fontName, fontStyle, options) {
  1746. var key = undefined,
  1747. fontNameLowerCase;
  1748. options = options || {};
  1749. fontName = fontName !== undefined ? fontName : fonts[activeFontKey].fontName;
  1750. fontStyle = fontStyle !== undefined ? fontStyle : fonts[activeFontKey].fontStyle;
  1751. fontNameLowerCase = fontName.toLowerCase();
  1752. if (fontmap[fontNameLowerCase] !== undefined && fontmap[fontNameLowerCase][fontStyle] !== undefined) {
  1753. key = fontmap[fontNameLowerCase][fontStyle];
  1754. } else if (fontmap[fontName] !== undefined && fontmap[fontName][fontStyle] !== undefined) {
  1755. key = fontmap[fontName][fontStyle];
  1756. } else {
  1757. if (options.disableWarning === false) {
  1758. console.warn("Unable to look up font label for font '" + fontName + "', '" + fontStyle + "'. Refer to getFontList() for available fonts.");
  1759. }
  1760. }
  1761. if (!key && !options.noFallback) {
  1762. key = fontmap["times"][fontStyle];
  1763. if (key == null) {
  1764. key = fontmap["times"]["normal"];
  1765. }
  1766. }
  1767. return key;
  1768. },
  1769. buildDocument = function buildDocument() {
  1770. outToPages = false; // switches out() to content
  1771. objectNumber = 2;
  1772. content_length = 0;
  1773. content = [];
  1774. offsets = [];
  1775. additionalObjects = []; // Added for AcroForm
  1776. events.publish("buildDocument"); // putHeader()
  1777. out("%PDF-" + pdfVersion);
  1778. out("%\xBA\xDF\xAC\xE0");
  1779. putPages(); // Must happen after putPages
  1780. // Modifies current object Id
  1781. putAdditionalObjects();
  1782. putResources(); // Info
  1783. newObject();
  1784. out("<<");
  1785. putInfo();
  1786. out(">>");
  1787. out("endobj"); // Catalog
  1788. newObject();
  1789. out("<<");
  1790. putCatalog();
  1791. out(">>");
  1792. out("endobj"); // Cross-ref
  1793. var o = content_length,
  1794. i,
  1795. p = "0000000000";
  1796. out("xref");
  1797. out("0 " + (objectNumber + 1));
  1798. out(p + " 65535 f ");
  1799. for (i = 1; i <= objectNumber; i++) {
  1800. var offset = offsets[i];
  1801. if (typeof offset === "function") {
  1802. out((p + offsets[i]()).slice(-10) + " 00000 n ");
  1803. } else {
  1804. out((p + offsets[i]).slice(-10) + " 00000 n ");
  1805. }
  1806. } // Trailer
  1807. out("trailer");
  1808. out("<<");
  1809. putTrailer();
  1810. out(">>");
  1811. out("startxref");
  1812. out("" + o);
  1813. out("%%EOF");
  1814. outToPages = true;
  1815. return content.join("\n");
  1816. },
  1817. getStyle = function getStyle(style) {
  1818. // see path-painting operators in PDF spec
  1819. // The default in MrRio's implementation is "S" (stroke), whereas the default in the yWorks implementation
  1820. // was "n" (none). Although this has nothing to do with transforms, we should use the API switch here.
  1821. var op = apiMode === ApiMode.COMPAT ? "S" : "n";
  1822. if (style === "D") {
  1823. op = "S"; // stroke
  1824. } else if (style === "F") {
  1825. op = "f"; // fill
  1826. } else if (style === "FD" || style === "DF") {
  1827. op = "B"; // both
  1828. } else if (style === "f" || style === "f*" || style === "B" || style === "B*") {
  1829. /*
  1830. Allow direct use of these PDF path-painting operators:
  1831. - f fill using nonzero winding number rule
  1832. - f* fill using even-odd rule
  1833. - B fill then stroke with fill using non-zero winding number rule
  1834. - B* fill then stroke with fill using even-odd rule
  1835. */
  1836. op = style;
  1837. }
  1838. return op;
  1839. },
  1840. // puts the style for the previously drawn path. If a patternKey is provided, the pattern is used to fill
  1841. // the path. Use patternMatrix to transform the pattern to rhe right location.
  1842. putStyle = function putStyle(style, patternKey, patternData) {
  1843. if (style === null || apiMode === ApiMode.ADVANCED && style === undefined) {
  1844. return;
  1845. }
  1846. style = getStyle(style); // stroking / filling / both the path
  1847. if (!patternKey) {
  1848. out(style);
  1849. return;
  1850. }
  1851. if (!patternData) {
  1852. patternData = {
  1853. matrix: unitMatrix
  1854. };
  1855. }
  1856. if (patternData instanceof Matrix) {
  1857. patternData = {
  1858. matrix: patternData
  1859. };
  1860. }
  1861. patternData.key = patternKey;
  1862. patternData || (patternData = unitMatrix);
  1863. fillWithPattern(patternData, style);
  1864. },
  1865. fillWithPattern = function fillWithPattern(patternData, style) {
  1866. var patternId = patternMap[patternData.key];
  1867. var pattern = patterns[patternId];
  1868. if (pattern instanceof API.ShadingPattern) {
  1869. out("q");
  1870. out(clipRuleFromStyle(style));
  1871. if (pattern.gState) {
  1872. API.setGState(pattern.gState);
  1873. }
  1874. out(patternData.matrix.toString() + " cm");
  1875. out("/" + patternId + " sh");
  1876. out("Q");
  1877. } else if (pattern instanceof API.TilingPattern) {
  1878. // pdf draws patterns starting at the bottom left corner and they are not affected by the global transformation,
  1879. // so we must flip them
  1880. var matrix = new Matrix(1, 0, 0, -1, 0, pageHeight);
  1881. if (patternData.matrix) {
  1882. matrix = matrixMult(patternData.matrix || unitMatrix, matrix); // we cannot apply a matrix to the pattern on use so we must abuse the pattern matrix and create new instances
  1883. // for each use
  1884. patternId = pattern.createClone(patternData.key, patternData.boundingBox, patternData.xStep, patternData.yStep, matrix).id;
  1885. }
  1886. out("q");
  1887. out("/Pattern cs");
  1888. out("/" + patternId + " scn");
  1889. if (pattern.gState) {
  1890. API.setGState(pattern.gState);
  1891. }
  1892. out(style);
  1893. out("Q");
  1894. }
  1895. },
  1896. clipRuleFromStyle = function clipRuleFromStyle(style) {
  1897. switch (style) {
  1898. case "f":
  1899. case "F":
  1900. return "W n";
  1901. case "f*":
  1902. return "W* n";
  1903. case "B":
  1904. return "W S";
  1905. case "B*":
  1906. return "W* S";
  1907. // these two are for compatibility reasons (in the past, calling any primitive method with a shading pattern
  1908. // and "n"/"S" as style would still fill/fill and stroke the path)
  1909. case "S":
  1910. return "W S";
  1911. case "n":
  1912. return "W n";
  1913. }
  1914. },
  1915. getArrayBuffer = function getArrayBuffer() {
  1916. var data = buildDocument(),
  1917. len = data.length,
  1918. ab = new ArrayBuffer(len),
  1919. u8 = new Uint8Array(ab);
  1920. while (len--) {
  1921. u8[len] = data.charCodeAt(len);
  1922. }
  1923. return ab;
  1924. },
  1925. getBlob = function getBlob() {
  1926. return new Blob([getArrayBuffer()], {
  1927. type: "application/pdf"
  1928. });
  1929. },
  1930. _output = SAFE(function (type, options) {
  1931. options = options || {};
  1932. options.filename = options.filename || "generated.pdf";
  1933. var datauri = ("" + type).substr(0, 6) === "dataur" ? "data:application/pdf;filename=" + options.filename + ";base64," + btoa(buildDocument()) : 0;
  1934. switch (type) {
  1935. case undefined:
  1936. return buildDocument();
  1937. case "save":
  1938. if ((typeof navigator === "undefined" ? "undefined" : _typeof(navigator)) === "object" && navigator.getUserMedia) {
  1939. if (global.URL === undefined || global.URL.createObjectURL === undefined) {
  1940. return API.output("dataurlnewwindow");
  1941. }
  1942. }
  1943. saveAs(getBlob(), options);
  1944. if (typeof saveAs.unload === "function") {
  1945. if (global.setTimeout) {
  1946. setTimeout(saveAs.unload, 911);
  1947. }
  1948. }
  1949. break;
  1950. case "arraybuffer":
  1951. return getArrayBuffer();
  1952. case "blob":
  1953. return getBlob();
  1954. case "bloburi":
  1955. case "bloburl":
  1956. // User is responsible of calling revokeObjectURL
  1957. return global.URL && global.URL.createObjectURL(getBlob()) || void 0;
  1958. case "datauristring":
  1959. case "dataurlstring":
  1960. return datauri;
  1961. case "dataurlnewwindow":
  1962. var htmlForNewWindow = "<html>" + "<style>html, body { padding: 0; margin: 0; } iframe { width: 100%; height: 100%; border: 0;} </style>" + "<body>" + '<iframe src="' + this.output("datauristring") + '"></iframe>' + "</body></html>";
  1963. var nW = global.open();
  1964. if (nW !== null) {
  1965. nW.document.write(htmlForNewWindow);
  1966. }
  1967. if (nW || typeof safari === "undefined") return nW;
  1968. /* pass through */
  1969. case "datauri":
  1970. case "dataurl":
  1971. return global.document.location.href = datauri;
  1972. default:
  1973. throw new Error('Output type "' + type + '" is not supported.');
  1974. } // @TODO: Add different output options
  1975. }),
  1976. /**
  1977. * Used to see if a supplied hotfix was requested when the pdf instance was created.
  1978. * @param {string} hotfixName - The name of the hotfix to check.
  1979. * @returns {boolean}
  1980. */
  1981. hasHotfix = function hasHotfix(hotfixName) {
  1982. return Array.isArray(hotfixes) === true && hotfixes.indexOf(hotfixName) > -1;
  1983. };
  1984. switch (unit) {
  1985. case "pt":
  1986. k = 1;
  1987. break;
  1988. case "mm":
  1989. k = 72 / 25.4000508;
  1990. break;
  1991. case "cm":
  1992. k = 72 / 2.54000508;
  1993. break;
  1994. case "in":
  1995. k = 72;
  1996. break;
  1997. case "px":
  1998. if (hasHotfix("px_scaling") == true) {
  1999. k = 72 / 96;
  2000. } else {
  2001. k = 96 / 72;
  2002. }
  2003. break;
  2004. case "pc":
  2005. k = 12;
  2006. break;
  2007. case "em":
  2008. k = 12;
  2009. break;
  2010. case "ex":
  2011. k = 6;
  2012. break;
  2013. default:
  2014. throw "Invalid unit: " + unit;
  2015. }
  2016. setCreationDate();
  2017. setFileId(); //---------------------------------------
  2018. // Public API
  2019. /**
  2020. * Object exposing internal API to plugins
  2021. * @public
  2022. * @ignore
  2023. */
  2024. API.internal = {
  2025. pdfEscape: pdfEscape,
  2026. getStyle: getStyle,
  2027. /**
  2028. * Returns {FontObject} describing a particular font.
  2029. * @public
  2030. * @function
  2031. * @param {String} fontName (Optional) Font's family name
  2032. * @param {String} fontStyle (Optional) Font's style variation name (Example:"Italic")
  2033. * @returns {FontObject}
  2034. */
  2035. getFont: function getFont() {
  2036. return fonts[_getFont.apply(API, arguments)];
  2037. },
  2038. getFontSize: function getFontSize() {
  2039. return activeFontSize;
  2040. },
  2041. getCharSpace: function getCharSpace() {
  2042. return activeCharSpace;
  2043. },
  2044. getTextColor: function getTextColor() {
  2045. var colorEncoded = textColor.split(" ");
  2046. if (colorEncoded.length === 2 && colorEncoded[1] === "g") {
  2047. // convert grayscale value to rgb so that it can be converted to hex for consistency
  2048. var floatVal = parseFloat(colorEncoded[0]);
  2049. colorEncoded = [floatVal, floatVal, floatVal, "r"];
  2050. }
  2051. var colorAsHex = "#";
  2052. for (var i = 0; i < 3; i++) {
  2053. colorAsHex += ("0" + Math.floor(parseFloat(colorEncoded[i]) * 255).toString(16)).slice(-2);
  2054. }
  2055. return colorAsHex;
  2056. },
  2057. getLineHeight: function getLineHeight() {
  2058. return activeFontSize * lineHeightProportion;
  2059. },
  2060. write: function write(string1
  2061. /*, string2, string3, etc */
  2062. ) {
  2063. out(arguments.length === 1 ? string1 : Array.prototype.join.call(arguments, " "));
  2064. },
  2065. getCoordinateString: function getCoordinateString(value) {
  2066. return hpf(scaleByK(value));
  2067. },
  2068. getVerticalCoordinateString: function getVerticalCoordinateString(value) {
  2069. return hpf(transformScaleY(value));
  2070. },
  2071. collections: {},
  2072. newObject: newObject,
  2073. newAdditionalObject: newAdditionalObject,
  2074. newObjectDeferred: newObjectDeferred,
  2075. newObjectDeferredBegin: newObjectDeferredBegin,
  2076. putStream: putStream,
  2077. events: events,
  2078. // ratio that you use in multiplication of a given "size" number to arrive to 'point'
  2079. // units of measurement.
  2080. // scaleFactor is set at initialization of the document and calculated against the stated
  2081. // default measurement units for the document.
  2082. // If default is "mm", k is the number that will turn number in 'mm' into 'points' number.
  2083. // through multiplication.
  2084. scaleFactor: k,
  2085. pageSize: {
  2086. getWidth: function getWidth() {
  2087. return pageWidth;
  2088. },
  2089. getHeight: function getHeight() {
  2090. return pageHeight;
  2091. }
  2092. },
  2093. output: function output(type, options) {
  2094. return _output(type, options);
  2095. },
  2096. getNumberOfPages: function getNumberOfPages() {
  2097. return pages.length - 1;
  2098. },
  2099. pages: pages,
  2100. out: out,
  2101. f2: f2,
  2102. getPageInfo: function getPageInfo(pageNumberOneBased) {
  2103. var objId = (pageNumberOneBased - 1) * 2 + 3;
  2104. return {
  2105. objId: objId,
  2106. pageNumber: pageNumberOneBased,
  2107. pageContext: pagesContext[pageNumberOneBased]
  2108. };
  2109. },
  2110. getCurrentPageInfo: function getCurrentPageInfo() {
  2111. var objId = (currentPage - 1) * 2 + 3;
  2112. return {
  2113. objId: objId,
  2114. pageNumber: currentPage,
  2115. pageContext: pagesContext[currentPage]
  2116. };
  2117. },
  2118. getPDFVersion: function getPDFVersion() {
  2119. return pdfVersion;
  2120. },
  2121. hasHotfix: hasHotfix //Expose the hasHotfix check so plugins can also check them.
  2122. };
  2123. function advancedAPI() {
  2124. // prepend global change of basis matrix
  2125. // (Now, instead of converting every coordinate to the pdf coordinate system, we apply a matrix
  2126. // that does this job for us (however, texts, images and similar objects must be drawn bottom up))
  2127. this.saveGraphicsState();
  2128. out(new Matrix(k, 0, 0, -k, 0, pageHeight * k).toString() + " cm");
  2129. this.setFontSize(this.getFontSize() / k);
  2130. apiMode = ApiMode.ADVANCED;
  2131. }
  2132. function compatAPI() {
  2133. this.restoreGraphicsState();
  2134. apiMode = ApiMode.COMPAT;
  2135. }
  2136. /**
  2137. * @callback ApiSwitchBody
  2138. * @param {jsPDF} pdf
  2139. */
  2140. /**
  2141. * For compatibility reasons jsPDF offers two API modes which differ in the way they convert between the the usual
  2142. * screen coordinates and the PDF coordinate system.
  2143. * - "compat": Offers full compatibility across all plugins but does not allow arbitrary transforms
  2144. * - "advanced": Allows arbitrary transforms and more advanced features like pattern fills. Some plugins might
  2145. * not support this mode, though.
  2146. * Initial mode is "compat".
  2147. *
  2148. * You can either provide a callback to the body argument, which means that jsPDF will automatically switch back to
  2149. * the original API mode afterwards; or you can omit the callback and switch back manually using {@link compatAPI}.
  2150. *
  2151. * Note, that the calls to {@link saveGraphicsState} and {@link restoreGraphicsState} need to be balanced within the
  2152. * callback or between calls of this method and its counterpart {@link compatAPI}. Calls to {@link beginFormObject}
  2153. * or {@link beginTilingPattern} need to be closed by their counterparts before switching back to "compat" API mode.
  2154. *
  2155. * @param {ApiSwitchBody=} body When provided, this callback will be called after the API mode has been switched.
  2156. * The API mode will be switched back automatically afterwards.
  2157. * @returns {jsPDF}
  2158. * @methodOf jsPDF#
  2159. * @name advancedAPI
  2160. */
  2161. API.advancedAPI = function (body) {
  2162. var doSwitch = apiMode === ApiMode.COMPAT;
  2163. if (doSwitch) {
  2164. advancedAPI.call(this);
  2165. }
  2166. if (typeof body !== "function") {
  2167. return this;
  2168. }
  2169. body(this);
  2170. if (doSwitch) {
  2171. compatAPI.call(this);
  2172. }
  2173. return this;
  2174. };
  2175. /**
  2176. * Switches to "compat" API mode. See {@link advancedAPI} for more details.
  2177. *
  2178. * @param {ApiSwitchBody=} body When provided, this callback will be called after the API mode has been switched.
  2179. * The API mode will be switched back automatically afterwards.
  2180. * @return {jsPDF}
  2181. * @methodOf jsPDF#
  2182. * @name compatApi
  2183. */
  2184. API.compatAPI = function (body) {
  2185. var doSwitch = apiMode === ApiMode.ADVANCED;
  2186. if (doSwitch) {
  2187. compatAPI.call(this);
  2188. }
  2189. if (typeof body !== "function") {
  2190. return this;
  2191. }
  2192. body(this);
  2193. if (doSwitch) {
  2194. advancedAPI.call(this);
  2195. }
  2196. return this;
  2197. };
  2198. /**
  2199. * @return {boolean} True iff the current API mode is "advanced". See {@link advancedAPI}.
  2200. * @methodOf jsPDF#
  2201. * @name isAdvancedAPI
  2202. */
  2203. API.isAdvancedAPI = function () {
  2204. return apiMode === ApiMode.ADVANCED;
  2205. };
  2206. /**
  2207. * Inserts a debug comment into the pdf.
  2208. * @param {String} text
  2209. * @returns {jsPDF}
  2210. * @methodOf jsPDF#
  2211. * @name comment
  2212. */
  2213. API.comment = function (text) {
  2214. out("#" + text);
  2215. return this;
  2216. };
  2217. /**
  2218. * An object representing a pdf graphics state.
  2219. * @param parameters A parameter object that contains all properties this graphics state wants to set.
  2220. * Supported are: opacity, stroke-opacity
  2221. * @constructor
  2222. */
  2223. API.GState = function (parameters) {
  2224. var supported = "opacity,stroke-opacity".split(",");
  2225. for (var p in parameters) {
  2226. if (parameters.hasOwnProperty(p) && supported.indexOf(p) >= 0) {
  2227. this[p] = parameters[p];
  2228. }
  2229. }
  2230. this.id = ""; // set by addGState()
  2231. this.objectNumber = -1; // will be set by putGState()
  2232. };
  2233. API.GState.prototype.equals = function equals(other) {
  2234. var ignore = "id,objectNumber,equals";
  2235. if (!other || _typeof(other) !== _typeof(this)) return false;
  2236. var count = 0;
  2237. for (var p in this) {
  2238. if (ignore.indexOf(p) >= 0) continue;
  2239. if (this.hasOwnProperty(p) && !other.hasOwnProperty(p)) return false;
  2240. if (this[p] !== other[p]) return false;
  2241. count++;
  2242. }
  2243. for (var p in other) {
  2244. if (other.hasOwnProperty(p) && ignore.indexOf(p) < 0) count--;
  2245. }
  2246. return count === 0;
  2247. };
  2248. /**
  2249. * Adds a new {@link GState} for later use. See {@link setGState}.
  2250. * @param {String} key
  2251. * @param {GState} gState
  2252. * @function
  2253. * @instance
  2254. * @returns {jsPDF}
  2255. *
  2256. * @methodOf jsPDF#
  2257. * @name addPage
  2258. */
  2259. API.addGState = function (key, gState) {
  2260. addGState(key, gState);
  2261. return this;
  2262. };
  2263. /**
  2264. * Adds (and transfers the focus to) new page to the PDF document.
  2265. * @param {String/Array} format The format of the new page. Can be <ul><li>a0 - a10</li><li>b0 - b10</li><li>c0 - c10</li><li>c0 - c10</li><li>dl</li><li>letter</li><li>government-letter</li><li>legal</li><li>junior-legal</li><li>ledger</li><li>tabloid</li><li>credit-card</li></ul><br />
  2266. * Default is "a4". If you want to use your own format just pass instead of one of the above predefined formats the size as an number-array , e.g. [595.28, 841.89]
  2267. * @param {string} orientation Orientation of the new page. Possible values are "portrait" or "landscape" (or shortcuts "p" (Default), "l")
  2268. * @function
  2269. * @instance
  2270. * @returns {jsPDF}
  2271. *
  2272. * @memberOf jsPDF
  2273. * @name addPage
  2274. */
  2275. API.addPage = function (format, orientation) {
  2276. _addPage.apply(this, arguments);
  2277. return this;
  2278. };
  2279. /**
  2280. * Adds (and transfers the focus to) new page to the PDF document.
  2281. * @function
  2282. * @instance
  2283. * @returns {jsPDF}
  2284. *
  2285. * @memberOf jsPDF
  2286. * @name setPage
  2287. * @param {number} page Switch the active page to the page number specified
  2288. * @example
  2289. * doc = jsPDF()
  2290. * doc.addPage()
  2291. * doc.addPage()
  2292. * doc.text('I am on page 3', 10, 10)
  2293. * doc.setPage(1)
  2294. * doc.text('I am on page 1', 10, 10)
  2295. */
  2296. API.setPage = function (page) {
  2297. _setPage.apply(this, arguments);
  2298. return this;
  2299. };
  2300. /**
  2301. * @name insertPage
  2302. * @memberOf jsPDF
  2303. *
  2304. * @function
  2305. * @instance
  2306. * @param {Object} beforePage
  2307. * @returns {jsPDF}
  2308. */
  2309. API.insertPage = function (beforePage) {
  2310. this.addPage();
  2311. this.movePage(currentPage, beforePage);
  2312. return this;
  2313. };
  2314. /**
  2315. * @name movePage
  2316. * @memberOf jsPDF
  2317. * @function
  2318. * @instance
  2319. * @param {Object} targetPage
  2320. * @param {Object} beforePage
  2321. * @returns {jsPDF}
  2322. */
  2323. API.movePage = function (targetPage, beforePage) {
  2324. var tmpPagesContext, tmpPagedim, tmpPages, i;
  2325. if (targetPage > beforePage) {
  2326. tmpPages = pages[targetPage];
  2327. tmpPagedim = pagedim[targetPage];
  2328. tmpPagesContext = pagesContext[targetPage];
  2329. for (i = targetPage; i > beforePage; i--) {
  2330. pages[i] = pages[i - 1];
  2331. pagedim[i] = pagedim[i - 1];
  2332. pagesContext[i] = pagesContext[i - 1];
  2333. }
  2334. pages[beforePage] = tmpPages;
  2335. pagedim[beforePage] = tmpPagedim;
  2336. pagesContext[beforePage] = tmpPagesContext;
  2337. this.setPage(beforePage);
  2338. } else if (targetPage < beforePage) {
  2339. tmpPages = pages[targetPage];
  2340. tmpPagedim = pagedim[targetPage];
  2341. tmpPagesContext = pagesContext[targetPage];
  2342. for (i = targetPage; i < beforePage; i++) {
  2343. pages[i] = pages[i + 1];
  2344. pagedim[i] = pagedim[i + 1];
  2345. pagesContext[i] = pagesContext[i + 1];
  2346. }
  2347. pages[beforePage] = tmpPages;
  2348. pagedim[beforePage] = tmpPagedim;
  2349. pagesContext[beforePage] = tmpPagesContext;
  2350. this.setPage(beforePage);
  2351. }
  2352. return this;
  2353. };
  2354. /**
  2355. * @name deletePage
  2356. * @memberOf jsPDF
  2357. * @function
  2358. * @instance
  2359. * @returns {jsPDF}
  2360. */
  2361. API.deletePage = function () {
  2362. _deletePage.apply(this, arguments);
  2363. return this;
  2364. };
  2365. /**
  2366. * @name setCreationDate
  2367. * @memberOf jsPDF
  2368. * @function
  2369. * @instance
  2370. * @param {Object} date
  2371. * @returns {jsPDF}
  2372. */
  2373. API.setCreationDate = function (date) {
  2374. setCreationDate(date);
  2375. return this;
  2376. };
  2377. /**
  2378. * @name getCreationDate
  2379. * @memberOf jsPDF
  2380. * @function
  2381. * @instance
  2382. * @param {Object} type
  2383. * @returns {Object}
  2384. */
  2385. API.getCreationDate = function (type) {
  2386. return getCreationDate(type);
  2387. };
  2388. /**
  2389. * @name setFileId
  2390. * @memberOf jsPDF
  2391. * @function
  2392. * @instance
  2393. * @param {string} value GUID
  2394. * @returns {jsPDF}
  2395. */
  2396. API.setFileId = function (value) {
  2397. setFileId(value);
  2398. return this;
  2399. };
  2400. /**
  2401. * @name getFileId
  2402. * @memberOf jsPDF
  2403. * @function
  2404. * @instance
  2405. *
  2406. * @returns {string} GUID
  2407. */
  2408. API.getFileId = function () {
  2409. return getFileId();
  2410. };
  2411. /**
  2412. * Set the display mode options of the page like zoom and layout.
  2413. *
  2414. * @param {integer|String} zoom You can pass an integer or percentage as
  2415. * a string. 2 will scale the document up 2x, '200%' will scale up by the
  2416. * same amount. You can also set it to 'fullwidth', 'fullheight',
  2417. * 'fullpage', or 'original'.
  2418. *
  2419. * Only certain PDF readers support this, such as Adobe Acrobat
  2420. *
  2421. * @param {string} layout Layout mode can be: 'continuous' - this is the
  2422. * default continuous scroll. 'single' - the single page mode only shows one
  2423. * page at a time. 'twoleft' - two column left mode, first page starts on
  2424. * the left, and 'tworight' - pages are laid out in two columns, with the
  2425. * first page on the right. This would be used for books.
  2426. * @param {string} pmode 'UseOutlines' - it shows the
  2427. * outline of the document on the left. 'UseThumbs' - shows thumbnails along
  2428. * the left. 'FullScreen' - prompts the user to enter fullscreen mode.
  2429. *
  2430. * @returns {jsPDF}
  2431. * @function
  2432. * @instance
  2433. * @name setDisplayMode
  2434. * @methodOf jsPDF#
  2435. */
  2436. API.setDisplayMode = function (zoom, layout, pmode) {
  2437. zoomMode = zoom;
  2438. layoutMode = layout;
  2439. pageMode = pmode;
  2440. var validPageModes = [undefined, null, "UseNone", "UseOutlines", "UseThumbs", "FullScreen"];
  2441. if (validPageModes.indexOf(pmode) == -1) {
  2442. throw new Error('Page mode must be one of UseNone, UseOutlines, UseThumbs, or FullScreen. "' + pmode + '" is not recognized.');
  2443. }
  2444. return this;
  2445. };
  2446. /**
  2447. * Saves the current graphics state ("pushes it on the stack"). It can be restored by {@link restoreGraphicsState}
  2448. * later. Here, the general pdf graphics state is meant, also including the current transformation matrix,
  2449. * fill and stroke colors etc.
  2450. * @function
  2451. * @returns {jsPDF}
  2452. * @methodOf jsPDF#
  2453. * @name saveGraphicsState
  2454. */
  2455. API.saveGraphicsState = function () {
  2456. out("q"); // as we cannot set font key and size independently we must keep track of both
  2457. fontStateStack.push({
  2458. key: activeFontKey,
  2459. size: activeFontSize,
  2460. color: textColor
  2461. });
  2462. return this;
  2463. };
  2464. /**
  2465. * Restores a previously saved graphics state saved by {@link saveGraphicsState} ("pops the stack").
  2466. * @function
  2467. * @returns {jsPDF}
  2468. * @methodOf jsPDF#
  2469. * @name restoreGraphicsState
  2470. */
  2471. API.restoreGraphicsState = function () {
  2472. out("Q"); // restore previous font state
  2473. var fontState = fontStateStack.pop();
  2474. activeFontKey = fontState.key;
  2475. activeFontSize = fontState.size;
  2476. textColor = fontState.color;
  2477. activeGState = null;
  2478. return this;
  2479. };
  2480. /**
  2481. * Appends this matrix to the left of all previously applied matrices.
  2482. *
  2483. * Only available in "advanced" API mode.
  2484. *
  2485. * @param {Matrix} matrix
  2486. * @function
  2487. * @returns {jsPDF}
  2488. * @methodOf jsPDF#
  2489. * @name setCurrentTransformationMatrix
  2490. */
  2491. API.setCurrentTransformationMatrix = function (matrix) {
  2492. advancedApiModeTrap("setCurrentTransformationMatrix()");
  2493. out(matrix.toString() + " cm");
  2494. return this;
  2495. };
  2496. /**
  2497. * Starts a new pdf form object, which means that all conseequent draw calls target a new independent object
  2498. * until {@link endFormObject} is called. The created object can be referenced and drawn later using
  2499. * {@link doFormObject}. Nested form objects are possible.
  2500. * x, y, width, height set the bounding box that is used to clip the content.
  2501. *
  2502. * Only available in "advanced" API mode.
  2503. *
  2504. * @param {number} x
  2505. * @param {number} y
  2506. * @param {number} width
  2507. * @param {number} height
  2508. * @param {Matrix} matrix The matrix that will be applied to convert the form objects coordinate system to
  2509. * the parent's.
  2510. * @function
  2511. * @returns {jsPDF}
  2512. * @methodOf jsPDF#
  2513. * @name beginFormObject
  2514. */
  2515. API.beginFormObject = function (x, y, width, height, matrix) {
  2516. advancedApiModeTrap("beginFormObject()"); // The user can set the output target to a new form object. Nested form objects are possible.
  2517. // Currently, they use the resource dictionary of the surrounding stream. This should be changed, as
  2518. // the PDF-Spec states:
  2519. // "In PDF 1.2 and later versions, form XObjects may be independent of the content streams in which
  2520. // they appear, and this is strongly recommended although not requiredIn PDF 1.2 and later versions,
  2521. // form XObjects may be independent of the content streams in which they appear, and this is strongly
  2522. // recommended although not required"
  2523. beginNewRenderTarget(x, y, width, height, matrix);
  2524. return this;
  2525. };
  2526. /**
  2527. * Completes and saves the form object. Only available in "advanced" API mode.
  2528. * @param {String} key The key by which this form object can be referenced.
  2529. * @function
  2530. * @returns {jsPDF}
  2531. * @methodOf jsPDF#
  2532. * @name endFormObject
  2533. */
  2534. API.endFormObject = function (key) {
  2535. advancedApiModeTrap("endFormObject()");
  2536. endFormObject(key);
  2537. return this;
  2538. };
  2539. /**
  2540. * Draws the specified form object by referencing to the respective pdf XObject created with
  2541. * {@link API.beginFormObject} and {@link endFormObject}.
  2542. * The location is determined by matrix.
  2543. *
  2544. * Only available in "advanced" API mode.
  2545. *
  2546. * @param {String} key The key to the form object.
  2547. * @param {Matrix} matrix The matrix applied before drawing the form object.
  2548. * @function
  2549. * @returns {jsPDF}
  2550. * @methodOf jsPDF#
  2551. * @name doFormObject
  2552. */
  2553. API.doFormObject = function (key, matrix) {
  2554. advancedApiModeTrap("doFormObject()");
  2555. var xObject = renderTargets[renderTargetMap[key]];
  2556. out("q");
  2557. out(matrix.toString() + " cm");
  2558. out("/" + xObject.id + " Do");
  2559. out("Q");
  2560. return this;
  2561. };
  2562. /**
  2563. * Returns the form object specified by key.
  2564. * @param key {String}
  2565. * @returns {{x: number, y: number, width: number, height: number, matrix: Matrix}}
  2566. * @function
  2567. * @returns {jsPDF}
  2568. * @methodOf jsPDF#
  2569. * @name getFormObject
  2570. */
  2571. API.getFormObject = function (key) {
  2572. var xObject = renderTargets[renderTargetMap[key]];
  2573. return {
  2574. x: xObject.x,
  2575. y: xObject.y,
  2576. width: xObject.width,
  2577. height: xObject.height,
  2578. matrix: xObject.matrix
  2579. };
  2580. };
  2581. /**
  2582. * A matrix object for 2D homogenous transformations:
  2583. * | a b 0 |
  2584. * | c d 0 |
  2585. * | e f 1 |
  2586. * pdf multiplies matrices righthand: v' = v x m1 x m2 x ...
  2587. * @param {number} a
  2588. * @param {number} b
  2589. * @param {number} c
  2590. * @param {number} d
  2591. * @param {number} e
  2592. * @param {number} f
  2593. * @constructor
  2594. */
  2595. API.Matrix = Matrix;
  2596. /**
  2597. * Multiplies two matrices. (see {@link Matrix})
  2598. * @param {Matrix} m1
  2599. * @param {Matrix} m2
  2600. * @methodOf jsPDF#
  2601. * @name matrixMult
  2602. */
  2603. API.matrixMult = matrixMult;
  2604. /**
  2605. * The unit matrix (equivalent to new Matrix(1, 0, 0, 1, 0, 0)).
  2606. * @type {Matrix}
  2607. * @fieldOf jsPDF#
  2608. * @name unitMatrix
  2609. */
  2610. API.unitMatrix = unitMatrix;
  2611. var Pattern = function Pattern(gState, matrix) {
  2612. this.gState = gState;
  2613. this.matrix = matrix;
  2614. this.id = ""; // set by addPattern()
  2615. this.objectNumber = -1; // will be set by putPattern()
  2616. };
  2617. /**
  2618. * A pattern describing a shading pattern.
  2619. *
  2620. * Only available in "advanced" API mode.
  2621. *
  2622. * @param {String} type One of "axial" or "radial"
  2623. * @param {Array<Number>} coords Either [x1, y1, x2, y2] for "axial" type describing the two interpolation points
  2624. * or [x1, y1, r, x2, y2, r2] for "radial" describing inner and the outer circle.
  2625. * @param {Array<Object>} colors An array of objects with the fields "offset" and "color". "offset" describes
  2626. * the offset in parameter space [0, 1]. "color" is an array of length 3 describing RGB values in [0, 255].
  2627. * @param {GState=} gState An additional graphics state that gets applied to the pattern (optional).
  2628. * @param {Matrix=} matrix A matrix that describes the transformation between the pattern coordinate system
  2629. * and the use coordinate system (optional).
  2630. * @constructor
  2631. * @extends API.Pattern
  2632. */
  2633. API.ShadingPattern = function (type, coords, colors, gState, matrix) {
  2634. advancedApiModeTrap("ShadingPattern"); // see putPattern() for information how they are realized
  2635. this.type = type === "axial" ? 2 : 3;
  2636. this.coords = coords;
  2637. this.colors = colors;
  2638. Pattern.call(this, gState, matrix);
  2639. };
  2640. /**
  2641. * A PDF Tiling pattern.
  2642. *
  2643. * Only available in "advanced" API mode.
  2644. *
  2645. * @param {Array.<Number>} boundingBox The bounding box at which one pattern cell gets clipped.
  2646. * @param {Number} xStep Horizontal spacing between pattern cells.
  2647. * @param {Number} yStep Vertical spacing between pattern cells.
  2648. * @param {API.GState=} gState An additional graphics state that gets applied to the pattern (optional).
  2649. * @param {Matrix=} matrix A matrix that describes the transformation between the pattern coordinate system
  2650. * and the use coordinate system (optional).
  2651. * @constructor
  2652. * @extends API.Pattern
  2653. */
  2654. API.TilingPattern = function (boundingBox, xStep, yStep, gState, matrix) {
  2655. advancedApiModeTrap("TilingPattern");
  2656. this.boundingBox = boundingBox;
  2657. this.xStep = xStep;
  2658. this.yStep = yStep;
  2659. this.stream = ""; // set by endTilingPattern();
  2660. this.cloneIndex = 0;
  2661. Pattern.call(this, gState, matrix);
  2662. };
  2663. API.TilingPattern.prototype = {
  2664. createClone: function createClone(patternKey, boundingBox, xStep, yStep, matrix) {
  2665. var clone = new API.TilingPattern(boundingBox || this.boundingBox, xStep || this.xStep, yStep || this.yStep, this.gState, matrix || this.matrix);
  2666. clone.stream = this.stream;
  2667. var key = patternKey + "$$" + this.cloneIndex++ + "$$";
  2668. addPattern(key, clone);
  2669. return clone;
  2670. }
  2671. };
  2672. /**
  2673. * Adds a new {@link API.ShadingPattern} for later use. Only available in "advanced" API mode.
  2674. * @param {String} key
  2675. * @param {Pattern} pattern
  2676. * @function
  2677. * @returns {jsPDF}
  2678. * @methodOf jsPDF#
  2679. * @name addPattern
  2680. */
  2681. API.addShadingPattern = function (key, pattern) {
  2682. advancedApiModeTrap("addShadingPattern()");
  2683. addPattern(key, pattern);
  2684. return this;
  2685. };
  2686. /**
  2687. * Begins a new tiling pattern. All subsequent render calls are drawn to this pattern until {@link API.endTilingPattern}
  2688. * gets called. Only available in "advanced" API mode.
  2689. * @param {API.Pattern} pattern
  2690. * @methodOf jsPDF#
  2691. * @name beginTilingPattern
  2692. */
  2693. API.beginTilingPattern = function (pattern) {
  2694. advancedApiModeTrap("beginTilingPattern()");
  2695. beginNewRenderTarget(pattern.boundingBox[0], pattern.boundingBox[1], pattern.boundingBox[2] - pattern.boundingBox[0], pattern.boundingBox[3] - pattern.boundingBox[1], pattern.matrix);
  2696. };
  2697. /**
  2698. * Ends a tiling pattern and sets the render target to the one active before {@link API.beginTilingPattern} has been called.
  2699. *
  2700. * Only available in "advanced" API mode.
  2701. *
  2702. * @param {string} key A unique key that is used to reference this pattern at later use.
  2703. * @param {API.Pattern} pattern The pattern to end.
  2704. * @methodOf jsPDF#
  2705. * @name endTilingPattern
  2706. */
  2707. API.endTilingPattern = function (key, pattern) {
  2708. advancedApiModeTrap("endTilingPattern()"); // retrieve the stream
  2709. pattern.stream = pages[currentPage].join("\n");
  2710. addPattern(key, pattern);
  2711. events.publish("endTilingPattern", pattern); // restore state from stack
  2712. renderTargetStack.pop().restore();
  2713. };
  2714. /**
  2715. * Adds text to page. Supports adding multiline text when 'text' argument is an Array of Strings.
  2716. *
  2717. * @function
  2718. * @param {String|Array} text String or array of strings to be added to the page. Each line is shifted one line down
  2719. * per font, spacing settings declared before this call.
  2720. * @param {number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
  2721. * @param {number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
  2722. * @param {Object} options Collection of settings signalling how the text must be encoded. Defaults are sane. If you
  2723. * think you want to pass some flags, you likely can read the source.
  2724. * @param {number|Matrix} transform If transform is a number the text will be rotated by this value around the
  2725. * anchor set by x and y.
  2726. *
  2727. * If it is a Matrix, this matrix gets directly applied to the text, which allows shearing
  2728. * effects etc.; the x and y offsets are then applied AFTER the coordinate system has been established by this
  2729. * matrix. This means passing a rotation matrix that is equivalent to some rotation angle will in general yield a
  2730. * DIFFERENT result. A matrix is only allowed in "advanced" API mode.
  2731. *
  2732. * @param align {string}
  2733. * @returns {jsPDF}
  2734. * @methodOf jsPDF#
  2735. * @name text
  2736. */
  2737. API.text = function (text, x, y, options, transform) {
  2738. /**
  2739. * Inserts something like this into PDF
  2740. * BT
  2741. * /F1 16 Tf % Font name + size
  2742. * 16 TL % How many units down for next line in multiline text
  2743. * 0 g % color
  2744. * 28.35 813.54 Td % position
  2745. * (line one) Tj
  2746. * T* (line two) Tj
  2747. * T* (line three) Tj
  2748. * ET
  2749. */
  2750. if (transform !== undefined && transform instanceof Matrix) {
  2751. advancedApiModeTrap("The transform parameter of text() with a Matrix value");
  2752. }
  2753. var xtra = "";
  2754. var isHex = false;
  2755. var lineHeight = lineHeightProportion;
  2756. var scope = this;
  2757. function ESC(s) {
  2758. s = s.split("\t").join(Array(options.TabLen || 9).join(" "));
  2759. return pdfEscape(s, flags);
  2760. }
  2761. function transformTextToSpecialArray(text) {
  2762. //we don't want to destroy original text array, so cloning it
  2763. var sa = text.concat();
  2764. var da = [];
  2765. var len = sa.length;
  2766. var curDa; //we do array.join('text that must not be PDFescaped")
  2767. //thus, pdfEscape each component separately
  2768. while (len--) {
  2769. curDa = sa.shift();
  2770. if (typeof curDa === "string") {
  2771. da.push(curDa);
  2772. } else {
  2773. if (Object.prototype.toString.call(text) === "[object Array]" && curDa.length === 1) {
  2774. da.push(curDa[0]);
  2775. } else {
  2776. da.push([curDa[0], curDa[1], curDa[2]]);
  2777. }
  2778. }
  2779. }
  2780. return da;
  2781. }
  2782. function processTextByFunction(text, processingFunction) {
  2783. var result;
  2784. if (typeof text === "string") {
  2785. result = processingFunction(text)[0];
  2786. } else if (Object.prototype.toString.call(text) === "[object Array]") {
  2787. //we don't want to destroy original text array, so cloning it
  2788. var sa = text.concat();
  2789. var da = [];
  2790. var len = sa.length;
  2791. var curDa;
  2792. var tmpResult; //we do array.join('text that must not be PDFescaped")
  2793. //thus, pdfEscape each component separately
  2794. while (len--) {
  2795. curDa = sa.shift();
  2796. if (typeof curDa === "string") {
  2797. da.push(processingFunction(curDa)[0]);
  2798. } else if (Object.prototype.toString.call(curDa) === "[object Array]" && curDa[0] === "string") {
  2799. tmpResult = processingFunction(curDa[0], curDa[1], curDa[2]);
  2800. da.push([tmpResult[0], tmpResult[1], tmpResult[2]]);
  2801. }
  2802. }
  2803. result = da;
  2804. }
  2805. return result;
  2806. } //backwardsCompatibility
  2807. var tmp; // Pre-August-2012 the order of arguments was function(x, y, text, flags)
  2808. // in effort to make all calls have similar signature like
  2809. // function(data, coordinates... , miscellaneous)
  2810. // this method had its args flipped.
  2811. // code below allows backward compatibility with old arg order.
  2812. if (typeof text === "number") {
  2813. tmp = y;
  2814. y = x;
  2815. x = text;
  2816. text = tmp;
  2817. }
  2818. var flags = arguments[3];
  2819. var angle = arguments[4];
  2820. var align = arguments[5];
  2821. if (_typeof(flags) !== "object" || flags === null) {
  2822. if (typeof angle === "string") {
  2823. align = angle;
  2824. angle = null;
  2825. }
  2826. if (typeof flags === "string") {
  2827. align = flags;
  2828. flags = null;
  2829. }
  2830. if (typeof flags === "number") {
  2831. angle = flags;
  2832. flags = null;
  2833. }
  2834. options = {
  2835. flags: flags,
  2836. angle: angle,
  2837. align: align
  2838. };
  2839. } //Check if text is of type String
  2840. var textIsOfTypeString = false;
  2841. var tmpTextIsOfTypeString = true;
  2842. if (typeof text === "string") {
  2843. textIsOfTypeString = true;
  2844. } else if (Object.prototype.toString.call(text) === "[object Array]") {
  2845. //we don't want to destroy original text array, so cloning it
  2846. var sa = text.concat();
  2847. var da = [];
  2848. var len = sa.length;
  2849. var curDa; //we do array.join('text that must not be PDFescaped")
  2850. //thus, pdfEscape each component separately
  2851. while (len--) {
  2852. curDa = sa.shift();
  2853. if (typeof curDa !== "string" || Object.prototype.toString.call(curDa) === "[object Array]" && typeof curDa[0] !== "string") {
  2854. tmpTextIsOfTypeString = false;
  2855. }
  2856. }
  2857. textIsOfTypeString = tmpTextIsOfTypeString;
  2858. }
  2859. if (textIsOfTypeString === false) {
  2860. throw new Error('Type of text must be string or Array. "' + text + '" is not recognized.');
  2861. } //Escaping
  2862. var activeFontEncoding = fonts[activeFontKey].encoding;
  2863. if (activeFontEncoding === "WinAnsiEncoding" || activeFontEncoding === "StandardEncoding") {
  2864. text = processTextByFunction(text, function (text, posX, posY) {
  2865. return [ESC(text), posX, posY];
  2866. });
  2867. } //If there are any newlines in text, we assume
  2868. //the user wanted to print multiple lines, so break the
  2869. //text up into an array. If the text is already an array,
  2870. //we assume the user knows what they are doing.
  2871. //Convert text into an array anyway to simplify
  2872. //later code.
  2873. if (typeof text === "string") {
  2874. if (text.match(/[\r?\n]/)) {
  2875. text = text.split(/\r\n|\r|\n/g);
  2876. } else {
  2877. text = [text];
  2878. }
  2879. } //multiline
  2880. var maxWidth = options.maxWidth || 0;
  2881. if (maxWidth > 0) {
  2882. if (typeof text === "string") {
  2883. text = scope.splitTextToSize(text, maxWidth);
  2884. } else if (Object.prototype.toString.call(text) === "[object Array]") {
  2885. text = scope.splitTextToSize(text.join(" "), maxWidth);
  2886. }
  2887. } //creating Payload-Object to make text byRef
  2888. var payload = {
  2889. text: text,
  2890. x: x,
  2891. y: y,
  2892. options: options,
  2893. mutex: {
  2894. pdfEscape: pdfEscape,
  2895. activeFontKey: activeFontKey,
  2896. fonts: fonts,
  2897. activeFontSize: activeFontSize
  2898. }
  2899. };
  2900. events.publish("preProcessText", payload);
  2901. text = payload.text;
  2902. options = payload.options; //angle
  2903. var angle = options.angle;
  2904. var transformationMatrix = null;
  2905. if (angle && typeof angle === "number") {
  2906. angle *= Math.PI / 180;
  2907. if (apiMode === ApiMode.ADVANCED) {
  2908. angle = -angle;
  2909. }
  2910. var c = Math.cos(angle),
  2911. s = Math.sin(angle);
  2912. transformationMatrix = new Matrix(c, s, -s, c, 0, 0);
  2913. } else if (angle && angle instanceof Matrix) {
  2914. transformationMatrix = angle;
  2915. } //charSpace
  2916. var charSpace = options.charSpace;
  2917. if (charSpace !== undefined) {
  2918. xtra += charSpace + " Tc\n";
  2919. } //lang
  2920. var lang = options.lang;
  2921. var tmpRenderingMode = -1;
  2922. var parmRenderingMode = options.renderingMode || options.stroke;
  2923. var pageContext = scope.internal.getCurrentPageInfo().pageContext;
  2924. switch (parmRenderingMode) {
  2925. case 0:
  2926. case false:
  2927. case "fill":
  2928. tmpRenderingMode = 0;
  2929. break;
  2930. case 1:
  2931. case true:
  2932. case "stroke":
  2933. tmpRenderingMode = 1;
  2934. break;
  2935. case 2:
  2936. case "fillThenStroke":
  2937. tmpRenderingMode = 2;
  2938. break;
  2939. case 3:
  2940. case "invisible":
  2941. tmpRenderingMode = 3;
  2942. break;
  2943. case 4:
  2944. case "fillAndAddForClipping":
  2945. tmpRenderingMode = 4;
  2946. break;
  2947. case 5:
  2948. case "strokeAndAddPathForClipping":
  2949. tmpRenderingMode = 5;
  2950. break;
  2951. case 6:
  2952. case "fillThenStrokeAndAddToPathForClipping":
  2953. tmpRenderingMode = 6;
  2954. break;
  2955. case 7:
  2956. case "addToPathForClipping":
  2957. tmpRenderingMode = 7;
  2958. break;
  2959. }
  2960. var usedRenderingMode = pageContext.usedRenderingMode || -1; //if the coder wrote it explicitly to use a specific
  2961. //renderingMode, then use it
  2962. if (tmpRenderingMode !== -1) {
  2963. xtra += tmpRenderingMode + " Tr\n"; //otherwise check if we used the rendering Mode already
  2964. //if so then set the rendering Mode...
  2965. } else if (usedRenderingMode !== -1) {
  2966. xtra += "0 Tr\n";
  2967. }
  2968. if (tmpRenderingMode !== -1) {
  2969. pageContext.usedRenderingMode = tmpRenderingMode;
  2970. } //align
  2971. var align = options.align || "left";
  2972. var leading = activeFontSize * lineHeight;
  2973. var pageWidth = scope.internal.pageSize.getWidth();
  2974. var k = scope.internal.scaleFactor;
  2975. var activeFont = fonts[activeFontKey];
  2976. var charSpace = options.charSpace || activeCharSpace;
  2977. var maxWidth = options.maxWidth || 0;
  2978. var lineWidths;
  2979. var flags = {};
  2980. var wordSpacingPerLine = [];
  2981. if (Object.prototype.toString.call(text) === "[object Array]") {
  2982. var da = transformTextToSpecialArray(text);
  2983. var newY;
  2984. var maxLineLength;
  2985. var lineWidths;
  2986. if (align !== "left") {
  2987. lineWidths = da.map(function (v) {
  2988. return scope.getStringUnitWidth(v, {
  2989. font: activeFont,
  2990. charSpace: charSpace,
  2991. fontSize: activeFontSize
  2992. }) * activeFontSize / k;
  2993. });
  2994. }
  2995. var maxLineLength = Math.max.apply(Math, lineWidths); //The first line uses the "main" Td setting,
  2996. //and the subsequent lines are offset by the
  2997. //previous line's x coordinate.
  2998. var prevWidth = 0;
  2999. var delta;
  3000. var newX;
  3001. var xOffset = 0;
  3002. if (align === "right") {
  3003. xOffset = -lineWidths[0];
  3004. text = [];
  3005. for (var i = 0, len = da.length; i < len; i++) {
  3006. delta = maxLineLength - lineWidths[i];
  3007. if (i === 0) {
  3008. newX = 0;
  3009. newY = 0;
  3010. } else {
  3011. newX = prevWidth - lineWidths[i];
  3012. newY = leading;
  3013. }
  3014. text.push([da[i], newX, newY]);
  3015. prevWidth = lineWidths[i];
  3016. }
  3017. } else if (align === "center") {
  3018. xOffset = -lineWidths[0] / 2;
  3019. text = [];
  3020. for (var i = 0, len = da.length; i < len; i++) {
  3021. delta = (maxLineLength - lineWidths[i]) / 2;
  3022. if (i === 0) {
  3023. newX = 0;
  3024. newY = 0;
  3025. } else {
  3026. newX = (prevWidth - lineWidths[i]) / 2;
  3027. newY = leading;
  3028. }
  3029. text.push([da[i], newX, newY]);
  3030. prevWidth = lineWidths[i];
  3031. }
  3032. } else if (align === "left") {
  3033. text = [];
  3034. for (var i = 0, len = da.length; i < len; i++) {
  3035. text.push(da[i]);
  3036. }
  3037. } else if (align === "justify") {
  3038. text = [];
  3039. var maxWidth = maxWidth !== 0 ? maxWidth : pageWidth;
  3040. for (var i = 0, len = da.length; i < len; i++) {
  3041. newX = 0;
  3042. newY = i === 0 ? 0 : leading;
  3043. if (i < len - 1) {
  3044. wordSpacingPerLine.push((maxWidth - lineWidths[i]) / (da[i].split(" ").length - 1));
  3045. }
  3046. text.push([da[i], newX, newY]);
  3047. }
  3048. } else {
  3049. throw new Error('Unrecognized alignment option, use "left", "center", "right" or "justify".');
  3050. }
  3051. } //R2L
  3052. var doReversing = typeof options.R2L === "boolean" ? options.R2L : R2L;
  3053. if (doReversing === true) {
  3054. text = processTextByFunction(text, function (text, posX, posY) {
  3055. return [text.split("").reverse().join(""), posX, posY];
  3056. });
  3057. } //creating Payload-Object to make text byRef
  3058. var payload = {
  3059. text: text,
  3060. x: x,
  3061. y: y,
  3062. options: options,
  3063. mutex: {
  3064. pdfEscape: pdfEscape,
  3065. activeFontKey: activeFontKey,
  3066. fonts: fonts,
  3067. activeFontSize: activeFontSize
  3068. }
  3069. };
  3070. events.publish("postProcessText", payload);
  3071. text = payload.text;
  3072. isHex = payload.mutex.isHex;
  3073. var da = transformTextToSpecialArray(text);
  3074. text = [];
  3075. var variant = 0;
  3076. var len = da.length;
  3077. var posX;
  3078. var posY;
  3079. var content;
  3080. var wordSpacing = "";
  3081. for (var i = 0; i < len; i++) {
  3082. wordSpacing = "";
  3083. if (Object.prototype.toString.call(da[i]) !== "[object Array]") {
  3084. content = (isHex ? "<" : "(") + da[i] + (isHex ? ">" : ")");
  3085. variant = 0;
  3086. } else if (Object.prototype.toString.call(da[i]) === "[object Array]") {
  3087. posX = da[i][1] * k; // x offset must always be scaled!
  3088. // y offset/leading must NOT be scaled by k as it is dependent of the font size, which is always given
  3089. // in plain pt
  3090. posY = -da[i][2];
  3091. content = (isHex ? "<" : "(") + da[i][0] + (isHex ? ">" : ")");
  3092. variant = 1;
  3093. }
  3094. if (wordSpacingPerLine !== undefined && wordSpacingPerLine[i] !== undefined) {
  3095. wordSpacing = wordSpacingPerLine[i] + " Tw\n";
  3096. }
  3097. if (variant === 1 && i > 0) {
  3098. text.push(wordSpacing + hpf(posX) + " " + hpf(posY) + " " + " Td\n" + content);
  3099. } else {
  3100. text.push(wordSpacing + content);
  3101. }
  3102. }
  3103. if (variant === 0) {
  3104. text = text.join(" Tj\nT* ");
  3105. } else {
  3106. text = text.join(" Tj\n");
  3107. }
  3108. if (apiMode === ApiMode.ADVANCED && transformationMatrix === null) {
  3109. transformationMatrix = unitMatrix;
  3110. }
  3111. if (transformationMatrix !== null) {
  3112. // It is kind of more intuitive to apply a plain rotation around the text anchor set by x and y
  3113. // but when the user supplies an arbitrary transformation matrix, the x and y offsets should be applied
  3114. // in the coordinate system established by this matrix
  3115. if (typeof angle === "number") {
  3116. transformationMatrix = matrixMult(transformationMatrix, new Matrix(1, 0, 0, 1, scaleByK(x), transformScaleY(y)));
  3117. } else {
  3118. transformationMatrix = matrixMult(new Matrix(1, 0, 0, 1, scaleByK(x), transformScaleY(y)), transformationMatrix);
  3119. }
  3120. transformationMatrix = matrixMult( // xOffset must always be scaled!
  3121. new Matrix(1, 0, 0, 1, xOffset * k, 0), transformationMatrix);
  3122. if (apiMode === ApiMode.ADVANCED) {
  3123. transformationMatrix = matrixMult(new Matrix(1, 0, 0, -1, 0, 0), transformationMatrix);
  3124. }
  3125. text = transformationMatrix.toString() + " Tm\n" + text;
  3126. } else {
  3127. text = hpf(scaleByK(x + xOffset)) + " " + hpf(transformScaleY(y)) + " " + " Td\n" + text;
  3128. }
  3129. text += " Tj\n";
  3130. var result = "BT\n/" + activeFontKey + " " + activeFontSize + " Tf\n" + // font face, style, size
  3131. (activeFontSize * lineHeight).toFixed(2) + " TL\n" + // line spacing
  3132. textColor + "\n";
  3133. result += xtra;
  3134. result += text;
  3135. result += "ET";
  3136. out(result);
  3137. return scope;
  3138. };
  3139. /**
  3140. * Letter spacing method to print text with gaps
  3141. *
  3142. * @function
  3143. * @instance
  3144. * @param {String|Array} text String to be added to the page.
  3145. * @param {number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
  3146. * @param {number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
  3147. * @param {number} spacing Spacing (in units declared at inception)
  3148. * @returns {jsPDF}
  3149. * @methodOf jsPDF#
  3150. * @name lstext
  3151. * @deprecated We'll be removing this function. It doesn't take character width into account.
  3152. */
  3153. API.lstext = function (text, x, y, spacing) {
  3154. console.warn("jsPDF.lstext is deprecated");
  3155. for (var i = 0, len = text.length; i < len; i++, x += spacing) {
  3156. this.text(text[i], x, y);
  3157. }
  3158. return this;
  3159. };
  3160. /**
  3161. * Draws a line from (x1, y1) to (x2, y2). No extra call to {@link API.stroke} is needed.
  3162. * @param {number} x1
  3163. * @param {number} y1
  3164. * @param {number} x2
  3165. * @param {number} y2
  3166. * @return {jsPDF}
  3167. * @methodOf jsPDF#
  3168. * @name line
  3169. */
  3170. API.line = function (x1, y1, x2, y2) {
  3171. if (apiMode === ApiMode.COMPAT) {
  3172. return this.lines([[x2 - x1, y2 - y1]], x1, y1, [1, 1], "D");
  3173. } else {
  3174. return this.lines([[x2 - x1, y2 - y1]], x1, y1, [1, 1]).stroke();
  3175. }
  3176. };
  3177. /**
  3178. * Begin a new subpath by moving the current point to coordinates (x, y). The PDF "m" operator.
  3179. * @param {number} x
  3180. * @param {number} y
  3181. * @methodOf jsPDF#
  3182. * @name moveTo
  3183. */
  3184. API.moveTo = function (x, y) {
  3185. out(hpf(scaleByK(x)) + " " + hpf(transformScaleY(y)) + " m");
  3186. };
  3187. /**
  3188. * Append a straight line segment from the current point to the point (x, y). The PDF "l" operator.
  3189. * @param {number} x
  3190. * @param {number} y
  3191. * @methodOf jsPDF#
  3192. * @name lineTo
  3193. */
  3194. API.lineTo = function (x, y) {
  3195. out(hpf(scaleByK(x)) + " " + hpf(transformScaleY(y)) + " l");
  3196. };
  3197. /**
  3198. * Append a cubic Bézier curve to the current path. The curve shall extend from the current point to the point
  3199. * (x3, y3), using (x1, y1) and (x2, y2) as Bézier control points. The new current point shall be (x3, x3).
  3200. * @param {number} x1
  3201. * @param {number} y1
  3202. * @param {number} x2
  3203. * @param {number} y2
  3204. * @param {number} x3
  3205. * @param {number} y3
  3206. * @methodOf jsPDF#
  3207. * @name curveTo
  3208. */
  3209. API.curveTo = function (x1, y1, x2, y2, x3, y3) {
  3210. out([hpf(scaleByK(x1)), hpf(transformScaleY(y1)), hpf(scaleByK(x2)), hpf(transformScaleY(y2)), hpf(scaleByK(x3)), hpf(transformScaleY(y3)), "c"].join(" "));
  3211. }; // PDF supports these path painting and clip path operators:
  3212. //
  3213. // S - stroke
  3214. // s - close/stroke
  3215. // f (F) - fill non-zero
  3216. // f* - fill evenodd
  3217. // B - fill stroke nonzero
  3218. // B* - fill stroke evenodd
  3219. // b - close fill stroke nonzero
  3220. // b* - close fill stroke evenodd
  3221. // n - nothing (consume path)
  3222. // W - clip nonzero
  3223. // W* - clip evenodd
  3224. //
  3225. // In order to keep the API small, we omit the close-and-fill/stroke operators and provide a separate close()
  3226. // method.
  3227. /**
  3228. * Close the current path. The PDF "h" operator.
  3229. * @return jsPDF
  3230. * @methodOf jsPDF#
  3231. * @name close
  3232. */
  3233. API.close = function () {
  3234. out("h");
  3235. return this;
  3236. };
  3237. /**
  3238. * Stroke the path. The PDF "S" operator.
  3239. * @return jsPDF
  3240. * @methodOf jsPDF#
  3241. * @name stroke
  3242. */
  3243. API.stroke = function () {
  3244. out("S");
  3245. return this;
  3246. };
  3247. /**
  3248. * @typedef {Object} PatternData
  3249. * @property {string} key The key of the pattern
  3250. * @property {Matrix} matrix The matrix that gets applied to the pattern right before drawing.
  3251. * @property {number[]|undefined} boundingBox Only relevant for tiling patterns. The bounding box at which one
  3252. * pattern cell gets clipped
  3253. * @property {number|undefined} xStep Only relevant for tiling patterns. Horizontal spacing between pattern cells
  3254. * @property {number|undefined} yStep Only relevant for tiling patterns. Vertical spacing between pattern cells
  3255. */
  3256. /**
  3257. * Fill the current path using the nonzero winding number rule. If a pattern is provided, the path will be filled
  3258. * with this pattern, otherwise with the current fill color. Equivalent to the PDF "f" operator.
  3259. * @param {PatternData=} pattern If provided the path will be filled with this pattern
  3260. * @return jsPDF
  3261. * @methodOf jsPDF#
  3262. * @name fill
  3263. */
  3264. API.fill = function (pattern) {
  3265. fillWithOptionalPattern("f", pattern);
  3266. return this;
  3267. };
  3268. /**
  3269. * Fill the current path using the even-odd rule. The PDF f* operator.
  3270. * @see API.fill
  3271. * @param {PatternData=} pattern Optional pattern
  3272. * @return jsPDF
  3273. * @methodOf jsPDF#
  3274. * @name fillEvenOdd
  3275. */
  3276. API.fillEvenOdd = function (pattern) {
  3277. fillWithOptionalPattern("f*", pattern);
  3278. return this;
  3279. };
  3280. /**
  3281. * Fill using the nonzero winding number rule and then stroke the current Path. The PDF "B" operator.
  3282. * @see API.fill
  3283. * @param {PatternData=} pattern Optional pattern
  3284. * @return jsPDF
  3285. * @methodOf jsPDF#
  3286. * @name fillStroke
  3287. */
  3288. API.fillStroke = function (pattern) {
  3289. fillWithOptionalPattern("B", pattern);
  3290. return this;
  3291. };
  3292. /**
  3293. * Fill using the even-odd rule and then stroke the current Path. The PDF "B" operator.
  3294. * @see API.fill
  3295. * @param {PatternData=} pattern Optional pattern
  3296. * @return jsPDF
  3297. * @methodOf jsPDF#
  3298. * @name fillStrokeEvenOdd
  3299. */
  3300. API.fillStrokeEvenOdd = function (pattern) {
  3301. fillWithOptionalPattern("B*", pattern);
  3302. return this;
  3303. };
  3304. function fillWithOptionalPattern(style, pattern) {
  3305. if (_typeof(pattern) === "object") {
  3306. fillWithPattern(pattern, style);
  3307. } else {
  3308. out(style);
  3309. }
  3310. }
  3311. /**
  3312. * Modify the current clip path by intersecting it with the current path using the nonzero winding number rule. Note
  3313. * that this will NOT consume the current path. In order to only use this path for clipping call
  3314. * {@link API.discardPath} afterwards.
  3315. *
  3316. * When in "compat" API mode this method has a historical bug and will always stroke the path as well, use
  3317. * {@link API.clip_fixed} instead.
  3318. * @return jsPDF
  3319. * @methodOf jsPDF#
  3320. * @name clip
  3321. */
  3322. API.clip = function () {
  3323. if (apiMode === ApiMode.COMPAT) {
  3324. // By patrick-roberts, github.com/MrRio/jsPDF/issues/328
  3325. // Call .clip() after calling .rect() with a style argument of null
  3326. out("W"); // clip
  3327. out("S"); // stroke path; necessary for clip to work
  3328. } else {
  3329. out("W");
  3330. }
  3331. return this;
  3332. };
  3333. /**
  3334. * Modify the current clip path by intersecting it with the current path using the even-odd rule. Note
  3335. * that this will NOT consume the current path. In order to only use this path for clipping call
  3336. * {@link API.discardPath} afterwards.
  3337. *
  3338. * @return jsPDF
  3339. * @methodOf jsPDF#
  3340. * @name clipEvenOdd
  3341. */
  3342. API.clipEvenOdd = function () {
  3343. out("W*");
  3344. return this;
  3345. };
  3346. /**
  3347. * Consumes the current path without any effect. Mainly used in combination with {@link clip} or
  3348. * {@link clipEvenOdd}. The PDF "n" operator.
  3349. * @return {jsPDF}
  3350. * @methodOf jsPDF#
  3351. * @name discardPath
  3352. */
  3353. API.discardPath = function () {
  3354. out("n");
  3355. return this;
  3356. };
  3357. /**
  3358. * This fixes the previous function clip(). Perhaps the 'stroke path' hack was due to the missing 'n' instruction?
  3359. * We introduce the fixed version so as to not break API.
  3360. * @param fillRule
  3361. * @deprecated Don't use this method when in "advanced" API mode.
  3362. * @methodOf jsPDF#
  3363. * @name clip_fixed
  3364. */
  3365. API.clip_fixed = function (fillRule) {
  3366. // Call .clip() after calling drawing ops with a style argument of null
  3367. // W is the PDF clipping op
  3368. if ("evenodd" === fillRule) {
  3369. out("W*");
  3370. } else {
  3371. out("W");
  3372. } // End the path object without filling or stroking it.
  3373. // This operator is a path-painting no-op, used primarily for the side effect of changing the current clipping path
  3374. // (see Section 4.4.3, “Clipping Path Operators”)
  3375. out("n");
  3376. };
  3377. /**
  3378. * @typedef {Object} PatternData
  3379. * {Matrix|undefined} matrix
  3380. * {Number|undefined} xStep
  3381. * {Number|undefined} yStep
  3382. * {Array.<Number>|undefined} boundingBox
  3383. */
  3384. /**
  3385. * Adds series of curves (straight lines or cubic bezier curves) to canvas, starting at `x`, `y` coordinates.
  3386. * All data points in `lines` are relative to last line origin.
  3387. * `x`, `y` become x1,y1 for first line / curve in the set.
  3388. * For lines you only need to specify [x2, y2] - (ending point) vector against x1, y1 starting point.
  3389. * For bezier curves you need to specify [x2,y2,x3,y3,x4,y4] - vectors to control points 1, 2, ending point. All vectors are against the start of the curve - x1,y1.
  3390. *
  3391. * @example .lines([[2,2],[-2,2],[1,1,2,2,3,3],[2,1]], 212,110, 10) // line, line, bezier curve, line
  3392. * @param {Array} lines Array of *vector* shifts as pairs (lines) or sextets (cubic bezier curves).
  3393. * @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
  3394. * @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
  3395. * @param {Number} scale (Defaults to [1.0,1.0]) x,y Scaling factor for all vectors. Elements can be any floating number Sub-one makes drawing smaller. Over-one grows the drawing. Negative flips the direction.
  3396. * @param {String=} style A string specifying the painting style or null. Valid styles include:
  3397. * 'S' [default] - stroke,
  3398. * 'F' - fill,
  3399. * and 'DF' (or 'FD') - fill then stroke.
  3400. * In "compat" API mode, a null value postpones setting the style so that a shape may be composed using multiple
  3401. * method calls. The last drawing method call used to define the shape should not have a null style argument.
  3402. *
  3403. * In "advanced" API mode this parameter is deprecated.
  3404. * @param {Boolean=} closed If true, the path is closed with a straight line from the end of the last curve to the starting point.
  3405. * @param {String=} patternKey The pattern key for the pattern that should be used to fill the path. Deprecated!
  3406. * @param {(Matrix|PatternData)=} patternData The matrix that transforms the pattern into user space, or an object that
  3407. * will modify the pattern on use. Deprecated!
  3408. * @function
  3409. * @instance
  3410. * @returns {jsPDF}
  3411. * @methodOf jsPDF#
  3412. * @name lines
  3413. */
  3414. API.lines = function (lines, x, y, scale, style, closed, patternKey, patternData) {
  3415. var scalex, scaley, i, l, leg, x2, y2, x3, y3, x4, y4; // Pre-August-2012 the order of arguments was function(x, y, lines, scale, style)
  3416. // in effort to make all calls have similar signature like
  3417. // function(content, coordinateX, coordinateY , miscellaneous)
  3418. // this method had its args flipped.
  3419. // code below allows backward compatibility with old arg order.
  3420. if (typeof lines === "number") {
  3421. var tmp = y;
  3422. y = x;
  3423. x = lines;
  3424. lines = tmp;
  3425. }
  3426. scale = scale || [1, 1]; // starting point
  3427. this.moveTo(x, y);
  3428. scalex = scale[0];
  3429. scaley = scale[1];
  3430. l = lines.length; //, x2, y2 // bezier only. In page default measurement "units", *after* scaling
  3431. //, x3, y3 // bezier only. In page default measurement "units", *after* scaling
  3432. // ending point for all, lines and bezier. . In page default measurement "units", *after* scaling
  3433. x4 = x; // last / ending point = starting point for first item.
  3434. y4 = y; // last / ending point = starting point for first item.
  3435. for (i = 0; i < l; i++) {
  3436. leg = lines[i];
  3437. if (leg.length === 2) {
  3438. // simple line
  3439. x4 = leg[0] * scalex + x4; // here last x4 was prior ending point
  3440. y4 = leg[1] * scaley + y4; // here last y4 was prior ending point
  3441. this.lineTo(x4, y4);
  3442. } else {
  3443. // bezier curve
  3444. x2 = leg[0] * scalex + x4; // here last x4 is prior ending point
  3445. y2 = leg[1] * scaley + y4; // here last y4 is prior ending point
  3446. x3 = leg[2] * scalex + x4; // here last x4 is prior ending point
  3447. y3 = leg[3] * scaley + y4; // here last y4 is prior ending point
  3448. x4 = leg[4] * scalex + x4; // here last x4 was prior ending point
  3449. y4 = leg[5] * scaley + y4; // here last y4 was prior ending point
  3450. this.curveTo(x2, y2, x3, y3, x4, y4);
  3451. }
  3452. }
  3453. if (closed) {
  3454. this.close();
  3455. }
  3456. putStyle(style, patternKey, patternData);
  3457. return this;
  3458. };
  3459. /**
  3460. * Similar to {@link API.lines} but all coordinates are interpreted as absolute coordinates instead of relative.
  3461. * @param {Array<Object>} lines An array of {op: operator, c: coordinates} object, where op is one of "m" (move to), "l" (line to)
  3462. * "c" (cubic bezier curve) and "h" (close (sub)path)). c is an array of coordinates. "m" and "l" expect two, "c"
  3463. * six and "h" an empty array (or undefined).
  3464. * @param {String=} style The style. Deprecated!
  3465. * @param {String=} patternKey The pattern key for the pattern that should be used to fill the path. Deprecated!
  3466. * @param {(Matrix|PatternData)=} patternData The matrix that transforms the pattern into user space, or an object that
  3467. * will modify the pattern on use. Deprecated!
  3468. * @function
  3469. * @returns {jsPDF}
  3470. * @methodOf jsPDF#
  3471. * @name path
  3472. */
  3473. API.path = function (lines, style, patternKey, patternData) {
  3474. for (var i = 0; i < lines.length; i++) {
  3475. var leg = lines[i];
  3476. var coords = leg.c;
  3477. switch (leg.op) {
  3478. case "m":
  3479. this.moveTo(coords[0], coords[1]);
  3480. break;
  3481. case "l":
  3482. this.lineTo(coords[0], coords[1]);
  3483. break;
  3484. case "c":
  3485. this.curveTo.apply(this, coords);
  3486. break;
  3487. case "h":
  3488. this.close();
  3489. break;
  3490. }
  3491. }
  3492. putStyle(style, patternKey, patternData);
  3493. return this;
  3494. };
  3495. /**
  3496. * Adds a rectangle to PDF
  3497. *
  3498. * @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
  3499. * @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
  3500. * @param {Number} w Width (in units declared at inception of PDF document)
  3501. * @param {Number} h Height (in units declared at inception of PDF document)
  3502. * @param {String=} style A string specifying the painting style or null. Valid styles include:
  3503. * 'S' [default] - stroke,
  3504. * 'F' - fill,
  3505. * and 'DF' (or 'FD') - fill then stroke.
  3506. * In "compat" API mode, a null value postpones setting the style so that a shape may be composed using multiple
  3507. * method calls. The last drawing method call used to define the shape should not have a null style argument.
  3508. *
  3509. * In "advanced" API mode this parameter is deprecated.
  3510. * @param {String=} patternKey The pattern key for the pattern that should be used to fill the primitive. Deprecated!
  3511. * @param {(Matrix|PatternData)=} patternData The matrix that transforms the pattern into user space, or an object that
  3512. * will modify the pattern on use. Deprecated!
  3513. * @function
  3514. * @instance
  3515. * @returns {jsPDF}
  3516. * @methodOf jsPDF#
  3517. * @name rect
  3518. */
  3519. API.rect = function (x, y, w, h, style, patternKey, patternData) {
  3520. if (apiMode === ApiMode.COMPAT) {
  3521. h = -h;
  3522. }
  3523. out([hpf(scaleByK(x)), hpf(transformScaleY(y)), hpf(scaleByK(w)), hpf(scaleByK(h)), "re"].join(" "));
  3524. putStyle(style, patternKey, patternData);
  3525. return this;
  3526. };
  3527. /**
  3528. * Adds a triangle to PDF
  3529. *
  3530. * @param {Number} x1 Coordinate (in units declared at inception of PDF document) against left edge of the page
  3531. * @param {Number} y1 Coordinate (in units declared at inception of PDF document) against upper edge of the page
  3532. * @param {Number} x2 Coordinate (in units declared at inception of PDF document) against left edge of the page
  3533. * @param {Number} y2 Coordinate (in units declared at inception of PDF document) against upper edge of the page
  3534. * @param {Number} x3 Coordinate (in units declared at inception of PDF document) against left edge of the page
  3535. * @param {Number} y3 Coordinate (in units declared at inception of PDF document) against upper edge of the page
  3536. * @param {String=} style A string specifying the painting style or null. Valid styles include:
  3537. * 'S' [default] - stroke,
  3538. * 'F' - fill,
  3539. * and 'DF' (or 'FD') - fill then stroke.
  3540. * In "compat" API mode, a null value postpones setting the style so that a shape may be composed using multiple
  3541. * method calls. The last drawing method call used to define the shape should not have a null style argument.
  3542. *
  3543. * In "advanced" API mode this parameter is deprecated.
  3544. * @param {String=} patternKey The pattern key for the pattern that should be used to fill the primitive. Deprecated!
  3545. * @param {(Matrix|PatternData)=} patternData The matrix that transforms the pattern into user space, or an object that
  3546. * will modify the pattern on use. Deprecated!
  3547. * @function
  3548. * @instance
  3549. * @returns {jsPDF}
  3550. * @methodOf jsPDF#
  3551. * @name triangle
  3552. */
  3553. API.triangle = function (x1, y1, x2, y2, x3, y3, style, patternKey, patternData) {
  3554. this.lines([[x2 - x1, y2 - y1], // vector to point 2
  3555. [x3 - x2, y3 - y2], // vector to point 3
  3556. [x1 - x3, y1 - y3] // closing vector back to point 1
  3557. ], x1, y1, // start of path
  3558. [1, 1], style, true, patternKey, patternData);
  3559. return this;
  3560. };
  3561. /**
  3562. * Adds a rectangle with rounded corners to PDF
  3563. *
  3564. * @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
  3565. * @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
  3566. * @param {Number} w Width (in units declared at inception of PDF document)
  3567. * @param {Number} h Height (in units declared at inception of PDF document)
  3568. * @param {Number} rx Radius along x axis (in units declared at inception of PDF document)
  3569. * @param {Number} ry Radius along y axis (in units declared at inception of PDF document)
  3570. * @param {String=} style A string specifying the painting style or null. Valid styles include:
  3571. * 'S' [default] - stroke,
  3572. * 'F' - fill,
  3573. * and 'DF' (or 'FD') - fill then stroke.
  3574. * In "compat" API mode, a null value postpones setting the style so that a shape may be composed using multiple
  3575. * method calls. The last drawing method call used to define the shape should not have a null style argument.
  3576. *
  3577. * In "advanced" API mode this parameter is deprecated.
  3578. * @param {String=} patternKey The pattern key for the pattern that should be used to fill the primitive. Deprecated!
  3579. * @param {(Matrix|PatternData)=} patternData The matrix that transforms the pattern into user space, or an object that
  3580. * will modify the pattern on use. Deprecated!
  3581. * @function
  3582. * @instance
  3583. * @returns {jsPDF}
  3584. * @methodOf jsPDF#
  3585. * @name roundedRect
  3586. */
  3587. API.roundedRect = function (x, y, w, h, rx, ry, style, patternKey, patternData) {
  3588. var MyArc = 4 / 3 * (Math.SQRT2 - 1);
  3589. rx = Math.min(rx, w * 0.5);
  3590. ry = Math.min(ry, h * 0.5);
  3591. this.lines([[w - 2 * rx, 0], [rx * MyArc, 0, rx, ry - ry * MyArc, rx, ry], [0, h - 2 * ry], [0, ry * MyArc, -(rx * MyArc), ry, -rx, ry], [-w + 2 * rx, 0], [-(rx * MyArc), 0, -rx, -(ry * MyArc), -rx, -ry], [0, -h + 2 * ry], [0, -(ry * MyArc), rx * MyArc, -ry, rx, -ry]], x + rx, y, // start of path
  3592. [1, 1], style, true, patternKey, patternData);
  3593. return this;
  3594. };
  3595. /**
  3596. * Adds an ellipse to PDF
  3597. *
  3598. * @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
  3599. * @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
  3600. * @param {Number} rx Radius along x axis (in units declared at inception of PDF document)
  3601. * @param {Number} ry Radius along y axis (in units declared at inception of PDF document)
  3602. * @param {String=} style A string specifying the painting style or null. Valid styles include:
  3603. * 'S' [default] - stroke,
  3604. * 'F' - fill,
  3605. * and 'DF' (or 'FD') - fill then stroke.
  3606. * In "compat" API mode, a null value postpones setting the style so that a shape may be composed using multiple
  3607. * method calls. The last drawing method call used to define the shape should not have a null style argument.
  3608. *
  3609. * In "advanced" API mode this parameter is deprecated.
  3610. * @param {String=} patternKey The pattern key for the pattern that should be used to fill the primitive. Deprecated!
  3611. * @param {(Matrix|PatternData)=} patternData The matrix that transforms the pattern into user space, or an object that
  3612. * will modify the pattern on use. Deprecated!
  3613. * @function
  3614. * @instance
  3615. * @returns {jsPDF}
  3616. * @methodOf jsPDF#
  3617. * @name ellipse
  3618. */
  3619. API.ellipse = function (x, y, rx, ry, style, patternKey, patternData) {
  3620. var lx = 4 / 3 * (Math.SQRT2 - 1) * rx,
  3621. ly = 4 / 3 * (Math.SQRT2 - 1) * ry;
  3622. this.moveTo(x + rx, y);
  3623. this.curveTo(x + rx, y - ly, x + lx, y - ry, x, y - ry);
  3624. this.curveTo(x - lx, y - ry, x - rx, y - ly, x - rx, y);
  3625. this.curveTo(x - rx, y + ly, x - lx, y + ry, x, y + ry);
  3626. this.curveTo(x + lx, y + ry, x + rx, y + ly, x + rx, y);
  3627. putStyle(style, patternKey, patternData);
  3628. return this;
  3629. };
  3630. /**
  3631. * Adds an circle to PDF
  3632. *
  3633. * @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
  3634. * @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
  3635. * @param {Number} r Radius (in units declared at inception of PDF document)
  3636. * @param {String=} style A string specifying the painting style or null. Valid styles include:
  3637. * 'S' [default] - stroke,
  3638. * 'F' - fill,
  3639. * and 'DF' (or 'FD') - fill then stroke.
  3640. * In "compat" API mode, a null value postpones setting the style so that a shape may be composed using multiple
  3641. * method calls. The last drawing method call used to define the shape should not have a null style argument.
  3642. *
  3643. * In "advanced" API mode this parameter is deprecated.
  3644. * @param {String=} patternKey The pattern key for the pattern that should be used to fill the primitive. Deprecated!
  3645. * @param {(Matrix|PatternData)=} patternData The matrix that transforms the pattern into user space, or an object that
  3646. * will modify the pattern on use. Deprecated!
  3647. * @function
  3648. * @instance
  3649. * @returns {jsPDF}
  3650. * @methodOf jsPDF#
  3651. * @name circle
  3652. */
  3653. API.circle = function (x, y, r, style, patternKey, patternData) {
  3654. return this.ellipse(x, y, r, r, style, patternKey, patternData);
  3655. };
  3656. /**
  3657. * Adds a properties to the PDF document
  3658. *
  3659. * @param {Object} properties A property_name-to-property_value object structure.
  3660. * @function
  3661. * @instance
  3662. * @returns {jsPDF}
  3663. * @methodOf jsPDF#
  3664. * @name setProperties
  3665. */
  3666. API.setProperties = function (properties) {
  3667. // copying only those properties we can render.
  3668. for (var property in documentProperties) {
  3669. if (documentProperties.hasOwnProperty(property) && properties[property]) {
  3670. documentProperties[property] = properties[property];
  3671. }
  3672. }
  3673. return this;
  3674. };
  3675. /**
  3676. * Sets font size for upcoming text elements.
  3677. *
  3678. * @param {number} size Font size in points.
  3679. * @function
  3680. * @instance
  3681. * @returns {jsPDF}
  3682. * @methodOf jsPDF#
  3683. * @name setFontSize
  3684. */
  3685. API.setFontSize = function (size) {
  3686. // convert font size into current unit system
  3687. if (apiMode === ApiMode.ADVANCED) {
  3688. activeFontSize = size / k;
  3689. } else {
  3690. activeFontSize = size;
  3691. }
  3692. out("/" + activeFontKey + " " + activeFontSize + " Tf");
  3693. return this;
  3694. };
  3695. /**
  3696. * @return {number}
  3697. * @methodOf jsPDF#
  3698. * @name getFontSize
  3699. */
  3700. API.getFontSize = function () {
  3701. if (apiMode === ApiMode.COMPAT) {
  3702. return activeFontSize;
  3703. } else {
  3704. return activeFontSize * k;
  3705. }
  3706. };
  3707. /**
  3708. * Sets text font face, variant for upcoming text elements.
  3709. * See output of jsPDF.getFontList() for possible font names, styles.
  3710. *
  3711. * @param {string} fontName Font name or family. Example: "times"
  3712. * @param {string} fontStyle Font style or variant. Example: "italic"
  3713. * @function
  3714. * @instance
  3715. * @returns {jsPDF}
  3716. * @methodOf jsPDF#
  3717. * @name setFont
  3718. */
  3719. API.setFont = function (fontName, fontStyle) {
  3720. activeFontKey = _getFont(fontName, fontStyle); // if font is not found, the above line blows up and we never go further
  3721. out("/" + activeFontKey + " " + activeFontSize + " Tf");
  3722. return this;
  3723. };
  3724. /**
  3725. * Switches font style or variant for upcoming text elements,
  3726. * while keeping the font face or family same.
  3727. * See output of jsPDF.getFontList() for possible font names, styles.
  3728. *
  3729. * @param {string} style Font style or variant. Example: "italic"
  3730. * @function
  3731. * @instance
  3732. * @returns {jsPDF}
  3733. * @methodOf jsPDF#
  3734. * @name setFontStyle
  3735. */
  3736. API.setFontStyle = API.setFontType = function (style) {
  3737. activeFontKey = _getFont(undefined, style); // if font is not found, the above line blows up and we never go further
  3738. out("/" + activeFontKey + " " + activeFontSize + " Tf");
  3739. return this;
  3740. };
  3741. /**
  3742. * Returns an object - a tree of fontName to fontStyle relationships available to
  3743. * active PDF document.
  3744. *
  3745. * @public
  3746. * @function
  3747. * @instance
  3748. * @returns {Object} Like {'times':['normal', 'italic', ... ], 'arial':['normal', 'bold', ... ], ... }
  3749. * @methodOf jsPDF#
  3750. * @name getFontList
  3751. */
  3752. API.getFontList = function () {
  3753. // TODO: iterate over fonts array or return copy of fontmap instead in case more are ever added.
  3754. var list = {},
  3755. fontName,
  3756. fontStyle,
  3757. tmp;
  3758. for (fontName in fontmap) {
  3759. if (fontmap.hasOwnProperty(fontName)) {
  3760. list[fontName] = tmp = [];
  3761. for (fontStyle in fontmap[fontName]) {
  3762. if (fontmap[fontName].hasOwnProperty(fontStyle)) {
  3763. tmp.push(fontStyle);
  3764. }
  3765. }
  3766. }
  3767. }
  3768. return list;
  3769. };
  3770. /**
  3771. * Add a custom font to the current instance.
  3772. *
  3773. * @param {String} postScriptName name of the Font. Example: "Menlo-Regular"
  3774. * @param {String} fontName of font-family from @font-face definition. Example: "Menlo Regular"
  3775. * @param {String} fontStyle style. Example: "normal"
  3776. * @function
  3777. * @instance
  3778. * @methodOf jsPDF
  3779. * @name addFont
  3780. */
  3781. API.addFont = function (postScriptName, fontName, fontStyle, encoding) {
  3782. encoding = encoding || "Identity-H";
  3783. addFont(postScriptName, fontName, fontStyle, encoding);
  3784. };
  3785. /**
  3786. * Sets line width for upcoming lines.
  3787. *
  3788. * @param {number} width Line width (in units declared at inception of PDF document)
  3789. * @function
  3790. * @instance
  3791. * @returns {jsPDF}
  3792. * @methodOf jsPDF#
  3793. * @name setLineWidth
  3794. */
  3795. API.setLineWidth = function (width) {
  3796. out(scaleByK(width).toFixed(2) + " w");
  3797. return this;
  3798. };
  3799. /**
  3800. * Sets the stroke color for upcoming elements.
  3801. *
  3802. * Depending on the number of arguments given, Gray, RGB, or CMYK
  3803. * color space is implied.
  3804. *
  3805. * When only ch1 is given, "Gray" color space is implied and it
  3806. * must be a value in the range from 0.00 (solid black) to to 1.00 (white)
  3807. * if values are communicated as String types, or in range from 0 (black)
  3808. * to 255 (white) if communicated as Number type.
  3809. * The RGB-like 0-255 range is provided for backward compatibility.
  3810. *
  3811. * When only ch1,ch2,ch3 are given, "RGB" color space is implied and each
  3812. * value must be in the range from 0.00 (minimum intensity) to to 1.00
  3813. * (max intensity) if values are communicated as String types, or
  3814. * from 0 (min intensity) to to 255 (max intensity) if values are communicated
  3815. * as Number types.
  3816. * The RGB-like 0-255 range is provided for backward compatibility.
  3817. *
  3818. * When ch1,ch2,ch3,ch4 are given, "CMYK" color space is implied and each
  3819. * value must be a in the range from 0.00 (0% concentration) to to
  3820. * 1.00 (100% concentration)
  3821. *
  3822. * Because JavaScript treats fixed point numbers badly (rounds to
  3823. * floating point nearest to binary representation) it is highly advised to
  3824. * communicate the fractional numbers as String types, not JavaScript Number type.
  3825. *
  3826. * @param {Number|String} ch1 Color channel value or {string} ch1 color value in hexadecimal, example: '#FFFFFF'
  3827. * @param {Number|String} ch2 Color channel value
  3828. * @param {Number|String} ch3 Color channel value
  3829. * @param {Number|String} ch4 Color channel value
  3830. *
  3831. * @function
  3832. * @instance
  3833. * @returns {jsPDF}
  3834. * @methodOf jsPDF#
  3835. * @name setDrawColor
  3836. */
  3837. API.setDrawColor = function (ch1, ch2, ch3, ch4) {
  3838. var options = {
  3839. ch1: ch1,
  3840. ch2: ch2,
  3841. ch3: ch3,
  3842. ch4: ch4,
  3843. pdfColorType: "draw",
  3844. precision: 2
  3845. };
  3846. out(generateColorString(options));
  3847. return this;
  3848. };
  3849. /**
  3850. * Sets the fill color for upcoming elements.
  3851. *
  3852. * Depending on the number of arguments given, Gray, RGB, or CMYK
  3853. * color space is implied.
  3854. *
  3855. * When only ch1 is given, "Gray" color space is implied and it
  3856. * must be a value in the range from 0.00 (solid black) to to 1.00 (white)
  3857. * if values are communicated as String types, or in range from 0 (black)
  3858. * to 255 (white) if communicated as Number type.
  3859. * The RGB-like 0-255 range is provided for backward compatibility.
  3860. *
  3861. * When only ch1,ch2,ch3 are given, "RGB" color space is implied and each
  3862. * value must be in the range from 0.00 (minimum intensity) to to 1.00
  3863. * (max intensity) if values are communicated as String types, or
  3864. * from 0 (min intensity) to to 255 (max intensity) if values are communicated
  3865. * as Number types.
  3866. * The RGB-like 0-255 range is provided for backward compatibility.
  3867. *
  3868. * When ch1,ch2,ch3,ch4 are given, "CMYK" color space is implied and each
  3869. * value must be a in the range from 0.00 (0% concentration) to to
  3870. * 1.00 (100% concentration)
  3871. *
  3872. * Because JavaScript treats fixed point numbers badly (rounds to
  3873. * floating point nearest to binary representation) it is highly advised to
  3874. * communicate the fractional numbers as String types, not JavaScript Number type.
  3875. *
  3876. * @param {Number|String} ch1 Color channel value or {string} ch1 color value in hexadecimal, example: '#FFFFFF'
  3877. * @param {Number|String} ch2 Color channel value
  3878. * @param {Number|String} ch3 Color channel value
  3879. * @param {Number|String} ch4 Color channel value
  3880. *
  3881. * @function
  3882. * @instance
  3883. * @returns {jsPDF}
  3884. * @methodOf jsPDF#
  3885. * @name setFillColor
  3886. */
  3887. API.setFillColor = function (ch1, ch2, ch3, ch4) {
  3888. var options = {
  3889. ch1: ch1,
  3890. ch2: ch2,
  3891. ch3: ch3,
  3892. ch4: ch4,
  3893. pdfColorType: "fill",
  3894. precision: 2
  3895. };
  3896. out(generateColorString(options));
  3897. return this;
  3898. };
  3899. /**
  3900. * Sets the text color for upcoming elements.
  3901. *
  3902. * Depending on the number of arguments given, Gray, RGB, or CMYK
  3903. * color space is implied.
  3904. *
  3905. * When only ch1 is given, "Gray" color space is implied and it
  3906. * must be a value in the range from 0.00 (solid black) to to 1.00 (white)
  3907. * if values are communicated as String types, or in range from 0 (black)
  3908. * to 255 (white) if communicated as Number type.
  3909. * The RGB-like 0-255 range is provided for backward compatibility.
  3910. *
  3911. * When only ch1,ch2,ch3 are given, "RGB" color space is implied and each
  3912. * value must be in the range from 0.00 (minimum intensity) to to 1.00
  3913. * (max intensity) if values are communicated as String types, or
  3914. * from 0 (min intensity) to to 255 (max intensity) if values are communicated
  3915. * as Number types.
  3916. * The RGB-like 0-255 range is provided for backward compatibility.
  3917. *
  3918. * When ch1,ch2,ch3,ch4 are given, "CMYK" color space is implied and each
  3919. * value must be a in the range from 0.00 (0% concentration) to to
  3920. * 1.00 (100% concentration)
  3921. *
  3922. * Because JavaScript treats fixed point numbers badly (rounds to
  3923. * floating point nearest to binary representation) it is highly advised to
  3924. * communicate the fractional numbers as String types, not JavaScript Number type.
  3925. *
  3926. * @param {Number|String} ch1 Color channel value or {string} ch1 color value in hexadecimal, example: '#FFFFFF'
  3927. * @param {Number|String} ch2 Color channel value
  3928. * @param {Number|String} ch3 Color channel value
  3929. * @param {Number|String} ch4 Color channel value
  3930. *
  3931. * @function
  3932. * @instance
  3933. * @returns {jsPDF}
  3934. * @methodOf jsPDF#
  3935. * @name setTextColor
  3936. */
  3937. API.setTextColor = function (ch1, ch2, ch3, ch4) {
  3938. var options = {
  3939. ch1: ch1,
  3940. ch2: ch2,
  3941. ch3: ch3,
  3942. ch4: ch4,
  3943. pdfColorType: "text",
  3944. precision: 3
  3945. };
  3946. textColor = generateColorString(options);
  3947. return this;
  3948. };
  3949. /**
  3950. * Initializes the default character set that the user wants to be global..
  3951. *
  3952. * @param {number} charSpace
  3953. * @function
  3954. * @instance
  3955. * @returns {jsPDF} jsPDF-instance
  3956. * @methodOf jsPDF
  3957. * @name setCharSpace
  3958. */
  3959. API.setCharSpace = function (charSpace) {
  3960. if (apiMode === ApiMode.COMPAT) {
  3961. activeCharSpace = charSpace;
  3962. } else if (apiMode === ApiMode.ADVANCED) {
  3963. activeCharSpace = charSpace / k;
  3964. }
  3965. return this;
  3966. };
  3967. /**
  3968. * Initializes the default character set that the user wants to be global..
  3969. *
  3970. * @param {boolean} boolean
  3971. * @function
  3972. * @instance
  3973. * @returns {jsPDF} jsPDF-instance
  3974. * @methodOf jsPDF
  3975. * @name setR2L
  3976. */
  3977. API.setR2L = function (boolean) {
  3978. R2L = boolean;
  3979. return this;
  3980. };
  3981. /**
  3982. * Sets a either previously added {@link GState} (via {@link addGState}) or a new {@link GState}.
  3983. * @param {String|GState} gState If type is string, a previously added GState is used, if type is GState
  3984. * it will be added before use.
  3985. * @function
  3986. * @returns {jsPDF}
  3987. * @methodOf jsPDF#
  3988. * @name setGState
  3989. */
  3990. API.setGState = function (gState) {
  3991. if (typeof gState === "string") {
  3992. gState = gStates[gStatesMap[gState]];
  3993. } else {
  3994. gState = addGState(null, gState);
  3995. }
  3996. if (!gState.equals(activeGState)) {
  3997. out("/" + gState.id + " gs");
  3998. activeGState = gState;
  3999. }
  4000. };
  4001. /**
  4002. * Is an Object providing a mapping from human-readable to
  4003. * integer flag values designating the varieties of line cap
  4004. * and join styles.
  4005. *
  4006. * @fieldOf jsPDF#
  4007. * @name CapJoinStyles
  4008. */
  4009. API.CapJoinStyles = {
  4010. 0: 0,
  4011. butt: 0,
  4012. but: 0,
  4013. miter: 0,
  4014. 1: 1,
  4015. round: 1,
  4016. rounded: 1,
  4017. circle: 1,
  4018. 2: 2,
  4019. projecting: 2,
  4020. project: 2,
  4021. square: 2,
  4022. bevel: 2
  4023. };
  4024. /**
  4025. * Sets the line cap styles
  4026. * See {jsPDF.CapJoinStyles} for variants
  4027. *
  4028. * @param {String|Number} style A string or number identifying the type of line cap
  4029. * @function
  4030. * @instance
  4031. * @returns {jsPDF}
  4032. * @methodOf jsPDF#
  4033. * @name setLineCap
  4034. */
  4035. API.setLineCap = function (style) {
  4036. var id = this.CapJoinStyles[style];
  4037. if (id === undefined) {
  4038. throw new Error("Line cap style of '" + style + "' is not recognized. See or extend .CapJoinStyles property for valid styles");
  4039. }
  4040. lineCapID = id;
  4041. out(id + " J");
  4042. return this;
  4043. };
  4044. /**
  4045. * Sets the line join styles
  4046. * See {jsPDF.CapJoinStyles} for variants
  4047. *
  4048. * @param {String|Number} style A string or number identifying the type of line join
  4049. * @function
  4050. * @instance
  4051. * @returns {jsPDF}
  4052. * @methodOf jsPDF#
  4053. * @name setLineJoin
  4054. */
  4055. API.setLineJoin = function (style) {
  4056. var id = this.CapJoinStyles[style];
  4057. if (id === undefined) {
  4058. throw new Error("Line join style of '" + style + "' is not recognized. See or extend .CapJoinStyles property for valid styles");
  4059. }
  4060. lineJoinID = id;
  4061. out(id + " j");
  4062. return this;
  4063. };
  4064. /**
  4065. * Sets the miter limit.
  4066. * @param {number} miterLimit
  4067. * @function
  4068. * @returns {jsPDF}
  4069. * @methodOf jsPDF#
  4070. * @name setMiterLimit
  4071. */
  4072. API.setLineMiterLimit = function (miterLimit) {
  4073. out(hpf(miterLimit) + " M");
  4074. return this;
  4075. };
  4076. /**
  4077. * Sets the line dash pattern.
  4078. * @param {Array<number>} array An array containing 0-2 numbers. The first number sets the length of the
  4079. * dashes, the second number the length of the gaps. If the second number is missing, the gaps are considered
  4080. * to be as long as the dashes. An empty array means solid, unbroken lines.
  4081. * @param phase The phase lines start with.
  4082. * @function
  4083. * @returns {jsPDF}
  4084. * @methodOf jsPDF#
  4085. * @name setLineDashPattern
  4086. */
  4087. API.setLineDashPattern = function (array, phase) {
  4088. out(["[" + (array[0] !== undefined ? array[0] : ""), (array[1] !== undefined ? array[1] : "") + "]", phase, "d"].join(" "));
  4089. return this;
  4090. };
  4091. /**
  4092. * Generates the PDF document.
  4093. *
  4094. * If `type` argument is undefined, output is raw body of resulting PDF returned as a string.
  4095. *
  4096. * @param {string} type A string identifying one of the possible output types.
  4097. * @param {Object} options An object providing some additional signalling to PDF generator.
  4098. *
  4099. * @function
  4100. * @instance
  4101. * @returns {jsPDF}
  4102. * @memberOf jsPDF
  4103. * @name output
  4104. */
  4105. API.output = _output;
  4106. /**
  4107. * Saves as PDF document. An alias of jsPDF.output('save', 'filename.pdf')
  4108. *
  4109. * @memberOf jsPDF
  4110. * @name save
  4111. * @function
  4112. * @instance
  4113. * @param {string} filename The filename including extension.
  4114. * @returns {jsPDF} jsPDF-instance
  4115. */
  4116. API.save = function (filename) {
  4117. API.output("save", filename);
  4118. }; // applying plugins (more methods) ON TOP of built-in API.
  4119. // this is intentional as we allow plugins to override
  4120. // built-ins
  4121. for (var plugin in jsPDF.API) {
  4122. if (jsPDF.API.hasOwnProperty(plugin)) {
  4123. if (plugin === "events" && jsPDF.API.events.length) {
  4124. (function (events, newEvents) {
  4125. // jsPDF.API.events is a JS Array of Arrays
  4126. // where each Array is a pair of event name, handler
  4127. // Events were added by plugins to the jsPDF instantiator.
  4128. // These are always added to the new instance and some ran
  4129. // during instantiation.
  4130. var eventname, handler_and_args, i;
  4131. for (i = newEvents.length - 1; i !== -1; i--) {
  4132. // subscribe takes 3 args: 'topic', function, runonce_flag
  4133. // if undefined, runonce is false.
  4134. // users can attach callback directly,
  4135. // or they can attach an array with [callback, runonce_flag]
  4136. // that's what the "apply" magic is for below.
  4137. eventname = newEvents[i][0];
  4138. handler_and_args = newEvents[i][1];
  4139. events.subscribe.apply(events, [eventname].concat(typeof handler_and_args === "function" ? [handler_and_args] : handler_and_args));
  4140. }
  4141. })(events, jsPDF.API.events);
  4142. } else {
  4143. API[plugin] = jsPDF.API[plugin];
  4144. }
  4145. }
  4146. } //////////////////////////////////////////////////////
  4147. // continuing initialization of jsPDF Document object
  4148. //////////////////////////////////////////////////////
  4149. // Add the first page automatically
  4150. addFonts();
  4151. activeFontKey = "F1";
  4152. _addPage(format, orientation);
  4153. events.publish("initialized");
  4154. return API;
  4155. }
  4156. /**
  4157. * jsPDF.API is a STATIC property of jsPDF class.
  4158. * jsPDF.API is an object you can add methods and properties to.
  4159. * The methods / properties you add will show up in new jsPDF objects.
  4160. *
  4161. * One property is prepopulated. It is the 'events' Object. Plugin authors can add topics,
  4162. * callbacks to this object. These will be reassigned to all new instances of jsPDF.
  4163. *
  4164. * @static
  4165. * @public
  4166. * @memberOf jsPDF
  4167. * @name API
  4168. *
  4169. * @example
  4170. * jsPDF.API.mymethod = function(){
  4171. * // 'this' will be ref to internal API object. see jsPDF source
  4172. * // , so you can refer to built-in methods like so:
  4173. * // this.line(....)
  4174. * // this.text(....)
  4175. * }
  4176. * var pdfdoc = new jsPDF()
  4177. * pdfdoc.mymethod() // <- !!!!!!
  4178. */
  4179. jsPDF.API = {
  4180. events: []
  4181. };
  4182. /**
  4183. * The version of jsPDF
  4184. * @name version
  4185. * @type {string}
  4186. * @memberOf jsPDF
  4187. */
  4188. jsPDF.version = "0.0.0";
  4189. if (typeof define === "function" && define.amd) {
  4190. define("jsPDF", function () {
  4191. return jsPDF;
  4192. });
  4193. } else if (typeof module !== "undefined" && module.exports) {
  4194. module.exports = jsPDF;
  4195. module.exports.jsPDF = jsPDF;
  4196. } else {
  4197. global.jsPDF = jsPDF;
  4198. }
  4199. return jsPDF;
  4200. }(typeof self !== "undefined" && self || typeof window !== "undefined" && window || typeof global !== "undefined" && global || Function('return typeof this === "object" && this.content')() || Function("return this")()); // `self` is undefined in Firefox for Android content script context
  4201. // while `this` is nsIContentFrameMessageManager
  4202. // with an attribute `content` that corresponds to the window
  4203. /**
  4204. * @license
  4205. * Copyright (c) 2016 Alexander Weidt,
  4206. * https://github.com/BiggA94
  4207. *
  4208. * Licensed under the MIT License. http://opensource.org/licenses/mit-license
  4209. */
  4210. /**
  4211. * jsPDF AcroForm Plugin
  4212. *
  4213. * @name AcroForm
  4214. * @module
  4215. */
  4216. (function (jsPDFAPI, globalObj) {
  4217. var scope;
  4218. var pageHeight;
  4219. var scaleFactor = 1;
  4220. var inherit = function inherit(child, parent) {
  4221. child.prototype = Object.create(parent.prototype);
  4222. child.prototype.constructor = child;
  4223. };
  4224. var scale = function scale(x) {
  4225. return x * (scaleFactor / 1); // 1 = (96 / 72)
  4226. };
  4227. var createFormXObject = function createFormXObject(formObject) {
  4228. var xobj = new AcroFormXObject();
  4229. var height = AcroFormAppearance.internal.getHeight(formObject) || 0;
  4230. var width = AcroFormAppearance.internal.getWidth(formObject) || 0;
  4231. xobj.BBox = [0, 0, width.toFixed(2), height.toFixed(2)];
  4232. return xobj;
  4233. };
  4234. var setBitPosition = function setBitPosition(variable, position, value) {
  4235. variable = variable || 0;
  4236. value = value || 1;
  4237. var bitMask = 1;
  4238. bitMask = bitMask << position - 1;
  4239. if (value == 1) {
  4240. // Set the Bit to 1
  4241. var variable = variable | bitMask;
  4242. } else {
  4243. // Set the Bit to 0
  4244. var variable = variable & ~bitMask;
  4245. }
  4246. return variable;
  4247. };
  4248. /**
  4249. * Calculating the Ff entry:
  4250. *
  4251. * The Ff entry contains flags, that have to be set bitwise In the Following
  4252. * the number in the Comment is the BitPosition
  4253. */
  4254. var calculateFlagsOnOptions = function calculateFlagsOnOptions(flags, opts, PDFVersion) {
  4255. var PDFVersion = PDFVersion || 1.3;
  4256. var flags = flags || 0; // 1, readOnly
  4257. if (opts.readOnly == true) {
  4258. flags = setBitPosition(flags, 1);
  4259. } // 2, required
  4260. if (opts.required == true) {
  4261. flags = setBitPosition(flags, 2);
  4262. } // 4, noExport
  4263. if (opts.noExport == true) {
  4264. flags = setBitPosition(flags, 3);
  4265. } // 13, multiline
  4266. if (opts.multiline == true) {
  4267. flags = setBitPosition(flags, 13);
  4268. } // 14, Password
  4269. if (opts.password) {
  4270. flags = setBitPosition(flags, 14);
  4271. } // 15, NoToggleToOff (Radio buttons only
  4272. if (opts.noToggleToOff) {
  4273. flags = setBitPosition(flags, 15);
  4274. } // 16, Radio
  4275. if (opts.radio) {
  4276. flags = setBitPosition(flags, 16);
  4277. } // 17, Pushbutton
  4278. if (opts.pushbutton) {
  4279. flags = setBitPosition(flags, 17);
  4280. } // 18, Combo (If not set, the choiceField is a listBox!!)
  4281. if (opts.combo) {
  4282. flags = setBitPosition(flags, 18);
  4283. } // 19, Edit
  4284. if (opts.edit) {
  4285. flags = setBitPosition(flags, 19);
  4286. } // 20, Sort
  4287. if (opts.sort) {
  4288. flags = setBitPosition(flags, 20);
  4289. } // 21, FileSelect, PDF 1.4...
  4290. if (opts.fileSelect && PDFVersion >= 1.4) {
  4291. flags = setBitPosition(flags, 21);
  4292. } // 22, MultiSelect (PDF 1.4)
  4293. if (opts.multiSelect && PDFVersion >= 1.4) {
  4294. flags = setBitPosition(flags, 22);
  4295. } // 23, DoNotSpellCheck (PDF 1.4)
  4296. if (opts.doNotSpellCheck && PDFVersion >= 1.4) {
  4297. flags = setBitPosition(flags, 23);
  4298. } // 24, DoNotScroll (PDF 1.4)
  4299. if (opts.doNotScroll == true && PDFVersion >= 1.4) {
  4300. flags = setBitPosition(flags, 24);
  4301. } // 25, RichText (PDF 1.4)
  4302. if (opts.richText && PDFVersion >= 1.4) {
  4303. flags = setBitPosition(flags, 25);
  4304. }
  4305. return flags;
  4306. };
  4307. var calculateCoordinates = function calculateCoordinates(args) {
  4308. var x = args[0];
  4309. var y = args[1];
  4310. var w = args[2];
  4311. var h = args[3];
  4312. var coordinates = {};
  4313. if (Array.isArray(x)) {
  4314. x[0] = scale(x[0]);
  4315. x[1] = scale(x[1]);
  4316. x[2] = scale(x[2]);
  4317. x[3] = scale(x[3]);
  4318. } else {
  4319. x = scale(x);
  4320. y = scale(y);
  4321. w = scale(w);
  4322. h = scale(h);
  4323. }
  4324. coordinates.lowerLeft_X = x || 0;
  4325. coordinates.lowerLeft_Y = scale(pageHeight) - y - h || 0;
  4326. coordinates.upperRight_X = x + w || 0;
  4327. coordinates.upperRight_Y = scale(pageHeight) - y || 0;
  4328. return [coordinates.lowerLeft_X.toFixed(2), coordinates.lowerLeft_Y.toFixed(2), coordinates.upperRight_X.toFixed(2), coordinates.upperRight_Y.toFixed(2)];
  4329. };
  4330. var calculateAppearanceStream = function calculateAppearanceStream(formObject) {
  4331. if (formObject.appearanceStreamContent) {
  4332. // If appearanceStream is already set, use it
  4333. return formObject.appearanceStreamContent;
  4334. }
  4335. if (!formObject.V && !formObject.DV) {
  4336. return;
  4337. } // else calculate it
  4338. var stream = [];
  4339. var text = formObject.V || formObject.DV;
  4340. var calcRes = calculateX(formObject, text);
  4341. stream.push("/Tx BMC");
  4342. stream.push("q");
  4343. stream.push("/F1 " + calcRes.fontSize.toFixed(2) + " Tf");
  4344. stream.push("1 0 0 1 0 0 Tm"); // Text Matrix
  4345. stream.push("BT"); // Begin Text
  4346. stream.push(calcRes.text);
  4347. stream.push("ET"); // End Text
  4348. stream.push("Q");
  4349. stream.push("EMC");
  4350. var appearanceStreamContent = new createFormXObject(formObject);
  4351. appearanceStreamContent.stream = stream.join("\n");
  4352. return appearanceStreamContent;
  4353. };
  4354. var calculateX = function calculateX(formObject, text, font, maxFontSize) {
  4355. var maxFontSize = maxFontSize || 12;
  4356. var font = font || "helvetica";
  4357. var returnValue = {
  4358. text: "",
  4359. fontSize: ""
  4360. }; // Remove Brackets
  4361. text = text.substr(0, 1) == "(" ? text.substr(1) : text;
  4362. text = text.substr(text.length - 1) == ")" ? text.substr(0, text.length - 1) : text; // split into array of words
  4363. var textSplit = text.split(" ");
  4364. var fontSize = maxFontSize; // The Starting fontSize (The Maximum)
  4365. var lineSpacing = 2;
  4366. var borderPadding = 2;
  4367. var height = AcroFormAppearance.internal.getHeight(formObject) || 0;
  4368. height = height < 0 ? -height : height;
  4369. var width = AcroFormAppearance.internal.getWidth(formObject) || 0;
  4370. width = width < 0 ? -width : width;
  4371. var isSmallerThanWidth = function isSmallerThanWidth(i, lastLine, fontSize) {
  4372. if (i + 1 < textSplit.length) {
  4373. var tmp = lastLine + " " + textSplit[i + 1];
  4374. var TextWidth = calculateFontSpace(tmp, fontSize + "px", font).width;
  4375. var FieldWidth = width - 2 * borderPadding;
  4376. return TextWidth <= FieldWidth;
  4377. } else {
  4378. return false;
  4379. }
  4380. };
  4381. fontSize++;
  4382. FontSize: while (true) {
  4383. var text = "";
  4384. fontSize--;
  4385. var textHeight = calculateFontSpace("3", fontSize + "px", font).height;
  4386. var startY = formObject.multiline ? height - fontSize : (height - textHeight) / 2;
  4387. startY += lineSpacing;
  4388. var startX = -borderPadding;
  4389. var lastY = startY;
  4390. var firstWordInLine = 0,
  4391. lastWordInLine = 0;
  4392. var lastLength = 0;
  4393. if (fontSize <= 0) {
  4394. // In case, the Text doesn't fit at all
  4395. fontSize = 12;
  4396. text = "(...) Tj\n";
  4397. text += "% Width of Text: " + calculateFontSpace(text, "1px").width + ", FieldWidth:" + width + "\n";
  4398. break;
  4399. }
  4400. lastLength = calculateFontSpace(textSplit[0] + " ", fontSize + "px", font).width;
  4401. var lastLine = "";
  4402. var lineCount = 0;
  4403. Line: for (var i in textSplit) {
  4404. if (textSplit.hasOwnProperty(i)) {
  4405. lastLine += textSplit[i] + " "; // Remove last blank
  4406. lastLine = lastLine.substr(lastLine.length - 1) == " " ? lastLine.substr(0, lastLine.length - 1) : lastLine;
  4407. var key = parseInt(i);
  4408. lastLength = calculateFontSpace(lastLine + " ", fontSize + "px", font).width;
  4409. var nextLineIsSmaller = isSmallerThanWidth(key, lastLine, fontSize);
  4410. var isLastWord = i >= textSplit.length - 1;
  4411. if (nextLineIsSmaller && !isLastWord) {
  4412. lastLine += " ";
  4413. continue; // Line
  4414. } else if (!nextLineIsSmaller && !isLastWord) {
  4415. if (!formObject.multiline) {
  4416. continue FontSize;
  4417. } else {
  4418. if ((textHeight + lineSpacing) * (lineCount + 2) + lineSpacing > height) {
  4419. // If the Text is higher than the
  4420. // FieldObject
  4421. continue FontSize;
  4422. }
  4423. lastWordInLine = key; // go on
  4424. }
  4425. } else if (isLastWord) {
  4426. lastWordInLine = key;
  4427. } else {
  4428. if (formObject.multiline && (textHeight + lineSpacing) * (lineCount + 2) + lineSpacing > height) {
  4429. // If the Text is higher than the FieldObject
  4430. continue FontSize;
  4431. }
  4432. }
  4433. var line = "";
  4434. for (var x = firstWordInLine; x <= lastWordInLine; x++) {
  4435. line += textSplit[x] + " ";
  4436. } // Remove last blank
  4437. line = line.substr(line.length - 1) == " " ? line.substr(0, line.length - 1) : line; // lastLength -= blankSpace.width;
  4438. lastLength = calculateFontSpace(line, fontSize + "px", font).width; // Calculate startX
  4439. switch (formObject.Q) {
  4440. case 2:
  4441. // Right justified
  4442. startX = width - lastLength - borderPadding;
  4443. break;
  4444. case 1:
  4445. // Q = 1 := Text-Alignment: Center
  4446. startX = (width - lastLength) / 2;
  4447. break;
  4448. case 0:
  4449. default:
  4450. startX = borderPadding;
  4451. break;
  4452. }
  4453. text += startX.toFixed(2) + " " + lastY.toFixed(2) + " Td\n";
  4454. text += "(" + line + ") Tj\n"; // reset X in PDF
  4455. text += -startX.toFixed(2) + " 0 Td\n"; // After a Line, adjust y position
  4456. lastY = -(fontSize + lineSpacing);
  4457. lastLength = 0;
  4458. firstWordInLine = lastWordInLine + 1;
  4459. lineCount++;
  4460. lastLine = "";
  4461. continue Line;
  4462. }
  4463. }
  4464. break;
  4465. }
  4466. returnValue.text = text;
  4467. returnValue.fontSize = fontSize;
  4468. return returnValue;
  4469. };
  4470. /**
  4471. * Small workaround for calculating the TextMetric approximately.
  4472. *
  4473. * @param text
  4474. * @param fontsize
  4475. * @returns {TextMetrics} (Has Height and Width)
  4476. */
  4477. var calculateFontSpace = function calculateFontSpace(text, fontSize, fontType) {
  4478. fontType = fontType || "helvetica";
  4479. var font = scope.internal.getFont(fontType);
  4480. var width = scope.getStringUnitWidth(text, {
  4481. font: font,
  4482. fontSize: parseFloat(fontSize),
  4483. charSpace: 0
  4484. }) * parseFloat(fontSize);
  4485. var height = scope.getStringUnitWidth("3", {
  4486. font: font,
  4487. fontSize: parseFloat(fontSize),
  4488. charSpace: 0
  4489. }) * parseFloat(fontSize) * 1.5;
  4490. var result = {
  4491. height: height,
  4492. width: width
  4493. };
  4494. return result;
  4495. };
  4496. var acroformPluginTemplate = {
  4497. fields: [],
  4498. xForms: [],
  4499. /**
  4500. * acroFormDictionaryRoot contains information about the AcroForm
  4501. * Dictionary 0: The Event-Token, the AcroFormDictionaryCallback has
  4502. * 1: The Object ID of the Root
  4503. */
  4504. acroFormDictionaryRoot: null,
  4505. /**
  4506. * After the PDF gets evaluated, the reference to the root has to be
  4507. * reset, this indicates, whether the root has already been printed
  4508. * out
  4509. */
  4510. printedOut: false,
  4511. internal: null,
  4512. isInitialized: false
  4513. };
  4514. var annotReferenceCallback = function annotReferenceCallback() {
  4515. var fields = scope.internal.acroformPlugin.acroFormDictionaryRoot.Fields;
  4516. for (var i in fields) {
  4517. if (fields.hasOwnProperty(i)) {
  4518. var formObject = fields[i]; // add Annot Reference!
  4519. if (formObject.hasAnnotation) {
  4520. // If theres an Annotation Widget in the Form Object, put the
  4521. // Reference in the /Annot array
  4522. createAnnotationReference.call(scope, formObject);
  4523. }
  4524. }
  4525. }
  4526. };
  4527. var putForm = function putForm(formObject) {
  4528. if (scope.internal.acroformPlugin.printedOut) {
  4529. scope.internal.acroformPlugin.printedOut = false;
  4530. scope.internal.acroformPlugin.acroFormDictionaryRoot = null;
  4531. }
  4532. if (!scope.internal.acroformPlugin.acroFormDictionaryRoot) {
  4533. initializeAcroForm.call(scope);
  4534. }
  4535. scope.internal.acroformPlugin.acroFormDictionaryRoot.Fields.push(formObject);
  4536. };
  4537. /**
  4538. * Create the Reference to the widgetAnnotation, so that it gets referenced
  4539. * in the Annot[] int the+ (Requires the Annotation Plugin)
  4540. */
  4541. var createAnnotationReference = function createAnnotationReference(object) {
  4542. var options = {
  4543. type: "reference",
  4544. object: object
  4545. };
  4546. scope.annotationPlugin.annotations[scope.internal.getPageInfo(object.page).pageNumber].push(options);
  4547. }; // Callbacks
  4548. var putCatalogCallback = function putCatalogCallback() {
  4549. // Put reference to AcroForm to DocumentCatalog
  4550. if (typeof scope.internal.acroformPlugin.acroFormDictionaryRoot != "undefined") {
  4551. // for safety, shouldn't normally be the case
  4552. scope.internal.write("/AcroForm " + scope.internal.acroformPlugin.acroFormDictionaryRoot.objId + " " + 0 + " R");
  4553. } else {
  4554. console.log("Root missing...");
  4555. }
  4556. };
  4557. /**
  4558. * Adds /Acroform X 0 R to Document Catalog, and creates the AcroForm
  4559. * Dictionary
  4560. */
  4561. var AcroFormDictionaryCallback = function AcroFormDictionaryCallback() {
  4562. // Remove event
  4563. scope.internal.events.unsubscribe(scope.internal.acroformPlugin.acroFormDictionaryRoot._eventID);
  4564. delete scope.internal.acroformPlugin.acroFormDictionaryRoot._eventID;
  4565. scope.internal.acroformPlugin.printedOut = true;
  4566. };
  4567. /**
  4568. * Creates the single Fields and writes them into the Document
  4569. *
  4570. * If fieldArray is set, use the fields that are inside it instead of the
  4571. * fields from the AcroRoot (for the FormXObjects...)
  4572. */
  4573. var createFieldCallback = function createFieldCallback(fieldArray) {
  4574. var standardFields = !fieldArray;
  4575. if (!fieldArray) {
  4576. // in case there is no fieldArray specified, we want to print out
  4577. // the Fields of the AcroForm
  4578. // Print out Root
  4579. scope.internal.newObjectDeferredBegin(scope.internal.acroformPlugin.acroFormDictionaryRoot.objId);
  4580. scope.internal.out(scope.internal.acroformPlugin.acroFormDictionaryRoot.getString());
  4581. }
  4582. var fieldArray = fieldArray || scope.internal.acroformPlugin.acroFormDictionaryRoot.Kids;
  4583. for (var i in fieldArray) {
  4584. if (fieldArray.hasOwnProperty(i)) {
  4585. var form = fieldArray[i];
  4586. var oldRect = form.Rect;
  4587. if (form.Rect) {
  4588. form.Rect = calculateCoordinates.call(this, form.Rect);
  4589. } // Start Writing the Object
  4590. scope.internal.newObjectDeferredBegin(form.objId);
  4591. var content = form.objId + " 0 obj\n<<\n";
  4592. if (_typeof(form) === "object" && typeof form.getContent === "function") {
  4593. content += form.getContent();
  4594. }
  4595. form.Rect = oldRect;
  4596. if (form.hasAppearanceStream && !form.appearanceStreamContent) {
  4597. // Calculate Appearance
  4598. var appearance = calculateAppearanceStream.call(this, form);
  4599. content += "/AP << /N " + appearance + " >>\n";
  4600. scope.internal.acroformPlugin.xForms.push(appearance);
  4601. } // Assume AppearanceStreamContent is a Array with N,R,D (at least
  4602. // one of them!)
  4603. if (form.appearanceStreamContent) {
  4604. content += "/AP << "; // Iterate over N,R and D
  4605. for (var k in form.appearanceStreamContent) {
  4606. if (form.appearanceStreamContent.hasOwnProperty(k)) {
  4607. var value = form.appearanceStreamContent[k];
  4608. content += "/" + k + " ";
  4609. content += "<< ";
  4610. if (Object.keys(value).length >= 1 || Array.isArray(value)) {
  4611. // appearanceStream is an Array or Object!
  4612. for (var i in value) {
  4613. if (value.hasOwnProperty(i)) {
  4614. var obj = value[i];
  4615. if (typeof obj === "function") {
  4616. // if Function is referenced, call it in order
  4617. // to get the FormXObject
  4618. obj = obj.call(this, form);
  4619. }
  4620. content += "/" + i + " " + obj + " "; // In case the XForm is already used, e.g. OffState
  4621. // of CheckBoxes, don't add it
  4622. if (!(scope.internal.acroformPlugin.xForms.indexOf(obj) >= 0)) scope.internal.acroformPlugin.xForms.push(obj);
  4623. }
  4624. }
  4625. } else {
  4626. var obj = value;
  4627. if (typeof obj === "function") {
  4628. // if Function is referenced, call it in order to
  4629. // get the FormXObject
  4630. obj = obj.call(this, form);
  4631. }
  4632. content += "/" + i + " " + obj + " \n";
  4633. if (!(scope.internal.acroformPlugin.xForms.indexOf(obj) >= 0)) scope.internal.acroformPlugin.xForms.push(obj);
  4634. }
  4635. content += " >>\n";
  4636. }
  4637. } // appearance stream is a normal Object..
  4638. content += ">>\n";
  4639. }
  4640. content += ">>\nendobj\n";
  4641. scope.internal.out(content);
  4642. }
  4643. }
  4644. if (standardFields) {
  4645. createXFormObjectCallback.call(this, scope.internal.acroformPlugin.xForms);
  4646. }
  4647. };
  4648. var createXFormObjectCallback = function createXFormObjectCallback(fieldArray) {
  4649. for (var i in fieldArray) {
  4650. if (fieldArray.hasOwnProperty(i)) {
  4651. var key = i;
  4652. var form = fieldArray[i]; // Start Writing the Object
  4653. scope.internal.newObjectDeferredBegin(form && form.objId);
  4654. var content = "";
  4655. if (_typeof(form) === "object" && typeof form.getString === "function") {
  4656. content = form.getString();
  4657. }
  4658. scope.internal.out(content);
  4659. delete fieldArray[key];
  4660. }
  4661. }
  4662. };
  4663. var initializeAcroForm = function initializeAcroForm() {
  4664. if (this.internal !== undefined && (this.internal.acroformPlugin === undefined || this.internal.acroformPlugin.isInitialized === false)) {
  4665. scope = this;
  4666. AcroFormField.FieldNum = 0;
  4667. this.internal.acroformPlugin = JSON.parse(JSON.stringify(acroformPluginTemplate));
  4668. if (this.internal.acroformPlugin.acroFormDictionaryRoot) {
  4669. // return;
  4670. throw new Error("Exception while creating AcroformDictionary");
  4671. }
  4672. scaleFactor = scope.internal.scaleFactor;
  4673. pageHeight = scope.internal.pageSize.getHeight(); // The Object Number of the AcroForm Dictionary
  4674. scope.internal.acroformPlugin.acroFormDictionaryRoot = new AcroFormDictionary(); // add Callback for creating the AcroForm Dictionary
  4675. scope.internal.acroformPlugin.acroFormDictionaryRoot._eventID = scope.internal.events.subscribe("postPutResources", AcroFormDictionaryCallback);
  4676. scope.internal.events.subscribe("buildDocument", annotReferenceCallback); // buildDocument
  4677. // Register event, that is triggered when the DocumentCatalog is
  4678. // written, in order to add /AcroForm
  4679. scope.internal.events.subscribe("putCatalog", putCatalogCallback); // Register event, that creates all Fields
  4680. scope.internal.events.subscribe("postPutPages", createFieldCallback);
  4681. scope.internal.acroformPlugin.isInitialized = true;
  4682. }
  4683. };
  4684. var arrayToPdfArray = function arrayToPdfArray(array) {
  4685. if (Array.isArray(array)) {
  4686. var content = " [";
  4687. for (var i in array) {
  4688. if (array.hasOwnProperty(i)) {
  4689. var element = array[i].toString();
  4690. content += element;
  4691. content += i < array.length - 1 ? " " : "";
  4692. }
  4693. }
  4694. content += "]";
  4695. return content;
  4696. }
  4697. };
  4698. var toPdfString = function toPdfString(string) {
  4699. string = string || ""; // put Bracket at the Beginning of the String
  4700. if (string.indexOf("(") !== 0) {
  4701. string = "(" + string;
  4702. }
  4703. if (string.substring(string.length - 1) != ")") {
  4704. string += ")";
  4705. }
  4706. return string;
  4707. }; // ##########################
  4708. // Classes
  4709. // ##########################
  4710. var AcroFormPDFObject = function AcroFormPDFObject() {
  4711. // The Object ID in the PDF Object Model
  4712. // todo
  4713. var _objId;
  4714. Object.defineProperty(this, "objId", {
  4715. get: function get() {
  4716. if (!_objId) {
  4717. _objId = scope.internal.newObjectDeferred();
  4718. }
  4719. if (!_objId) {
  4720. console.log("Couldn't create Object ID");
  4721. }
  4722. return _objId;
  4723. },
  4724. configurable: false
  4725. });
  4726. };
  4727. AcroFormPDFObject.prototype.toString = function () {
  4728. return this.objId + " 0 R";
  4729. };
  4730. AcroFormPDFObject.prototype.getString = function () {
  4731. var res = this.objId + " 0 obj\n<<";
  4732. var content = this.getContent();
  4733. res += content + ">>\n";
  4734. if (this.stream) {
  4735. res += "stream\n";
  4736. res += this.stream;
  4737. res += "\nendstream\n";
  4738. }
  4739. res += "endobj\n";
  4740. return res;
  4741. };
  4742. AcroFormPDFObject.prototype.getContent = function () {
  4743. /**
  4744. * Prints out all enumerable Variables from the Object
  4745. *
  4746. * @param fieldObject
  4747. * @returns {string}
  4748. */
  4749. var createContentFromFieldObject = function createContentFromFieldObject(fieldObject) {
  4750. var content = "";
  4751. var keys = Object.keys(fieldObject).filter(function (key) {
  4752. return key != "content" && key != "appearanceStreamContent" && key.substring(0, 1) != "_";
  4753. });
  4754. for (var i in keys) {
  4755. if (keys.hasOwnProperty(i)) {
  4756. var key = keys[i];
  4757. var value = fieldObject[key];
  4758. /*
  4759. * if (key == 'Rect' && value) { value =
  4760. * AcroForm.internal.calculateCoordinates.call(jsPDF.API.acroformPlugin.internal,
  4761. * value); }
  4762. */
  4763. if (value) {
  4764. if (Array.isArray(value)) {
  4765. content += "/" + key + " " + arrayToPdfArray(value) + "\n";
  4766. } else if (value instanceof AcroFormPDFObject) {
  4767. // In case it is a reference to another PDFObject,
  4768. // take the referennce number
  4769. content += "/" + key + " " + value.objId + " 0 R" + "\n";
  4770. } else {
  4771. content += "/" + key + " " + value + "\n";
  4772. }
  4773. }
  4774. }
  4775. }
  4776. return content;
  4777. };
  4778. var object = "";
  4779. object += createContentFromFieldObject(this);
  4780. return object;
  4781. };
  4782. var AcroFormXObject = function AcroFormXObject() {
  4783. AcroFormPDFObject.call(this);
  4784. this.Type = "/XObject";
  4785. this.Subtype = "/Form";
  4786. this.FormType = 1;
  4787. this.BBox;
  4788. this.Matrix;
  4789. this.Resources = "2 0 R";
  4790. this.PieceInfo;
  4791. var _stream;
  4792. Object.defineProperty(this, "Length", {
  4793. enumerable: true,
  4794. get: function get() {
  4795. return _stream !== undefined ? _stream.length : 0;
  4796. }
  4797. });
  4798. Object.defineProperty(this, "stream", {
  4799. enumerable: false,
  4800. set: function set(val) {
  4801. _stream = val.trim();
  4802. },
  4803. get: function get() {
  4804. if (_stream) {
  4805. return _stream;
  4806. } else {
  4807. return null;
  4808. }
  4809. }
  4810. });
  4811. };
  4812. inherit(AcroFormXObject, AcroFormPDFObject); // ##### The Objects, the User can Create:
  4813. var AcroFormDictionary = function AcroFormDictionary() {
  4814. AcroFormPDFObject.call(this);
  4815. var _Kids = [];
  4816. Object.defineProperty(this, "Kids", {
  4817. enumerable: false,
  4818. configurable: true,
  4819. get: function get() {
  4820. if (_Kids.length > 0) {
  4821. return _Kids;
  4822. } else {
  4823. return;
  4824. }
  4825. }
  4826. });
  4827. Object.defineProperty(this, "Fields", {
  4828. enumerable: true,
  4829. configurable: true,
  4830. get: function get() {
  4831. return _Kids;
  4832. }
  4833. }); // Default Appearance
  4834. this.DA;
  4835. };
  4836. inherit(AcroFormDictionary, AcroFormPDFObject); // The Field Object contains the Variables, that every Field needs
  4837. // Rectangle for Appearance: lower_left_X, lower_left_Y, width, height
  4838. var AcroFormField = function AcroFormField() {
  4839. AcroFormPDFObject.call(this);
  4840. var _Rect = null;
  4841. Object.defineProperty(this, "Rect", {
  4842. enumerable: true,
  4843. configurable: false,
  4844. get: function get() {
  4845. if (!_Rect) {
  4846. return;
  4847. }
  4848. var tmp = _Rect; // var calculatedRes =
  4849. // AcroForm.internal.calculateCoordinates(_Rect); // do
  4850. // later!
  4851. return tmp;
  4852. },
  4853. set: function set(val) {
  4854. _Rect = val;
  4855. }
  4856. });
  4857. var _FT = "";
  4858. Object.defineProperty(this, "FT", {
  4859. enumerable: true,
  4860. set: function set(val) {
  4861. _FT = val;
  4862. },
  4863. get: function get() {
  4864. return _FT;
  4865. }
  4866. });
  4867. var _F = 4;
  4868. Object.defineProperty(this, "F", {
  4869. enumerable: true,
  4870. set: function set(val) {
  4871. _F = val;
  4872. },
  4873. get: function get() {
  4874. return _F;
  4875. }
  4876. });
  4877. /**
  4878. * The Partial name of the Field Object. It has to be unique.
  4879. */
  4880. var _T = null;
  4881. Object.defineProperty(this, "T", {
  4882. enumerable: true,
  4883. configurable: false,
  4884. set: function set(val) {
  4885. _T = val;
  4886. },
  4887. get: function get() {
  4888. if (!_T || _T.length < 1) {
  4889. if (this instanceof AcroFormChildClass) {
  4890. // In case of a Child from a Radio´Group, you don't
  4891. // need a FieldName!!!
  4892. return;
  4893. }
  4894. return "(FieldObject" + AcroFormField.FieldNum++ + ")";
  4895. }
  4896. if (_T.substring(0, 1) == "(" && _T.substring(_T.length - 1)) {
  4897. return _T;
  4898. }
  4899. return "(" + _T + ")";
  4900. }
  4901. });
  4902. var _DA = null; // Defines the default appearance (Needed for variable Text)
  4903. Object.defineProperty(this, "DA", {
  4904. enumerable: true,
  4905. get: function get() {
  4906. if (!_DA) {
  4907. return;
  4908. }
  4909. return "(" + _DA + ")";
  4910. },
  4911. set: function set(val) {
  4912. _DA = val;
  4913. }
  4914. });
  4915. var _DV = null; // Defines the default value
  4916. Object.defineProperty(this, "DV", {
  4917. enumerable: true,
  4918. configurable: true,
  4919. get: function get() {
  4920. if (!_DV) {
  4921. return;
  4922. }
  4923. return _DV;
  4924. },
  4925. set: function set(val) {
  4926. _DV = val;
  4927. }
  4928. });
  4929. var _V = null; // Defines the default value
  4930. Object.defineProperty(this, "V", {
  4931. enumerable: true,
  4932. configurable: true,
  4933. get: function get() {
  4934. if (!_V) {
  4935. return;
  4936. }
  4937. return _V;
  4938. },
  4939. set: function set(val) {
  4940. _V = val;
  4941. }
  4942. }); // this.Type = "/Annot";
  4943. // this.Subtype = "/Widget";
  4944. Object.defineProperty(this, "Type", {
  4945. enumerable: true,
  4946. get: function get() {
  4947. return this.hasAnnotation ? "/Annot" : null;
  4948. }
  4949. });
  4950. Object.defineProperty(this, "Subtype", {
  4951. enumerable: true,
  4952. get: function get() {
  4953. return this.hasAnnotation ? "/Widget" : null;
  4954. }
  4955. });
  4956. /**
  4957. *
  4958. * @type {Array}
  4959. */
  4960. this.BG;
  4961. Object.defineProperty(this, "hasAnnotation", {
  4962. enumerable: false,
  4963. get: function get() {
  4964. if (this.Rect || this.BC || this.BG) {
  4965. return true;
  4966. }
  4967. return false;
  4968. }
  4969. });
  4970. Object.defineProperty(this, "hasAppearanceStream", {
  4971. enumerable: false,
  4972. configurable: true,
  4973. writable: true
  4974. });
  4975. Object.defineProperty(this, "page", {
  4976. enumerable: false,
  4977. configurable: true,
  4978. writable: true
  4979. });
  4980. };
  4981. inherit(AcroFormField, AcroFormPDFObject);
  4982. var AcroFormChoiceField = function AcroFormChoiceField() {
  4983. AcroFormField.call(this); // Field Type = Choice Field
  4984. this.FT = "/Ch"; // options
  4985. this.Opt = [];
  4986. this.V = "()"; // Top Index
  4987. this.TI = 0;
  4988. /**
  4989. * Defines, whether the
  4990. *
  4991. * @type {boolean}
  4992. */
  4993. var _combo = false;
  4994. Object.defineProperty(this, "combo", {
  4995. enumerable: false,
  4996. get: function get() {
  4997. return _combo;
  4998. },
  4999. set: function set(val) {
  5000. _combo = val;
  5001. }
  5002. });
  5003. /**
  5004. * Defines, whether the Choice Field is an Edit Field. An Edit Field
  5005. * is automatically an Combo Field.
  5006. */
  5007. Object.defineProperty(this, "edit", {
  5008. enumerable: true,
  5009. set: function set(val) {
  5010. if (val == true) {
  5011. this._edit = true; // ComboBox has to be true
  5012. this.combo = true;
  5013. } else {
  5014. this._edit = false;
  5015. }
  5016. },
  5017. get: function get() {
  5018. if (!this._edit) {
  5019. return false;
  5020. }
  5021. return this._edit;
  5022. },
  5023. configurable: false
  5024. });
  5025. this.hasAppearanceStream = true;
  5026. };
  5027. inherit(AcroFormChoiceField, AcroFormField);
  5028. var AcroFormListBox = function AcroFormListBox() {
  5029. AcroFormChoiceField.call(this);
  5030. this.combo = false;
  5031. };
  5032. inherit(AcroFormListBox, AcroFormChoiceField);
  5033. var AcroFormComboBox = function AcroFormComboBox() {
  5034. AcroFormListBox.call(this);
  5035. this.combo = true;
  5036. };
  5037. inherit(AcroFormComboBox, AcroFormListBox);
  5038. var AcroFormEditBox = function AcroFormEditBox() {
  5039. AcroFormComboBox.call(this);
  5040. this.edit = true;
  5041. };
  5042. inherit(AcroFormEditBox, AcroFormComboBox);
  5043. var AcroFormButton = function AcroFormButton() {
  5044. AcroFormField.call(this);
  5045. this.FT = "/Btn"; // this.hasAnnotation = true;
  5046. };
  5047. inherit(AcroFormButton, AcroFormField);
  5048. var AcroFormPushButton = function AcroFormPushButton() {
  5049. AcroFormButton.call(this);
  5050. var _pushbutton = true;
  5051. Object.defineProperty(this, "pushbutton", {
  5052. enumerable: false,
  5053. get: function get() {
  5054. return _pushbutton;
  5055. },
  5056. set: function set(val) {
  5057. _pushbutton = val;
  5058. }
  5059. });
  5060. };
  5061. inherit(AcroFormPushButton, AcroFormButton);
  5062. var AcroFormRadioButton = function AcroFormRadioButton() {
  5063. AcroFormButton.call(this);
  5064. var _radio = true;
  5065. Object.defineProperty(this, "radio", {
  5066. enumerable: false,
  5067. get: function get() {
  5068. return _radio;
  5069. },
  5070. set: function set(val) {
  5071. _radio = val;
  5072. }
  5073. });
  5074. var _Kids = [];
  5075. Object.defineProperty(this, "Kids", {
  5076. enumerable: true,
  5077. get: function get() {
  5078. if (_Kids.length > 0) {
  5079. return _Kids;
  5080. }
  5081. }
  5082. });
  5083. Object.defineProperty(this, "__Kids", {
  5084. get: function get() {
  5085. return _Kids;
  5086. }
  5087. });
  5088. var _noToggleToOff;
  5089. Object.defineProperty(this, "noToggleToOff", {
  5090. enumerable: false,
  5091. get: function get() {
  5092. return _noToggleToOff;
  5093. },
  5094. set: function set(val) {
  5095. _noToggleToOff = val;
  5096. }
  5097. }); // this.hasAnnotation = false;
  5098. };
  5099. inherit(AcroFormRadioButton, AcroFormButton);
  5100. /*
  5101. * The Child classs of a RadioButton (the radioGroup) -> The single
  5102. * Buttons
  5103. */
  5104. var AcroFormChildClass = function AcroFormChildClass(parent, name) {
  5105. AcroFormField.call(this);
  5106. this.Parent = parent; // todo: set AppearanceType as variable that can be set from the
  5107. // outside...
  5108. this._AppearanceType = AcroFormAppearance.RadioButton.Circle; // The Default appearanceType is the Circle
  5109. this.appearanceStreamContent = this._AppearanceType.createAppearanceStream(name); // Set Print in the Annot Flag
  5110. this.F = setBitPosition(this.F, 3, 1); // Set AppearanceCharacteristicsDictionary with default appearance
  5111. // if field is not interacting with user
  5112. this.MK = this._AppearanceType.createMK(); // (8) -> Cross, (1)-> Circle, ()-> nothing
  5113. // Default Appearance is Off
  5114. this.AS = "/Off"; // + name;
  5115. this._Name = name;
  5116. };
  5117. inherit(AcroFormChildClass, AcroFormField);
  5118. AcroFormRadioButton.prototype.setAppearance = function (appearance) {
  5119. if (!("createAppearanceStream" in appearance && "createMK" in appearance)) {
  5120. console.log("Couldn't assign Appearance to RadioButton. Appearance was Invalid!");
  5121. return;
  5122. }
  5123. for (var i in this.__Kids) {
  5124. if (this.__Kids.hasOwnProperty(i)) {
  5125. var child = this.__Kids[i];
  5126. child.appearanceStreamContent = appearance.createAppearanceStream(child._Name);
  5127. child.MK = appearance.createMK();
  5128. }
  5129. }
  5130. };
  5131. AcroFormRadioButton.prototype.createOption = function (name) {
  5132. var parent = this;
  5133. var kidCount = this.__Kids.length; // Create new Child for RadioGroup
  5134. var child = new AcroFormChildClass(parent, name); // Add to Parent
  5135. this.__Kids.push(child);
  5136. jsPDFAPI.addField(child);
  5137. return child;
  5138. };
  5139. /**
  5140. * @name AcroFormCheckBox
  5141. *
  5142. * @memberOf AcroForm
  5143. * @function
  5144. */
  5145. var AcroFormCheckBox = function AcroFormCheckBox() {
  5146. AcroFormButton.call(this);
  5147. this.appearanceStreamContent = AcroFormAppearance.CheckBox.createAppearanceStream();
  5148. this.MK = AcroFormAppearance.CheckBox.createMK();
  5149. this.AS = "/On";
  5150. this.V = "/On";
  5151. };
  5152. inherit(AcroFormCheckBox, AcroFormButton);
  5153. var AcroFormTextField = function AcroFormTextField() {
  5154. AcroFormField.call(this);
  5155. this.DA = AcroFormAppearance.createDefaultAppearanceStream();
  5156. this.F = 4;
  5157. var _V;
  5158. Object.defineProperty(this, "V", {
  5159. get: function get() {
  5160. if (_V) {
  5161. return toPdfString(_V);
  5162. } else {
  5163. return _V;
  5164. }
  5165. },
  5166. enumerable: true,
  5167. set: function set(val) {
  5168. _V = val;
  5169. }
  5170. });
  5171. var _DV;
  5172. Object.defineProperty(this, "DV", {
  5173. get: function get() {
  5174. if (_DV) {
  5175. return toPdfString(_DV);
  5176. } else {
  5177. return _DV;
  5178. }
  5179. },
  5180. enumerable: true,
  5181. set: function set(val) {
  5182. _DV = val;
  5183. }
  5184. });
  5185. var _multiline = false;
  5186. Object.defineProperty(this, "multiline", {
  5187. enumerable: false,
  5188. get: function get() {
  5189. return _multiline;
  5190. },
  5191. set: function set(val) {
  5192. _multiline = val;
  5193. }
  5194. });
  5195. /**
  5196. * For PDF 1.4
  5197. *
  5198. * @type {boolean}
  5199. */
  5200. var _fileSelect = false;
  5201. Object.defineProperty(this, "fileSelect", {
  5202. enumerable: false,
  5203. get: function get() {
  5204. return _fileSelect;
  5205. },
  5206. set: function set(val) {
  5207. _fileSelect = val;
  5208. }
  5209. });
  5210. /**
  5211. * For PDF 1.4
  5212. *
  5213. * @type {boolean}
  5214. */
  5215. var _doNotSpellCheck = false;
  5216. Object.defineProperty(this, "doNotSpellCheck", {
  5217. enumerable: false,
  5218. get: function get() {
  5219. return _doNotSpellCheck;
  5220. },
  5221. set: function set(val) {
  5222. _doNotSpellCheck = val;
  5223. }
  5224. });
  5225. /**
  5226. * For PDF 1.4
  5227. *
  5228. * @type {boolean}
  5229. */
  5230. var _doNotScroll = false;
  5231. Object.defineProperty(this, "doNotScroll", {
  5232. enumerable: false,
  5233. get: function get() {
  5234. return _doNotScroll;
  5235. },
  5236. set: function set(val) {
  5237. _doNotScroll = val;
  5238. }
  5239. });
  5240. var _MaxLen = false;
  5241. Object.defineProperty(this, "MaxLen", {
  5242. enumerable: true,
  5243. get: function get() {
  5244. return _MaxLen;
  5245. },
  5246. set: function set(val) {
  5247. _MaxLen = val;
  5248. }
  5249. });
  5250. Object.defineProperty(this, "hasAppearanceStream", {
  5251. enumerable: false,
  5252. get: function get() {
  5253. return this.V || this.DV;
  5254. }
  5255. });
  5256. };
  5257. inherit(AcroFormTextField, AcroFormField);
  5258. var AcroFormPasswordField = function AcroFormPasswordField() {
  5259. AcroFormTextField.call(this);
  5260. var _password = true;
  5261. Object.defineProperty(this, "password", {
  5262. enumerable: false,
  5263. get: function get() {
  5264. return _password;
  5265. },
  5266. set: function set(val) {
  5267. _password = val;
  5268. }
  5269. });
  5270. };
  5271. inherit(AcroFormPasswordField, AcroFormTextField); // Contains Methods for creating standard appearances
  5272. var AcroFormAppearance = {
  5273. CheckBox: {
  5274. createAppearanceStream: function createAppearanceStream() {
  5275. var appearance = {
  5276. N: {
  5277. On: AcroFormAppearance.CheckBox.YesNormal
  5278. },
  5279. D: {
  5280. On: AcroFormAppearance.CheckBox.YesPushDown,
  5281. Off: AcroFormAppearance.CheckBox.OffPushDown
  5282. }
  5283. };
  5284. return appearance;
  5285. },
  5286. /**
  5287. * If any other icons are needed, the number between the
  5288. * brackets can be changed
  5289. *
  5290. * @returns {string}
  5291. */
  5292. createMK: function createMK() {
  5293. return "<< /CA (3)>>";
  5294. },
  5295. /**
  5296. * Returns the standard On Appearance for a CheckBox
  5297. *
  5298. * @returns {AcroFormXObject}
  5299. */
  5300. YesPushDown: function YesPushDown(formObject) {
  5301. var xobj = createFormXObject(formObject);
  5302. var stream = [];
  5303. var zapfDingbatsId = scope.internal.getFont("zapfdingbats", "normal").id;
  5304. formObject.Q = 1; // set text-alignment as centered
  5305. var calcRes = calculateX(formObject, "3", "ZapfDingbats", 50);
  5306. stream.push("0.749023 g");
  5307. stream.push("0 0 " + AcroFormAppearance.internal.getWidth(formObject).toFixed(2) + " " + AcroFormAppearance.internal.getHeight(formObject).toFixed(2) + " re");
  5308. stream.push("f");
  5309. stream.push("BMC");
  5310. stream.push("q");
  5311. stream.push("0 0 1 rg");
  5312. stream.push("/" + zapfDingbatsId + " " + calcRes.fontSize.toFixed(2) + " Tf 0 g");
  5313. stream.push("BT");
  5314. stream.push(calcRes.text);
  5315. stream.push("ET");
  5316. stream.push("Q");
  5317. stream.push("EMC");
  5318. xobj.stream = stream.join("\n");
  5319. return xobj;
  5320. },
  5321. YesNormal: function YesNormal(formObject) {
  5322. var xobj = createFormXObject(formObject);
  5323. var zapfDingbatsId = scope.internal.getFont("zapfdingbats", "normal").id;
  5324. var stream = [];
  5325. formObject.Q = 1; // set text-alignment as centered
  5326. var height = AcroFormAppearance.internal.getHeight(formObject);
  5327. var width = AcroFormAppearance.internal.getWidth(formObject);
  5328. var calcRes = calculateX(formObject, "3", "ZapfDingbats", height * 0.9);
  5329. stream.push("1 g");
  5330. stream.push("0 0 " + width.toFixed(2) + " " + height.toFixed(2) + " re");
  5331. stream.push("f");
  5332. stream.push("q");
  5333. stream.push("0 0 1 rg");
  5334. stream.push("0 0 " + (width - 1).toFixed(2) + " " + (height - 1).toFixed(2) + " re");
  5335. stream.push("W");
  5336. stream.push("n");
  5337. stream.push("0 g");
  5338. stream.push("BT");
  5339. stream.push("/" + zapfDingbatsId + " " + calcRes.fontSize.toFixed(2) + " Tf 0 g");
  5340. stream.push(calcRes.text);
  5341. stream.push("ET");
  5342. stream.push("Q");
  5343. xobj.stream = stream.join("\n");
  5344. return xobj;
  5345. },
  5346. /**
  5347. * Returns the standard Off Appearance for a CheckBox
  5348. *
  5349. * @returns {AcroFormXObject}
  5350. */
  5351. OffPushDown: function OffPushDown(formObject) {
  5352. var xobj = createFormXObject(formObject);
  5353. var stream = [];
  5354. stream.push("0.749023 g");
  5355. stream.push("0 0 " + AcroFormAppearance.internal.getWidth(formObject).toFixed(2) + " " + AcroFormAppearance.internal.getHeight(formObject).toFixed(2) + " re");
  5356. stream.push("f");
  5357. xobj.stream = stream.join("\n");
  5358. return xobj;
  5359. }
  5360. },
  5361. RadioButton: {
  5362. Circle: {
  5363. createAppearanceStream: function createAppearanceStream(name) {
  5364. var appearanceStreamContent = {
  5365. D: {
  5366. Off: AcroFormAppearance.RadioButton.Circle.OffPushDown
  5367. },
  5368. N: {}
  5369. };
  5370. appearanceStreamContent.N[name] = AcroFormAppearance.RadioButton.Circle.YesNormal;
  5371. appearanceStreamContent.D[name] = AcroFormAppearance.RadioButton.Circle.YesPushDown;
  5372. return appearanceStreamContent;
  5373. },
  5374. createMK: function createMK() {
  5375. return "<< /CA (l)>>";
  5376. },
  5377. YesNormal: function YesNormal(formObject) {
  5378. var xobj = createFormXObject(formObject);
  5379. var stream = []; // Make the Radius of the Circle relative to min(height,
  5380. // width) of formObject
  5381. var DotRadius = AcroFormAppearance.internal.getWidth(formObject) <= AcroFormAppearance.internal.getHeight(formObject) ? AcroFormAppearance.internal.getWidth(formObject) / 4 : AcroFormAppearance.internal.getHeight(formObject) / 4; // The Borderpadding...
  5382. DotRadius *= 0.9;
  5383. var c = AcroFormAppearance.internal.Bezier_C;
  5384. /*
  5385. * The Following is a Circle created with Bezier-Curves.
  5386. */
  5387. stream.push("q");
  5388. stream.push("1 0 0 1 " + AcroFormAppearance.internal.getWidth(formObject) / 2 + " " + AcroFormAppearance.internal.getHeight(formObject) / 2 + " cm");
  5389. stream.push(DotRadius + " 0 m");
  5390. stream.push(DotRadius + " " + DotRadius * c + " " + DotRadius * c + " " + DotRadius + " 0 " + DotRadius + " c");
  5391. stream.push("-" + DotRadius * c + " " + DotRadius + " -" + DotRadius + " " + DotRadius * c + " -" + DotRadius + " 0 c");
  5392. stream.push("-" + DotRadius + " -" + DotRadius * c + " -" + DotRadius * c + " -" + DotRadius + " 0 -" + DotRadius + " c");
  5393. stream.push(DotRadius * c + " -" + DotRadius + " " + DotRadius + " -" + DotRadius * c + " " + DotRadius + " 0 c");
  5394. stream.push("f");
  5395. stream.push("Q");
  5396. xobj.stream = stream.join("\n");
  5397. return xobj;
  5398. },
  5399. YesPushDown: function YesPushDown(formObject) {
  5400. var xobj = createFormXObject(formObject);
  5401. var stream = [];
  5402. var DotRadius = AcroFormAppearance.internal.getWidth(formObject) <= AcroFormAppearance.internal.getHeight(formObject) ? AcroFormAppearance.internal.getWidth(formObject) / 4 : AcroFormAppearance.internal.getHeight(formObject) / 4; // The Borderpadding...
  5403. DotRadius *= 0.9; // Save results for later use; no need to waste
  5404. // processor ticks on doing math
  5405. var k = DotRadius * 2; // var c = AcroFormAppearance.internal.Bezier_C;
  5406. var kc = k * AcroFormAppearance.internal.Bezier_C;
  5407. var dc = DotRadius * AcroFormAppearance.internal.Bezier_C;
  5408. stream.push("0.749023 g");
  5409. stream.push("q");
  5410. stream.push("1 0 0 1 " + (AcroFormAppearance.internal.getWidth(formObject) / 2).toFixed(2) + " " + (AcroFormAppearance.internal.getHeight(formObject) / 2).toFixed(2) + " cm");
  5411. stream.push(k + " 0 m");
  5412. stream.push(k + " " + kc + " " + kc + " " + k + " 0 " + k + " c");
  5413. stream.push("-" + kc + " " + k + " -" + k + " " + kc + " -" + k + " 0 c");
  5414. stream.push("-" + k + " -" + kc + " -" + kc + " -" + k + " 0 -" + k + " c");
  5415. stream.push(kc + " -" + k + " " + k + " -" + kc + " " + k + " 0 c");
  5416. stream.push("f");
  5417. stream.push("Q");
  5418. stream.push("0 g");
  5419. stream.push("q");
  5420. stream.push("1 0 0 1 " + (AcroFormAppearance.internal.getWidth(formObject) / 2).toFixed(2) + " " + (AcroFormAppearance.internal.getHeight(formObject) / 2).toFixed(2) + " cm");
  5421. stream.push(DotRadius + " 0 m");
  5422. stream.push("" + DotRadius + " " + dc + " " + dc + " " + DotRadius + " 0 " + DotRadius + " c");
  5423. stream.push("-" + dc + " " + DotRadius + " -" + DotRadius + " " + dc + " -" + DotRadius + " 0 c");
  5424. stream.push("-" + DotRadius + " -" + dc + " -" + dc + " -" + DotRadius + " 0 -" + DotRadius + " c");
  5425. stream.push(dc + " -" + DotRadius + " " + DotRadius + " -" + dc + " " + DotRadius + " 0 c");
  5426. stream.push("f");
  5427. stream.push("Q");
  5428. xobj.stream = stream.join("\n");
  5429. return xobj;
  5430. },
  5431. OffPushDown: function OffPushDown(formObject) {
  5432. var xobj = createFormXObject(formObject);
  5433. var stream = [];
  5434. var DotRadius = AcroFormAppearance.internal.getWidth(formObject) <= AcroFormAppearance.internal.getHeight(formObject) ? AcroFormAppearance.internal.getWidth(formObject) / 4 : AcroFormAppearance.internal.getHeight(formObject) / 4; // The Borderpadding...
  5435. DotRadius *= 0.9; // Save results for later use; no need to waste
  5436. // processor ticks on doing math
  5437. var k = DotRadius * 2; // var c = AcroFormAppearance.internal.Bezier_C;
  5438. var kc = k * AcroFormAppearance.internal.Bezier_C;
  5439. stream.push("0.749023 g");
  5440. stream.push("q");
  5441. stream.push("1 0 0 1 " + (AcroFormAppearance.internal.getWidth(formObject) / 2).toFixed(2) + " " + (AcroFormAppearance.internal.getHeight(formObject) / 2).toFixed(2) + " cm");
  5442. stream.push(k + " 0 m");
  5443. stream.push(k + " " + kc + " " + kc + " " + k + " 0 " + k + " c");
  5444. stream.push("-" + kc + " " + k + " -" + k + " " + kc + " -" + k + " 0 c");
  5445. stream.push("-" + k + " -" + kc + " -" + kc + " -" + k + " 0 -" + k + " c");
  5446. stream.push(kc + " -" + k + " " + k + " -" + kc + " " + k + " 0 c");
  5447. stream.push("f");
  5448. stream.push("Q");
  5449. xobj.stream = stream.join("\n");
  5450. return xobj;
  5451. }
  5452. },
  5453. Cross: {
  5454. /**
  5455. * Creates the Actual AppearanceDictionary-References
  5456. *
  5457. * @param {string} name
  5458. * @returns {Object}
  5459. * @ignore
  5460. */
  5461. createAppearanceStream: function createAppearanceStream(name) {
  5462. var appearanceStreamContent = {
  5463. D: {
  5464. Off: AcroFormAppearance.RadioButton.Cross.OffPushDown
  5465. },
  5466. N: {}
  5467. };
  5468. appearanceStreamContent.N[name] = AcroFormAppearance.RadioButton.Cross.YesNormal;
  5469. appearanceStreamContent.D[name] = AcroFormAppearance.RadioButton.Cross.YesPushDown;
  5470. return appearanceStreamContent;
  5471. },
  5472. createMK: function createMK() {
  5473. return "<< /CA (8)>>";
  5474. },
  5475. YesNormal: function YesNormal(formObject) {
  5476. var xobj = createFormXObject(formObject);
  5477. var stream = [];
  5478. var cross = AcroFormAppearance.internal.calculateCross(formObject);
  5479. stream.push("q");
  5480. stream.push("1 1 " + (AcroFormAppearance.internal.getWidth(formObject) - 2).toFixed(2) + " " + (AcroFormAppearance.internal.getHeight(formObject) - 2).toFixed(2) + " re");
  5481. stream.push("W");
  5482. stream.push("n");
  5483. stream.push(cross.x1.x.toFixed(2) + " " + cross.x1.y.toFixed(2) + " m");
  5484. stream.push(cross.x2.x.toFixed(2) + " " + cross.x2.y.toFixed(2) + " l");
  5485. stream.push(cross.x4.x.toFixed(2) + " " + cross.x4.y.toFixed(2) + " m");
  5486. stream.push(cross.x3.x.toFixed(2) + " " + cross.x3.y.toFixed(2) + " l");
  5487. stream.push("s");
  5488. stream.push("Q");
  5489. xobj.stream = stream.join("\n");
  5490. return xobj;
  5491. },
  5492. YesPushDown: function YesPushDown(formObject) {
  5493. var xobj = createFormXObject(formObject);
  5494. var cross = AcroFormAppearance.internal.calculateCross(formObject);
  5495. var stream = [];
  5496. stream.push("0.749023 g");
  5497. stream.push("0 0 " + AcroFormAppearance.internal.getWidth(formObject).toFixed(2) + " " + AcroFormAppearance.internal.getHeight(formObject).toFixed(2) + " re");
  5498. stream.push("f");
  5499. stream.push("q");
  5500. stream.push("1 1 " + (AcroFormAppearance.internal.getWidth(formObject) - 2).toFixed(2) + " " + (AcroFormAppearance.internal.getHeight(formObject) - 2).toFixed(2) + " re");
  5501. stream.push("W");
  5502. stream.push("n");
  5503. stream.push(cross.x1.x.toFixed(2) + " " + cross.x1.y.toFixed(2) + " m");
  5504. stream.push(cross.x2.x.toFixed(2) + " " + cross.x2.y.toFixed(2) + " l");
  5505. stream.push(cross.x4.x.toFixed(2) + " " + cross.x4.y.toFixed(2) + " m");
  5506. stream.push(cross.x3.x.toFixed(2) + " " + cross.x3.y.toFixed(2) + " l");
  5507. stream.push("s");
  5508. stream.push("Q");
  5509. xobj.stream = stream.join("\n");
  5510. return xobj;
  5511. },
  5512. OffPushDown: function OffPushDown(formObject) {
  5513. var xobj = createFormXObject(formObject);
  5514. var stream = [];
  5515. stream.push("0.749023 g");
  5516. stream.push("0 0 " + AcroFormAppearance.internal.getWidth(formObject).toFixed(2) + " " + AcroFormAppearance.internal.getHeight(formObject).toFixed(2) + " re");
  5517. stream.push("f");
  5518. xobj.stream = stream.join("\n");
  5519. return xobj;
  5520. }
  5521. }
  5522. },
  5523. /**
  5524. * Returns the standard Appearance
  5525. *
  5526. * @returns {AcroFormXObject}
  5527. */
  5528. createDefaultAppearanceStream: function createDefaultAppearanceStream(formObject) {
  5529. // Set Helvetica to Standard Font (size: auto)
  5530. // Color: Black
  5531. return "/F1 0 Tf 0 g";
  5532. }
  5533. };
  5534. AcroFormAppearance.internal = {
  5535. Bezier_C: 0.551915024494,
  5536. calculateCross: function calculateCross(formObject) {
  5537. var min = function min(x, y) {
  5538. return x > y ? y : x;
  5539. };
  5540. var width = AcroFormAppearance.internal.getWidth(formObject);
  5541. var height = AcroFormAppearance.internal.getHeight(formObject);
  5542. var a = min(width, height);
  5543. var cross = {
  5544. x1: {
  5545. // upperLeft
  5546. x: (width - a) / 2,
  5547. y: (height - a) / 2 + a // height - borderPadding
  5548. },
  5549. x2: {
  5550. // lowerRight
  5551. x: (width - a) / 2 + a,
  5552. y: (height - a) / 2 // borderPadding
  5553. },
  5554. x3: {
  5555. // lowerLeft
  5556. x: (width - a) / 2,
  5557. y: (height - a) / 2 // borderPadding
  5558. },
  5559. x4: {
  5560. // upperRight
  5561. x: (width - a) / 2 + a,
  5562. y: (height - a) / 2 + a // height - borderPadding
  5563. }
  5564. };
  5565. return cross;
  5566. }
  5567. };
  5568. AcroFormAppearance.internal.getWidth = function (formObject) {
  5569. var result = 0;
  5570. if (_typeof(formObject) === "object") {
  5571. result = scale(formObject.Rect[2]); // (formObject.Rect[2] -
  5572. // formObject.Rect[0]) || 0;
  5573. }
  5574. return result;
  5575. };
  5576. AcroFormAppearance.internal.getHeight = function (formObject) {
  5577. var result = 0;
  5578. if (_typeof(formObject) === "object") {
  5579. result = scale(formObject.Rect[3]); // (formObject.Rect[1] -
  5580. // formObject.Rect[3]) || 0;
  5581. }
  5582. return result;
  5583. }; // Public:
  5584. /**
  5585. * Add an AcroForm-Field to the {jsPDF}-instance
  5586. *
  5587. * @memberOf AcroForm
  5588. * @name addField
  5589. * @param {Object} fieldObject
  5590. * @returns {jsPDF}
  5591. */
  5592. jsPDFAPI.addField = function (fieldObject) {
  5593. initializeAcroForm.call(this); // var opt = parseOptions(fieldObject);
  5594. if (fieldObject instanceof AcroFormTextField) {
  5595. this.addTextField.call(this, fieldObject);
  5596. } else if (fieldObject instanceof AcroFormChoiceField) {
  5597. this.addChoiceField.call(this, fieldObject);
  5598. } else if (fieldObject instanceof AcroFormButton) {
  5599. this.addButton.call(this, fieldObject);
  5600. } else if (fieldObject instanceof AcroFormChildClass) {
  5601. putForm.call(this, fieldObject);
  5602. } else if (fieldObject) {
  5603. // try to put..
  5604. putForm.call(this, fieldObject);
  5605. }
  5606. fieldObject.page = scope.internal.getCurrentPageInfo().pageNumber;
  5607. return this;
  5608. };
  5609. /**
  5610. * @name addButton
  5611. * @param {AcroFormButton}
  5612. * @memberOf AcroForm
  5613. */
  5614. jsPDFAPI.addButton = function (opts) {
  5615. initializeAcroForm.call(this);
  5616. var options = opts || new AcroFormField();
  5617. options.FT = "/Btn";
  5618. options.Ff = calculateFlagsOnOptions(options.Ff, opts, scope.internal.getPDFVersion());
  5619. putForm.call(this, options);
  5620. };
  5621. jsPDFAPI.addTextField = function (opts) {
  5622. initializeAcroForm.call(this);
  5623. var options = opts || new AcroFormField();
  5624. options.FT = "/Tx";
  5625. options.Ff = calculateFlagsOnOptions(options.Ff, opts, scope.internal.getPDFVersion()); // Add field
  5626. putForm.call(this, options);
  5627. };
  5628. jsPDFAPI.addChoiceField = function (opts) {
  5629. initializeAcroForm.call(this);
  5630. var options = opts || new AcroFormField();
  5631. options.FT = "/Ch";
  5632. options.Ff = calculateFlagsOnOptions(options.Ff, opts, scope.internal.getPDFVersion()); // options.hasAnnotation = true;
  5633. // Add field
  5634. putForm.call(this, options);
  5635. };
  5636. if (_typeof(globalObj) == "object") {
  5637. globalObj["ChoiceField"] = AcroFormChoiceField;
  5638. globalObj["ListBox"] = AcroFormListBox;
  5639. globalObj["ComboBox"] = AcroFormComboBox;
  5640. globalObj["EditBox"] = AcroFormEditBox;
  5641. globalObj["Button"] = AcroFormButton;
  5642. globalObj["PushButton"] = AcroFormPushButton;
  5643. globalObj["RadioButton"] = AcroFormRadioButton;
  5644. globalObj["CheckBox"] = AcroFormCheckBox;
  5645. globalObj["TextField"] = AcroFormTextField;
  5646. globalObj["PasswordField"] = AcroFormPasswordField; // backwardsCompatibility
  5647. globalObj["AcroForm"] = {
  5648. Appearance: AcroFormAppearance
  5649. };
  5650. }
  5651. jsPDFAPI.AcroFormChoiceField = AcroFormChoiceField;
  5652. jsPDFAPI.AcroFormListBox = AcroFormListBox;
  5653. jsPDFAPI.AcroFormComboBox = AcroFormComboBox;
  5654. jsPDFAPI.AcroFormEditBox = AcroFormEditBox;
  5655. jsPDFAPI.AcroFormButton = AcroFormButton;
  5656. jsPDFAPI.AcroFormPushButton = AcroFormPushButton;
  5657. jsPDFAPI.AcroFormRadioButton = AcroFormRadioButton;
  5658. jsPDFAPI.AcroFormCheckBox = AcroFormCheckBox;
  5659. jsPDFAPI.AcroFormTextField = AcroFormTextField;
  5660. jsPDFAPI.AcroFormPasswordField = AcroFormPasswordField;
  5661. jsPDFAPI.AcroFormAppearance = AcroFormAppearance;
  5662. jsPDFAPI.AcroForm = {
  5663. ChoiceField: AcroFormChoiceField,
  5664. ListBox: AcroFormListBox,
  5665. ComboBox: AcroFormComboBox,
  5666. EditBox: AcroFormEditBox,
  5667. Button: AcroFormButton,
  5668. PushButton: AcroFormPushButton,
  5669. RadioButton: AcroFormRadioButton,
  5670. CheckBox: AcroFormCheckBox,
  5671. TextField: AcroFormTextField,
  5672. PasswordField: AcroFormPasswordField,
  5673. Appearance: AcroFormAppearance
  5674. };
  5675. })(jsPDF.API, typeof window !== "undefined" && window || typeof global !== "undefined" && global);
  5676. /** @license
  5677. * jsPDF addImage plugin
  5678. * Copyright (c) 2012 Jason Siefken, https://github.com/siefkenj/
  5679. * 2013 Chris Dowling, https://github.com/gingerchris
  5680. * 2013 Trinh Ho, https://github.com/ineedfat
  5681. * 2013 Edwin Alejandro Perez, https://github.com/eaparango
  5682. * 2013 Norah Smith, https://github.com/burnburnrocket
  5683. * 2014 Diego Casorran, https://github.com/diegocr
  5684. * 2014 James Robb, https://github.com/jamesbrobb
  5685. *
  5686. *
  5687. */
  5688. /**
  5689. * @name addImage
  5690. * @module
  5691. */
  5692. (function (jsPDFAPI) {
  5693. var namespace = "addImage_";
  5694. var imageFileTypeHeaders = {
  5695. PNG: [[0x89, 0x50, 0x4e, 0x47]],
  5696. TIFF: [[0x4d, 0x4d, 0x00, 0x2a], //Motorola
  5697. [0x49, 0x49, 0x2a, 0x00] //Intel
  5698. ],
  5699. JPEG: [[0xff, 0xd8, 0xff, 0xe0, undefined, undefined, 0x4a, 0x46, 0x49, 0x46, 0x00], //JFIF
  5700. [0xff, 0xd8, 0xff, 0xe1, undefined, undefined, 0x45, 0x78, 0x69, 0x66, 0x00, 0x00] //Exif
  5701. ],
  5702. JPEG2000: [[0x00, 0x00, 0x00, 0x0c, 0x6a, 0x50, 0x20, 0x20]],
  5703. GIF87a: [[0x47, 0x49, 0x46, 0x38, 0x37, 0x61]],
  5704. GIF89a: [[0x47, 0x49, 0x46, 0x38, 0x39, 0x61]],
  5705. BMP: [[0x42, 0x4d], //BM - Windows 3.1x, 95, NT, ... etc.
  5706. [0x42, 0x41], //BA - OS/2 struct bitmap array
  5707. [0x43, 0x49], //CI - OS/2 struct color icon
  5708. [0x43, 0x50], //CP - OS/2 const color pointer
  5709. [0x49, 0x43], //IC - OS/2 struct icon
  5710. [0x50, 0x54] //PT - OS/2 pointer
  5711. ]
  5712. };
  5713. /**
  5714. * Recognize filetype of Image by magic-bytes
  5715. *
  5716. * https://en.wikipedia.org/wiki/List_of_file_signatures
  5717. *
  5718. * @name getImageFileTypeByImageData
  5719. * @public
  5720. * @function
  5721. * @param {string|arraybuffer} imageData imageData as base64 encoded DataUrl or arraybuffer
  5722. * @param {string} format format of file if filetype-recognition fails, e.g. 'JPEG'
  5723. *
  5724. * @returns {string} filetype of Image
  5725. */
  5726. jsPDFAPI.getImageFileTypeByImageData = function (imageData, fallbackFormat) {
  5727. fallbackFormat = fallbackFormat || "UNKNOWN";
  5728. var i;
  5729. var j;
  5730. var result = "UNKNOWN";
  5731. var headerSchemata;
  5732. var compareResult;
  5733. var fileType;
  5734. if (jsPDFAPI.isArrayBufferView(imageData)) {
  5735. imageData = jsPDFAPI.arrayBufferToBinaryString(imageData);
  5736. }
  5737. for (fileType in imageFileTypeHeaders) {
  5738. headerSchemata = imageFileTypeHeaders[fileType];
  5739. for (i = 0; i < headerSchemata.length; i += 1) {
  5740. compareResult = true;
  5741. for (j = 0; j < headerSchemata[i].length; j += 1) {
  5742. if (headerSchemata[i][j] === undefined) {
  5743. continue;
  5744. }
  5745. if (headerSchemata[i][j] !== imageData.charCodeAt(j)) {
  5746. compareResult = false;
  5747. break;
  5748. }
  5749. }
  5750. if (compareResult === true) {
  5751. result = fileType;
  5752. break;
  5753. }
  5754. }
  5755. }
  5756. if (result === "UNKNOWN" && fallbackFormat !== "UNKNOWN") {
  5757. console.warn('FileType of Image not recognized. Processing image as "' + fallbackFormat + '".');
  5758. result = fallbackFormat;
  5759. }
  5760. return result;
  5761. }; // Image functionality ported from pdf.js
  5762. var putImage = function putImage(img) {
  5763. var objectNumber = this.internal.newObject(),
  5764. out = this.internal.write,
  5765. putStream = this.internal.putStream;
  5766. img["n"] = objectNumber;
  5767. out("<</Type /XObject");
  5768. out("/Subtype /Image");
  5769. out("/Width " + img["w"]);
  5770. out("/Height " + img["h"]);
  5771. if (img["cs"] === this.color_spaces.INDEXED) {
  5772. out("/ColorSpace [/Indexed /DeviceRGB " + ( // if an indexed png defines more than one colour with transparency, we've created a smask
  5773. img["pal"].length / 3 - 1) + " " + ("smask" in img ? objectNumber + 2 : objectNumber + 1) + " 0 R]");
  5774. } else {
  5775. out("/ColorSpace /" + img["cs"]);
  5776. if (img["cs"] === this.color_spaces.DEVICE_CMYK) {
  5777. out("/Decode [1 0 1 0 1 0 1 0]");
  5778. }
  5779. }
  5780. out("/BitsPerComponent " + img["bpc"]);
  5781. if ("f" in img) {
  5782. out("/Filter /" + img["f"]);
  5783. }
  5784. if ("dp" in img) {
  5785. out("/DecodeParms <<" + img["dp"] + ">>");
  5786. }
  5787. if ("trns" in img && img["trns"].constructor == Array) {
  5788. var trns = "",
  5789. i = 0,
  5790. len = img["trns"].length;
  5791. for (; i < len; i++) {
  5792. trns += img["trns"][i] + " " + img["trns"][i] + " ";
  5793. }
  5794. out("/Mask [" + trns + "]");
  5795. }
  5796. if ("smask" in img) {
  5797. out("/SMask " + (objectNumber + 1) + " 0 R");
  5798. }
  5799. out("/Length " + img["data"].length + ">>");
  5800. putStream(img["data"]);
  5801. out("endobj"); // Soft mask
  5802. if ("smask" in img) {
  5803. var dp = "/Predictor " + img["p"] + " /Colors 1 /BitsPerComponent " + img["bpc"] + " /Columns " + img["w"];
  5804. var smask = {
  5805. w: img["w"],
  5806. h: img["h"],
  5807. cs: "DeviceGray",
  5808. bpc: img["bpc"],
  5809. dp: dp,
  5810. data: img["smask"]
  5811. };
  5812. if ("f" in img) smask.f = img["f"];
  5813. putImage.call(this, smask);
  5814. } //Palette
  5815. if (img["cs"] === this.color_spaces.INDEXED) {
  5816. this.internal.newObject(); //out('<< /Filter / ' + img['f'] +' /Length ' + img['pal'].length + '>>');
  5817. //putStream(zlib.compress(img['pal']));
  5818. out("<< /Length " + img["pal"].length + ">>");
  5819. putStream(this.arrayBufferToBinaryString(new Uint8Array(img["pal"])));
  5820. out("endobj");
  5821. }
  5822. },
  5823. putResourcesCallback = function putResourcesCallback() {
  5824. var images = this.internal.collections[namespace + "images"];
  5825. for (var i in images) {
  5826. putImage.call(this, images[i]);
  5827. }
  5828. },
  5829. putXObjectsDictCallback = function putXObjectsDictCallback() {
  5830. var images = this.internal.collections[namespace + "images"],
  5831. out = this.internal.write,
  5832. image;
  5833. for (var i in images) {
  5834. image = images[i];
  5835. out("/I" + image["i"], image["n"], "0", "R");
  5836. }
  5837. },
  5838. checkCompressValue = function checkCompressValue(value) {
  5839. if (value && typeof value === "string") value = value.toUpperCase();
  5840. return value in jsPDFAPI.image_compression ? value : jsPDFAPI.image_compression.NONE;
  5841. },
  5842. getImages = function getImages() {
  5843. var images = this.internal.collections[namespace + "images"]; //first run, so initialise stuff
  5844. if (!images) {
  5845. this.internal.collections[namespace + "images"] = images = {};
  5846. this.internal.events.subscribe("putResources", putResourcesCallback);
  5847. this.internal.events.subscribe("putXobjectDict", putXObjectsDictCallback);
  5848. }
  5849. return images;
  5850. },
  5851. getImageIndex = function getImageIndex(images) {
  5852. var imageIndex = 0;
  5853. if (images) {
  5854. // this is NOT the first time this method is ran on this instance of jsPDF object.
  5855. imageIndex = Object.keys ? Object.keys(images).length : function (o) {
  5856. var i = 0;
  5857. for (var e in o) {
  5858. if (o.hasOwnProperty(e)) {
  5859. i++;
  5860. }
  5861. }
  5862. return i;
  5863. }(images);
  5864. }
  5865. return imageIndex;
  5866. },
  5867. notDefined = function notDefined(value) {
  5868. return typeof value === "undefined" || value === null || value.length === 0;
  5869. },
  5870. generateAliasFromData = function generateAliasFromData(data) {
  5871. return typeof data === "string" && jsPDFAPI.sHashCode(data);
  5872. },
  5873. isImageTypeSupported = function isImageTypeSupported(type) {
  5874. return typeof jsPDFAPI["process" + type.toUpperCase()] === "function";
  5875. },
  5876. isDOMElement = function isDOMElement(object) {
  5877. return _typeof(object) === "object" && object.nodeType === 1;
  5878. },
  5879. createDataURIFromElement = function createDataURIFromElement(element, format) {
  5880. //if element is an image which uses data url definition, just return the dataurl
  5881. if (element.nodeName === "IMG" && element.hasAttribute("src")) {
  5882. var src = "" + element.getAttribute("src");
  5883. if (src.indexOf("data:image/") === 0) return unescape(src); // only if the user doesn't care about a format
  5884. if (!format && /\.png(?:[?#].*)?$/i.test(src)) format = "png";
  5885. }
  5886. if (element.nodeName === "CANVAS") {
  5887. var canvas = element;
  5888. } else {
  5889. var canvas = document.createElement("canvas");
  5890. canvas.width = element.clientWidth || element.width;
  5891. canvas.height = element.clientHeight || element.height;
  5892. var ctx = canvas.getContext("2d");
  5893. if (!ctx) {
  5894. throw "addImage requires canvas to be supported by browser.";
  5895. }
  5896. ctx.drawImage(element, 0, 0, canvas.width, canvas.height);
  5897. }
  5898. return canvas.toDataURL(("" + format).toLowerCase() == "png" ? "image/png" : "image/jpeg");
  5899. },
  5900. checkImagesForAlias = function checkImagesForAlias(alias, images) {
  5901. var cached_info;
  5902. if (images) {
  5903. for (var e in images) {
  5904. if (alias === images[e].alias) {
  5905. cached_info = images[e];
  5906. break;
  5907. }
  5908. }
  5909. }
  5910. return cached_info;
  5911. },
  5912. determineWidthAndHeight = function determineWidthAndHeight(w, h, info) {
  5913. if (!w && !h) {
  5914. w = -96;
  5915. h = -96;
  5916. }
  5917. if (w < 0) {
  5918. w = -1 * info["w"] * 72 / w / this.internal.scaleFactor;
  5919. }
  5920. if (h < 0) {
  5921. h = -1 * info["h"] * 72 / h / this.internal.scaleFactor;
  5922. }
  5923. if (w === 0) {
  5924. w = h * info["w"] / info["h"];
  5925. }
  5926. if (h === 0) {
  5927. h = w * info["h"] / info["w"];
  5928. }
  5929. return [w, h];
  5930. },
  5931. writeImageToPDF = function writeImageToPDF(x, y, w, h, info, index, images, rotation) {
  5932. var dims = determineWidthAndHeight.call(this, w, h, info),
  5933. coord = this.internal.getCoordinateString,
  5934. vcoord = this.internal.getVerticalCoordinateString;
  5935. w = dims[0];
  5936. h = dims[1];
  5937. images[index] = info;
  5938. if (rotation) {
  5939. rotation *= Math.PI / 180;
  5940. var c = Math.cos(rotation);
  5941. var s = Math.sin(rotation); //like in pdf Reference do it 4 digits instead of 2
  5942. var f4 = function f4(number) {
  5943. return number.toFixed(4);
  5944. };
  5945. var rotationTransformationMatrix = [f4(c), f4(s), f4(s * -1), f4(c), 0, 0, "cm"];
  5946. }
  5947. this.internal.write("q"); //Save graphics state
  5948. if (rotation) {
  5949. this.internal.write([1, "0", "0", 1, coord(x), vcoord(y + h), "cm"].join(" ")); //Translate
  5950. this.internal.write(rotationTransformationMatrix.join(" ")); //Rotate
  5951. this.internal.write([coord(w), "0", "0", coord(h), "0", "0", "cm"].join(" ")); //Scale
  5952. } else {
  5953. this.internal.write([coord(w), "0", "0", coord(h), coord(x), vcoord(y + h), "cm"].join(" ")); //Translate and Scale
  5954. }
  5955. if (this.isAdvancedAPI()) {
  5956. // draw image bottom up when in "advanced" API mode
  5957. this.internal.write([1, 0, 0, -1, 0, 0, "cm"].join(" "));
  5958. }
  5959. this.internal.write("/I" + info["i"] + " Do"); //Paint Image
  5960. this.internal.write("Q"); //Restore graphics state
  5961. };
  5962. /**
  5963. * COLOR SPACES
  5964. */
  5965. jsPDFAPI.color_spaces = {
  5966. DEVICE_RGB: "DeviceRGB",
  5967. DEVICE_GRAY: "DeviceGray",
  5968. DEVICE_CMYK: "DeviceCMYK",
  5969. CAL_GREY: "CalGray",
  5970. CAL_RGB: "CalRGB",
  5971. LAB: "Lab",
  5972. ICC_BASED: "ICCBased",
  5973. INDEXED: "Indexed",
  5974. PATTERN: "Pattern",
  5975. SEPARATION: "Separation",
  5976. DEVICE_N: "DeviceN"
  5977. };
  5978. /**
  5979. * DECODE METHODS
  5980. */
  5981. jsPDFAPI.decode = {
  5982. DCT_DECODE: "DCTDecode",
  5983. FLATE_DECODE: "FlateDecode",
  5984. LZW_DECODE: "LZWDecode",
  5985. JPX_DECODE: "JPXDecode",
  5986. JBIG2_DECODE: "JBIG2Decode",
  5987. ASCII85_DECODE: "ASCII85Decode",
  5988. ASCII_HEX_DECODE: "ASCIIHexDecode",
  5989. RUN_LENGTH_DECODE: "RunLengthDecode",
  5990. CCITT_FAX_DECODE: "CCITTFaxDecode"
  5991. };
  5992. /**
  5993. * IMAGE COMPRESSION TYPES
  5994. */
  5995. jsPDFAPI.image_compression = {
  5996. NONE: "NONE",
  5997. FAST: "FAST",
  5998. MEDIUM: "MEDIUM",
  5999. SLOW: "SLOW"
  6000. };
  6001. /**
  6002. * @name sHashCode
  6003. * @function
  6004. * @param {string} str
  6005. * @returns {string}
  6006. */
  6007. jsPDFAPI.sHashCode = function (str) {
  6008. str = str || "";
  6009. return Array.prototype.reduce && str.split("").reduce(function (a, b) {
  6010. a = (a << 5) - a + b.charCodeAt(0);
  6011. return a & a;
  6012. }, 0);
  6013. };
  6014. /**
  6015. * @name isString
  6016. * @function
  6017. * @param {any} object
  6018. * @returns {boolean}
  6019. */
  6020. jsPDFAPI.isString = function (object) {
  6021. return typeof object === "string";
  6022. };
  6023. /**
  6024. * Validates if given String is a valid Base64-String
  6025. *
  6026. * @name validateStringAsBase64
  6027. * @public
  6028. * @function
  6029. * @param {String} possible Base64-String
  6030. *
  6031. * @returns {boolean}
  6032. */
  6033. jsPDFAPI.validateStringAsBase64 = function (possibleBase64String) {
  6034. possibleBase64String = possibleBase64String || "";
  6035. var result = true;
  6036. if (possibleBase64String.length % 4 !== 0) {
  6037. result = false;
  6038. }
  6039. if (/[A-Za-z0-9\/]+/.test(possibleBase64String.substr(0, possibleBase64String.length - 2)) === false) {
  6040. result = false;
  6041. }
  6042. if (/[A-Za-z0-9\/][A-Za-z0-9+\/]|[A-Za-z0-9+\/]=|==/.test(possibleBase64String.substr(-2)) === false) {
  6043. result = false;
  6044. }
  6045. return result;
  6046. };
  6047. /**
  6048. * Strips out and returns info from a valid base64 data URI
  6049. *
  6050. * @name extractInfoFromBase64DataURI
  6051. * @function
  6052. * @param {string} dataUrl a valid data URI of format 'data:[<MIME-type>][;base64],<data>'
  6053. * @returns {Array}an Array containing the following
  6054. * [0] the complete data URI
  6055. * [1] <MIME-type>
  6056. * [2] format - the second part of the mime-type i.e 'png' in 'image/png'
  6057. * [4] <data>
  6058. */
  6059. jsPDFAPI.extractInfoFromBase64DataURI = function (dataURI) {
  6060. return /^data:([\w]+?\/([\w]+?));\S*;*base64,(.+)$/g.exec(dataURI);
  6061. };
  6062. /**
  6063. * Check to see if ArrayBuffer is supported
  6064. *
  6065. * @name supportsArrayBuffer
  6066. * @function
  6067. * @returns {boolean}
  6068. */
  6069. jsPDFAPI.supportsArrayBuffer = function () {
  6070. return typeof ArrayBuffer !== "undefined" && typeof Uint8Array !== "undefined";
  6071. };
  6072. /**
  6073. * Tests supplied object to determine if ArrayBuffer
  6074. *
  6075. * @name isArrayBuffer
  6076. * @function
  6077. * @param {Object} object an Object
  6078. *
  6079. * @returns {boolean}
  6080. */
  6081. jsPDFAPI.isArrayBuffer = function (object) {
  6082. if (!this.supportsArrayBuffer()) return false;
  6083. return object instanceof ArrayBuffer;
  6084. };
  6085. /**
  6086. * Tests supplied object to determine if it implements the ArrayBufferView (TypedArray) interface
  6087. *
  6088. * @name isArrayBufferView
  6089. * @function
  6090. * @param {Object} object an Object
  6091. * @returns {boolean}
  6092. */
  6093. jsPDFAPI.isArrayBufferView = function (object) {
  6094. if (!this.supportsArrayBuffer()) return false;
  6095. if (typeof Uint32Array === "undefined") return false;
  6096. return object instanceof Int8Array || object instanceof Uint8Array || typeof Uint8ClampedArray !== "undefined" && object instanceof Uint8ClampedArray || object instanceof Int16Array || object instanceof Uint16Array || object instanceof Int32Array || object instanceof Uint32Array || object instanceof Float32Array || object instanceof Float64Array;
  6097. };
  6098. /**
  6099. * Convert the Buffer to a Binary String
  6100. *
  6101. * @name binaryStringToUint8Array
  6102. * @public
  6103. * @function
  6104. * @param {ArrayBuffer} BinaryString with ImageData
  6105. *
  6106. * @returns {Uint8Array}
  6107. */
  6108. jsPDFAPI.binaryStringToUint8Array = function (binary_string) {
  6109. /*
  6110. * not sure how efficient this will be will bigger files. Is there a native method?
  6111. */
  6112. var len = binary_string.length;
  6113. var bytes = new Uint8Array(len);
  6114. for (var i = 0; i < len; i++) {
  6115. bytes[i] = binary_string.charCodeAt(i);
  6116. }
  6117. return bytes;
  6118. };
  6119. /**
  6120. * Convert the Buffer to a Binary String
  6121. *
  6122. * @name arrayBufferToBinaryString
  6123. * @public
  6124. * @function
  6125. * @param {ArrayBuffer} ArrayBuffer with ImageData
  6126. *
  6127. * @returns {String}
  6128. */
  6129. jsPDFAPI.arrayBufferToBinaryString = function (buffer) {
  6130. if (typeof atob === "function") {
  6131. return atob(this.arrayBufferToBase64(buffer));
  6132. }
  6133. if (typeof TextDecoder === "function") {
  6134. var decoder = new TextDecoder("ascii"); // test if the encoding is supported
  6135. if (decoder.encoding === "ascii") {
  6136. return decoder.decode(buffer);
  6137. }
  6138. } //Fallback-solution
  6139. var data = this.isArrayBuffer(buffer) ? buffer : new Uint8Array(buffer);
  6140. var chunkSizeForSlice = 0x5000;
  6141. var binary_string = "";
  6142. var slicesCount = Math.ceil(data.byteLength / chunkSizeForSlice);
  6143. for (var i = 0; i < slicesCount; i++) {
  6144. binary_string += String.fromCharCode.apply(null, data.slice(i * chunkSizeForSlice, i * chunkSizeForSlice + chunkSizeForSlice));
  6145. }
  6146. return binary_string;
  6147. };
  6148. /**
  6149. * Converts an ArrayBuffer directly to base64
  6150. *
  6151. * Taken from http://jsperf.com/encoding-xhr-image-data/31
  6152. *
  6153. * Need to test if this is a better solution for larger files
  6154. *
  6155. * @name arrayBufferToBase64
  6156. * @param {arraybuffer} arrayBuffer
  6157. * @public
  6158. * @function
  6159. *
  6160. * @returns {string}
  6161. */
  6162. jsPDFAPI.arrayBufferToBase64 = function (arrayBuffer) {
  6163. var base64 = "";
  6164. var encodings = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  6165. var bytes = new Uint8Array(arrayBuffer);
  6166. var byteLength = bytes.byteLength;
  6167. var byteRemainder = byteLength % 3;
  6168. var mainLength = byteLength - byteRemainder;
  6169. var a, b, c, d;
  6170. var chunk; // Main loop deals with bytes in chunks of 3
  6171. for (var i = 0; i < mainLength; i = i + 3) {
  6172. // Combine the three bytes into a single integer
  6173. chunk = bytes[i] << 16 | bytes[i + 1] << 8 | bytes[i + 2]; // Use bitmasks to extract 6-bit segments from the triplet
  6174. a = (chunk & 16515072) >> 18; // 16515072 = (2^6 - 1) << 18
  6175. b = (chunk & 258048) >> 12; // 258048 = (2^6 - 1) << 12
  6176. c = (chunk & 4032) >> 6; // 4032 = (2^6 - 1) << 6
  6177. d = chunk & 63; // 63 = 2^6 - 1
  6178. // Convert the raw binary segments to the appropriate ASCII encoding
  6179. base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d];
  6180. } // Deal with the remaining bytes and padding
  6181. if (byteRemainder == 1) {
  6182. chunk = bytes[mainLength];
  6183. a = (chunk & 252) >> 2; // 252 = (2^6 - 1) << 2
  6184. // Set the 4 least significant bits to zero
  6185. b = (chunk & 3) << 4; // 3 = 2^2 - 1
  6186. base64 += encodings[a] + encodings[b] + "==";
  6187. } else if (byteRemainder == 2) {
  6188. chunk = bytes[mainLength] << 8 | bytes[mainLength + 1];
  6189. a = (chunk & 64512) >> 10; // 64512 = (2^6 - 1) << 10
  6190. b = (chunk & 1008) >> 4; // 1008 = (2^6 - 1) << 4
  6191. // Set the 2 least significant bits to zero
  6192. c = (chunk & 15) << 2; // 15 = 2^4 - 1
  6193. base64 += encodings[a] + encodings[b] + encodings[c] + "=";
  6194. }
  6195. return base64;
  6196. };
  6197. /**
  6198. *
  6199. * @name createImageInfo
  6200. * @param {Object} data
  6201. * @param {number} wd width
  6202. * @param {number} ht height
  6203. * @param {Object} cs colorSpace
  6204. * @param {number} bpc bits per channel
  6205. * @param {any} f
  6206. * @param {number} imageIndex
  6207. * @param {string} alias
  6208. * @param {any} dp
  6209. * @param {any} trns
  6210. * @param {any} pal
  6211. * @param {any} smask
  6212. * @param {any} p
  6213. * @public
  6214. * @function
  6215. *
  6216. * @returns {Object}
  6217. */
  6218. jsPDFAPI.createImageInfo = function (data, wd, ht, cs, bpc, f, imageIndex, alias, dp, trns, pal, smask, p) {
  6219. var info = {
  6220. alias: alias,
  6221. w: wd,
  6222. h: ht,
  6223. cs: cs,
  6224. bpc: bpc,
  6225. i: imageIndex,
  6226. data: data // n: objectNumber will be added by putImage code
  6227. };
  6228. if (f) info.f = f;
  6229. if (dp) info.dp = dp;
  6230. if (trns) info.trns = trns;
  6231. if (pal) info.pal = pal;
  6232. if (smask) info.smask = smask;
  6233. if (p) info.p = p; // predictor parameter for PNG compression
  6234. return info;
  6235. };
  6236. /**
  6237. * Adds an Image to the PDF.
  6238. *
  6239. * @name addImage
  6240. * @public
  6241. * @function
  6242. * @param {string/Image-Element/Canvas-Element/Uint8Array} imageData imageData as base64 encoded DataUrl or Image-HTMLElement or Canvas-HTMLElement
  6243. * @param {string} format format of file if filetype-recognition fails, e.g. 'JPEG'
  6244. * @param {number} x x Coordinate (in units declared at inception of PDF document) against left edge of the page
  6245. * @param {number} y y Coordinate (in units declared at inception of PDF document) against upper edge of the page
  6246. * @param {number} width width of the image (in units declared at inception of PDF document)
  6247. * @param {number} height height of the Image (in units declared at inception of PDF document)
  6248. * @param {string} alias alias of the image (if used multiple times)
  6249. * @param {string} compression compression of the generated JPEG, can have the values 'NONE', 'FAST', 'MEDIUM' and 'SLOW'
  6250. * @param {number} rotation rotation of the image in degrees (0-359)
  6251. *
  6252. * @returns jsPDF
  6253. */
  6254. jsPDFAPI.addImage = function (imageData, format, x, y, w, h, alias, compression, rotation) {
  6255. var tmpImageData = "";
  6256. if (typeof format !== "string") {
  6257. var tmp = h;
  6258. h = w;
  6259. w = y;
  6260. y = x;
  6261. x = format;
  6262. format = tmp;
  6263. }
  6264. if (_typeof(imageData) === "object" && !isDOMElement(imageData) && "imageData" in imageData) {
  6265. var options = imageData;
  6266. imageData = options.imageData;
  6267. format = options.format || format;
  6268. x = options.x || x || 0;
  6269. y = options.y || y || 0;
  6270. w = options.w || w;
  6271. h = options.h || h;
  6272. alias = options.alias || alias;
  6273. compression = options.compression || compression;
  6274. rotation = options.rotation || options.angle || rotation;
  6275. }
  6276. if (typeof imageData === "string") {
  6277. imageData = unescape(imageData);
  6278. }
  6279. if (isNaN(x) || isNaN(y)) {
  6280. console.error("jsPDF.addImage: Invalid coordinates", arguments);
  6281. throw new Error("Invalid coordinates passed to jsPDF.addImage");
  6282. }
  6283. var images = getImages.call(this),
  6284. info;
  6285. if (!(info = checkImagesForAlias(imageData, images))) {
  6286. var dataAsBinaryString;
  6287. if (isDOMElement(imageData)) imageData = createDataURIFromElement(imageData, format);
  6288. if (notDefined(alias)) alias = generateAliasFromData(imageData);
  6289. if (!(info = checkImagesForAlias(alias, images))) {
  6290. if (this.isString(imageData)) {
  6291. tmpImageData = this.convertStringToImageData(imageData);
  6292. if (tmpImageData !== "") {
  6293. imageData = tmpImageData;
  6294. } else {
  6295. tmpImageData = this.loadImageFile(imageData);
  6296. if (tmpImageData !== undefined) {
  6297. imageData = tmpImageData;
  6298. }
  6299. }
  6300. }
  6301. format = this.getImageFileTypeByImageData(imageData, format);
  6302. if (!isImageTypeSupported(format)) throw new Error("addImage does not support files of type '" + format + "', please ensure that a plugin for '" + format + "' support is added.");
  6303. /**
  6304. * need to test if it's more efficient to convert all binary strings
  6305. * to TypedArray - or should we just leave and process as string?
  6306. */
  6307. if (this.supportsArrayBuffer()) {
  6308. // no need to convert if imageData is already uint8array
  6309. if (!(imageData instanceof Uint8Array)) {
  6310. dataAsBinaryString = imageData;
  6311. imageData = this.binaryStringToUint8Array(imageData);
  6312. }
  6313. }
  6314. info = this["process" + format.toUpperCase()](imageData, getImageIndex(images), alias, checkCompressValue(compression), dataAsBinaryString);
  6315. if (!info) throw new Error("An unkwown error occurred whilst processing the image");
  6316. }
  6317. }
  6318. writeImageToPDF.call(this, x, y, w, h, info, info.i, images, rotation);
  6319. return this;
  6320. };
  6321. /**
  6322. * @name convertStringToImageData
  6323. * @function
  6324. * @param {string} stringData
  6325. * @returns {string} binary data
  6326. */
  6327. jsPDFAPI.convertStringToImageData = function (stringData) {
  6328. var base64Info;
  6329. var imageData = "";
  6330. if (this.isString(stringData)) {
  6331. var base64Info = this.extractInfoFromBase64DataURI(stringData);
  6332. if (base64Info !== null) {
  6333. if (jsPDFAPI.validateStringAsBase64(base64Info[3])) {
  6334. imageData = atob(base64Info[3]); //convert to binary string
  6335. }
  6336. } else if (jsPDFAPI.validateStringAsBase64(stringData)) {
  6337. imageData = atob(stringData);
  6338. }
  6339. }
  6340. return imageData;
  6341. };
  6342. /**
  6343. * JPEG SUPPORT
  6344. **/
  6345. //takes a string imgData containing the raw bytes of
  6346. //a jpeg image and returns [width, height]
  6347. //Algorithm from: http://www.64lines.com/jpeg-width-height
  6348. var getJpegSize = function getJpegSize(imgData) {
  6349. var width, height, numcomponents; // Verify we have a valid jpeg header 0xff,0xd8,0xff,0xe0,?,?,'J','F','I','F',0x00
  6350. if (!imgData.charCodeAt(0) === 0xff || !imgData.charCodeAt(1) === 0xd8 || !imgData.charCodeAt(2) === 0xff || !imgData.charCodeAt(3) === 0xe0 || !imgData.charCodeAt(6) === "J".charCodeAt(0) || !imgData.charCodeAt(7) === "F".charCodeAt(0) || !imgData.charCodeAt(8) === "I".charCodeAt(0) || !imgData.charCodeAt(9) === "F".charCodeAt(0) || !imgData.charCodeAt(10) === 0x00) {
  6351. throw new Error("getJpegSize requires a binary string jpeg file");
  6352. }
  6353. var blockLength = imgData.charCodeAt(4) * 256 + imgData.charCodeAt(5);
  6354. var i = 4,
  6355. len = imgData.length;
  6356. while (i < len) {
  6357. i += blockLength;
  6358. if (imgData.charCodeAt(i) !== 0xff) {
  6359. throw new Error("getJpegSize could not find the size of the image");
  6360. }
  6361. if (imgData.charCodeAt(i + 1) === 0xc0 || //(SOF) Huffman - Baseline DCT
  6362. imgData.charCodeAt(i + 1) === 0xc1 || //(SOF) Huffman - Extended sequential DCT
  6363. imgData.charCodeAt(i + 1) === 0xc2 || // Progressive DCT (SOF2)
  6364. imgData.charCodeAt(i + 1) === 0xc3 || // Spatial (sequential) lossless (SOF3)
  6365. imgData.charCodeAt(i + 1) === 0xc4 || // Differential sequential DCT (SOF5)
  6366. imgData.charCodeAt(i + 1) === 0xc5 || // Differential progressive DCT (SOF6)
  6367. imgData.charCodeAt(i + 1) === 0xc6 || // Differential spatial (SOF7)
  6368. imgData.charCodeAt(i + 1) === 0xc7) {
  6369. height = imgData.charCodeAt(i + 5) * 256 + imgData.charCodeAt(i + 6);
  6370. width = imgData.charCodeAt(i + 7) * 256 + imgData.charCodeAt(i + 8);
  6371. numcomponents = imgData.charCodeAt(i + 9);
  6372. return [width, height, numcomponents];
  6373. } else {
  6374. i += 2;
  6375. blockLength = imgData.charCodeAt(i) * 256 + imgData.charCodeAt(i + 1);
  6376. }
  6377. }
  6378. },
  6379. getJpegSizeFromBytes = function getJpegSizeFromBytes(data) {
  6380. var hdr = data[0] << 8 | data[1];
  6381. if (hdr !== 0xffd8) throw new Error("Supplied data is not a JPEG");
  6382. var len = data.length,
  6383. block = (data[4] << 8) + data[5],
  6384. pos = 4,
  6385. bytes,
  6386. width,
  6387. height,
  6388. numcomponents;
  6389. while (pos < len) {
  6390. pos += block;
  6391. bytes = readBytes(data, pos);
  6392. block = (bytes[2] << 8) + bytes[3];
  6393. if ((bytes[1] === 0xc0 || bytes[1] === 0xc2) && bytes[0] === 0xff && block > 7) {
  6394. bytes = readBytes(data, pos + 5);
  6395. width = (bytes[2] << 8) + bytes[3];
  6396. height = (bytes[0] << 8) + bytes[1];
  6397. numcomponents = bytes[4];
  6398. return {
  6399. width: width,
  6400. height: height,
  6401. numcomponents: numcomponents
  6402. };
  6403. }
  6404. pos += 2;
  6405. }
  6406. throw new Error("getJpegSizeFromBytes could not find the size of the image");
  6407. },
  6408. readBytes = function readBytes(data, offset) {
  6409. return data.subarray(offset, offset + 5);
  6410. };
  6411. /**
  6412. * @ignore
  6413. */
  6414. jsPDFAPI.processJPEG = function (data, index, alias, compression, dataAsBinaryString, colorSpace) {
  6415. var filter = this.decode.DCT_DECODE,
  6416. bpc = 8,
  6417. dims;
  6418. if (!this.isString(data) && !this.isArrayBuffer(data) && !this.isArrayBufferView(data)) {
  6419. return null;
  6420. }
  6421. if (this.isString(data)) {
  6422. dims = getJpegSize(data);
  6423. }
  6424. if (this.isArrayBuffer(data)) {
  6425. data = new Uint8Array(data);
  6426. }
  6427. if (this.isArrayBufferView(data)) {
  6428. dims = getJpegSizeFromBytes(data); // if we already have a stored binary string rep use that
  6429. data = dataAsBinaryString || this.arrayBufferToBinaryString(data);
  6430. }
  6431. if (colorSpace === undefined) {
  6432. switch (dims.numcomponents) {
  6433. case 1:
  6434. colorSpace = this.color_spaces.DEVICE_GRAY;
  6435. break;
  6436. case 4:
  6437. colorSpace = this.color_spaces.DEVICE_CMYK;
  6438. break;
  6439. default:
  6440. case 3:
  6441. colorSpace = this.color_spaces.DEVICE_RGB;
  6442. break;
  6443. }
  6444. }
  6445. return this.createImageInfo(data, dims.width, dims.height, colorSpace, bpc, filter, index, alias);
  6446. };
  6447. /**
  6448. * @ignore
  6449. */
  6450. jsPDFAPI.processJPG = function ()
  6451. /*data, index, alias, compression, dataAsBinaryString*/
  6452. {
  6453. return this.processJPEG.apply(this, arguments);
  6454. };
  6455. /**
  6456. * @name loadImageFile
  6457. * @function
  6458. * @param {string} path
  6459. * @param {boolean} sync
  6460. * @param {function} callback
  6461. */
  6462. jsPDFAPI.loadImageFile = function (path, sync, callback) {
  6463. sync = sync || true;
  6464. callback = callback || function () {};
  6465. var isNode = Object.prototype.toString.call(typeof process !== "undefined" ? process : 0) === "[object process]";
  6466. var xhrMethod = function xhrMethod(url, sync, callback) {
  6467. var req = new XMLHttpRequest();
  6468. var byteArray = [];
  6469. var i = 0;
  6470. var sanitizeUnicode = function sanitizeUnicode(data) {
  6471. var dataLength = data.length;
  6472. var StringFromCharCode = String.fromCharCode; //Transform Unicode to ASCII
  6473. for (i = 0; i < dataLength; i += 1) {
  6474. byteArray.push(StringFromCharCode(data.charCodeAt(i) & 0xff));
  6475. }
  6476. return byteArray.join("");
  6477. };
  6478. req.open("GET", url, !sync); // XHR binary charset opt by Marcus Granado 2006 [http://mgran.blogspot.com]
  6479. req.overrideMimeType("text/plain; charset=x-user-defined");
  6480. if (sync === false) {
  6481. req.onload = function () {
  6482. return sanitizeUnicode(this.responseText);
  6483. };
  6484. }
  6485. req.send(null);
  6486. if (req.status !== 200) {
  6487. console.warn('Unable to load file "' + url + '"');
  6488. return;
  6489. }
  6490. if (sync) {
  6491. return sanitizeUnicode(req.responseText);
  6492. }
  6493. }; //we have a browser and probably no CORS-Problem
  6494. if ((typeof window === "undefined" ? "undefined" : _typeof(window)) !== undefined && (typeof location === "undefined" ? "undefined" : _typeof(location)) === "object" && location.protocol.substr(0, 4) === "http") {
  6495. return xhrMethod(path, sync, callback);
  6496. }
  6497. };
  6498. /**
  6499. * @name getImageProperties
  6500. * @function
  6501. * @param {Object} imageData
  6502. * @returns {Object}
  6503. */
  6504. jsPDFAPI.getImageProperties = function (imageData) {
  6505. var info;
  6506. var tmpImageData = "";
  6507. var format;
  6508. if (isDOMElement(imageData)) {
  6509. imageData = createDataURIFromElement(imageData);
  6510. }
  6511. if (this.isString(imageData)) {
  6512. tmpImageData = this.convertStringToImageData(imageData);
  6513. if (tmpImageData !== "") {
  6514. imageData = tmpImageData;
  6515. } else {
  6516. tmpImageData = this.loadImageFile(imageData);
  6517. if (tmpImageData !== undefined) {
  6518. imageData = tmpImageData;
  6519. }
  6520. }
  6521. }
  6522. format = this.getImageFileTypeByImageData(imageData);
  6523. if (!isImageTypeSupported(format)) throw new Error("addImage does not support files of type '" + format + "', please ensure that a plugin for '" + format + "' support is added.");
  6524. /**
  6525. * need to test if it's more efficient to convert all binary strings
  6526. * to TypedArray - or should we just leave and process as string?
  6527. */
  6528. if (this.supportsArrayBuffer()) {
  6529. // no need to convert if imageData is already uint8array
  6530. if (!(imageData instanceof Uint8Array)) {
  6531. imageData = this.binaryStringToUint8Array(imageData);
  6532. }
  6533. }
  6534. info = this["process" + format.toUpperCase()](imageData);
  6535. if (!info) {
  6536. throw new Error("An unkwown error occurred whilst processing the image");
  6537. }
  6538. return {
  6539. fileType: format,
  6540. width: info.w,
  6541. height: info.h,
  6542. colorSpace: info.cs,
  6543. compressionMode: info.f,
  6544. bitsPerComponent: info.bpc
  6545. };
  6546. };
  6547. })(jsPDF.API);
  6548. /**
  6549. * @license
  6550. * Copyright (c) 2014 Steven Spungin (TwelveTone LLC) steven@twelvetone.tv
  6551. *
  6552. * Licensed under the MIT License.
  6553. * http://opensource.org/licenses/mit-license
  6554. */
  6555. /**
  6556. * jsPDF Annotations PlugIn
  6557. *
  6558. * There are many types of annotations in a PDF document. Annotations are placed
  6559. * on a page at a particular location. They are not 'attached' to an object.
  6560. * <br />
  6561. * This plugin current supports <br />
  6562. * <li> Goto Page (set pageNumber and top in options)
  6563. * <li> Goto Name (set name and top in options)
  6564. * <li> Goto URL (set url in options)
  6565. * <p>
  6566. * The destination magnification factor can also be specified when goto is a page number or a named destination. (see documentation below)
  6567. * (set magFactor in options). XYZ is the default.
  6568. * </p>
  6569. * <p>
  6570. * Links, Text, Popup, and FreeText are supported.
  6571. * </p>
  6572. * <p>
  6573. * Options In PDF spec Not Implemented Yet
  6574. * <li> link border
  6575. * <li> named target
  6576. * <li> page coordinates
  6577. * <li> destination page scaling and layout
  6578. * <li> actions other than URL and GotoPage
  6579. * <li> background / hover actions
  6580. * </p>
  6581. * @name annotations
  6582. * @module
  6583. */
  6584. /*
  6585. Destination Magnification Factors
  6586. See PDF 1.3 Page 386 for meanings and options
  6587. [supported]
  6588. XYZ (options; left top zoom)
  6589. Fit (no options)
  6590. FitH (options: top)
  6591. FitV (options: left)
  6592. [not supported]
  6593. FitR
  6594. FitB
  6595. FitBH
  6596. FitBV
  6597. */
  6598. (function (jsPDFAPI) {
  6599. var annotationPlugin = {
  6600. /**
  6601. * An array of arrays, indexed by <em>pageNumber</em>.
  6602. */
  6603. annotations: [],
  6604. f2: function f2(number) {
  6605. return number.toFixed(2);
  6606. },
  6607. notEmpty: function notEmpty(obj) {
  6608. if (typeof obj != "undefined") {
  6609. if (obj != "") {
  6610. return true;
  6611. }
  6612. }
  6613. }
  6614. };
  6615. jsPDF.API.annotationPlugin = annotationPlugin;
  6616. jsPDF.API.events.push(["addPage", function (info) {
  6617. this.annotationPlugin.annotations[info.pageNumber] = [];
  6618. }]);
  6619. jsPDFAPI.events.push(["putPage", function (info) {
  6620. //TODO store annotations in pageContext so reorder/remove will not affect them.
  6621. var pageAnnos = this.annotationPlugin.annotations[info.pageNumber];
  6622. var found = false;
  6623. for (var a = 0; a < pageAnnos.length && !found; a++) {
  6624. var anno = pageAnnos[a];
  6625. switch (anno.type) {
  6626. case "link":
  6627. if (annotationPlugin.notEmpty(anno.options.url) || annotationPlugin.notEmpty(anno.options.pageNumber)) {
  6628. found = true;
  6629. break;
  6630. }
  6631. case "reference":
  6632. case "text":
  6633. case "freetext":
  6634. found = true;
  6635. break;
  6636. }
  6637. }
  6638. if (found == false) {
  6639. return;
  6640. }
  6641. this.internal.write("/Annots [");
  6642. var f2 = this.annotationPlugin.f2;
  6643. var k = this.internal.scaleFactor;
  6644. var pageHeight = this.internal.pageSize.getHeight();
  6645. var pageInfo = this.internal.getPageInfo(info.pageNumber);
  6646. for (var a = 0; a < pageAnnos.length; a++) {
  6647. var anno = pageAnnos[a];
  6648. switch (anno.type) {
  6649. case "reference":
  6650. // References to Widget Anotations (for AcroForm Fields)
  6651. this.internal.write(" " + anno.object.objId + " 0 R ");
  6652. break;
  6653. case "text":
  6654. // Create a an object for both the text and the popup
  6655. var objText = this.internal.newAdditionalObject();
  6656. var objPopup = this.internal.newAdditionalObject();
  6657. var title = anno.title || "Note";
  6658. var rect = "/Rect [" + f2(anno.bounds.x * k) + " " + f2(pageHeight - (anno.bounds.y + anno.bounds.h) * k) + " " + f2((anno.bounds.x + anno.bounds.w) * k) + " " + f2((pageHeight - anno.bounds.y) * k) + "] ";
  6659. line = "<</Type /Annot /Subtype /" + "Text" + " " + rect + "/Contents (" + anno.contents + ")";
  6660. line += " /Popup " + objPopup.objId + " 0 R";
  6661. line += " /P " + pageInfo.objId + " 0 R";
  6662. line += " /T (" + title + ") >>";
  6663. objText.content = line;
  6664. var parent = objText.objId + " 0 R";
  6665. var popoff = 30;
  6666. var rect = "/Rect [" + f2((anno.bounds.x + popoff) * k) + " " + f2(pageHeight - (anno.bounds.y + anno.bounds.h) * k) + " " + f2((anno.bounds.x + anno.bounds.w + popoff) * k) + " " + f2((pageHeight - anno.bounds.y) * k) + "] "; //var rect2 = "/Rect [" + f2(anno.bounds.x * k) + " " + f2((pageHeight - anno.bounds.y) * k) + " " + f2(anno.bounds.x + anno.bounds.w * k) + " " + f2(pageHeight - (anno.bounds.y + anno.bounds.h) * k) + "] ";
  6667. line = "<</Type /Annot /Subtype /" + "Popup" + " " + rect + " /Parent " + parent;
  6668. if (anno.open) {
  6669. line += " /Open true";
  6670. }
  6671. line += " >>";
  6672. objPopup.content = line;
  6673. this.internal.write(objText.objId, "0 R", objPopup.objId, "0 R");
  6674. break;
  6675. case "freetext":
  6676. var rect = "/Rect [" + f2(anno.bounds.x * k) + " " + f2((pageHeight - anno.bounds.y) * k) + " " + f2(anno.bounds.x + anno.bounds.w * k) + " " + f2(pageHeight - (anno.bounds.y + anno.bounds.h) * k) + "] ";
  6677. var color = anno.color || "#000000";
  6678. line = "<</Type /Annot /Subtype /" + "FreeText" + " " + rect + "/Contents (" + anno.contents + ")";
  6679. line += " /DS(font: Helvetica,sans-serif 12.0pt; text-align:left; color:#" + color + ")";
  6680. line += " /Border [0 0 0]";
  6681. line += " >>";
  6682. this.internal.write(line);
  6683. break;
  6684. case "link":
  6685. if (anno.options.name) {
  6686. var loc = this.annotations._nameMap[anno.options.name];
  6687. anno.options.pageNumber = loc.page;
  6688. anno.options.top = loc.y;
  6689. } else {
  6690. if (!anno.options.top) {
  6691. anno.options.top = 0;
  6692. }
  6693. }
  6694. var rect = "/Rect [" + f2(anno.x * k) + " " + f2((pageHeight - anno.y) * k) + " " + f2((anno.x + anno.w) * k) + " " + f2((pageHeight - (anno.y + anno.h)) * k) + "] ";
  6695. var line = "";
  6696. if (anno.options.url) {
  6697. line = "<</Type /Annot /Subtype /Link " + rect + "/Border [0 0 0] /A <</S /URI /URI (" + anno.options.url + ") >>";
  6698. } else if (anno.options.pageNumber) {
  6699. // first page is 0
  6700. var info = this.internal.getPageInfo(anno.options.pageNumber);
  6701. line = "<</Type /Annot /Subtype /Link " + rect + "/Border [0 0 0] /Dest [" + info.objId + " 0 R";
  6702. anno.options.magFactor = anno.options.magFactor || "XYZ";
  6703. switch (anno.options.magFactor) {
  6704. case "Fit":
  6705. line += " /Fit]";
  6706. break;
  6707. case "FitH":
  6708. //anno.options.top = anno.options.top || f2(pageHeight * k);
  6709. line += " /FitH " + anno.options.top + "]";
  6710. break;
  6711. case "FitV":
  6712. anno.options.left = anno.options.left || 0;
  6713. line += " /FitV " + anno.options.left + "]";
  6714. break;
  6715. case "XYZ":
  6716. default:
  6717. var top = f2((pageHeight - anno.options.top) * k); // || f2(pageHeight * k);
  6718. anno.options.left = anno.options.left || 0; // 0 or null zoom will not change zoom factor
  6719. if (typeof anno.options.zoom === "undefined") {
  6720. anno.options.zoom = 0;
  6721. }
  6722. line += " /XYZ " + anno.options.left + " " + top + " " + anno.options.zoom + "]";
  6723. break;
  6724. }
  6725. }
  6726. if (line != "") {
  6727. line += " >>";
  6728. this.internal.write(line);
  6729. }
  6730. break;
  6731. }
  6732. }
  6733. this.internal.write("]");
  6734. }]);
  6735. /**
  6736. * @name createAnnotation
  6737. * @function
  6738. * @param {Object} options
  6739. */
  6740. jsPDFAPI.createAnnotation = function (options) {
  6741. switch (options.type) {
  6742. case "link":
  6743. this.link(options.bounds.x, options.bounds.y, options.bounds.w, options.bounds.h, options);
  6744. break;
  6745. case "text":
  6746. case "freetext":
  6747. this.annotationPlugin.annotations[this.internal.getCurrentPageInfo().pageNumber].push(options);
  6748. break;
  6749. }
  6750. };
  6751. /**
  6752. * Create a link
  6753. *
  6754. * valid options
  6755. * <li> pageNumber or url [required]
  6756. * <p>If pageNumber is specified, top and zoom may also be specified</p>
  6757. * @name link
  6758. * @function
  6759. * @param {number} x
  6760. * @param {number} y
  6761. * @param {number} w
  6762. * @param {number} h
  6763. * @param {Object} options
  6764. */
  6765. jsPDFAPI.link = function (x, y, w, h, options) {
  6766. this.annotationPlugin.annotations[this.internal.getCurrentPageInfo().pageNumber].push({
  6767. x: x,
  6768. y: y,
  6769. w: w,
  6770. h: h,
  6771. options: options,
  6772. type: "link"
  6773. });
  6774. };
  6775. /**
  6776. * Currently only supports single line text.
  6777. * Returns the width of the text/link
  6778. *
  6779. * @name textWithLink
  6780. * @function
  6781. * @param {string} text
  6782. * @param {number} x
  6783. * @param {number} y
  6784. * @param {Object} options
  6785. * @returns {number} width the width of the text/link
  6786. */
  6787. jsPDFAPI.textWithLink = function (text, x, y, options) {
  6788. var width = this.getTextWidth(text);
  6789. var height = this.internal.getLineHeight() / this.internal.scaleFactor;
  6790. this.text(text, x, y); //TODO We really need the text baseline height to do this correctly.
  6791. // Or ability to draw text on top, bottom, center, or baseline.
  6792. y += height * 0.2;
  6793. this.link(x, y - height, width, height, options);
  6794. return width;
  6795. }; //TODO move into external library
  6796. /**
  6797. * @name getTextWidth
  6798. * @function
  6799. * @param {string} text
  6800. * @returns {number} txtWidth
  6801. */
  6802. jsPDFAPI.getTextWidth = function (text) {
  6803. var fontSize = this.internal.getFontSize();
  6804. var txtWidth = this.getStringUnitWidth(text) * fontSize / this.internal.scaleFactor;
  6805. return txtWidth;
  6806. }; //TODO move into external library
  6807. /**
  6808. * @name getLineHeight
  6809. * @function
  6810. * @returns {number} lineHeight
  6811. */
  6812. jsPDFAPI.getLineHeight = function () {
  6813. return this.internal.getLineHeight();
  6814. };
  6815. return this;
  6816. })(jsPDF.API);
  6817. /**
  6818. * @license
  6819. * Copyright (c) 2017 Aras Abbasi
  6820. *
  6821. * Licensed under the MIT License.
  6822. * http://opensource.org/licenses/mit-license
  6823. */
  6824. /**
  6825. * jsPDF arabic parser PlugIn
  6826. *
  6827. * @name arabic
  6828. * @module
  6829. */
  6830. (function (jsPDFAPI) {
  6831. var arLangCodes = {
  6832. ar: "Arabic (Standard)",
  6833. "ar-DZ": "Arabic (Algeria)",
  6834. "ar-BH": "Arabic (Bahrain)",
  6835. "ar-EG": "Arabic (Egypt)",
  6836. "ar-IQ": "Arabic (Iraq)",
  6837. "ar-JO": "Arabic (Jordan)",
  6838. "ar-KW": "Arabic (Kuwait)",
  6839. "ar-LB": "Arabic (Lebanon)",
  6840. "ar-LY": "Arabic (Libya)",
  6841. "ar-MA": "Arabic (Morocco)",
  6842. "ar-OM": "Arabic (Oman)",
  6843. "ar-QA": "Arabic (Qatar)",
  6844. "ar-SA": "Arabic (Saudi Arabia)",
  6845. "ar-SY": "Arabic (Syria)",
  6846. "ar-TN": "Arabic (Tunisia)",
  6847. "ar-AE": "Arabic (U.A.E.)",
  6848. "ar-YE": "Arabic (Yemen)",
  6849. fa: "Persian",
  6850. "fa-IR": "Persian/Iran",
  6851. ur: "Urdu"
  6852. };
  6853. var arLangCodesKeys = Object.keys(arLangCodes);
  6854. /**
  6855. * Arabic shape substitutions: char code => (isolated, final, initial, medial).
  6856. */
  6857. var arabicSubst = {
  6858. 1569: [65152],
  6859. 1570: [65153, 65154, 65153, 65154],
  6860. 1571: [65155, 65156, 65155, 65156],
  6861. 1572: [65157, 65158],
  6862. 1573: [65159, 65160, 65159, 65160],
  6863. 1574: [65161, 65162, 65163, 65164],
  6864. 1575: [65165, 65166, 65165, 65166],
  6865. 1576: [65167, 65168, 65169, 65170],
  6866. 1577: [65171, 65172],
  6867. 1578: [65173, 65174, 65175, 65176],
  6868. 1579: [65177, 65178, 65179, 65180],
  6869. 1580: [65181, 65182, 65183, 65184],
  6870. 1581: [65185, 65186, 65187, 65188],
  6871. 1582: [65189, 65190, 65191, 65192],
  6872. 1583: [65193, 65194, 65193],
  6873. 1584: [65195, 65196, 65195],
  6874. 1585: [65197, 65198, 65197],
  6875. 1586: [65199, 65200, 65199],
  6876. 1587: [65201, 65202, 65203, 65204],
  6877. 1588: [65205, 65206, 65207, 65208],
  6878. 1589: [65209, 65210, 65211, 65212],
  6879. 1590: [65213, 65214, 65215, 65216],
  6880. 1591: [65217, 65218, 65219, 65220],
  6881. 1592: [65221, 65222, 65223, 65224],
  6882. 1593: [65225, 65226, 65227, 65228],
  6883. 1594: [65229, 65230, 65231, 65232],
  6884. 1601: [65233, 65234, 65235, 65236],
  6885. 1602: [65237, 65238, 65239, 65240],
  6886. 1603: [65241, 65242, 65243, 65244],
  6887. 1604: [65245, 65246, 65247, 65248],
  6888. 1605: [65249, 65250, 65251, 65252],
  6889. 1606: [65253, 65254, 65255, 65256],
  6890. 1607: [65257, 65258, 65259, 65260],
  6891. 1608: [65261, 65262, 65261],
  6892. 1609: [65263, 65264, 64488, 64489],
  6893. 1610: [65265, 65266, 65267, 65268],
  6894. 1649: [64336, 64337],
  6895. 1655: [64477],
  6896. 1657: [64358, 64359, 64360, 64361],
  6897. 1658: [64350, 64351, 64352, 64353],
  6898. 1659: [64338, 64339, 64340, 64341],
  6899. 1662: [64342, 64343, 64344, 64345],
  6900. 1663: [64354, 64355, 64356, 64357],
  6901. 1664: [64346, 64347, 64348, 64349],
  6902. 1667: [64374, 64375, 64376, 64377],
  6903. 1668: [64370, 64371, 64372, 64373],
  6904. 1670: [64378, 64379, 64380, 64381],
  6905. 1671: [64382, 64383, 64384, 64385],
  6906. 1672: [64392, 64393],
  6907. 1676: [64388, 64389],
  6908. 1677: [64386, 64387],
  6909. 1678: [64390, 64391],
  6910. 1681: [64396, 64397],
  6911. 1688: [64394, 64395, 64394],
  6912. 1700: [64362, 64363, 64364, 64365],
  6913. 1702: [64366, 64367, 64368, 64369],
  6914. 1705: [64398, 64399, 64400, 64401],
  6915. 1709: [64467, 64468, 64469, 64470],
  6916. 1711: [64402, 64403, 64404, 64405],
  6917. 1713: [64410, 64411, 64412, 64413],
  6918. 1715: [64406, 64407, 64408, 64409],
  6919. 1722: [64414, 64415],
  6920. 1723: [64416, 64417, 64418, 64419],
  6921. 1726: [64426, 64427, 64428, 64429],
  6922. 1728: [64420, 64421],
  6923. 1729: [64422, 64423, 64424, 64425],
  6924. 1733: [64480, 64481],
  6925. 1734: [64473, 64474],
  6926. 1735: [64471, 64472],
  6927. 1736: [64475, 64476],
  6928. 1737: [64482, 64483],
  6929. 1739: [64478, 64479],
  6930. 1740: [64508, 64509, 64510, 64511],
  6931. 1744: [64484, 64485, 64486, 64487],
  6932. 1746: [64430, 64431],
  6933. 1747: [64432, 64433]
  6934. };
  6935. var arabiclaasubst = {
  6936. 1570: [65269, 65270, 65269, 65270],
  6937. 1571: [65271, 65272, 65271, 65272],
  6938. 1573: [65273, 65274, 65273, 65274],
  6939. 1575: [65275, 65276, 65275, 65276]
  6940. };
  6941. var arabicorigsubst = {
  6942. 1570: [65153, 65154, 65153, 65154],
  6943. 1571: [65155, 65156, 65155, 65156],
  6944. 1573: [65159, 65160, 65159, 65160],
  6945. 1575: [65165, 65166, 65165, 65166]
  6946. };
  6947. var arabic_diacritics = {
  6948. 1612: 64606,
  6949. // Shadda + Dammatan
  6950. 1613: 64607,
  6951. // Shadda + Kasratan
  6952. 1614: 64608,
  6953. // Shadda + Fatha
  6954. 1615: 64609,
  6955. // Shadda + Damma
  6956. 1616: 64610 // Shadda + Kasra
  6957. };
  6958. var alfletter = [1570, 1571, 1573, 1575];
  6959. var endedletter = [1569, 1570, 1571, 1572, 1573, 1575, 1577, 1583, 1584, 1585, 1586, 1608, 1688];
  6960. var isolatedForm = 0;
  6961. var finalForm = 1;
  6962. var initialForm = 2;
  6963. var medialForm = 3; //private
  6964. function isArabicLetter(letter) {
  6965. return letter !== undefined && arabicSubst[letter.charCodeAt(0)] !== undefined;
  6966. }
  6967. function isArabicEndLetter(letter) {
  6968. return letter !== undefined && endedletter.indexOf(letter.charCodeAt(0)) >= 0;
  6969. }
  6970. function isArabicAlfLetter(letter) {
  6971. return letter !== undefined && alfletter.indexOf(letter.charCodeAt(0)) >= 0;
  6972. }
  6973. function arabicLetterHasFinalForm(letter) {
  6974. return isArabicLetter(letter) && arabicSubst[letter.charCodeAt(0)].length >= 2;
  6975. }
  6976. function arabicLetterHasMedialForm(letter) {
  6977. return isArabicLetter(letter) && arabicSubst[letter.charCodeAt(0)].length == 4;
  6978. }
  6979. function isArabicDiacritic(letter) {
  6980. return letter !== undefined && arabic_diacritics[letter.charCodeAt(0)] !== undefined;
  6981. }
  6982. function getCorrectForm(currentChar, beforeChar, nextChar, arabicSubstition) {
  6983. if (!isArabicLetter(currentChar)) {
  6984. return -1;
  6985. }
  6986. arabicSubstition = arabicSubstition || {};
  6987. arabicSubst = Object.assign(arabicSubst, arabicSubstition);
  6988. if (!arabicLetterHasFinalForm(currentChar) || !isArabicLetter(beforeChar) && !isArabicLetter(nextChar) || !isArabicLetter(nextChar) && isArabicEndLetter(beforeChar) || isArabicEndLetter(currentChar) && !isArabicLetter(beforeChar) || isArabicEndLetter(currentChar) && isArabicAlfLetter(beforeChar) || isArabicEndLetter(currentChar) && isArabicEndLetter(beforeChar)) {
  6989. arabicSubst = Object.assign(arabicSubst, arabicorigsubst);
  6990. return isolatedForm;
  6991. }
  6992. if (arabicLetterHasMedialForm(currentChar) && isArabicLetter(beforeChar) && !isArabicEndLetter(beforeChar) && isArabicLetter(nextChar) && arabicLetterHasFinalForm(nextChar)) {
  6993. arabicSubst = Object.assign(arabicSubst, arabicorigsubst);
  6994. return medialForm;
  6995. }
  6996. if (isArabicEndLetter(currentChar) || !isArabicLetter(nextChar)) {
  6997. arabicSubst = Object.assign(arabicSubst, arabicorigsubst);
  6998. return finalForm;
  6999. }
  7000. arabicSubst = Object.assign(arabicSubst, arabicorigsubst);
  7001. return initialForm;
  7002. }
  7003. var commonSubstition = function commonSubstition(character) {
  7004. var replacementTable = {
  7005. "(": ")",
  7006. ")": "("
  7007. };
  7008. return replacementTable[character] || character;
  7009. };
  7010. /**
  7011. * @name processArabic
  7012. * @function
  7013. * @param {string} text
  7014. * @param {boolean} reverse
  7015. * @returns {string}
  7016. */
  7017. var processArabic = jsPDFAPI.processArabic = function (text, reverse) {
  7018. text = text || "";
  7019. reverse = reverse || false;
  7020. var result = "";
  7021. var i = 0;
  7022. var position = 0;
  7023. var currentLetter = "";
  7024. var prevLetter = "";
  7025. var nextLetter = "";
  7026. var resultingLetter;
  7027. var localPrevLetter;
  7028. var localCurrentLetter;
  7029. var localNextLetter;
  7030. for (i = 0; i < text.length; i += 1) {
  7031. currentLetter = text[i];
  7032. prevLetter = text[i - 1];
  7033. nextLetter = text[i + 1];
  7034. if (!isArabicLetter(currentLetter)) {
  7035. result += reverse ? commonSubstition(currentLetter) : currentLetter;
  7036. } else {
  7037. if (prevLetter !== undefined && prevLetter.charCodeAt(0) === 1604 && isArabicAlfLetter(currentLetter)) {
  7038. localPrevLetter = text[i - 2];
  7039. localCurrentLetter = currentLetter;
  7040. localNextLetter = text[i + 1];
  7041. position = getCorrectForm(localCurrentLetter, localPrevLetter, localNextLetter, arabiclaasubst);
  7042. resultingLetter = String.fromCharCode(arabiclaasubst[currentLetter.charCodeAt(0)][position]);
  7043. result = result.substr(0, result.length - 1) + resultingLetter;
  7044. } else if (prevLetter !== undefined && prevLetter.charCodeAt(0) === 1617 && isArabicDiacritic(currentLetter)) {
  7045. localPrevLetter = text[i - 2];
  7046. localCurrentLetter = currentLetter;
  7047. localNextLetter = text[i + 1];
  7048. position = getCorrectForm(localCurrentLetter, localPrevLetter, localNextLetter, arabicorigsubst);
  7049. resultingLetter = String.fromCharCode(arabic_diacritics[currentLetter.charCodeAt(0)][position]);
  7050. result = result.substr(0, result.length - 1) + resultingLetter;
  7051. } else {
  7052. position = getCorrectForm(currentLetter, prevLetter, nextLetter, arabicorigsubst);
  7053. result += String.fromCharCode(arabicSubst[currentLetter.charCodeAt(0)][position]);
  7054. }
  7055. }
  7056. }
  7057. return reverse ? result.split("").reverse().join("") : result;
  7058. };
  7059. var arabicParserFunction = function arabicParserFunction(args) {
  7060. var text = args.text;
  7061. var x = args.x;
  7062. var y = args.y;
  7063. var options = args.options || {};
  7064. var mutex = args.mutex || {};
  7065. var lang = options.lang;
  7066. var tmpText = [];
  7067. if (arLangCodesKeys.indexOf(lang) >= 0) {
  7068. if (Object.prototype.toString.call(text) === "[object Array]") {
  7069. var i = 0;
  7070. tmpText = [];
  7071. for (i = 0; i < text.length; i += 1) {
  7072. if (Object.prototype.toString.call(text[i]) === "[object Array]") {
  7073. tmpText.push([processArabic(text[i][0], true), text[i][1], text[i][2]]);
  7074. } else {
  7075. tmpText.push([processArabic(text[i], true)]);
  7076. }
  7077. }
  7078. args.text = tmpText;
  7079. } else {
  7080. args.text = processArabic(text, true);
  7081. } //force charSpace if not given.
  7082. if (options.charSpace === undefined) {
  7083. args.options.charSpace = 0;
  7084. } //if R2L is true, set it false.
  7085. if (options.R2L === true) {
  7086. args.options.R2L = false;
  7087. }
  7088. }
  7089. };
  7090. jsPDFAPI.events.push(["preProcessText", arabicParserFunction]);
  7091. })(jsPDF.API);
  7092. /** @license
  7093. * jsPDF Autoprint Plugin
  7094. *
  7095. * Licensed under the MIT License.
  7096. * http://opensource.org/licenses/mit-license
  7097. */
  7098. /**
  7099. * @name autoprint
  7100. * @module
  7101. */
  7102. (function (jsPDFAPI) {
  7103. /**
  7104. * Makes the PDF automatically print. This works in Chrome, Firefox, Acrobat
  7105. * Reader.
  7106. *
  7107. * @name autoPrint
  7108. * @function
  7109. * @param {Object} options (optional) Set the attribute variant to 'non-conform' (default) or 'javascript' to activate different methods of automatic printing when opening in a PDF-viewer .
  7110. * @returns {jsPDF}
  7111. * @example
  7112. * var doc = new jsPDF();
  7113. * doc.text(10, 10, 'This is a test');
  7114. * doc.autoPrint({variant: 'non-conform'});
  7115. * doc.save('autoprint.pdf');
  7116. */
  7117. jsPDFAPI.autoPrint = function (options) {
  7118. var refAutoPrintTag;
  7119. options = options || {};
  7120. options.variant = options.variant || "non-conform";
  7121. switch (options.variant) {
  7122. case "javascript":
  7123. //https://github.com/Rob--W/pdf.js/commit/c676ecb5a0f54677b9f3340c3ef2cf42225453bb
  7124. this.addJS("print({});");
  7125. break;
  7126. case "non-conform":
  7127. default:
  7128. this.internal.events.subscribe("postPutResources", function () {
  7129. refAutoPrintTag = this.internal.newObject();
  7130. this.internal.out("<<");
  7131. this.internal.out("/S /Named");
  7132. this.internal.out("/Type /Action");
  7133. this.internal.out("/N /Print");
  7134. this.internal.out(">>");
  7135. this.internal.out("endobj");
  7136. });
  7137. this.internal.events.subscribe("putCatalog", function () {
  7138. this.internal.out("/OpenAction " + refAutoPrintTag + " 0 R");
  7139. });
  7140. break;
  7141. }
  7142. return this;
  7143. };
  7144. })(jsPDF.API);
  7145. /**
  7146. * @license
  7147. * Copyright (c) 2014 Steven Spungin (TwelveTone LLC) steven@twelvetone.tv
  7148. *
  7149. * Licensed under the MIT License.
  7150. * http://opensource.org/licenses/mit-license
  7151. */
  7152. /**
  7153. * jsPDF Canvas PlugIn
  7154. * This plugin mimics the HTML5 Canvas
  7155. *
  7156. * The goal is to provide a way for current canvas users to print directly to a PDF.
  7157. * @name canvas
  7158. * @module
  7159. */
  7160. (function (jsPDFAPI) {
  7161. jsPDFAPI.events.push(["initialized", function () {
  7162. this.canvas.pdf = this;
  7163. }]);
  7164. /**
  7165. * @name canvas
  7166. * @static
  7167. * @type {Object}
  7168. */
  7169. jsPDFAPI.canvas = {
  7170. /**
  7171. * @name getContext
  7172. * @function
  7173. * @param {string} the context type
  7174. */
  7175. getContext: function getContext(name) {
  7176. this.pdf.context2d._canvas = this;
  7177. return this.pdf.context2d;
  7178. },
  7179. childNodes: [],
  7180. style: {},
  7181. autoContext2dResizeX: true,
  7182. autoContext2dResizeY: true
  7183. };
  7184. /**
  7185. * Width of the canvas
  7186. *
  7187. * @name width
  7188. * @property {number} width
  7189. */
  7190. Object.defineProperty(jsPDFAPI.canvas, "width", {
  7191. get: function get() {
  7192. return this._width;
  7193. },
  7194. set: function set(value) {
  7195. this._width = value;
  7196. if (this.autoContext2dResizeX) {
  7197. this.getContext("2d").pageWrapX = value + 1;
  7198. }
  7199. }
  7200. });
  7201. /**
  7202. * Height of the canvas
  7203. *
  7204. * @name height
  7205. * @property {number} height
  7206. */
  7207. Object.defineProperty(jsPDFAPI.canvas, "height", {
  7208. get: function get() {
  7209. return this._height;
  7210. },
  7211. set: function set(value) {
  7212. this._height = value;
  7213. if (this.autoContext2dResizeY) {
  7214. this.getContext("2d").pageWrapY = value + 1;
  7215. }
  7216. }
  7217. });
  7218. return this;
  7219. })(jsPDF.API);
  7220. /**
  7221. * @license
  7222. * ====================================================================
  7223. * Copyright (c) 2013 Youssef Beddad, youssef.beddad@gmail.com
  7224. * 2013 Eduardo Menezes de Morais, eduardo.morais@usp.br
  7225. * 2013 Lee Driscoll, https://github.com/lsdriscoll
  7226. * 2014 Juan Pablo Gaviria, https://github.com/juanpgaviria
  7227. * 2014 James Hall, james@parall.ax
  7228. * 2014 Diego Casorran, https://github.com/diegocr
  7229. *
  7230. *
  7231. * ====================================================================
  7232. */
  7233. /**
  7234. * @name cell
  7235. * @module
  7236. */
  7237. (function (jsPDFAPI) {
  7238. /*jslint browser:true */
  7239. /*global document: false, jsPDF */
  7240. var padding = 3,
  7241. margin = 13,
  7242. headerFunction,
  7243. lastCellPos = {
  7244. x: undefined,
  7245. y: undefined,
  7246. w: undefined,
  7247. h: undefined,
  7248. ln: undefined
  7249. },
  7250. pages = 1,
  7251. setLastCellPosition = function setLastCellPosition(x, y, w, h, ln) {
  7252. lastCellPos = {
  7253. x: x,
  7254. y: y,
  7255. w: w,
  7256. h: h,
  7257. ln: ln
  7258. };
  7259. },
  7260. getLastCellPosition = function getLastCellPosition() {
  7261. return lastCellPos;
  7262. },
  7263. NO_MARGINS = {
  7264. left: 0,
  7265. top: 0,
  7266. bottom: 0
  7267. };
  7268. /**
  7269. * @name setHeaderFunction
  7270. * @function
  7271. * @param {function} func
  7272. */
  7273. jsPDFAPI.setHeaderFunction = function (func) {
  7274. headerFunction = func;
  7275. };
  7276. /**
  7277. * @name getTextDimensions
  7278. * @function
  7279. * @param {string} txt
  7280. * @returns {Object} dimensions
  7281. */
  7282. jsPDFAPI.getTextDimensions = function (text, options) {
  7283. var fontSize = this.table_font_size || this.internal.getFontSize();
  7284. var fontStyle = this.internal.getFont().fontStyle;
  7285. options = options || {};
  7286. var scaleFactor = options.scaleFactor || this.internal.scaleFactor;
  7287. var width = 0;
  7288. var amountOfLines = 0;
  7289. var height = 0;
  7290. var tempWidth = 0;
  7291. if (typeof text === "string") {
  7292. width = this.getStringUnitWidth(text) * fontSize;
  7293. if (width !== 0) {
  7294. amountOfLines = 1;
  7295. }
  7296. } else if (Object.prototype.toString.call(text) === "[object Array]") {
  7297. for (var i = 0; i < text.length; i++) {
  7298. tempWidth = this.getStringUnitWidth(text[i]) * fontSize;
  7299. if (width < tempWidth) {
  7300. width = tempWidth;
  7301. }
  7302. }
  7303. if (width !== 0) {
  7304. amountOfLines = text.length;
  7305. }
  7306. } else {
  7307. console.error("getTextDimensions expects text-parameter to be of type String or an Array of Strings.");
  7308. }
  7309. width = width / scaleFactor;
  7310. height = amountOfLines * fontSize * 1.15 / scaleFactor;
  7311. return {
  7312. w: width,
  7313. h: height
  7314. };
  7315. };
  7316. /**
  7317. * @name cellAddPage
  7318. * @function
  7319. */
  7320. jsPDFAPI.cellAddPage = function () {
  7321. var margins = this.margins || NO_MARGINS;
  7322. this.addPage();
  7323. setLastCellPosition(margins.left, margins.top, undefined, undefined); //setLastCellPosition(undefined, undefined, undefined, undefined, undefined);
  7324. pages += 1;
  7325. };
  7326. /**
  7327. * @name cellInitialize
  7328. * @function
  7329. */
  7330. jsPDFAPI.cellInitialize = function () {
  7331. lastCellPos = {
  7332. x: undefined,
  7333. y: undefined,
  7334. w: undefined,
  7335. h: undefined,
  7336. ln: undefined
  7337. };
  7338. pages = 1;
  7339. };
  7340. /**
  7341. * @name cell
  7342. * @function
  7343. * @param {number} x
  7344. * @param {number} y
  7345. * @param {number} w
  7346. * @param {number} h
  7347. * @param {string} txt
  7348. * @param {number} ln lineNumber
  7349. * @param {string} align
  7350. * @return {jsPDF} jsPDF-instance
  7351. */
  7352. jsPDFAPI.cell = function (x, y, w, h, txt, ln, align) {
  7353. var curCell = getLastCellPosition();
  7354. var pgAdded = false; // If this is not the first cell, we must change its position
  7355. if (curCell.ln !== undefined) {
  7356. if (curCell.ln === ln) {
  7357. //Same line
  7358. x = curCell.x + curCell.w;
  7359. y = curCell.y;
  7360. } else {
  7361. //New line
  7362. var margins = this.margins || NO_MARGINS;
  7363. if (curCell.y + curCell.h + h + margin >= this.internal.pageSize.getHeight() - margins.bottom) {
  7364. this.cellAddPage();
  7365. pgAdded = true;
  7366. if (this.printHeaders && this.tableHeaderRow) {
  7367. this.printHeaderRow(ln, true);
  7368. }
  7369. } //We ignore the passed y: the lines may have different heights
  7370. y = getLastCellPosition().y + getLastCellPosition().h;
  7371. if (pgAdded) y = margin + 10;
  7372. }
  7373. }
  7374. if (txt[0] !== undefined) {
  7375. if (this.printingHeaderRow) {
  7376. this.rect(x, y, w, h, "FD");
  7377. } else {
  7378. this.rect(x, y, w, h);
  7379. }
  7380. if (align === "right") {
  7381. if (!(txt instanceof Array)) {
  7382. txt = [txt];
  7383. }
  7384. for (var i = 0; i < txt.length; i++) {
  7385. var currentLine = txt[i];
  7386. var textSize = this.getStringUnitWidth(currentLine) * this.internal.getFontSize();
  7387. this.text(currentLine, x + w - textSize - padding, y + this.internal.getLineHeight() * (i + 1));
  7388. }
  7389. } else {
  7390. this.text(txt, x + padding, y + this.internal.getLineHeight());
  7391. }
  7392. }
  7393. setLastCellPosition(x, y, w, h, ln);
  7394. return this;
  7395. };
  7396. /**
  7397. * Return the maximum value from an array
  7398. *
  7399. * @name arrayMax
  7400. * @function
  7401. * @param {Array} array
  7402. * @param comparisonFn
  7403. * @returns {number}
  7404. */
  7405. jsPDFAPI.arrayMax = function (array, comparisonFn) {
  7406. var max = array[0],
  7407. i,
  7408. ln,
  7409. item;
  7410. for (i = 0, ln = array.length; i < ln; i += 1) {
  7411. item = array[i];
  7412. if (comparisonFn) {
  7413. if (comparisonFn(max, item) === -1) {
  7414. max = item;
  7415. }
  7416. } else {
  7417. if (item > max) {
  7418. max = item;
  7419. }
  7420. }
  7421. }
  7422. return max;
  7423. };
  7424. /**
  7425. * Create a table from a set of data.
  7426. * @name table
  7427. * @function
  7428. * @param {Integer} [x] : left-position for top-left corner of table
  7429. * @param {Integer} [y] top-position for top-left corner of table
  7430. * @param {Object[]} [data] As array of objects containing key-value pairs corresponding to a row of data.
  7431. * @param {String[]} [headers] Omit or null to auto-generate headers at a performance cost
  7432. * @param {Object} [config.printHeaders] True to print column headers at the top of every page
  7433. * @param {Object} [config.autoSize] True to dynamically set the column widths to match the widest cell value
  7434. * @param {Object} [config.margins] margin values for left, top, bottom, and width
  7435. * @param {Object} [config.fontSize] Integer fontSize to use (optional)
  7436. * @returns {jsPDF} jsPDF-instance
  7437. */
  7438. jsPDFAPI.table = function (x, y, data, headers, config) {
  7439. if (!data) {
  7440. throw "No data for PDF table";
  7441. }
  7442. var headerNames = [],
  7443. headerPrompts = [],
  7444. header,
  7445. i,
  7446. ln,
  7447. cln,
  7448. columnMatrix = {},
  7449. columnWidths = {},
  7450. columnData,
  7451. column,
  7452. columnMinWidths = [],
  7453. j,
  7454. tableHeaderConfigs = [],
  7455. model,
  7456. jln,
  7457. func,
  7458. //set up defaults. If a value is provided in config, defaults will be overwritten:
  7459. autoSize = false,
  7460. printHeaders = true,
  7461. fontSize = 12,
  7462. margins = NO_MARGINS;
  7463. margins.width = this.internal.pageSize.getWidth();
  7464. if (config) {
  7465. //override config defaults if the user has specified non-default behavior:
  7466. if (config.autoSize === true) {
  7467. autoSize = true;
  7468. }
  7469. if (config.printHeaders === false) {
  7470. printHeaders = false;
  7471. }
  7472. if (config.fontSize) {
  7473. fontSize = config.fontSize;
  7474. }
  7475. if (config.css && typeof config.css["font-size"] !== "undefined") {
  7476. fontSize = config.css["font-size"] * 16;
  7477. }
  7478. if (config.margins) {
  7479. margins = config.margins;
  7480. }
  7481. }
  7482. /**
  7483. * @property {Number} lnMod
  7484. * Keep track of the current line number modifier used when creating cells
  7485. */
  7486. this.lnMod = 0;
  7487. lastCellPos = {
  7488. x: undefined,
  7489. y: undefined,
  7490. w: undefined,
  7491. h: undefined,
  7492. ln: undefined
  7493. }, pages = 1;
  7494. this.printHeaders = printHeaders;
  7495. this.margins = margins;
  7496. this.setFontSize(fontSize);
  7497. this.table_font_size = fontSize; // Set header values
  7498. if (headers === undefined || headers === null) {
  7499. // No headers defined so we derive from data
  7500. headerNames = Object.keys(data[0]);
  7501. } else if (headers[0] && typeof headers[0] !== "string") {
  7502. var px2pt = 0.264583 * 72 / 25.4; // Split header configs into names and prompts
  7503. for (i = 0, ln = headers.length; i < ln; i += 1) {
  7504. header = headers[i];
  7505. headerNames.push(header.name);
  7506. headerPrompts.push(header.prompt);
  7507. columnWidths[header.name] = header.width * px2pt;
  7508. }
  7509. } else {
  7510. headerNames = headers;
  7511. }
  7512. if (autoSize) {
  7513. // Create a matrix of columns e.g., {column_title: [row1_Record, row2_Record]}
  7514. func = function func(rec) {
  7515. return rec[header];
  7516. };
  7517. for (i = 0, ln = headerNames.length; i < ln; i += 1) {
  7518. header = headerNames[i];
  7519. columnMatrix[header] = data.map(func); // get header width
  7520. columnMinWidths.push(this.getTextDimensions(headerPrompts[i] || header, {
  7521. scaleFactor: 1
  7522. }).w);
  7523. column = columnMatrix[header]; // get cell widths
  7524. for (j = 0, cln = column.length; j < cln; j += 1) {
  7525. columnData = column[j];
  7526. columnMinWidths.push(this.getTextDimensions(columnData, {
  7527. scaleFactor: 1
  7528. }).w);
  7529. } // get final column width
  7530. columnWidths[header] = jsPDFAPI.arrayMax(columnMinWidths); //have to reset
  7531. columnMinWidths = [];
  7532. }
  7533. } // -- Construct the table
  7534. if (printHeaders) {
  7535. var lineHeight = this.calculateLineHeight(headerNames, columnWidths, headerPrompts.length ? headerPrompts : headerNames); // Construct the header row
  7536. for (i = 0, ln = headerNames.length; i < ln; i += 1) {
  7537. header = headerNames[i];
  7538. tableHeaderConfigs.push([x, y, columnWidths[header], lineHeight, String(headerPrompts.length ? headerPrompts[i] : header)]);
  7539. } // Store the table header config
  7540. this.setTableHeaderRow(tableHeaderConfigs); // Print the header for the start of the table
  7541. this.printHeaderRow(1, false);
  7542. } // Construct the data rows
  7543. for (i = 0, ln = data.length; i < ln; i += 1) {
  7544. var lineHeight;
  7545. model = data[i];
  7546. lineHeight = this.calculateLineHeight(headerNames, columnWidths, model);
  7547. for (j = 0, jln = headerNames.length; j < jln; j += 1) {
  7548. header = headerNames[j];
  7549. this.cell(x, y, columnWidths[header], lineHeight, model[header], i + 2, header.align);
  7550. }
  7551. }
  7552. this.lastCellPos = lastCellPos;
  7553. this.table_x = x;
  7554. this.table_y = y;
  7555. return this;
  7556. };
  7557. /**
  7558. * Calculate the height for containing the highest column
  7559. *
  7560. * @name calculateLineHeight
  7561. * @function
  7562. * @param {String[]} headerNames is the header, used as keys to the data
  7563. * @param {Integer[]} columnWidths is size of each column
  7564. * @param {Object[]} model is the line of data we want to calculate the height of
  7565. * @returns {number} lineHeight
  7566. */
  7567. jsPDFAPI.calculateLineHeight = function (headerNames, columnWidths, model) {
  7568. var header,
  7569. lineHeight = 0;
  7570. for (var j = 0; j < headerNames.length; j++) {
  7571. header = headerNames[j];
  7572. model[header] = this.splitTextToSize(String(model[header]), columnWidths[header] - padding);
  7573. var h = this.internal.getLineHeight() * model[header].length + padding;
  7574. if (h > lineHeight) lineHeight = h;
  7575. }
  7576. return lineHeight;
  7577. };
  7578. /**
  7579. * Store the config for outputting a table header
  7580. *
  7581. * @name setTableHeaderRow
  7582. * @function
  7583. * @param {Object[]} config
  7584. * An array of cell configs that would define a header row: Each config matches the config used by jsPDFAPI.cell
  7585. * except the ln parameter is excluded
  7586. */
  7587. jsPDFAPI.setTableHeaderRow = function (config) {
  7588. this.tableHeaderRow = config;
  7589. };
  7590. /**
  7591. * Output the store header row
  7592. *
  7593. * @name printHeaderRow
  7594. * @function
  7595. * @param {number} lineNumber The line number to output the header at
  7596. * @param {boolean} new_page
  7597. */
  7598. jsPDFAPI.printHeaderRow = function (lineNumber, new_page) {
  7599. if (!this.tableHeaderRow) {
  7600. throw "Property tableHeaderRow does not exist.";
  7601. }
  7602. var tableHeaderCell, tmpArray, i, ln;
  7603. this.printingHeaderRow = true;
  7604. if (headerFunction !== undefined) {
  7605. var position = headerFunction(this, pages);
  7606. setLastCellPosition(position[0], position[1], position[2], position[3], -1);
  7607. }
  7608. this.setFontStyle("bold");
  7609. var tempHeaderConf = [];
  7610. for (i = 0, ln = this.tableHeaderRow.length; i < ln; i += 1) {
  7611. this.setFillColor(200, 200, 200);
  7612. tableHeaderCell = this.tableHeaderRow[i];
  7613. if (new_page) {
  7614. this.margins.top = margin;
  7615. tableHeaderCell[1] = this.margins && this.margins.top || 0;
  7616. tempHeaderConf.push(tableHeaderCell);
  7617. }
  7618. tmpArray = [].concat(tableHeaderCell);
  7619. this.cell.apply(this, tmpArray.concat(lineNumber));
  7620. }
  7621. if (tempHeaderConf.length > 0) {
  7622. this.setTableHeaderRow(tempHeaderConf);
  7623. }
  7624. this.setFontStyle("normal");
  7625. this.printingHeaderRow = false;
  7626. };
  7627. })(jsPDF.API);
  7628. /**
  7629. * jsPDF Context2D PlugIn Copyright (c) 2014 Steven Spungin (TwelveTone LLC) steven@twelvetone.tv
  7630. *
  7631. * Licensed under the MIT License. http://opensource.org/licenses/mit-license
  7632. */
  7633. /**
  7634. * TODO implement stroke opacity (refactor from fill() method )
  7635. * TODO transform angle and radii parameters
  7636. */
  7637. /**
  7638. * This plugin mimics the HTML5 Canvas's context2d.
  7639. *
  7640. * The goal is to provide a way for current canvas implementations to print directly to a PDF.
  7641. *
  7642. * @name context2d
  7643. * @module
  7644. */
  7645. (function (jsPDFAPI, globalObj) {
  7646. jsPDFAPI.events.push(["initialized", function () {
  7647. this.context2d.pdf = this;
  7648. this.context2d.internal.pdf = this;
  7649. this.context2d.ctx = new context();
  7650. this.context2d.ctxStack = [];
  7651. this.context2d.path = [];
  7652. }]);
  7653. jsPDFAPI.context2d = {
  7654. /**
  7655. * @name pageWrapXEnabled
  7656. * @type {boolean}
  7657. * @default false
  7658. */
  7659. pageWrapXEnabled: false,
  7660. /**
  7661. * @name pageWrapYEnabled
  7662. * @type {boolean}
  7663. * @default false
  7664. */
  7665. pageWrapYEnabled: false,
  7666. /**
  7667. * @name pageWrapX
  7668. * @type {number}
  7669. * @default 9999999
  7670. */
  7671. pageWrapX: 9999999,
  7672. /**
  7673. * @name pageWrapY
  7674. * @type {number}
  7675. * @default 9999999
  7676. */
  7677. pageWrapY: 9999999,
  7678. /**
  7679. * @name ctx
  7680. * @type {Object}
  7681. */
  7682. ctx: new context(),
  7683. /**
  7684. * @name f2
  7685. * @type {function}
  7686. * @ignore
  7687. */
  7688. f2: function f2(number) {
  7689. return number.toFixed(2);
  7690. },
  7691. /**
  7692. * Fills the current drawing (path)
  7693. *
  7694. * @name fill
  7695. * @function
  7696. * @description The fill() method fills the current drawing (path). The default color is black.
  7697. */
  7698. fill: function fill() {
  7699. //evenodd or nonzero (default)
  7700. var rule = "fill";
  7701. this._drawPaths(rule, false);
  7702. },
  7703. /**
  7704. * Actually draws the path you have defined
  7705. *
  7706. * @name stroke
  7707. * @function
  7708. * @description The stroke() method actually draws the path you have defined with all those moveTo() and lineTo() methods. The default color is black.
  7709. */
  7710. stroke: function stroke() {
  7711. var rule = "stroke";
  7712. this._drawPaths(rule, false);
  7713. },
  7714. /**
  7715. * Begins a path, or resets the current
  7716. *
  7717. * @name beginPath
  7718. * @function
  7719. * @description The beginPath() method begins a path, or resets the current path.
  7720. */
  7721. beginPath: function beginPath() {
  7722. this._resetPath();
  7723. this._beginPath();
  7724. },
  7725. /**
  7726. * Moves the path to the specified point in the canvas, without creating a line
  7727. *
  7728. * @name moveTo
  7729. * @function
  7730. * @param x {Number} The x-coordinate of where to move the path to
  7731. * @param y {Number} The y-coordinate of where to move the path to
  7732. */
  7733. moveTo: function moveTo(x, y) {
  7734. x = this._wrapX(x);
  7735. y = this._wrapY(y);
  7736. var xpt = this._matrix_map_point(this.ctx._transform, [x, y]);
  7737. x = xpt[0];
  7738. y = xpt[1];
  7739. var obj = {
  7740. type: "mt",
  7741. x: x,
  7742. y: y
  7743. };
  7744. this.path.push(obj);
  7745. },
  7746. /**
  7747. * Creates a path from the current point back to the starting point
  7748. *
  7749. * @name closePath
  7750. * @function
  7751. * @description The closePath() method creates a path from the current point back to the starting point.
  7752. */
  7753. closePath: function closePath() {
  7754. this._closePath();
  7755. var obj = {
  7756. type: "close"
  7757. };
  7758. this.path.push(obj);
  7759. },
  7760. /**
  7761. * Adds a new point and creates a line to that point from the last specified point in the canvas
  7762. *
  7763. * @name lineTo
  7764. * @function
  7765. * @param x The x-coordinate of where to create the line to
  7766. * @param y The y-coordinate of where to create the line to
  7767. * @description The lineTo() method adds a new point and creates a line TO that point FROM the last specified point in the canvas (this method does not draw the line).
  7768. */
  7769. lineTo: function lineTo(x, y) {
  7770. x = this._wrapX(x);
  7771. y = this._wrapY(y);
  7772. var xpt = this._matrix_map_point(this.ctx._transform, [x, y]);
  7773. x = xpt[0];
  7774. y = xpt[1];
  7775. var obj = {
  7776. type: "lt",
  7777. x: x,
  7778. y: y
  7779. };
  7780. this.path.push(obj);
  7781. },
  7782. /**
  7783. * Clips a region of any shape and size from the original canvas
  7784. *
  7785. * @name clip
  7786. * @function
  7787. * @description The clip() method clips a region of any shape and size from the original canvas.
  7788. */
  7789. clip: function clip() {
  7790. this._drawPaths(null, true);
  7791. },
  7792. /**
  7793. * Creates a cubic Bézier curve
  7794. *
  7795. * @name quadraticCurveTo
  7796. * @function
  7797. * @param cpx {Number} The x-coordinate of the Bézier control point
  7798. * @param cpy {Number} The y-coordinate of the Bézier control point
  7799. * @param x {Number} The x-coordinate of the ending point
  7800. * @param y {Number} The y-coordinate of the ending point
  7801. * @description The quadraticCurveTo() method adds a point to the current path by using the specified control points that represent a quadratic Bézier curve.<br /><br /> A quadratic Bézier curve requires two points. The first point is a control point that is used in the quadratic Bézier calculation and the second point is the ending point for the curve. The starting point for the curve is the last point in the current path. If a path does not exist, use the beginPath() and moveTo() methods to define a starting point.
  7802. */
  7803. quadraticCurveTo: function quadraticCurveTo(cpx, cpy, x, y) {
  7804. var x1 = this._wrapX(cpx);
  7805. var y1 = this._wrapY(cpy);
  7806. x = this._wrapX(x);
  7807. y = this._wrapY(y);
  7808. var xpt;
  7809. xpt = this._matrix_map_point(this.ctx._transform, [x, y]);
  7810. x = xpt[0];
  7811. y = xpt[1];
  7812. xpt = this._matrix_map_point(this.ctx._transform, [x1, y1]);
  7813. x1 = xpt[0];
  7814. y1 = xpt[1];
  7815. var obj = {
  7816. type: "qct",
  7817. x1: x1,
  7818. y1: y1,
  7819. x: x,
  7820. y: y
  7821. };
  7822. this.path.push(obj);
  7823. },
  7824. /**
  7825. * Creates a cubic Bézier curve
  7826. *
  7827. * @name bezierCurveTo
  7828. * @function
  7829. * @param cp1x {Number} The x-coordinate of the first Bézier control point
  7830. * @param cp1y {Number} The y-coordinate of the first Bézier control point
  7831. * @param cp2x {Number} The x-coordinate of the second Bézier control point
  7832. * @param cp2y {Number} The y-coordinate of the second Bézier control point
  7833. * @param x {Number} The x-coordinate of the ending point
  7834. * @param y {Number} The y-coordinate of the ending point
  7835. * @description The bezierCurveTo() method adds a point to the current path by using the specified control points that represent a cubic Bézier curve. <br /><br />A cubic bezier curve requires three points. The first two points are control points that are used in the cubic Bézier calculation and the last point is the ending point for the curve. The starting point for the curve is the last point in the current path. If a path does not exist, use the beginPath() and moveTo() methods to define a starting point.
  7836. */
  7837. bezierCurveTo: function bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) {
  7838. var x1 = this._wrapX(cp1x);
  7839. var y1 = this._wrapY(cp1y);
  7840. var x2 = this._wrapX(cp2x);
  7841. var y2 = this._wrapY(cp2y);
  7842. x = this._wrapX(x);
  7843. y = this._wrapY(y);
  7844. var xpt;
  7845. xpt = this._matrix_map_point(this.ctx._transform, [x, y]);
  7846. x = xpt[0];
  7847. y = xpt[1];
  7848. xpt = this._matrix_map_point(this.ctx._transform, [x1, y1]);
  7849. x1 = xpt[0];
  7850. y1 = xpt[1];
  7851. xpt = this._matrix_map_point(this.ctx._transform, [x2, y2]);
  7852. x2 = xpt[0];
  7853. y2 = xpt[1];
  7854. var obj = {
  7855. type: "bct",
  7856. x1: x1,
  7857. y1: y1,
  7858. x2: x2,
  7859. y2: y2,
  7860. x: x,
  7861. y: y
  7862. };
  7863. this.path.push(obj);
  7864. },
  7865. /**
  7866. * Creates an arc/curve (used to create circles, or parts of circles)
  7867. *
  7868. * @name arc
  7869. * @function
  7870. * @param x {Number} The x-coordinate of the center of the circle
  7871. * @param y {Number} The y-coordinate of the center of the circle
  7872. * @param radius {Number} The radius of the circle
  7873. * @param startAngle {Number} The starting angle, in radians (0 is at the 3 o'clock position of the arc's circle)
  7874. * @param endAngle {Number} The ending angle, in radians
  7875. * @param counterclockwise {Boolean} Optional. Specifies whether the drawing should be counterclockwise or clockwise. False is default, and indicates clockwise, while true indicates counter-clockwise.
  7876. * @description The arc() method creates an arc/curve (used to create circles, or parts of circles).
  7877. */
  7878. arc: function arc(x, y, radius, startAngle, endAngle, counterclockwise) {
  7879. x = this._wrapX(x);
  7880. y = this._wrapY(y);
  7881. counterclockwise = counterclockwise || false;
  7882. if (!this._matrix_is_identity(this.ctx._transform)) {
  7883. var xpt = this._matrix_map_point(this.ctx._transform, [x, y]);
  7884. x = xpt[0];
  7885. y = xpt[1];
  7886. var x_radPt0 = this._matrix_map_point(this.ctx._transform, [0, 0]);
  7887. var x_radPt = this._matrix_map_point(this.ctx._transform, [0, radius]);
  7888. radius = Math.sqrt(Math.pow(x_radPt[0] - x_radPt0[0], 2) + Math.pow(x_radPt[1] - x_radPt0[1], 2));
  7889. }
  7890. var obj = {
  7891. type: "arc",
  7892. x: x,
  7893. y: y,
  7894. radius: radius,
  7895. startAngle: startAngle,
  7896. endAngle: endAngle,
  7897. counterclockwise: counterclockwise
  7898. };
  7899. this.path.push(obj);
  7900. },
  7901. /**
  7902. * Creates an arc/curve between two tangents
  7903. *
  7904. * @name arcTo
  7905. * @function
  7906. * @param x1 {Number} The x-coordinate of the first tangent
  7907. * @param y1 {Number} The y-coordinate of the first tangent
  7908. * @param x2 {Number} The x-coordinate of the second tangent
  7909. * @param y2 {Number} The y-coordinate of the second tangent
  7910. * @param radius The radius of the
  7911. * @description The arcTo() method creates an arc/curve between two tangents on the canvas.
  7912. */
  7913. arcTo: function arcTo(x1, y1, x2, y2, radius) {//TODO needs to be implemented
  7914. },
  7915. //Rectangles
  7916. /**
  7917. * Creates a rectangle
  7918. *
  7919. * @name rect
  7920. * @function
  7921. * @param x {Number} The x-coordinate of the upper-left corner of the rectangle
  7922. * @param y {Number} The y-coordinate of the upper-left corner of the rectangle
  7923. * @param w {Number} The width of the rectangle, in pixels
  7924. * @param h {Number} The height of the rectangle, in pixels
  7925. * @description The rect() method creates a rectangle.
  7926. */
  7927. rect: function rect(x, y, w, h) {
  7928. this.moveTo(x, y);
  7929. this.lineTo(x + w, y);
  7930. this.lineTo(x + w, y + h);
  7931. this.lineTo(x, y + h);
  7932. this.lineTo(x, y);
  7933. this.lineTo(x + w, y);
  7934. this.lineTo(x, y);
  7935. },
  7936. /**
  7937. * Draws a "filled" rectangle
  7938. *
  7939. * @name fillRect
  7940. * @function
  7941. * @param x {Number} The x-coordinate of the upper-left corner of the rectangle
  7942. * @param y {Number} The y-coordinate of the upper-left corner of the rectangle
  7943. * @param w {Number} The width of the rectangle, in pixels
  7944. * @param h {Number} The height of the rectangle, in pixels
  7945. * @description The fillRect() method draws a "filled" rectangle. The default color of the fill is black.
  7946. */
  7947. fillRect: function fillRect(x, y, w, h) {
  7948. if (this._isFillTransparent()) {
  7949. return;
  7950. }
  7951. x = this._wrapX(x);
  7952. y = this._wrapY(y);
  7953. var xpt1 = this._matrix_map_point(this.ctx._transform, [x, y]);
  7954. var xpt2 = this._matrix_map_point(this.ctx._transform, [x + w, y]);
  7955. var xpt3 = this._matrix_map_point(this.ctx._transform, [x + w, y + h]);
  7956. var xpt4 = this._matrix_map_point(this.ctx._transform, [x, y + h]);
  7957. this.pdf.internal.out("q");
  7958. this.pdf.setLineCap("butt");
  7959. this.pdf.setLineJoin("miter");
  7960. var lines = [];
  7961. lines.push([xpt2[0] - xpt1[0], xpt2[1] - xpt1[1]]);
  7962. lines.push([xpt3[0] - xpt2[0], xpt3[1] - xpt2[1]]);
  7963. lines.push([xpt4[0] - xpt3[0], xpt4[1] - xpt3[1]]);
  7964. lines.push([xpt1[0] - xpt4[0], xpt1[1] - xpt4[1]]);
  7965. lines.push([xpt2[0] - xpt1[0], xpt2[1] - xpt1[1]]);
  7966. lines.push([xpt1[0] - xpt2[0], xpt1[1] - xpt2[1]]);
  7967. this.pdf.lines(lines, xpt1[0], xpt1[1], null, "F");
  7968. this.pdf.internal.out("Q");
  7969. },
  7970. /**
  7971. * Draws a rectangle (no fill)
  7972. *
  7973. * @name strokeRect
  7974. * @function
  7975. * @param x {Number} The x-coordinate of the upper-left corner of the rectangle
  7976. * @param y {Number} The y-coordinate of the upper-left corner of the rectangle
  7977. * @param w {Number} The width of the rectangle, in pixels
  7978. * @param h {Number} The height of the rectangle, in pixels
  7979. * @description The strokeRect() method draws a rectangle (no fill). The default color of the stroke is black.
  7980. */
  7981. strokeRect: function strokeRect(x, y, w, h) {
  7982. if (this._isStrokeTransparent()) {
  7983. return;
  7984. }
  7985. x = this._wrapX(x);
  7986. y = this._wrapY(y);
  7987. var xpt1 = this._matrix_map_point(this.ctx._transform, [x, y]);
  7988. var xpt2 = this._matrix_map_point(this.ctx._transform, [x + w, y]);
  7989. var xpt3 = this._matrix_map_point(this.ctx._transform, [x + w, y + h]);
  7990. var xpt4 = this._matrix_map_point(this.ctx._transform, [x, y + h]);
  7991. var lines = [];
  7992. lines.push([xpt2[0] - xpt1[0], xpt2[1] - xpt1[1]]);
  7993. lines.push([xpt3[0] - xpt2[0], xpt3[1] - xpt2[1]]);
  7994. lines.push([xpt4[0] - xpt3[0], xpt4[1] - xpt3[1]]);
  7995. lines.push([xpt1[0] - xpt4[0], xpt1[1] - xpt4[1]]);
  7996. lines.push([xpt2[0] - xpt1[0], xpt2[1] - xpt1[1]]);
  7997. lines.push([xpt1[0] - xpt2[0], xpt1[1] - xpt2[1]]);
  7998. this.pdf.lines(lines, xpt1[0], xpt1[1], null, "S");
  7999. },
  8000. /**
  8001. * Clears the specified pixels within a given rectangle
  8002. *
  8003. * @name clearRect
  8004. * @function
  8005. * @param x {Number} The x-coordinate of the upper-left corner of the rectangle
  8006. * @param y {Number} The y-coordinate of the upper-left corner of the rectangle
  8007. * @param w {Number} The width of the rectangle to clear, in pixels
  8008. * @param h {Number} The height of the rectangle to clear, in pixels
  8009. * @description We cannot clear PDF commands that were already written to PDF, so we use white instead. <br />
  8010. * As a special case, read a special flag (ignoreClearRect) and do nothing if it is set.
  8011. * This results in all calls to clearRect() to do nothing, and keep the canvas transparent.
  8012. * This flag is stored in the save/restore context and is managed the same way as other drawing states.
  8013. *
  8014. */
  8015. clearRect: function clearRect(x, y, w, h) {
  8016. if (this.ctx.ignoreClearRect) {
  8017. return;
  8018. }
  8019. this.save();
  8020. this._setFillStyle("#ffffff");
  8021. this.fillRect(x, y, w, h);
  8022. this.restore();
  8023. },
  8024. //Other
  8025. /**
  8026. * Saves the state of the current context
  8027. *
  8028. * @name save
  8029. * @function
  8030. */
  8031. save: function save() {
  8032. this.pdf.internal.out("q");
  8033. this.ctx._fontSize = this.pdf.internal.getFontSize();
  8034. var ctx = new context();
  8035. ctx.copy(this.ctx);
  8036. this.ctxStack.push(this.ctx);
  8037. this.ctx = ctx;
  8038. },
  8039. /**
  8040. * Returns previously saved path state and attributes
  8041. *
  8042. * @name restore
  8043. * @function
  8044. */
  8045. restore: function restore() {
  8046. this.pdf.internal.out("Q");
  8047. if (this.ctxStack.length !== 0) {
  8048. this.ctx = this.ctxStack.pop();
  8049. this._setFillStyle(this.ctx.fillStyle);
  8050. this._setStrokeStyle(this.ctx.strokeStyle);
  8051. this._setFont(this.ctx.font);
  8052. this.pdf.setFontSize(this.ctx._fontSize);
  8053. this._setLineCap(this.ctx.lineCap);
  8054. this._setLineWidth(this.ctx.lineWidth);
  8055. this._setLineJoin(this.ctx.lineJoin);
  8056. }
  8057. },
  8058. // some stubs
  8059. /**
  8060. * @name createEvent
  8061. * @function
  8062. */
  8063. createEvent: function createEvent() {
  8064. console.log("createEvent not implemented (yet)");
  8065. },
  8066. /**
  8067. * @name toDataURL
  8068. * @function
  8069. */
  8070. toDataURL: function toDataURL() {
  8071. console.log("toDataUrl not implemented (yet)");
  8072. },
  8073. //helper functions
  8074. _beginPath: function _beginPath() {
  8075. this.path.push({
  8076. type: "begin"
  8077. });
  8078. },
  8079. _closePath: function _closePath() {
  8080. var pathBegin = {
  8081. x: 0,
  8082. y: 0
  8083. };
  8084. var i = 0;
  8085. var len = this.path.length;
  8086. for (i = this.path.length - 1; i !== -1; i--) {
  8087. if (this.path[i].type === "begin") {
  8088. if (_typeof(this.path[i + 1]) === "object" && typeof this.path[i + 1].x === "number") {
  8089. pathBegin = {
  8090. x: this.path[i + 1].x,
  8091. y: this.path[i + 1].y
  8092. };
  8093. var obj = {
  8094. type: "lt",
  8095. x: pathBegin.x,
  8096. y: pathBegin.y
  8097. };
  8098. this.path.push(obj);
  8099. break;
  8100. }
  8101. }
  8102. } //TODO Repeat second move to get lineJoins correct, maybe only when lineJoin active in _drawPaths
  8103. if (_typeof(this.path[i + 2]) === "object" && typeof this.path[i + 2].x === "number") {
  8104. this.path.push(JSON.parse(JSON.stringify(this.path[i + 2])));
  8105. }
  8106. },
  8107. _resetPath: function _resetPath() {
  8108. this.path = [];
  8109. },
  8110. /**
  8111. * Get the decimal values of r, g, b and a
  8112. *
  8113. * @name _getRGBA
  8114. * @function
  8115. * @private
  8116. * @ignore
  8117. */
  8118. _getRGBA: function _getRGBA(style) {
  8119. var r, g, b, a;
  8120. if (style.isCanvasGradient === true) {
  8121. style = style.getColor();
  8122. }
  8123. var rgbColor = new RGBColor(style);
  8124. if (!style) {
  8125. return {
  8126. r: 0,
  8127. g: 0,
  8128. b: 0,
  8129. a: 0,
  8130. style: style
  8131. };
  8132. }
  8133. if (this.internal.rxTransparent.test(style)) {
  8134. r = 0;
  8135. g = 0;
  8136. b = 0;
  8137. a = 0;
  8138. } else {
  8139. var m = this.internal.rxRgb.exec(style);
  8140. if (m != null) {
  8141. r = parseInt(m[1]);
  8142. g = parseInt(m[2]);
  8143. b = parseInt(m[3]);
  8144. a = 1;
  8145. } else {
  8146. m = this.internal.rxRgba.exec(style);
  8147. if (m != null) {
  8148. r = parseInt(m[1]);
  8149. g = parseInt(m[2]);
  8150. b = parseInt(m[3]);
  8151. a = parseFloat(m[4]);
  8152. } else {
  8153. a = 1;
  8154. if (style.charAt(0) != "#") {
  8155. if (rgbColor.ok) {
  8156. style = rgbColor.toHex();
  8157. } else {
  8158. style = "#000000";
  8159. }
  8160. }
  8161. if (style.length === 4) {
  8162. r = style.substring(1, 2);
  8163. r += r;
  8164. g = style.substring(2, 3);
  8165. g += g;
  8166. b = style.substring(3, 4);
  8167. b += b;
  8168. } else {
  8169. r = style.substring(1, 3);
  8170. g = style.substring(3, 5);
  8171. b = style.substring(5, 7);
  8172. }
  8173. r = parseInt(r, 16);
  8174. g = parseInt(g, 16);
  8175. b = parseInt(b, 16);
  8176. }
  8177. }
  8178. }
  8179. return {
  8180. r: r,
  8181. g: g,
  8182. b: b,
  8183. a: a,
  8184. style: style
  8185. };
  8186. },
  8187. /**
  8188. * @name _isFilllTransparent
  8189. * @function
  8190. * @private
  8191. * @ignore
  8192. * @returns {Boolean}
  8193. */
  8194. _isFillTransparent: function _isFillTransparent() {
  8195. return this.ctx._isFillTransparent || this.globalAlpha == 0;
  8196. },
  8197. /**
  8198. * @name _isStrokeTransparent
  8199. * @function
  8200. * @private
  8201. * @ignore
  8202. * @returns {Boolean}
  8203. */
  8204. _isStrokeTransparent: function _isStrokeTransparent() {
  8205. return this.ctx._isStrokeTransparent || this.globalAlpha == 0;
  8206. },
  8207. /**
  8208. * Sets the color, gradient, or pattern used to fill the drawing
  8209. *
  8210. * @name _setFillStyle
  8211. * @function
  8212. * @private
  8213. * @ignore
  8214. */
  8215. _setFillStyle: function _setFillStyle(style) {
  8216. var rgba;
  8217. rgba = this._getRGBA(style);
  8218. this.ctx.fillStyle = style;
  8219. this.ctx._isFillTransparent = rgba.a === 0;
  8220. this.ctx._fillOpacity = rgba.a;
  8221. this.pdf.setFillColor(rgba.r, rgba.g, rgba.b, {
  8222. a: rgba.a
  8223. });
  8224. this.pdf.setTextColor(rgba.r, rgba.g, rgba.b, {
  8225. a: rgba.a
  8226. });
  8227. },
  8228. /**
  8229. * Sets the color, gradient, or pattern used for strokes
  8230. *
  8231. * @name _setStrokeStyle
  8232. * @function
  8233. * @private
  8234. * @ignore
  8235. */
  8236. _setStrokeStyle: function _setStrokeStyle(style) {
  8237. var rgba = this._getRGBA(style);
  8238. this.ctx.strokeStyle = rgba.style;
  8239. this.ctx._isStrokeTransparent = rgba.a === 0;
  8240. this.ctx._strokeOpacity = rgba.a; //TODO jsPDF to handle rgba
  8241. if (rgba.a === 0) {
  8242. this.pdf.setDrawColor(255, 255, 255);
  8243. } else if (rgba.a === 1) {
  8244. this.pdf.setDrawColor(rgba.r, rgba.g, rgba.b);
  8245. } else {
  8246. //this.pdf.setDrawColor(rgba.r, rgba.g, rgba.b, {a: rgba.a});
  8247. this.pdf.setDrawColor(rgba.r, rgba.g, rgba.b);
  8248. }
  8249. },
  8250. /**
  8251. * Sets font properties for text content
  8252. *
  8253. * @name _setFont
  8254. * @function
  8255. * @param {String} The font property uses the same syntax as the CSS font property.
  8256. * @private
  8257. * @ignore
  8258. */
  8259. _setFont: function _setFont(font) {
  8260. this.ctx.font = font;
  8261. var rx, m; //source: https://stackoverflow.com/a/10136041
  8262. rx = /^\s*(?=(?:(?:[-a-z]+\s*){0,2}(italic|oblique))?)(?=(?:(?:[-a-z]+\s*){0,2}(small-caps))?)(?=(?:(?:[-a-z]+\s*){0,2}(bold(?:er)?|lighter|[1-9]00))?)(?:(?:normal|\1|\2|\3)\s*){0,3}((?:xx?-)?(?:small|large)|medium|smaller|larger|[.\d]+(?:\%|in|[cem]m|ex|p[ctx]))(?:\s*\/\s*(normal|[.\d]+(?:\%|in|[cem]m|ex|p[ctx])))?\s*([-,\"\'\sa-z]+?)\s*$/i;
  8263. m = rx.exec(font);
  8264. if (m != null) {
  8265. var fontStyle = m[1];
  8266. var fontVariant = m[2];
  8267. var fontWeight = m[3];
  8268. var fontSize = m[4];
  8269. var fontSizeUnit = m[5];
  8270. var fontFamily = m[6];
  8271. } else {
  8272. return;
  8273. }
  8274. if ("px" === fontSizeUnit) {
  8275. fontSize = Math.floor(parseFloat(fontSize)); // fontSize = fontSize * 1.25;
  8276. } else if ("em" === fontSizeUnit) {
  8277. fontSize = Math.floor(parseFloat(fontSize) * this.pdf.getFontSize());
  8278. } else {
  8279. fontSize = Math.floor(parseFloat(fontSize));
  8280. }
  8281. this.pdf.setFontSize(fontSize);
  8282. var style = "";
  8283. if (fontWeight === "bold" || parseInt(fontWeight, 10) >= 700 || fontStyle === "bold") {
  8284. style = "bold";
  8285. }
  8286. if (fontStyle === "italic") {
  8287. style += "italic";
  8288. }
  8289. if (style.length === 0) {
  8290. style = "normal";
  8291. }
  8292. var jsPdfFontName = "";
  8293. var parts = fontFamily.toLowerCase().replace(/"|'/g, "").split(/\s*,\s*/);
  8294. var fallbackFonts = {
  8295. arial: "Helvetica",
  8296. verdana: "Helvetica",
  8297. helvetica: "Helvetica",
  8298. "sans-serif": "Helvetica",
  8299. fixed: "Courier",
  8300. monospace: "Courier",
  8301. terminal: "Courier",
  8302. courier: "Courier",
  8303. times: "Times",
  8304. cursive: "Times",
  8305. fantasy: "Times",
  8306. serif: "Times"
  8307. };
  8308. for (var i = 0; i < parts.length; i++) {
  8309. if (this.pdf.internal.getFont(parts[i], style, {
  8310. noFallback: true,
  8311. disableWarning: true
  8312. }) !== undefined) {
  8313. jsPdfFontName = parts[i];
  8314. break;
  8315. } else if (style === "bolditalic" && this.pdf.internal.getFont(parts[i], "bold", {
  8316. noFallback: true,
  8317. disableWarning: true
  8318. }) !== undefined) {
  8319. jsPdfFontName = parts[i];
  8320. style = "bold";
  8321. } else if (this.pdf.internal.getFont(parts[i], "normal", {
  8322. noFallback: true,
  8323. disableWarning: true
  8324. }) !== undefined) {
  8325. jsPdfFontName = parts[i];
  8326. style = "normal";
  8327. break;
  8328. }
  8329. }
  8330. if (jsPdfFontName === "") {
  8331. for (var i = 0; i < parts.length; i++) {
  8332. if (fallbackFonts[parts[i]]) {
  8333. jsPdfFontName = fallbackFonts[parts[i]];
  8334. break;
  8335. }
  8336. }
  8337. }
  8338. jsPdfFontName = jsPdfFontName === "" ? "Times" : jsPdfFontName;
  8339. this.pdf.setFont(jsPdfFontName, style);
  8340. },
  8341. /**
  8342. * @name _setTextBaseline
  8343. * @function
  8344. * @private
  8345. * @ignore
  8346. */
  8347. _setTextBaseline: function _setTextBaseline(baseline) {
  8348. this.ctx.textBaseline = baseline;
  8349. },
  8350. /**
  8351. * @name _getTextBaseline
  8352. * @function
  8353. * @private
  8354. * @ignore
  8355. * @returns {Number}
  8356. */
  8357. _getTextBaseline: function _getTextBaseline() {
  8358. return this.ctx.textBaseline;
  8359. },
  8360. /**
  8361. * @name _setTextAlign
  8362. * @function
  8363. * @private
  8364. * @ignore
  8365. */
  8366. _setTextAlign: function _setTextAlign(canvasAlign) {
  8367. switch (canvasAlign) {
  8368. case "right":
  8369. case "end":
  8370. this.ctx.textAlign = "right";
  8371. break;
  8372. case "center":
  8373. this.ctx.textAlign = "center";
  8374. break;
  8375. case "left":
  8376. case "start":
  8377. default:
  8378. this.ctx.textAlign = "left";
  8379. break;
  8380. }
  8381. },
  8382. /**
  8383. * @name _getTextAlign
  8384. * @function
  8385. * @private
  8386. * @ignore
  8387. * @returns {String}
  8388. */
  8389. _getTextAlign: function _getTextAlign() {
  8390. return this.ctx.textAlign;
  8391. },
  8392. /**
  8393. * Draws "filled" text on the canvas
  8394. *
  8395. * @name fillText
  8396. * @function
  8397. * @param text {String} Specifies the text that will be written on the canvas
  8398. * @param x {Number} The x coordinate where to start painting the text (relative to the canvas)
  8399. * @param y {Number} The y coordinate where to start painting the text (relative to the canvas)
  8400. * @param maxWidth {Number} Optional. The maximum allowed width of the text, in pixels
  8401. * @description The fillText() method draws filled text on the canvas. The default color of the text is black.
  8402. */
  8403. fillText: function fillText(text, x, y, maxWidth) {
  8404. if (this._isFillTransparent()) {
  8405. return;
  8406. }
  8407. x = this._wrapX(x);
  8408. y = this._wrapY(y);
  8409. var xpt = this._matrix_map_point(this.ctx._transform, [x, y]);
  8410. x = xpt[0];
  8411. y = xpt[1];
  8412. var rads = this._matrix_rotation(this.ctx._transform);
  8413. var degs = rads * 57.2958; // We only use X axis as scale hint
  8414. var scale = 1;
  8415. try {
  8416. scale = this._matrix_decompose(this._getTransform()).scale[0];
  8417. } catch (e) {
  8418. console.warn(e);
  8419. } // In some cases the transform was very small (5.715760606202283e-17). Most likely a canvg rounding error.
  8420. if (scale < 0.01) {
  8421. this.pdf.text(text, x, this._getBaseline(y), {
  8422. angle: degs,
  8423. align: this.textAlign
  8424. });
  8425. } else {
  8426. var oldSize = this.pdf.internal.getFontSize();
  8427. this.pdf.setFontSize(oldSize * scale);
  8428. this.pdf.text(text, x, this._getBaseline(y), {
  8429. angle: degs,
  8430. align: this.textAlign
  8431. });
  8432. this.pdf.setFontSize(oldSize);
  8433. }
  8434. },
  8435. /**
  8436. * Draws text on the canvas (no fill)
  8437. *
  8438. * @name strokeText
  8439. * @function
  8440. * @param text {String} Specifies the text that will be written on the canvas
  8441. * @param x {Number} The x coordinate where to start painting the text (relative to the canvas)
  8442. * @param y {Number} The y coordinate where to start painting the text (relative to the canvas)
  8443. * @param maxWidth {Number} Optional. The maximum allowed width of the text, in pixels
  8444. * @description The strokeText() method draws text (with no fill) on the canvas. The default color of the text is black.
  8445. */
  8446. strokeText: function strokeText(text, x, y, maxWidth) {
  8447. if (this._isStrokeTransparent()) {
  8448. return;
  8449. }
  8450. x = this._wrapX(x);
  8451. y = this._wrapY(y);
  8452. var xpt = this._matrix_map_point(this.ctx._transform, [x, y]);
  8453. x = xpt[0];
  8454. y = xpt[1];
  8455. var rads = this._matrix_rotation(this.ctx._transform);
  8456. var degs = rads * 57.2958;
  8457. var scale = 1; // We only use the X axis as scale hint
  8458. try {
  8459. scale = this._matrix_decompose(this._getTransform()).scale[0];
  8460. } catch (e) {
  8461. console.warn(e);
  8462. }
  8463. if (scale < 0.01) {
  8464. this.pdf.text(text, x, this._getBaseline(y), {
  8465. angle: degs,
  8466. align: this.textAlign,
  8467. renderingMode: "stroke"
  8468. });
  8469. } else {
  8470. var oldSize = this.pdf.internal.getFontSize();
  8471. this.pdf.setFontSize(oldSize * scale);
  8472. this.pdf.text(text, x, this._getBaseline(y), {
  8473. angle: degs,
  8474. align: this.textAlign,
  8475. renderingMode: "stroke"
  8476. });
  8477. this.pdf.setFontSize(oldSize);
  8478. }
  8479. },
  8480. /**
  8481. * Returns an object that contains the width of the specified text
  8482. *
  8483. * @name measureText
  8484. * @function
  8485. * @param text {String} The text to be measured
  8486. * @description The measureText() method returns an object that contains the width of the specified text, in pixels.
  8487. * @returns {Number}
  8488. */
  8489. measureText: function measureText(text) {
  8490. var pdf = this.pdf;
  8491. return {
  8492. getWidth: function getWidth() {
  8493. var fontSize = pdf.internal.getFontSize();
  8494. var txtWidth = pdf.getStringUnitWidth(text) * fontSize / pdf.internal.scaleFactor; // Convert points to pixels
  8495. //TODO Use scaleFactor?
  8496. txtWidth *= 1.3333;
  8497. return txtWidth;
  8498. },
  8499. get width() {
  8500. return this.getWidth(text);
  8501. }
  8502. };
  8503. },
  8504. //Line Styles
  8505. /**
  8506. *
  8507. * @name _setLineWidth
  8508. * @function
  8509. * @private
  8510. * @ignore
  8511. */
  8512. _setLineWidth: function _setLineWidth(width) {
  8513. this.ctx.lineWidth = width;
  8514. this.pdf.setLineWidth(width);
  8515. },
  8516. /**
  8517. * @name _setLineCap
  8518. * @function
  8519. * @private
  8520. * @ignore
  8521. */
  8522. _setLineCap: function _setLineCap(style) {
  8523. this.ctx.lineCap = style;
  8524. this.pdf.setLineCap(style);
  8525. },
  8526. /**
  8527. *
  8528. * @name _setLineJoin
  8529. * @function
  8530. * @private
  8531. * @ignore
  8532. */
  8533. _setLineJoin: function _setLineJoin(style) {
  8534. this.ctx.lineJoin = style;
  8535. this.pdf.setLineJoin(style);
  8536. },
  8537. /**
  8538. *
  8539. * @name _getLineJoin
  8540. * @function
  8541. * @private
  8542. * @ignore
  8543. */
  8544. _getLineJoin: function _getLineJoin() {
  8545. return this.ctx.lineJoin;
  8546. },
  8547. /**
  8548. *
  8549. * @name _wrapX
  8550. * @function
  8551. * @private
  8552. * @ignore
  8553. */
  8554. _wrapX: function _wrapX(x) {
  8555. if (this.pageWrapXEnabled) {
  8556. return x % this.pageWrapX;
  8557. } else {
  8558. return x;
  8559. }
  8560. },
  8561. /**
  8562. * @name _wrapY
  8563. * @function
  8564. * @private
  8565. * @ignore
  8566. */
  8567. _wrapY: function _wrapY(y) {
  8568. if (this.pageWrapYEnabled) {
  8569. this._gotoPage(this._page(y));
  8570. return (y - this.lastBreak) % this.pageWrapY;
  8571. } else {
  8572. return y;
  8573. }
  8574. },
  8575. //Transformations
  8576. /**
  8577. * Scales the current drawing bigger or smaller
  8578. *
  8579. * @name scale
  8580. * @function
  8581. * @param scalewidth {Number} Scales the width of the current drawing (1=100%, 0.5=50%, 2=200%, etc.)
  8582. * @param scaleheight {Number} Scales the height of the current drawing (1=100%, 0.5=50%, 2=200%, etc.)
  8583. * @description The scale() method scales the current drawing, bigger or smaller.
  8584. */
  8585. scale: function scale(scalewidth, scaleheight) {
  8586. var matrix = [scalewidth, 0.0, 0.0, scaleheight, 0.0, 0.0];
  8587. this.ctx._transform = this._matrix_multiply(this.ctx._transform, matrix);
  8588. },
  8589. /**
  8590. * Rotates the current drawing
  8591. *
  8592. * @name rotate
  8593. * @function
  8594. * @param angle {Number} The rotation angle, in radians.
  8595. * @description To calculate from degrees to radians: degrees*Math.PI/180. <br />
  8596. * Example: to rotate 5 degrees, specify the following: 5*Math.PI/180
  8597. */
  8598. rotate: function rotate(angle) {
  8599. var matrix = [Math.cos(angle), Math.sin(angle), -Math.sin(angle), Math.cos(angle), 0.0, 0.0];
  8600. this.ctx._transform = this._matrix_multiply(this.ctx._transform, matrix);
  8601. },
  8602. /**
  8603. * Remaps the (0,0) position on the canvas
  8604. *
  8605. * @name translate
  8606. * @function
  8607. * @param x {Number} The value to add to horizontal (x) coordinates
  8608. * @param y {Number} The value to add to vertical (y) coordinates
  8609. * @description The translate() method remaps the (0,0) position on the canvas.
  8610. */
  8611. translate: function translate(x, y) {
  8612. var matrix = [1.0, 0.0, 0.0, 1.0, x, y];
  8613. this.ctx._transform = this._matrix_multiply(this.ctx._transform, matrix);
  8614. },
  8615. /**
  8616. * Replaces the current transformation matrix for the drawing
  8617. *
  8618. * @name transform
  8619. * @function
  8620. * @param a {Number} Horizontal scaling
  8621. * @param b {Number} Horizontal skewing
  8622. * @param c {Number} Vertical skewing
  8623. * @param d {Number} Vertical scaling
  8624. * @param e {Number} Horizontal moving
  8625. * @param f {Number} Vertical moving
  8626. * @description Each object on the canvas has a current transformation matrix.<br /><br />The transform() method replaces the current transformation matrix. It multiplies the current transformation matrix with the matrix described by:<br /><br /><br /><br />a c e<br /><br />b d f<br /><br />0 0 1<br /><br />In other words, the transform() method lets you scale, rotate, move, and skew the current context.
  8627. */
  8628. transform: function transform(a, b, c, d, e, f) {
  8629. this.ctx._transform = this._matrix_multiply(this.ctx._transform, [a, b, c, d, e, f]);
  8630. },
  8631. /**
  8632. * Resets the current transform to the identity matrix. Then runs transform()
  8633. *
  8634. * @name setTransform
  8635. * @function
  8636. * @param a {Number} Horizontal scaling
  8637. * @param b {Number} Horizontal skewing
  8638. * @param c {Number} Vertical skewing
  8639. * @param d {Number} Vertical scaling
  8640. * @param e {Number} Horizontal moving
  8641. * @param f {Number} Vertical moving
  8642. * @description Each object on the canvas has a current transformation matrix. <br /><br />The setTransform() method resets the current transform to the identity matrix, and then runs transform() with the same arguments.<br /><br />In other words, the setTransform() method lets you scale, rotate, move, and skew the current context.
  8643. */
  8644. setTransform: function setTransform(a, b, c, d, e, f) {
  8645. this.ctx._transform = [a, b, c, d, e, f];
  8646. },
  8647. /**
  8648. * @name _getTransform
  8649. * @function
  8650. * @private
  8651. * @ignore
  8652. */
  8653. _getTransform: function _getTransform() {
  8654. return this.ctx._transform;
  8655. },
  8656. lastBreak: 0,
  8657. // Y Position of page breaks.
  8658. pageBreaks: [],
  8659. /**
  8660. * Should only be used if pageWrapYEnabled is true
  8661. *
  8662. * @name _page
  8663. * @function
  8664. * @private
  8665. * @ignore
  8666. * @returns One-based Page Number
  8667. */
  8668. _page: function _page(y) {
  8669. if (this.pageWrapYEnabled) {
  8670. this.lastBreak = 0;
  8671. var manualBreaks = 0;
  8672. var autoBreaks = 0;
  8673. for (var i = 0; i < this.pageBreaks.length; i++) {
  8674. if (y >= this.pageBreaks[i]) {
  8675. manualBreaks++;
  8676. if (this.lastBreak === 0) {
  8677. autoBreaks++;
  8678. }
  8679. var spaceBetweenLastBreak = this.pageBreaks[i] - this.lastBreak;
  8680. this.lastBreak = this.pageBreaks[i];
  8681. var pagesSinceLastBreak = Math.floor(spaceBetweenLastBreak / this.pageWrapY);
  8682. autoBreaks += pagesSinceLastBreak;
  8683. }
  8684. }
  8685. if (this.lastBreak === 0) {
  8686. var pagesSinceLastBreak = Math.floor(y / this.pageWrapY) + 1;
  8687. autoBreaks += pagesSinceLastBreak;
  8688. }
  8689. return autoBreaks + manualBreaks;
  8690. } else {
  8691. return this.pdf.internal.getCurrentPageInfo().pageNumber;
  8692. }
  8693. },
  8694. _gotoPage: function _gotoPage(pageOneBased) {// This is a stub to be overriden if needed
  8695. },
  8696. /**
  8697. * Draws an image, canvas, or video onto the canvas
  8698. *
  8699. * @function
  8700. * @param img {} Specifies the image, canvas, or video element to use
  8701. * @param sx {Number} Optional. The x coordinate where to start clipping
  8702. * @param sy {Number} Optional. The y coordinate where to start clipping
  8703. * @param swidth {Number} Optional. The width of the clipped image
  8704. * @param sheight {Number} Optional. The height of the clipped image
  8705. * @param x {Number} The x coordinate where to place the image on the canvas
  8706. * @param y {Number} The y coordinate where to place the image on the canvas
  8707. * @param width {Number} Optional. The width of the image to use (stretch or reduce the image)
  8708. * @param height {Number} Optional. The height of the image to use (stretch or reduce the image)
  8709. *
  8710. */
  8711. drawImage: function drawImage(img, x, y, w, h, x2, y2, w2, h2) {
  8712. if (x2 !== undefined) {
  8713. x = x2;
  8714. y = y2;
  8715. w = w2;
  8716. h = h2;
  8717. }
  8718. x = this._wrapX(x);
  8719. y = this._wrapY(y);
  8720. var xRect = this._matrix_map_rect(this.ctx._transform, {
  8721. x: x,
  8722. y: y,
  8723. w: w,
  8724. h: h
  8725. });
  8726. var xRect2 = this._matrix_map_rect(this.ctx._transform, {
  8727. x: x2,
  8728. y: y2,
  8729. w: w2,
  8730. h: h2
  8731. }); // TODO implement source clipping and image scaling
  8732. var format;
  8733. var rx = /data:image\/(\w+).*/i;
  8734. var m = rx.exec(img);
  8735. if (m != null) {
  8736. format = m[1];
  8737. } else {
  8738. // format = "jpeg";
  8739. format = "png";
  8740. }
  8741. this.pdf.addImage(img, format, xRect.x, xRect.y, xRect.w, xRect.h);
  8742. },
  8743. /**
  8744. * Multiply the first matrix by the second
  8745. *
  8746. * @name matrix_multiply
  8747. * @function
  8748. * @param m1
  8749. * @param m2
  8750. * @returns {Array}
  8751. * @private
  8752. * @ignore
  8753. */
  8754. _matrix_multiply: function _matrix_multiply(m2, m1) {
  8755. var sx = m1[0];
  8756. var shy = m1[1];
  8757. var shx = m1[2];
  8758. var sy = m1[3];
  8759. var tx = m1[4];
  8760. var ty = m1[5];
  8761. var t0 = sx * m2[0] + shy * m2[2];
  8762. var t2 = shx * m2[0] + sy * m2[2];
  8763. var t4 = tx * m2[0] + ty * m2[2] + m2[4];
  8764. shy = sx * m2[1] + shy * m2[3];
  8765. sy = shx * m2[1] + sy * m2[3];
  8766. ty = tx * m2[1] + ty * m2[3] + m2[5];
  8767. sx = t0;
  8768. shx = t2;
  8769. tx = t4;
  8770. return [sx, shy, shx, sy, tx, ty];
  8771. },
  8772. /**
  8773. * @name _matrix_rotation
  8774. * @function
  8775. * @private
  8776. * @ignore
  8777. */
  8778. _matrix_rotation: function _matrix_rotation(m) {
  8779. return Math.atan2(m[2], m[0]);
  8780. },
  8781. /**
  8782. * @name _matrix_decompose
  8783. * @function
  8784. * @private
  8785. * @ignore
  8786. */
  8787. _matrix_decompose: function _matrix_decompose(matrix) {
  8788. var a = matrix[0];
  8789. var b = matrix[1];
  8790. var c = matrix[2];
  8791. var d = matrix[3];
  8792. var scaleX = Math.sqrt(a * a + b * b);
  8793. a /= scaleX;
  8794. b /= scaleX;
  8795. var shear = a * c + b * d;
  8796. c -= a * shear;
  8797. d -= b * shear;
  8798. var scaleY = Math.sqrt(c * c + d * d);
  8799. c /= scaleY;
  8800. d /= scaleY;
  8801. shear /= scaleY;
  8802. if (a * d < b * c) {
  8803. a = -a;
  8804. b = -b;
  8805. shear = -shear;
  8806. scaleX = -scaleX;
  8807. }
  8808. return {
  8809. scale: [scaleX, 0, 0, scaleY, 0, 0],
  8810. translate: [1, 0, 0, 1, matrix[4], matrix[5]],
  8811. rotate: [a, b, -b, a, 0, 0],
  8812. skew: [1, 0, shear, 1, 0, 0]
  8813. };
  8814. },
  8815. /**
  8816. * @name _matrix_map_point
  8817. * @function
  8818. * @private
  8819. * @ignore
  8820. */
  8821. _matrix_map_point: function _matrix_map_point(m1, pt) {
  8822. var sx = m1[0];
  8823. var shy = m1[1];
  8824. var shx = m1[2];
  8825. var sy = m1[3];
  8826. var tx = m1[4];
  8827. var ty = m1[5];
  8828. var px = pt[0];
  8829. var py = pt[1];
  8830. var x = px * sx + py * shx + tx;
  8831. var y = px * shy + py * sy + ty;
  8832. return [x, y];
  8833. },
  8834. /**
  8835. * @name _matrix_map_point_obj
  8836. * @function
  8837. * @private
  8838. * @ignore
  8839. */
  8840. _matrix_map_point_obj: function _matrix_map_point_obj(m1, pt) {
  8841. var xpt = this._matrix_map_point(m1, [pt.x, pt.y]);
  8842. return {
  8843. x: xpt[0],
  8844. y: xpt[1]
  8845. };
  8846. },
  8847. /**
  8848. * @name _matrix_map_rect
  8849. * @function
  8850. * @private
  8851. * @ignore
  8852. */
  8853. _matrix_map_rect: function _matrix_map_rect(m1, rect) {
  8854. var p1 = this._matrix_map_point(m1, [rect.x, rect.y]);
  8855. var p2 = this._matrix_map_point(m1, [rect.x + rect.w, rect.y + rect.h]);
  8856. return {
  8857. x: p1[0],
  8858. y: p1[1],
  8859. w: p2[0] - p1[0],
  8860. h: p2[1] - p1[1]
  8861. };
  8862. },
  8863. /**
  8864. * @name _matrix_is_identity
  8865. * @function
  8866. * @private
  8867. * @ignore
  8868. */
  8869. _matrix_is_identity: function _matrix_is_identity(m1) {
  8870. if (m1[0] != 1) {
  8871. return false;
  8872. }
  8873. if (m1[1] != 0) {
  8874. return false;
  8875. }
  8876. if (m1[2] != 0) {
  8877. return false;
  8878. }
  8879. if (m1[3] != 1) {
  8880. return false;
  8881. }
  8882. if (m1[4] != 0) {
  8883. return false;
  8884. }
  8885. if (m1[5] != 0) {
  8886. return false;
  8887. }
  8888. return true;
  8889. },
  8890. /**
  8891. * Processes the paths
  8892. *
  8893. * @function
  8894. * @param rule {String}
  8895. * @param isClip {Boolean}
  8896. * @private
  8897. * @ignore
  8898. */
  8899. _drawPaths: function _drawPaths(rule, isClip) {
  8900. var isStroke = rule === "stroke";
  8901. var isFill = !isStroke;
  8902. if (isStroke && !isClip && this._isStrokeTransparent()) {
  8903. return;
  8904. }
  8905. if (isFill && !isClip && this._isFillTransparent()) {
  8906. return;
  8907. }
  8908. var v2Support = typeof this.pdf.internal.newObject2 === "function";
  8909. var lines;
  8910. if (globalObj.outIntercept) {
  8911. lines = globalObj.outIntercept.type === "group" ? globalObj.outIntercept.stream : globalObj.outIntercept;
  8912. } else {
  8913. lines = this.internal.getCurrentPage();
  8914. }
  8915. var moves = [];
  8916. var outInterceptOld = globalObj.outIntercept;
  8917. /*
  8918. if (v2Support) {
  8919. // Blend and Mask
  8920. switch (this.ctx.globalCompositeOperation) {
  8921. case 'normal':
  8922. case 'source-over':
  8923. break;
  8924. case 'destination-in':
  8925. case 'destination-out':
  8926. //TODO this need to be added to the current group or page
  8927. // define a mask stream
  8928. var obj = this.pdf.internal.newStreamObject(); // define a mask state
  8929. var obj2 = this.pdf.internal.newObject2();
  8930. obj2.push('<</Type /ExtGState');
  8931. obj2.push('/SMask <</S /Alpha /G ' + obj.objId + ' 0 R>>'); // /S /Luminosity will need to define color space
  8932. obj2.push('>>'); // add mask to page resources
  8933. var gsName = 'MASK' + obj2.objId;
  8934. this.pdf.internal.addGraphicsState(gsName, obj2.objId);
  8935. var instruction = '/' + gsName + ' gs'; // add mask to page, group, or stream
  8936. lines.splice(0, 0, 'q');
  8937. lines.splice(1, 0, instruction);
  8938. lines.push('Q');
  8939. globalObj.outIntercept = obj;
  8940. break;
  8941. default:
  8942. var dictionaryEntry = '/' + this.pdf.internal.blendModeMap[this.ctx.globalCompositeOperation.toUpperCase()];
  8943. if (dictionaryEntry) {
  8944. this.pdf.internal.out(dictionaryEntry + ' gs');
  8945. }
  8946. break;
  8947. }
  8948. }
  8949. */
  8950. var alpha = this.ctx.globalAlpha;
  8951. if (this.ctx._fillOpacity < 1) {
  8952. // TODO combine this with global opacity
  8953. alpha = this.ctx._fillOpacity;
  8954. } //TODO check for an opacity graphics state that was already created
  8955. //TODO do not set opacity if current value is already active
  8956. /*
  8957. if (v2Support) {
  8958. var objOpac = this.pdf.internal.newObject2();
  8959. objOpac.push('<</Type /ExtGState'); //objOpac.push(this.ctx.globalAlpha + " CA"); // Stroke
  8960. //objOpac.push(this.ctx.globalAlpha + " ca"); // Not Stroke
  8961. objOpac.push('/CA ' + alpha); // Stroke
  8962. objOpac.push('/ca ' + alpha); // Not Stroke
  8963. objOpac.push('>>');
  8964. var gsName = 'GS_O_' + objOpac.objId;
  8965. this.pdf.internal.addGraphicsState(gsName, objOpac.objId);
  8966. this.pdf.internal.out('/' + gsName + ' gs');
  8967. }
  8968. */
  8969. var xPath = this.path;
  8970. for (var i = 0; i < xPath.length; i++) {
  8971. var pt = xPath[i];
  8972. switch (pt.type) {
  8973. case "begin":
  8974. moves.push({
  8975. begin: true
  8976. });
  8977. break;
  8978. case "close":
  8979. moves.push({
  8980. close: true
  8981. });
  8982. break;
  8983. case "mt":
  8984. moves.push({
  8985. start: pt,
  8986. deltas: [],
  8987. abs: []
  8988. });
  8989. break;
  8990. case "lt":
  8991. var delta = [pt.x - xPath[i - 1].x, pt.y - xPath[i - 1].y];
  8992. var iii = moves.length;
  8993. if (iii > 0) {
  8994. for (iii; iii > 0; iii--) {
  8995. if (moves[iii - 1].close !== true && moves[iii - 1].begin !== true) {
  8996. moves[iii - 1].deltas.push(delta);
  8997. moves[iii - 1].abs.push(pt);
  8998. break;
  8999. }
  9000. }
  9001. }
  9002. break;
  9003. case "bct":
  9004. var delta = [pt.x1 - xPath[i - 1].x, pt.y1 - xPath[i - 1].y, pt.x2 - xPath[i - 1].x, pt.y2 - xPath[i - 1].y, pt.x - xPath[i - 1].x, pt.y - xPath[i - 1].y];
  9005. moves[moves.length - 1].deltas.push(delta);
  9006. break;
  9007. case "qct":
  9008. // convert to bezier
  9009. var x1 = xPath[i - 1].x + 2.0 / 3.0 * (pt.x1 - xPath[i - 1].x);
  9010. var y1 = xPath[i - 1].y + 2.0 / 3.0 * (pt.y1 - xPath[i - 1].y);
  9011. var x2 = pt.x + 2.0 / 3.0 * (pt.x1 - pt.x);
  9012. var y2 = pt.y + 2.0 / 3.0 * (pt.y1 - pt.y);
  9013. var x3 = pt.x;
  9014. var y3 = pt.y;
  9015. var delta = [x1 - xPath[i - 1].x, y1 - xPath[i - 1].y, x2 - xPath[i - 1].x, y2 - xPath[i - 1].y, x3 - xPath[i - 1].x, y3 - xPath[i - 1].y];
  9016. moves[moves.length - 1].deltas.push(delta);
  9017. break;
  9018. case "arc":
  9019. moves.push({
  9020. deltas: [],
  9021. abs: []
  9022. });
  9023. moves[moves.length - 1].arc = true;
  9024. if (Array.isArray(moves[moves.length - 1].abs)) {
  9025. moves[moves.length - 1].abs.push(pt);
  9026. }
  9027. break;
  9028. }
  9029. }
  9030. var style;
  9031. if (!isClip) {
  9032. if (isStroke) {
  9033. style = "S";
  9034. } else {
  9035. style = "f";
  9036. }
  9037. } else {
  9038. style = null;
  9039. }
  9040. for (var i = 0; i < moves.length; i++) {
  9041. if (moves[i].begin) ;
  9042. if (moves[i].arc) {
  9043. if (moves[i].start) {
  9044. this.internal.move2(this, moves[i].start.x, moves[i].start.y);
  9045. }
  9046. var arcs = moves[i].abs;
  9047. for (var ii = 0; ii < arcs.length; ii++) {
  9048. var arc = arcs[ii]; //TODO lines deltas were getting in here
  9049. if (typeof arc.startAngle !== "undefined") {
  9050. var start = arc.startAngle * 360 / (2 * Math.PI);
  9051. var end = arc.endAngle * 360 / (2 * Math.PI);
  9052. var x = arc.x;
  9053. var y = arc.y;
  9054. this.internal.arc2(this, x, y, arc.radius, start, end, arc.counterclockwise, style, isClip);
  9055. } else {
  9056. this.internal.line2(c2d, arc.x, arc.y);
  9057. }
  9058. }
  9059. }
  9060. if (!moves[i].arc) {
  9061. if (moves[i].close !== true && moves[i].begin !== true) {
  9062. var x = moves[i].start.x;
  9063. var y = moves[i].start.y;
  9064. this.pdf.lines(moves[i].deltas, x, y, null, null);
  9065. }
  9066. }
  9067. if (moves[i].close) ;
  9068. }
  9069. if (style) {
  9070. this.pdf.internal.out(style);
  9071. }
  9072. if (isClip) {
  9073. this.pdf.clip();
  9074. }
  9075. globalObj.outIntercept = outInterceptOld; // if (this.ctx._clip_path.length > 0) {
  9076. // lines.push('Q');
  9077. // }
  9078. },
  9079. /*
  9080. _pushMask: function () {
  9081. var v2Support = typeof this.pdf.internal.newObject2 === 'function';
  9082. if (!v2Support) {
  9083. console.log('jsPDF v2 not enabled')
  9084. return;
  9085. }
  9086. // define a mask stream
  9087. var obj = this.pdf.internal.newStreamObject();
  9088. // define a mask state
  9089. var obj2 = this.pdf.internal.newObject2();
  9090. obj2.push('<</Type /ExtGState');
  9091. obj2.push('/SMask <</S /Alpha /G ' + obj.objId + ' 0 R>>'); // /S /Luminosity will need to define color space
  9092. obj2.push('>>');
  9093. // add mask to page resources
  9094. var gsName = 'MASK' + obj2.objId;
  9095. this.pdf.internal.addGraphicsState(gsName, obj2.objId);
  9096. var instruction = '/' + gsName + ' gs';
  9097. this.pdf.internal.out(instruction);
  9098. },
  9099. */
  9100. _getBaseline: function _getBaseline(y) {
  9101. var height = parseInt(this.pdf.internal.getFontSize() / this.pdf.internal.scaleFactor); // TODO Get descent from font descriptor
  9102. var descent = height * 0.25;
  9103. switch (this.ctx.textBaseline) {
  9104. case "bottom":
  9105. return y - descent;
  9106. case "top":
  9107. return y + height;
  9108. case "hanging":
  9109. return y + height - descent;
  9110. case "middle":
  9111. return y + height / 2 - descent;
  9112. case "ideographic":
  9113. // TODO not implemented
  9114. return y;
  9115. case "alphabetic":
  9116. default:
  9117. return y;
  9118. }
  9119. },
  9120. createLinearGradient: function createLinearGradient() {
  9121. var canvasGradient = function canvasGradient() {};
  9122. canvasGradient.colorStops = [];
  9123. canvasGradient.addColorStop = function (offset, color) {
  9124. this.colorStops.push([offset, color]);
  9125. };
  9126. canvasGradient.getColor = function () {
  9127. if (this.colorStops.length === 0) {
  9128. return "#000000";
  9129. }
  9130. return this.colorStops[0][1];
  9131. };
  9132. canvasGradient.isCanvasGradient = true;
  9133. return canvasGradient;
  9134. },
  9135. createPattern: function createPattern() {
  9136. return this.createLinearGradient();
  9137. },
  9138. createRadialGradient: function createRadialGradient() {
  9139. return this.createLinearGradient();
  9140. }
  9141. };
  9142. var c2d = jsPDFAPI.context2d;
  9143. /**
  9144. * Sets or returns the color, gradient, or pattern used to fill the drawing
  9145. *
  9146. * @name fillStyle
  9147. * @default #000000
  9148. * @property {(color|gradient|pattern)} value The color of the drawing. Default value is #000000<br />
  9149. * A gradient object (linear or radial) used to fill the drawing (not supported by context2d)<br />
  9150. * A pattern object to use to fill the drawing (not supported by context2d)
  9151. */
  9152. Object.defineProperty(c2d, "fillStyle", {
  9153. set: function set(value) {
  9154. this._setFillStyle(value);
  9155. },
  9156. get: function get() {
  9157. return this.ctx.fillStyle;
  9158. }
  9159. });
  9160. /**
  9161. * Sets or returns the color, gradient, or pattern used for strokes
  9162. *
  9163. * @name strokeStyle
  9164. * @default #000000
  9165. * @property {color} color A CSS color value that indicates the stroke color of the drawing. Default value is #000000 (not supported by context2d)
  9166. * @property {gradient} gradient A gradient object (linear or radial) used to create a gradient stroke (not supported by context2d)
  9167. * @property {pattern} pattern A pattern object used to create a pattern stroke (not supported by context2d)
  9168. */
  9169. Object.defineProperty(c2d, "strokeStyle", {
  9170. set: function set(value) {
  9171. this._setStrokeStyle(value);
  9172. },
  9173. get: function get() {
  9174. return this.ctx.strokeStyle;
  9175. }
  9176. }); //Line Styles
  9177. /**
  9178. * Sets or returns the style of the end caps for a line
  9179. *
  9180. * @name lineCap
  9181. * @default butt
  9182. * @property {(butt|round|square)} lineCap butt A flat edge is added to each end of the line <br/>
  9183. * round A rounded end cap is added to each end of the line<br/>
  9184. * square A square end cap is added to each end of the line<br/>
  9185. */
  9186. Object.defineProperty(c2d, "lineCap", {
  9187. set: function set(val) {
  9188. this._setLineCap(val);
  9189. },
  9190. get: function get() {
  9191. return this.ctx.lineCap;
  9192. }
  9193. });
  9194. /**
  9195. * Sets or returns the current line width
  9196. *
  9197. * @name lineWidth
  9198. * @default 1
  9199. * @property {number} lineWidth The current line width, in pixels
  9200. */
  9201. Object.defineProperty(c2d, "lineWidth", {
  9202. set: function set(value) {
  9203. this._setLineWidth(value);
  9204. },
  9205. get: function get() {
  9206. return this.ctx.lineWidth;
  9207. }
  9208. });
  9209. /**
  9210. * Sets or returns the type of corner created, when two lines meet
  9211. */
  9212. Object.defineProperty(c2d, "lineJoin", {
  9213. set: function set(val) {
  9214. this._setLineJoin(val);
  9215. },
  9216. get: function get() {
  9217. return this.ctx.lineJoin;
  9218. }
  9219. });
  9220. /**
  9221. * Sets or returns the maximum miter length
  9222. */
  9223. Object.defineProperty(c2d, "miterLimit", {
  9224. set: function set(val) {
  9225. this.ctx.miterLimit = val;
  9226. },
  9227. get: function get() {
  9228. return this.ctx.miterLimit;
  9229. }
  9230. });
  9231. Object.defineProperty(c2d, "textBaseline", {
  9232. set: function set(value) {
  9233. this._setTextBaseline(value);
  9234. },
  9235. get: function get() {
  9236. return this._getTextBaseline();
  9237. }
  9238. });
  9239. Object.defineProperty(c2d, "textAlign", {
  9240. set: function set(value) {
  9241. this._setTextAlign(value);
  9242. },
  9243. get: function get() {
  9244. return this._getTextAlign();
  9245. }
  9246. });
  9247. Object.defineProperty(c2d, "font", {
  9248. set: function set(value) {
  9249. this._setFont(value);
  9250. },
  9251. get: function get() {
  9252. return this.ctx.font;
  9253. }
  9254. });
  9255. Object.defineProperty(c2d, "globalCompositeOperation", {
  9256. set: function set(value) {
  9257. this.ctx.globalCompositeOperation = value;
  9258. },
  9259. get: function get() {
  9260. return this.ctx.globalCompositeOperation;
  9261. }
  9262. });
  9263. Object.defineProperty(c2d, "globalAlpha", {
  9264. set: function set(value) {
  9265. this.ctx.globalAlpha = value;
  9266. },
  9267. get: function get() {
  9268. return this.ctx.globalAlpha;
  9269. }
  9270. });
  9271. Object.defineProperty(c2d, "canvas", {
  9272. get: function get() {
  9273. return {
  9274. parentNode: false,
  9275. style: false
  9276. };
  9277. }
  9278. }); // Not HTML API
  9279. Object.defineProperty(c2d, "ignoreClearRect", {
  9280. set: function set(value) {
  9281. this.ctx.ignoreClearRect = value;
  9282. },
  9283. get: function get() {
  9284. return this.ctx.ignoreClearRect;
  9285. }
  9286. }); // End Not HTML API
  9287. c2d.internal = {};
  9288. c2d.internal.rxRgb = /rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/;
  9289. c2d.internal.rxRgba = /rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*([\d\.]+)\s*\)/;
  9290. c2d.internal.rxTransparent = /transparent|rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*0+\s*\)/; // http://hansmuller-flex.blogspot.com/2011/10/more-about-approximating-circular-arcs.html
  9291. c2d.internal.arc = function (c2d, xc, yc, r, a1, a2, counterclockwise, style) {
  9292. var k = this.pdf.internal.scaleFactor;
  9293. var pageHeight = this.pdf.internal.pageSize.getHeight();
  9294. var f2 = this.pdf.internal.f2;
  9295. var a1r = a1 * (Math.PI / 180);
  9296. var a2r = a2 * (Math.PI / 180);
  9297. var curves = this.createArc(r, a1r, a2r, counterclockwise);
  9298. for (var i = 0; i < curves.length; i++) {
  9299. var curve = curves[i];
  9300. if (i === 0) {
  9301. this.pdf.internal.out([f2((curve.x1 + xc) * k), f2((pageHeight - (curve.y1 + yc)) * k), "m", f2((curve.x2 + xc) * k), f2((pageHeight - (curve.y2 + yc)) * k), f2((curve.x3 + xc) * k), f2((pageHeight - (curve.y3 + yc)) * k), f2((curve.x4 + xc) * k), f2((pageHeight - (curve.y4 + yc)) * k), "c"].join(" "));
  9302. } else {
  9303. this.pdf.internal.out([f2((curve.x2 + xc) * k), f2((pageHeight - (curve.y2 + yc)) * k), f2((curve.x3 + xc) * k), f2((pageHeight - (curve.y3 + yc)) * k), f2((curve.x4 + xc) * k), f2((pageHeight - (curve.y4 + yc)) * k), "c"].join(" "));
  9304. } //c2d._lastPoint = {x: curve.x1 + xc, y: curve.y1 + yc};
  9305. c2d._lastPoint = {
  9306. x: xc,
  9307. y: yc
  9308. }; // f2((curve.x1 + xc) * k), f2((pageHeight - (curve.y1 + yc)) * k), 'm', f2((curve.x2 + xc) * k), f2((pageHeight - (curve.y2 + yc)) * k), f2((curve.x3 + xc) * k), f2((pageHeight - (curve.y3 + yc)) * k), f2((curve.x4 + xc) * k), f2((pageHeight - (curve.y4 + yc)) * k), 'c'
  9309. }
  9310. if (style !== null) {
  9311. this.pdf.internal.out(this.pdf.internal.getStyle(style));
  9312. }
  9313. };
  9314. /**
  9315. *
  9316. * @param x Edge point X
  9317. * @param y Edge point Y
  9318. * @param r Radius
  9319. * @param a1 start angle
  9320. * @param a2 end angle
  9321. * @param counterclockwise
  9322. * @param style
  9323. * @param isClip
  9324. */
  9325. c2d.internal.arc2 = function (c2d, x, y, r, a1, a2, counterclockwise, style, isClip) {
  9326. // we need to convert from cartesian to polar here methinks.
  9327. var centerX = x; // + r;
  9328. var centerY = y;
  9329. if (!isClip) {
  9330. this.arc(c2d, centerX, centerY, r, a1, a2, counterclockwise, style);
  9331. } else {
  9332. this.arc(c2d, centerX, centerY, r, a1, a2, counterclockwise, null);
  9333. this.pdf.clip();
  9334. }
  9335. };
  9336. c2d.internal.move2 = function (c2d, x, y) {
  9337. var k = this.pdf.internal.scaleFactor;
  9338. var pageHeight = this.pdf.internal.pageSize.getHeight();
  9339. var f2 = this.pdf.internal.f2;
  9340. this.pdf.internal.out([f2(x * k), f2((pageHeight - y) * k), "m"].join(" "));
  9341. c2d._lastPoint = {
  9342. x: x,
  9343. y: y
  9344. };
  9345. };
  9346. c2d.internal.line2 = function (c2d, dx, dy) {
  9347. var k = this.pdf.internal.scaleFactor;
  9348. var pageHeight = this.pdf.internal.pageSize.getHeight();
  9349. var f2 = this.pdf.internal.f2; //var pt = {x: c2d._lastPoint.x + dx, y: c2d._lastPoint.y + dy};
  9350. var pt = {
  9351. x: dx,
  9352. y: dy
  9353. };
  9354. this.pdf.internal.out([f2(pt.x * k), f2((pageHeight - pt.y) * k), "l"].join(" ")); //this.pdf.internal.out('f');
  9355. c2d._lastPoint = pt;
  9356. };
  9357. /**
  9358. * Return a array of objects that represent bezier curves which approximate the circular arc centered at the origin, from startAngle to endAngle (radians) with the specified radius.
  9359. *
  9360. * Each bezier curve is an object with four points, where x1,y1 and x4,y4 are the arc's end points and x2,y2 and x3,y3 are the cubic bezier's control points.
  9361. */
  9362. c2d.internal.createArc = function (radius, startAngle, endAngle, anticlockwise) {
  9363. var EPSILON = 0.00001; // Roughly 1/1000th of a degree, see below
  9364. // normalize startAngle, endAngle to [-2PI, 2PI]
  9365. var twoPI = Math.PI * 2;
  9366. var startAngleN = startAngle;
  9367. if (startAngleN < twoPI || startAngleN > twoPI) {
  9368. startAngleN = startAngleN % twoPI;
  9369. }
  9370. var endAngleN = endAngle;
  9371. if (endAngleN < twoPI || endAngleN > twoPI) {
  9372. endAngleN = endAngleN % twoPI;
  9373. } // Compute the sequence of arc curves, up to PI/2 at a time.
  9374. // Total arc angle is less than 2PI.
  9375. var curves = [];
  9376. var piOverTwo = Math.PI / 2.0; //var sgn = (startAngle < endAngle) ? +1 : -1; // clockwise or counterclockwise
  9377. var sgn = anticlockwise ? -1 : +1;
  9378. var a1 = startAngle;
  9379. for (var totalAngle = Math.min(twoPI, Math.abs(endAngleN - startAngleN)); totalAngle > EPSILON;) {
  9380. var a2 = a1 + sgn * Math.min(totalAngle, piOverTwo);
  9381. curves.push(this.createSmallArc(radius, a1, a2));
  9382. totalAngle -= Math.abs(a2 - a1);
  9383. a1 = a2;
  9384. }
  9385. return curves;
  9386. };
  9387. c2d.internal.getCurrentPage = function () {
  9388. return this.pdf.internal.pages[this.pdf.internal.getCurrentPageInfo().pageNumber];
  9389. };
  9390. /**
  9391. * Cubic bezier approximation of a circular arc centered at the origin, from (radians) a1 to a2, where a2-a1 < pi/2. The arc's radius is r.
  9392. *
  9393. * Returns an object with four points, where x1,y1 and x4,y4 are the arc's end points and x2,y2 and x3,y3 are the cubic bezier's control points.
  9394. *
  9395. * This algorithm is based on the approach described in: A. Riškus, "Approximation of a Cubic Bezier Curve by Circular Arcs and Vice Versa," Information Technology and Control, 35(4), 2006 pp. 371-378.
  9396. */
  9397. c2d.internal.createSmallArc = function (r, a1, a2) {
  9398. // Compute all four points for an arc that subtends the same total angle
  9399. // but is centered on the X-axis
  9400. var a = (a2 - a1) / 2.0;
  9401. var x4 = r * Math.cos(a);
  9402. var y4 = r * Math.sin(a);
  9403. var x1 = x4;
  9404. var y1 = -y4;
  9405. var q1 = x1 * x1 + y1 * y1;
  9406. var q2 = q1 + x1 * x4 + y1 * y4;
  9407. var k2 = 4 / 3 * (Math.sqrt(2 * q1 * q2) - q2) / (x1 * y4 - y1 * x4);
  9408. var x2 = x1 - k2 * y1;
  9409. var y2 = y1 + k2 * x1;
  9410. var x3 = x2;
  9411. var y3 = -y2; // Find the arc points' actual locations by computing x1,y1 and x4,y4
  9412. // and rotating the control points by a + a1
  9413. var ar = a + a1;
  9414. var cos_ar = Math.cos(ar);
  9415. var sin_ar = Math.sin(ar);
  9416. return {
  9417. x1: r * Math.cos(a1),
  9418. y1: r * Math.sin(a1),
  9419. x2: x2 * cos_ar - y2 * sin_ar,
  9420. y2: x2 * sin_ar + y2 * cos_ar,
  9421. x3: x3 * cos_ar - y3 * sin_ar,
  9422. y3: x3 * sin_ar + y3 * cos_ar,
  9423. x4: r * Math.cos(a2),
  9424. y4: r * Math.sin(a2)
  9425. };
  9426. };
  9427. /**
  9428. *
  9429. * @function
  9430. * @constructor
  9431. */
  9432. function context() {
  9433. this._isStrokeTransparent = false;
  9434. this._strokeOpacity = 1;
  9435. this.strokeStyle = "#000000";
  9436. this.fillStyle = "#000000";
  9437. this._isFillTransparent = false;
  9438. this._fillOpacity = 1;
  9439. this.font = "12pt times";
  9440. this.textBaseline = "alphabetic"; // top,bottom,middle,ideographic,alphabetic,hanging
  9441. this.textAlign = "left";
  9442. this.lineWidth = 1;
  9443. this.lineJoin = "miter"; // round, bevel, miter
  9444. this.lineCap = "butt"; // butt, round, square
  9445. this._transform = [1, 0, 0, 1, 0, 0]; // sx, shy, shx, sy, tx, ty
  9446. this.globalCompositeOperation = "normal";
  9447. this.globalAlpha = 1.0;
  9448. this._clip_path = [];
  9449. this.currentPoint = {
  9450. x: 0,
  9451. y: 0
  9452. }; // TODO miter limit //default 10
  9453. // Not HTML API
  9454. this.ignoreClearRect = false;
  9455. this.copy = function (ctx) {
  9456. this._isStrokeTransparent = ctx._isStrokeTransparent;
  9457. this._strokeOpacity = ctx._strokeOpacity;
  9458. this.strokeStyle = ctx.strokeStyle;
  9459. this._isFillTransparent = ctx._isFillTransparent;
  9460. this._fillOpacity = ctx._fillOpacity;
  9461. this.fillStyle = ctx.fillStyle;
  9462. this.font = ctx.font;
  9463. this.lineWidth = ctx.lineWidth;
  9464. this.lineJoin = ctx.lineJoin;
  9465. this.lineCap = ctx.lineCap;
  9466. this.textBaseline = ctx.textBaseline;
  9467. this.textAlign = ctx.textAlign;
  9468. this._fontSize = ctx._fontSize;
  9469. this._transform = ctx._transform.slice(0);
  9470. this.globalCompositeOperation = ctx.globalCompositeOperation;
  9471. this.globalAlpha = ctx.globalAlpha;
  9472. this._clip_path = ctx._clip_path.slice(0); //TODO deep copy?
  9473. this.currentPoint = ctx.currentPoint; // Not HTML API
  9474. this.ignoreClearRect = ctx.ignoreClearRect;
  9475. };
  9476. }
  9477. return this;
  9478. })(jsPDF.API, typeof self !== "undefined" && self || typeof window !== "undefined" && window || typeof global !== "undefined" && global || Function('return typeof this === "object" && this.content')() || Function("return this")());
  9479. /**
  9480. * Copyright (c) 2018 Erik Koopmans
  9481. * Released under the MIT License.
  9482. *
  9483. * Licensed under the MIT License.
  9484. * http://opensource.org/licenses/mit-license
  9485. */
  9486. /**
  9487. * jsPDF html PlugIn
  9488. *
  9489. * @name html
  9490. * @module
  9491. */
  9492. (function (jsPDFAPI, global) {
  9493. /**
  9494. * Determine the type of a variable/object.
  9495. *
  9496. * @private
  9497. * @ignore
  9498. */
  9499. var objType = function objType(obj) {
  9500. var type = _typeof(obj);
  9501. if (type === "undefined") return "undefined";else if (type === "string" || obj instanceof String) return "string";else if (type === "number" || obj instanceof Number) return "number";else if (type === "function" || obj instanceof Function) return "function";else if (!!obj && obj.constructor === Array) return "array";else if (obj && obj.nodeType === 1) return "element";else if (type === "object") return "object";else return "unknown";
  9502. };
  9503. /**
  9504. * Create an HTML element with optional className, innerHTML, and style.
  9505. *
  9506. * @private
  9507. * @ignore
  9508. */
  9509. var createElement = function createElement(tagName, opt) {
  9510. var el = document.createElement(tagName);
  9511. if (opt.className) el.className = opt.className;
  9512. if (opt.innerHTML) {
  9513. el.innerHTML = opt.innerHTML;
  9514. var scripts = el.getElementsByTagName("script");
  9515. for (var i = scripts.length; i-- > 0; null) {
  9516. scripts[i].parentNode.removeChild(scripts[i]);
  9517. }
  9518. }
  9519. for (var key in opt.style) {
  9520. el.style[key] = opt.style[key];
  9521. }
  9522. return el;
  9523. };
  9524. /**
  9525. * Deep-clone a node and preserve contents/properties.
  9526. *
  9527. * @private
  9528. * @ignore
  9529. */
  9530. var cloneNode = function cloneNode(node, javascriptEnabled) {
  9531. // Recursively clone the node.
  9532. var clone = node.nodeType === 3 ? document.createTextNode(node.nodeValue) : node.cloneNode(false);
  9533. for (var child = node.firstChild; child; child = child.nextSibling) {
  9534. if (javascriptEnabled === true || child.nodeType !== 1 || child.nodeName !== "SCRIPT") {
  9535. clone.appendChild(cloneNode(child, javascriptEnabled));
  9536. }
  9537. }
  9538. if (node.nodeType === 1) {
  9539. // Preserve contents/properties of special nodes.
  9540. if (node.nodeName === "CANVAS") {
  9541. clone.width = node.width;
  9542. clone.height = node.height;
  9543. clone.getContext("2d").drawImage(node, 0, 0);
  9544. } else if (node.nodeName === "TEXTAREA" || node.nodeName === "SELECT") {
  9545. clone.value = node.value;
  9546. } // Preserve the node's scroll position when it loads.
  9547. clone.addEventListener("load", function () {
  9548. clone.scrollTop = node.scrollTop;
  9549. clone.scrollLeft = node.scrollLeft;
  9550. }, true);
  9551. } // Return the cloned node.
  9552. return clone;
  9553. };
  9554. /* ----- CONSTRUCTOR ----- */
  9555. var Worker = function Worker(opt) {
  9556. // Create the root parent for the proto chain, and the starting Worker.
  9557. var root = Object.assign(Worker.convert(Promise.resolve()), JSON.parse(JSON.stringify(Worker.template)));
  9558. var self = Worker.convert(Promise.resolve(), root); // Set progress, optional settings, and return.
  9559. self = self.setProgress(1, Worker, 1, [Worker]);
  9560. self = self.set(opt);
  9561. return self;
  9562. }; // Boilerplate for subclassing Promise.
  9563. Worker.prototype = Object.create(Promise.prototype);
  9564. Worker.prototype.constructor = Worker; // Converts/casts promises into Workers.
  9565. Worker.convert = function convert(promise, inherit) {
  9566. // Uses prototypal inheritance to receive changes made to ancestors' properties.
  9567. promise.__proto__ = inherit || Worker.prototype;
  9568. return promise;
  9569. };
  9570. Worker.template = {
  9571. prop: {
  9572. src: null,
  9573. container: null,
  9574. overlay: null,
  9575. canvas: null,
  9576. img: null,
  9577. pdf: null,
  9578. pageSize: null,
  9579. callback: function callback() {}
  9580. },
  9581. progress: {
  9582. val: 0,
  9583. state: null,
  9584. n: 0,
  9585. stack: []
  9586. },
  9587. opt: {
  9588. filename: "file.pdf",
  9589. margin: [0, 0, 0, 0],
  9590. enableLinks: true,
  9591. html2canvas: {},
  9592. jsPDF: {}
  9593. }
  9594. };
  9595. /* ----- FROM / TO ----- */
  9596. Worker.prototype.from = function from(src, type) {
  9597. function getType(src) {
  9598. switch (objType(src)) {
  9599. case "string":
  9600. return "string";
  9601. case "element":
  9602. return src.nodeName.toLowerCase === "canvas" ? "canvas" : "element";
  9603. default:
  9604. return "unknown";
  9605. }
  9606. }
  9607. return this.then(function from_main() {
  9608. type = type || getType(src);
  9609. switch (type) {
  9610. case "string":
  9611. return this.set({
  9612. src: createElement("div", {
  9613. innerHTML: src
  9614. })
  9615. });
  9616. case "element":
  9617. return this.set({
  9618. src: src
  9619. });
  9620. case "canvas":
  9621. return this.set({
  9622. canvas: src
  9623. });
  9624. case "img":
  9625. return this.set({
  9626. img: src
  9627. });
  9628. default:
  9629. return this.error("Unknown source type.");
  9630. }
  9631. });
  9632. };
  9633. Worker.prototype.to = function to(target) {
  9634. // Route the 'to' request to the appropriate method.
  9635. switch (target) {
  9636. case "container":
  9637. return this.toContainer();
  9638. case "canvas":
  9639. return this.toCanvas();
  9640. case "img":
  9641. return this.toImg();
  9642. case "pdf":
  9643. return this.toPdf();
  9644. default:
  9645. return this.error("Invalid target.");
  9646. }
  9647. };
  9648. Worker.prototype.toContainer = function toContainer() {
  9649. // Set up function prerequisites.
  9650. var prereqs = [function checkSrc() {
  9651. return this.prop.src || this.error("Cannot duplicate - no source HTML.");
  9652. }, function checkPageSize() {
  9653. return this.prop.pageSize || this.setPageSize();
  9654. }];
  9655. return this.thenList(prereqs).then(function toContainer_main() {
  9656. // Define the CSS styles for the container and its overlay parent.
  9657. var overlayCSS = {
  9658. position: "fixed",
  9659. overflow: "hidden",
  9660. zIndex: 1000,
  9661. left: "-100000px",
  9662. right: 0,
  9663. bottom: 0,
  9664. top: 0
  9665. };
  9666. var containerCSS = {
  9667. position: "relative",
  9668. display: "inline-block",
  9669. width: Math.max(this.prop.src.clientWidth, this.prop.src.scrollWidth, this.prop.src.offsetWidth) + "px",
  9670. left: 0,
  9671. right: 0,
  9672. top: 0,
  9673. margin: "auto",
  9674. backgroundColor: "white"
  9675. }; // Set the overlay to hidden (could be changed in the future to provide a print preview).
  9676. var source = cloneNode(this.prop.src, this.opt.html2canvas.javascriptEnabled);
  9677. if (source.tagName === "BODY") {
  9678. containerCSS.height = Math.max(document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight) + "px";
  9679. }
  9680. this.prop.overlay = createElement("div", {
  9681. className: "html2pdf__overlay",
  9682. style: overlayCSS
  9683. });
  9684. this.prop.container = createElement("div", {
  9685. className: "html2pdf__container",
  9686. style: containerCSS
  9687. });
  9688. this.prop.container.appendChild(source);
  9689. this.prop.container.firstChild.appendChild(createElement("div", {
  9690. style: {
  9691. clear: "both",
  9692. border: "0 none transparent",
  9693. margin: 0,
  9694. padding: 0,
  9695. height: 0
  9696. }
  9697. }));
  9698. this.prop.container.style.float = "none";
  9699. this.prop.overlay.appendChild(this.prop.container);
  9700. document.body.appendChild(this.prop.overlay);
  9701. this.prop.container.firstChild.style.position = "relative";
  9702. this.prop.container.height = Math.max(this.prop.container.firstChild.clientHeight, this.prop.container.firstChild.scrollHeight, this.prop.container.firstChild.offsetHeight) + "px";
  9703. });
  9704. };
  9705. Worker.prototype.toCanvas = function toCanvas() {
  9706. // Set up function prerequisites.
  9707. var prereqs = [function checkContainer() {
  9708. return document.body.contains(this.prop.container) || this.toContainer();
  9709. }]; // Fulfill prereqs then create the canvas.
  9710. return this.thenList(prereqs).then(function toCanvas_main() {
  9711. // Handle old-fashioned 'onrendered' argument.
  9712. var options = Object.assign({}, this.opt.html2canvas);
  9713. delete options.onrendered;
  9714. if (!this.isHtml2CanvasLoaded()) {
  9715. return;
  9716. }
  9717. return html2canvas(this.prop.container, options);
  9718. }).then(function toCanvas_post(canvas) {
  9719. // Handle old-fashioned 'onrendered' argument.
  9720. var onRendered = this.opt.html2canvas.onrendered || function () {};
  9721. onRendered(canvas);
  9722. this.prop.canvas = canvas;
  9723. document.body.removeChild(this.prop.overlay);
  9724. });
  9725. };
  9726. Worker.prototype.toContext2d = function toContext2d() {
  9727. // Set up function prerequisites.
  9728. var prereqs = [function checkContainer() {
  9729. return document.body.contains(this.prop.container) || this.toContainer();
  9730. }]; // Fulfill prereqs then create the canvas.
  9731. return this.thenList(prereqs).then(function toContext2d_main() {
  9732. // Handle old-fashioned 'onrendered' argument.
  9733. var pdf = this.opt.jsPDF;
  9734. var options = Object.assign({
  9735. async: true,
  9736. allowTaint: true,
  9737. backgroundColor: "#ffffff",
  9738. imageTimeout: 15000,
  9739. logging: true,
  9740. proxy: null,
  9741. removeContainer: true,
  9742. foreignObjectRendering: false,
  9743. useCORS: false
  9744. }, this.opt.html2canvas);
  9745. delete options.onrendered;
  9746. options.windowHeight = options.windowHeight || 0;
  9747. options.windowHeight = options.windowHeight == 0 ? Math.max(this.prop.container.clientHeight, this.prop.container.scrollHeight, this.prop.container.offsetHeight) : options.windowHeight;
  9748. if (!this.isHtml2CanvasLoaded()) {
  9749. return;
  9750. }
  9751. return html2canvas(this.prop.container, options);
  9752. }).then(function toContext2d_post(canvas) {
  9753. // Handle old-fashioned 'onrendered' argument.
  9754. var onRendered = this.opt.html2canvas.onrendered || function () {};
  9755. onRendered(canvas);
  9756. this.prop.canvas = canvas;
  9757. document.body.removeChild(this.prop.overlay);
  9758. });
  9759. };
  9760. Worker.prototype.toImg = function toImg() {
  9761. // Set up function prerequisites.
  9762. var prereqs = [function checkCanvas() {
  9763. return this.prop.canvas || this.toCanvas();
  9764. }]; // Fulfill prereqs then create the image.
  9765. return this.thenList(prereqs).then(function toImg_main() {
  9766. var imgData = this.prop.canvas.toDataURL("image/" + this.opt.image.type, this.opt.image.quality);
  9767. this.prop.img = document.createElement("img");
  9768. this.prop.img.src = imgData;
  9769. });
  9770. };
  9771. Worker.prototype.toPdf = function toPdf() {
  9772. // Set up function prerequisites.
  9773. var prereqs = [function checkContext2d() {
  9774. return this.toContext2d();
  9775. } //function checkCanvas() { return this.prop.canvas || this.toCanvas(); }
  9776. ]; // Fulfill prereqs then create the image.
  9777. return this.thenList(prereqs).then(function toPdf_main() {
  9778. // Create local copies of frequently used properties.
  9779. this.prop.pdf = this.prop.pdf || this.opt.jsPDF;
  9780. });
  9781. };
  9782. /* ----- OUTPUT / SAVE ----- */
  9783. Worker.prototype.output = function output(type, options, src) {
  9784. // Redirect requests to the correct function (outputPdf / outputImg).
  9785. src = src || "pdf";
  9786. if (src.toLowerCase() === "img" || src.toLowerCase() === "image") {
  9787. return this.outputImg(type, options);
  9788. } else {
  9789. return this.outputPdf(type, options);
  9790. }
  9791. };
  9792. Worker.prototype.outputPdf = function outputPdf(type, options) {
  9793. // Set up function prerequisites.
  9794. var prereqs = [function checkPdf() {
  9795. return this.prop.pdf || this.toPdf();
  9796. }]; // Fulfill prereqs then perform the appropriate output.
  9797. return this.thenList(prereqs).then(function outputPdf_main() {
  9798. /* Currently implemented output types:
  9799. * https://rawgit.com/MrRio/jsPDF/master/docs/jspdf.js.html#line992
  9800. * save(options), arraybuffer, blob, bloburi/bloburl,
  9801. * datauristring/dataurlstring, dataurlnewwindow, datauri/dataurl
  9802. */
  9803. return this.prop.pdf.output(type, options);
  9804. });
  9805. };
  9806. Worker.prototype.outputImg = function outputImg(type, options) {
  9807. // Set up function prerequisites.
  9808. var prereqs = [function checkImg() {
  9809. return this.prop.img || this.toImg();
  9810. }]; // Fulfill prereqs then perform the appropriate output.
  9811. return this.thenList(prereqs).then(function outputImg_main() {
  9812. switch (type) {
  9813. case undefined:
  9814. case "img":
  9815. return this.prop.img;
  9816. case "datauristring":
  9817. case "dataurlstring":
  9818. return this.prop.img.src;
  9819. case "datauri":
  9820. case "dataurl":
  9821. return document.location.href = this.prop.img.src;
  9822. default:
  9823. throw 'Image output type "' + type + '" is not supported.';
  9824. }
  9825. });
  9826. };
  9827. Worker.prototype.isHtml2CanvasLoaded = function () {
  9828. var result = typeof global.html2canvas !== "undefined";
  9829. if (!result) {
  9830. console.error("html2canvas not loaded.");
  9831. }
  9832. return result;
  9833. };
  9834. Worker.prototype.save = function save(filename) {
  9835. // Set up function prerequisites.
  9836. var prereqs = [function checkPdf() {
  9837. return this.prop.pdf || this.toPdf();
  9838. }];
  9839. if (!this.isHtml2CanvasLoaded()) {
  9840. return;
  9841. } // Fulfill prereqs, update the filename (if provided), and save the PDF.
  9842. return this.thenList(prereqs).set(filename ? {
  9843. filename: filename
  9844. } : null).then(function save_main() {
  9845. this.prop.pdf.save(this.opt.filename);
  9846. });
  9847. };
  9848. Worker.prototype.doCallback = function doCallback(filename) {
  9849. // Set up function prerequisites.
  9850. var prereqs = [function checkPdf() {
  9851. return this.prop.pdf || this.toPdf();
  9852. }];
  9853. if (!this.isHtml2CanvasLoaded()) {
  9854. return;
  9855. } // Fulfill prereqs, update the filename (if provided), and save the PDF.
  9856. return this.thenList(prereqs).then(function doCallback_main() {
  9857. this.prop.callback(this.prop.pdf);
  9858. });
  9859. };
  9860. /* ----- SET / GET ----- */
  9861. Worker.prototype.set = function set(opt) {
  9862. // TODO: Implement ordered pairs?
  9863. // Silently ignore invalid or empty input.
  9864. if (objType(opt) !== "object") {
  9865. return this;
  9866. } // Build an array of setter functions to queue.
  9867. var fns = Object.keys(opt || {}).map(function (key) {
  9868. if (key in Worker.template.prop) {
  9869. // Set pre-defined properties.
  9870. return function set_prop() {
  9871. this.prop[key] = opt[key];
  9872. };
  9873. } else {
  9874. switch (key) {
  9875. case "margin":
  9876. return this.setMargin.bind(this, opt.margin);
  9877. case "jsPDF":
  9878. return function set_jsPDF() {
  9879. this.opt.jsPDF = opt.jsPDF;
  9880. return this.setPageSize();
  9881. };
  9882. case "pageSize":
  9883. return this.setPageSize.bind(this, opt.pageSize);
  9884. default:
  9885. // Set any other properties in opt.
  9886. return function set_opt() {
  9887. this.opt[key] = opt[key];
  9888. };
  9889. }
  9890. }
  9891. }, this); // Set properties within the promise chain.
  9892. return this.then(function set_main() {
  9893. return this.thenList(fns);
  9894. });
  9895. };
  9896. Worker.prototype.get = function get(key, cbk) {
  9897. return this.then(function get_main() {
  9898. // Fetch the requested property, either as a predefined prop or in opt.
  9899. var val = key in Worker.template.prop ? this.prop[key] : this.opt[key];
  9900. return cbk ? cbk(val) : val;
  9901. });
  9902. };
  9903. Worker.prototype.setMargin = function setMargin(margin) {
  9904. return this.then(function setMargin_main() {
  9905. // Parse the margin property.
  9906. switch (objType(margin)) {
  9907. case "number":
  9908. margin = [margin, margin, margin, margin];
  9909. case "array":
  9910. if (margin.length === 2) {
  9911. margin = [margin[0], margin[1], margin[0], margin[1]];
  9912. }
  9913. if (margin.length === 4) {
  9914. break;
  9915. }
  9916. default:
  9917. return this.error("Invalid margin array.");
  9918. } // Set the margin property, then update pageSize.
  9919. this.opt.margin = margin;
  9920. }).then(this.setPageSize);
  9921. };
  9922. Worker.prototype.setPageSize = function setPageSize(pageSize) {
  9923. function toPx(val, k) {
  9924. return Math.floor(val * k / 72 * 96);
  9925. }
  9926. return this.then(function setPageSize_main() {
  9927. // Retrieve page-size based on jsPDF settings, if not explicitly provided.
  9928. pageSize = pageSize || jsPDF.getPageSize(this.opt.jsPDF); // Add 'inner' field if not present.
  9929. if (!pageSize.hasOwnProperty("inner")) {
  9930. pageSize.inner = {
  9931. width: pageSize.width - this.opt.margin[1] - this.opt.margin[3],
  9932. height: pageSize.height - this.opt.margin[0] - this.opt.margin[2]
  9933. };
  9934. pageSize.inner.px = {
  9935. width: toPx(pageSize.inner.width, pageSize.k),
  9936. height: toPx(pageSize.inner.height, pageSize.k)
  9937. };
  9938. pageSize.inner.ratio = pageSize.inner.height / pageSize.inner.width;
  9939. } // Attach pageSize to this.
  9940. this.prop.pageSize = pageSize;
  9941. });
  9942. };
  9943. Worker.prototype.setProgress = function setProgress(val, state, n, stack) {
  9944. // Immediately update all progress values.
  9945. if (val != null) this.progress.val = val;
  9946. if (state != null) this.progress.state = state;
  9947. if (n != null) this.progress.n = n;
  9948. if (stack != null) this.progress.stack = stack;
  9949. this.progress.ratio = this.progress.val / this.progress.state; // Return this for command chaining.
  9950. return this;
  9951. };
  9952. Worker.prototype.updateProgress = function updateProgress(val, state, n, stack) {
  9953. // Immediately update all progress values, using setProgress.
  9954. return this.setProgress(val ? this.progress.val + val : null, state ? state : null, n ? this.progress.n + n : null, stack ? this.progress.stack.concat(stack) : null);
  9955. };
  9956. /* ----- PROMISE MAPPING ----- */
  9957. Worker.prototype.then = function then(onFulfilled, onRejected) {
  9958. // Wrap `this` for encapsulation.
  9959. var self = this;
  9960. return this.thenCore(onFulfilled, onRejected, function then_main(onFulfilled, onRejected) {
  9961. // Update progress while queuing, calling, and resolving `then`.
  9962. self.updateProgress(null, null, 1, [onFulfilled]);
  9963. return Promise.prototype.then.call(this, function then_pre(val) {
  9964. self.updateProgress(null, onFulfilled);
  9965. return val;
  9966. }).then(onFulfilled, onRejected).then(function then_post(val) {
  9967. self.updateProgress(1);
  9968. return val;
  9969. });
  9970. });
  9971. };
  9972. Worker.prototype.thenCore = function thenCore(onFulfilled, onRejected, thenBase) {
  9973. // Handle optional thenBase parameter.
  9974. thenBase = thenBase || Promise.prototype.then; // Wrap `this` for encapsulation and bind it to the promise handlers.
  9975. var self = this;
  9976. if (onFulfilled) {
  9977. onFulfilled = onFulfilled.bind(self);
  9978. }
  9979. if (onRejected) {
  9980. onRejected = onRejected.bind(self);
  9981. } // Cast self into a Promise to avoid polyfills recursively defining `then`.
  9982. var isNative = Promise.toString().indexOf("[native code]") !== -1 && Promise.name === "Promise";
  9983. var selfPromise = isNative ? self : Worker.convert(Object.assign({}, self), Promise.prototype); // Return the promise, after casting it into a Worker and preserving props.
  9984. var returnVal = thenBase.call(selfPromise, onFulfilled, onRejected);
  9985. return Worker.convert(returnVal, self.__proto__);
  9986. };
  9987. Worker.prototype.thenExternal = function thenExternal(onFulfilled, onRejected) {
  9988. // Call `then` and return a standard promise (exits the Worker chain).
  9989. return Promise.prototype.then.call(this, onFulfilled, onRejected);
  9990. };
  9991. Worker.prototype.thenList = function thenList(fns) {
  9992. // Queue a series of promise 'factories' into the promise chain.
  9993. var self = this;
  9994. fns.forEach(function thenList_forEach(fn) {
  9995. self = self.thenCore(fn);
  9996. });
  9997. return self;
  9998. };
  9999. Worker.prototype["catch"] = function (onRejected) {
  10000. // Bind `this` to the promise handler, call `catch`, and return a Worker.
  10001. if (onRejected) {
  10002. onRejected = onRejected.bind(this);
  10003. }
  10004. var returnVal = Promise.prototype["catch"].call(this, onRejected);
  10005. return Worker.convert(returnVal, this);
  10006. };
  10007. Worker.prototype.catchExternal = function catchExternal(onRejected) {
  10008. // Call `catch` and return a standard promise (exits the Worker chain).
  10009. return Promise.prototype["catch"].call(this, onRejected);
  10010. };
  10011. Worker.prototype.error = function error(msg) {
  10012. // Throw the error in the Promise chain.
  10013. return this.then(function error_main() {
  10014. throw new Error(msg);
  10015. });
  10016. };
  10017. /* ----- ALIASES ----- */
  10018. Worker.prototype.using = Worker.prototype.set;
  10019. Worker.prototype.saveAs = Worker.prototype.save;
  10020. Worker.prototype.export = Worker.prototype.output;
  10021. Worker.prototype.run = Worker.prototype.then; // Get dimensions of a PDF page, as determined by jsPDF.
  10022. jsPDF.getPageSize = function (orientation, unit, format) {
  10023. // Decode options object
  10024. if (_typeof(orientation) === "object") {
  10025. var options = orientation;
  10026. orientation = options.orientation;
  10027. unit = options.unit || unit;
  10028. format = options.format || format;
  10029. } // Default options
  10030. unit = unit || "mm";
  10031. format = format || "a4";
  10032. orientation = ("" + (orientation || "P")).toLowerCase();
  10033. var format_as_string = ("" + format).toLowerCase(); // Size in pt of various paper formats
  10034. var pageFormats = {
  10035. a0: [2383.94, 3370.39],
  10036. a1: [1683.78, 2383.94],
  10037. a2: [1190.55, 1683.78],
  10038. a3: [841.89, 1190.55],
  10039. a4: [595.28, 841.89],
  10040. a5: [419.53, 595.28],
  10041. a6: [297.64, 419.53],
  10042. a7: [209.76, 297.64],
  10043. a8: [147.4, 209.76],
  10044. a9: [104.88, 147.4],
  10045. a10: [73.7, 104.88],
  10046. b0: [2834.65, 4008.19],
  10047. b1: [2004.09, 2834.65],
  10048. b2: [1417.32, 2004.09],
  10049. b3: [1000.63, 1417.32],
  10050. b4: [708.66, 1000.63],
  10051. b5: [498.9, 708.66],
  10052. b6: [354.33, 498.9],
  10053. b7: [249.45, 354.33],
  10054. b8: [175.75, 249.45],
  10055. b9: [124.72, 175.75],
  10056. b10: [87.87, 124.72],
  10057. c0: [2599.37, 3676.54],
  10058. c1: [1836.85, 2599.37],
  10059. c2: [1298.27, 1836.85],
  10060. c3: [918.43, 1298.27],
  10061. c4: [649.13, 918.43],
  10062. c5: [459.21, 649.13],
  10063. c6: [323.15, 459.21],
  10064. c7: [229.61, 323.15],
  10065. c8: [161.57, 229.61],
  10066. c9: [113.39, 161.57],
  10067. c10: [79.37, 113.39],
  10068. dl: [311.81, 623.62],
  10069. letter: [612, 792],
  10070. "government-letter": [576, 756],
  10071. legal: [612, 1008],
  10072. "junior-legal": [576, 360],
  10073. ledger: [1224, 792],
  10074. tabloid: [792, 1224],
  10075. "credit-card": [153, 243]
  10076. }; // Unit conversion
  10077. switch (unit) {
  10078. case "pt":
  10079. var k = 1;
  10080. break;
  10081. case "mm":
  10082. var k = 72 / 25.4;
  10083. break;
  10084. case "cm":
  10085. var k = 72 / 2.54;
  10086. break;
  10087. case "in":
  10088. var k = 72;
  10089. break;
  10090. case "px":
  10091. var k = 72 / 96;
  10092. break;
  10093. case "pc":
  10094. var k = 12;
  10095. break;
  10096. case "em":
  10097. var k = 12;
  10098. break;
  10099. case "ex":
  10100. var k = 6;
  10101. break;
  10102. default:
  10103. throw "Invalid unit: " + unit;
  10104. } // Dimensions are stored as user units and converted to points on output
  10105. if (pageFormats.hasOwnProperty(format_as_string)) {
  10106. var pageHeight = pageFormats[format_as_string][1] / k;
  10107. var pageWidth = pageFormats[format_as_string][0] / k;
  10108. } else {
  10109. try {
  10110. var pageHeight = format[1];
  10111. var pageWidth = format[0];
  10112. } catch (err) {
  10113. throw new Error("Invalid format: " + format);
  10114. }
  10115. } // Handle page orientation
  10116. if (orientation === "p" || orientation === "portrait") {
  10117. orientation = "p";
  10118. if (pageWidth > pageHeight) {
  10119. var tmp = pageWidth;
  10120. pageWidth = pageHeight;
  10121. pageHeight = tmp;
  10122. }
  10123. } else if (orientation === "l" || orientation === "landscape") {
  10124. orientation = "l";
  10125. if (pageHeight > pageWidth) {
  10126. var tmp = pageWidth;
  10127. pageWidth = pageHeight;
  10128. pageHeight = tmp;
  10129. }
  10130. } else {
  10131. throw "Invalid orientation: " + orientation;
  10132. } // Return information (k is the unit conversion ratio from pts)
  10133. var info = {
  10134. width: pageWidth,
  10135. height: pageHeight,
  10136. unit: unit,
  10137. k: k
  10138. };
  10139. return info;
  10140. };
  10141. /**
  10142. * Generate a PDF from an HTML element or string using.
  10143. *
  10144. * @name html
  10145. * @function
  10146. * @param {Element|string} source The source element or HTML string.
  10147. * @param {Object=} options An object of optional settings.
  10148. * @description The Plugin needs html2canvas from niklasvh
  10149. */
  10150. jsPDFAPI.html = function (src, options) {
  10151. options = options || {};
  10152. options.callback = options.callback || function () {};
  10153. options.html2canvas = options.html2canvas || {};
  10154. options.html2canvas.canvas = options.html2canvas.canvas || this.canvas;
  10155. options.jsPDF = options.jsPDF || this; // Create a new worker with the given options.
  10156. var pdf = options.jsPDF;
  10157. pdf.annotations = {
  10158. _nameMap: [],
  10159. createAnnotation: function createAnnotation(href, bounds) {
  10160. var x = pdf.context2d._wrapX(bounds.left);
  10161. var y = pdf.context2d._wrapY(bounds.top);
  10162. var page = pdf.context2d._page(bounds.top);
  10163. var options;
  10164. var index = href.indexOf("#");
  10165. if (index >= 0) {
  10166. options = {
  10167. name: href.substring(index + 1)
  10168. };
  10169. } else {
  10170. options = {
  10171. url: href
  10172. };
  10173. }
  10174. pdf.link(x, y, bounds.right - bounds.left, bounds.bottom - bounds.top, options);
  10175. },
  10176. setName: function setName(name, bounds) {
  10177. var x = pdf.context2d._wrapX(bounds.left);
  10178. var y = pdf.context2d._wrapY(bounds.top);
  10179. var page = pdf.context2d._page(bounds.top);
  10180. this._nameMap[name] = {
  10181. page: page,
  10182. x: x,
  10183. y: y
  10184. };
  10185. }
  10186. };
  10187. pdf.context2d._pageBreakAt = function (y) {
  10188. this.pageBreaks.push(y);
  10189. };
  10190. pdf.context2d._gotoPage = function (pageOneBased) {
  10191. while (pdf.internal.getNumberOfPages() < pageOneBased) {
  10192. pdf.addPage();
  10193. }
  10194. pdf.setPage(pageOneBased);
  10195. };
  10196. pdf.context2d.pageWrapYEnabled = true;
  10197. pdf.context2d.pageWrapY = pdf.internal.pageSize.getHeight() / pdf.internal.scaleFactor + 1;
  10198. pdf.canvas.autoContext2dResizeY = false;
  10199. var worker = new Worker(options);
  10200. if (!options.worker) {
  10201. // If worker is not set to true, perform the traditional 'simple' operation.
  10202. return worker.from(src).doCallback();
  10203. } else {
  10204. // Otherwise, return the worker for new Promise-based operation.
  10205. return worker;
  10206. }
  10207. return this;
  10208. };
  10209. })(jsPDF.API, typeof window !== "undefined" && window || typeof global !== "undefined" && global);
  10210. /**
  10211. * @license
  10212. * ====================================================================
  10213. * Copyright (c) 2013 Youssef Beddad, youssef.beddad@gmail.com
  10214. *
  10215. *
  10216. * ====================================================================
  10217. */
  10218. /*global jsPDF */
  10219. /**
  10220. * jsPDF JavaScript plugin
  10221. *
  10222. * @name javascript
  10223. * @module
  10224. */
  10225. (function (jsPDFAPI) {
  10226. var jsNamesObj, jsJsObj, text;
  10227. /**
  10228. * @name addJS
  10229. * @function
  10230. * @param {string} javascript The javascript to be embedded into the PDF-file.
  10231. * @returns {jsPDF}
  10232. */
  10233. jsPDFAPI.addJS = function (javascript) {
  10234. text = javascript;
  10235. this.internal.events.subscribe("postPutResources", function (javascript) {
  10236. jsNamesObj = this.internal.newObject();
  10237. this.internal.out("<<");
  10238. this.internal.out("/Names [(EmbeddedJS) " + (jsNamesObj + 1) + " 0 R]");
  10239. this.internal.out(">>");
  10240. this.internal.out("endobj");
  10241. jsJsObj = this.internal.newObject();
  10242. this.internal.out("<<");
  10243. this.internal.out("/S /JavaScript");
  10244. this.internal.out("/JS (" + text + ")");
  10245. this.internal.out(">>");
  10246. this.internal.out("endobj");
  10247. });
  10248. this.internal.events.subscribe("putCatalog", function () {
  10249. if (jsNamesObj !== undefined && jsJsObj !== undefined) {
  10250. this.internal.out("/Names <</JavaScript " + jsNamesObj + " 0 R>>");
  10251. }
  10252. });
  10253. return this;
  10254. };
  10255. })(jsPDF.API);
  10256. /**
  10257. * @license
  10258. * Copyright (c) 2014 Steven Spungin (TwelveTone LLC) steven@twelvetone.tv
  10259. *
  10260. * Licensed under the MIT License.
  10261. * http://opensource.org/licenses/mit-license
  10262. */
  10263. /**
  10264. * jsPDF Outline PlugIn
  10265. *
  10266. * Generates a PDF Outline
  10267. * @name outline
  10268. * @module
  10269. */
  10270. (function (jsPDFAPI) {
  10271. jsPDFAPI.events.push(["postPutResources", function () {
  10272. var pdf = this;
  10273. var rx = /^(\d+) 0 obj$/; // Write action goto objects for each page
  10274. // this.outline.destsGoto = [];
  10275. // for (var i = 0; i < totalPages; i++) {
  10276. // var id = pdf.internal.newObject();
  10277. // this.outline.destsGoto.push(id);
  10278. // pdf.internal.write("<</D[" + (i * 2 + 3) + " 0 R /XYZ null
  10279. // null null]/S/GoTo>> endobj");
  10280. // }
  10281. //
  10282. // for (var i = 0; i < dests.length; i++) {
  10283. // pdf.internal.write("(page_" + (i + 1) + ")" + dests[i] + " 0
  10284. // R");
  10285. // }
  10286. //
  10287. if (this.outline.root.children.length > 0) {
  10288. var lines = pdf.outline.render().split(/\r\n/);
  10289. for (var i = 0; i < lines.length; i++) {
  10290. var line = lines[i];
  10291. var m = rx.exec(line);
  10292. if (m != null) {
  10293. var oid = m[1];
  10294. pdf.internal.newObjectDeferredBegin(oid);
  10295. }
  10296. pdf.internal.write(line);
  10297. }
  10298. } // This code will write named destination for each page reference
  10299. // (page_1, etc)
  10300. if (this.outline.createNamedDestinations) {
  10301. var totalPages = this.internal.pages.length; // WARNING: this assumes jsPDF starts on page 3 and pageIDs
  10302. // follow 5, 7, 9, etc
  10303. // Write destination objects for each page
  10304. var dests = [];
  10305. for (var i = 0; i < totalPages; i++) {
  10306. var id = pdf.internal.newObject();
  10307. dests.push(id);
  10308. var info = pdf.internal.getPageInfo(i + 1);
  10309. pdf.internal.write("<< /D[" + info.objId + " 0 R /XYZ null null null]>> endobj");
  10310. } // assign a name for each destination
  10311. var names2Oid = pdf.internal.newObject();
  10312. pdf.internal.write("<< /Names [ ");
  10313. for (var i = 0; i < dests.length; i++) {
  10314. pdf.internal.write("(page_" + (i + 1) + ")" + dests[i] + " 0 R");
  10315. }
  10316. pdf.internal.write(" ] >>", "endobj"); // var kids = pdf.internal.newObject();
  10317. // pdf.internal.write('<< /Kids [ ' + names2Oid + ' 0 R');
  10318. // pdf.internal.write(' ] >>', 'endobj');
  10319. var namesOid = pdf.internal.newObject();
  10320. pdf.internal.write("<< /Dests " + names2Oid + " 0 R");
  10321. pdf.internal.write(">>", "endobj");
  10322. }
  10323. }]);
  10324. jsPDFAPI.events.push(["putCatalog", function () {
  10325. var pdf = this;
  10326. if (pdf.outline.root.children.length > 0) {
  10327. pdf.internal.write("/Outlines", this.outline.makeRef(this.outline.root));
  10328. if (this.outline.createNamedDestinations) {
  10329. pdf.internal.write("/Names " + namesOid + " 0 R");
  10330. } // Open with Bookmarks showing
  10331. // pdf.internal.write("/PageMode /UseOutlines");
  10332. }
  10333. }]);
  10334. jsPDFAPI.events.push(["initialized", function () {
  10335. var pdf = this;
  10336. pdf.outline = {
  10337. createNamedDestinations: false,
  10338. root: {
  10339. children: []
  10340. }
  10341. };
  10342. /**
  10343. * Options: pageNumber
  10344. */
  10345. pdf.outline.add = function (parent, title, options) {
  10346. var item = {
  10347. title: title,
  10348. options: options,
  10349. children: []
  10350. };
  10351. if (parent == null) {
  10352. parent = this.root;
  10353. }
  10354. parent.children.push(item);
  10355. return item;
  10356. };
  10357. pdf.outline.render = function () {
  10358. this.ctx = {};
  10359. this.ctx.val = "";
  10360. this.ctx.pdf = pdf;
  10361. this.genIds_r(this.root);
  10362. this.renderRoot(this.root);
  10363. this.renderItems(this.root);
  10364. return this.ctx.val;
  10365. };
  10366. pdf.outline.genIds_r = function (node) {
  10367. node.id = pdf.internal.newObjectDeferred();
  10368. for (var i = 0; i < node.children.length; i++) {
  10369. this.genIds_r(node.children[i]);
  10370. }
  10371. };
  10372. pdf.outline.renderRoot = function (node) {
  10373. this.objStart(node);
  10374. this.line("/Type /Outlines");
  10375. if (node.children.length > 0) {
  10376. this.line("/First " + this.makeRef(node.children[0]));
  10377. this.line("/Last " + this.makeRef(node.children[node.children.length - 1]));
  10378. }
  10379. this.line("/Count " + this.count_r({
  10380. count: 0
  10381. }, node));
  10382. this.objEnd();
  10383. };
  10384. pdf.outline.renderItems = function (node) {
  10385. for (var i = 0; i < node.children.length; i++) {
  10386. var item = node.children[i];
  10387. this.objStart(item);
  10388. this.line("/Title " + this.makeString(item.title));
  10389. this.line("/Parent " + this.makeRef(node));
  10390. if (i > 0) {
  10391. this.line("/Prev " + this.makeRef(node.children[i - 1]));
  10392. }
  10393. if (i < node.children.length - 1) {
  10394. this.line("/Next " + this.makeRef(node.children[i + 1]));
  10395. }
  10396. if (item.children.length > 0) {
  10397. this.line("/First " + this.makeRef(item.children[0]));
  10398. this.line("/Last " + this.makeRef(item.children[item.children.length - 1]));
  10399. }
  10400. var count = this.count = this.count_r({
  10401. count: 0
  10402. }, item);
  10403. if (count > 0) {
  10404. this.line("/Count " + count);
  10405. }
  10406. if (item.options) {
  10407. if (item.options.pageNumber) {
  10408. // Explicit Destination
  10409. //WARNING this assumes page ids are 3,5,7, etc.
  10410. var info = pdf.internal.getPageInfo(item.options.pageNumber);
  10411. this.line("/Dest " + "[" + info.objId + " 0 R /XYZ 0 " + this.ctx.pdf.internal.pageSize.getHeight() * this.ctx.pdf.internal.scaleFactor + " 0]"); // this line does not work on all clients (pageNumber instead of page ref)
  10412. //this.line('/Dest ' + '[' + (item.options.pageNumber - 1) + ' /XYZ 0 ' + this.ctx.pdf.internal.pageSize.getHeight() + ' 0]');
  10413. // Named Destination
  10414. // this.line('/Dest (page_' + (item.options.pageNumber) + ')');
  10415. // Action Destination
  10416. // var id = pdf.internal.newObject();
  10417. // pdf.internal.write('<</D[' + (item.options.pageNumber - 1) + ' /XYZ null null null]/S/GoTo>> endobj');
  10418. // this.line('/A ' + id + ' 0 R' );
  10419. }
  10420. }
  10421. this.objEnd();
  10422. }
  10423. for (var i = 0; i < node.children.length; i++) {
  10424. var item = node.children[i];
  10425. this.renderItems(item);
  10426. }
  10427. };
  10428. pdf.outline.line = function (text) {
  10429. this.ctx.val += text + "\r\n";
  10430. };
  10431. pdf.outline.makeRef = function (node) {
  10432. return node.id + " 0 R";
  10433. };
  10434. pdf.outline.makeString = function (val) {
  10435. return "(" + pdf.internal.pdfEscape(val) + ")";
  10436. };
  10437. pdf.outline.objStart = function (node) {
  10438. this.ctx.val += "\r\n" + node.id + " 0 obj" + "\r\n<<\r\n";
  10439. };
  10440. pdf.outline.objEnd = function (node) {
  10441. this.ctx.val += ">> \r\n" + "endobj" + "\r\n";
  10442. };
  10443. pdf.outline.count_r = function (ctx, node) {
  10444. for (var i = 0; i < node.children.length; i++) {
  10445. ctx.count++;
  10446. this.count_r(ctx, node.children[i]);
  10447. }
  10448. return ctx.count;
  10449. };
  10450. }]);
  10451. return this;
  10452. })(jsPDF.API);
  10453. /**
  10454. * @license
  10455. *
  10456. * Copyright (c) 2014 James Robb, https://github.com/jamesbrobb
  10457. *
  10458. *
  10459. * ====================================================================
  10460. */
  10461. /**
  10462. * jsPDF PNG PlugIn
  10463. * @name png_support
  10464. * @module
  10465. */
  10466. (function (jsPDFAPI) {
  10467. /*
  10468. * @see http://www.w3.org/TR/PNG-Chunks.html
  10469. *
  10470. Color Allowed Interpretation
  10471. Type Bit Depths
  10472. 0 1,2,4,8,16 Each pixel is a grayscale sample.
  10473. 2 8,16 Each pixel is an R,G,B triple.
  10474. 3 1,2,4,8 Each pixel is a palette index;
  10475. a PLTE chunk must appear.
  10476. 4 8,16 Each pixel is a grayscale sample,
  10477. followed by an alpha sample.
  10478. 6 8,16 Each pixel is an R,G,B triple,
  10479. followed by an alpha sample.
  10480. */
  10481. /*
  10482. * PNG filter method types
  10483. *
  10484. * @see http://www.w3.org/TR/PNG-Filters.html
  10485. * @see http://www.libpng.org/pub/png/book/chapter09.html
  10486. *
  10487. * This is what the value 'Predictor' in decode params relates to
  10488. *
  10489. * 15 is "optimal prediction", which means the prediction algorithm can change from line to line.
  10490. * In that case, you actually have to read the first byte off each line for the prediction algorthim (which should be 0-4, corresponding to PDF 10-14) and select the appropriate unprediction algorithm based on that byte.
  10491. *
  10492. 0 None
  10493. 1 Sub
  10494. 2 Up
  10495. 3 Average
  10496. 4 Paeth
  10497. */
  10498. var doesNotHavePngJS = function doesNotHavePngJS() {
  10499. return typeof PNG !== "function" || typeof FlateStream !== "function";
  10500. },
  10501. canCompress = function canCompress(value) {
  10502. return value !== jsPDFAPI.image_compression.NONE && hasCompressionJS();
  10503. },
  10504. hasCompressionJS = function hasCompressionJS() {
  10505. var inst = typeof Deflater === "function";
  10506. if (!inst) throw new Error("requires deflate.js for compression");
  10507. return inst;
  10508. },
  10509. compressBytes = function compressBytes(bytes, lineLength, colorsPerPixel, compression) {
  10510. var level = 5,
  10511. filter_method = filterUp;
  10512. switch (compression) {
  10513. case jsPDFAPI.image_compression.FAST:
  10514. level = 3;
  10515. filter_method = filterSub;
  10516. break;
  10517. case jsPDFAPI.image_compression.MEDIUM:
  10518. level = 6;
  10519. filter_method = filterAverage;
  10520. break;
  10521. case jsPDFAPI.image_compression.SLOW:
  10522. level = 9;
  10523. filter_method = filterPaeth; //uses to sum to choose best filter for each line
  10524. break;
  10525. }
  10526. bytes = applyPngFilterMethod(bytes, lineLength, colorsPerPixel, filter_method);
  10527. var header = new Uint8Array(createZlibHeader(level));
  10528. var checksum = adler32(bytes);
  10529. var deflate = new Deflater(level);
  10530. var a = deflate.append(bytes);
  10531. var cBytes = deflate.flush();
  10532. var len = header.length + a.length + cBytes.length;
  10533. var cmpd = new Uint8Array(len + 4);
  10534. cmpd.set(header);
  10535. cmpd.set(a, header.length);
  10536. cmpd.set(cBytes, header.length + a.length);
  10537. cmpd[len++] = checksum >>> 24 & 0xff;
  10538. cmpd[len++] = checksum >>> 16 & 0xff;
  10539. cmpd[len++] = checksum >>> 8 & 0xff;
  10540. cmpd[len++] = checksum & 0xff;
  10541. return jsPDFAPI.arrayBufferToBinaryString(cmpd);
  10542. },
  10543. createZlibHeader = function createZlibHeader(bytes, level) {
  10544. /*
  10545. * @see http://www.ietf.org/rfc/rfc1950.txt for zlib header
  10546. */
  10547. var cm = 8;
  10548. var cinfo = Math.LOG2E * Math.log(0x8000) - 8;
  10549. var cmf = cinfo << 4 | cm;
  10550. var hdr = cmf << 8;
  10551. var flevel = Math.min(3, (level - 1 & 0xff) >> 1);
  10552. hdr |= flevel << 6;
  10553. hdr |= 0; //FDICT
  10554. hdr += 31 - hdr % 31;
  10555. return [cmf, hdr & 0xff & 0xff];
  10556. },
  10557. adler32 = function adler32(array, param) {
  10558. var adler = 1;
  10559. var s1 = adler & 0xffff,
  10560. s2 = adler >>> 16 & 0xffff;
  10561. var len = array.length;
  10562. var tlen;
  10563. var i = 0;
  10564. while (len > 0) {
  10565. tlen = len > param ? param : len;
  10566. len -= tlen;
  10567. do {
  10568. s1 += array[i++];
  10569. s2 += s1;
  10570. } while (--tlen);
  10571. s1 %= 65521;
  10572. s2 %= 65521;
  10573. }
  10574. return (s2 << 16 | s1) >>> 0;
  10575. },
  10576. applyPngFilterMethod = function applyPngFilterMethod(bytes, lineLength, colorsPerPixel, filter_method) {
  10577. var lines = bytes.length / lineLength,
  10578. result = new Uint8Array(bytes.length + lines),
  10579. filter_methods = getFilterMethods(),
  10580. i = 0,
  10581. line,
  10582. prevLine,
  10583. offset;
  10584. for (; i < lines; i++) {
  10585. offset = i * lineLength;
  10586. line = bytes.subarray(offset, offset + lineLength);
  10587. if (filter_method) {
  10588. result.set(filter_method(line, colorsPerPixel, prevLine), offset + i);
  10589. } else {
  10590. var j = 0,
  10591. len = filter_methods.length,
  10592. results = [];
  10593. for (; j < len; j++) {
  10594. results[j] = filter_methods[j](line, colorsPerPixel, prevLine);
  10595. }
  10596. var ind = getIndexOfSmallestSum(results.concat());
  10597. result.set(results[ind], offset + i);
  10598. }
  10599. prevLine = line;
  10600. }
  10601. return result;
  10602. },
  10603. filterNone = function filterNone(line, colorsPerPixel, prevLine) {
  10604. /*var result = new Uint8Array(line.length + 1);
  10605. result[0] = 0;
  10606. result.set(line, 1);*/
  10607. var result = Array.apply([], line);
  10608. result.unshift(0);
  10609. return result;
  10610. },
  10611. filterSub = function filterSub(line, colorsPerPixel, prevLine) {
  10612. var result = [],
  10613. i = 0,
  10614. len = line.length,
  10615. left;
  10616. result[0] = 1;
  10617. for (; i < len; i++) {
  10618. left = line[i - colorsPerPixel] || 0;
  10619. result[i + 1] = line[i] - left + 0x0100 & 0xff;
  10620. }
  10621. return result;
  10622. },
  10623. filterUp = function filterUp(line, colorsPerPixel, prevLine) {
  10624. var result = [],
  10625. i = 0,
  10626. len = line.length,
  10627. up;
  10628. result[0] = 2;
  10629. for (; i < len; i++) {
  10630. up = prevLine && prevLine[i] || 0;
  10631. result[i + 1] = line[i] - up + 0x0100 & 0xff;
  10632. }
  10633. return result;
  10634. },
  10635. filterAverage = function filterAverage(line, colorsPerPixel, prevLine) {
  10636. var result = [],
  10637. i = 0,
  10638. len = line.length,
  10639. left,
  10640. up;
  10641. result[0] = 3;
  10642. for (; i < len; i++) {
  10643. left = line[i - colorsPerPixel] || 0;
  10644. up = prevLine && prevLine[i] || 0;
  10645. result[i + 1] = line[i] + 0x0100 - (left + up >>> 1) & 0xff;
  10646. }
  10647. return result;
  10648. },
  10649. filterPaeth = function filterPaeth(line, colorsPerPixel, prevLine) {
  10650. var result = [],
  10651. i = 0,
  10652. len = line.length,
  10653. left,
  10654. up,
  10655. upLeft,
  10656. paeth;
  10657. result[0] = 4;
  10658. for (; i < len; i++) {
  10659. left = line[i - colorsPerPixel] || 0;
  10660. up = prevLine && prevLine[i] || 0;
  10661. upLeft = prevLine && prevLine[i - colorsPerPixel] || 0;
  10662. paeth = paethPredictor(left, up, upLeft);
  10663. result[i + 1] = line[i] - paeth + 0x0100 & 0xff;
  10664. }
  10665. return result;
  10666. },
  10667. paethPredictor = function paethPredictor(left, up, upLeft) {
  10668. var p = left + up - upLeft,
  10669. pLeft = Math.abs(p - left),
  10670. pUp = Math.abs(p - up),
  10671. pUpLeft = Math.abs(p - upLeft);
  10672. return pLeft <= pUp && pLeft <= pUpLeft ? left : pUp <= pUpLeft ? up : upLeft;
  10673. },
  10674. getFilterMethods = function getFilterMethods() {
  10675. return [filterNone, filterSub, filterUp, filterAverage, filterPaeth];
  10676. },
  10677. getIndexOfSmallestSum = function getIndexOfSmallestSum(arrays) {
  10678. var i = 0,
  10679. len = arrays.length,
  10680. sum,
  10681. min,
  10682. ind;
  10683. while (i < len) {
  10684. sum = absSum(arrays[i].slice(1));
  10685. if (sum < min || !min) {
  10686. min = sum;
  10687. ind = i;
  10688. }
  10689. i++;
  10690. }
  10691. return ind;
  10692. },
  10693. absSum = function absSum(array) {
  10694. var i = 0,
  10695. len = array.length,
  10696. sum = 0;
  10697. while (i < len) {
  10698. sum += Math.abs(array[i++]);
  10699. }
  10700. return sum;
  10701. },
  10702. getPredictorFromCompression = function getPredictorFromCompression(compression) {
  10703. var predictor;
  10704. switch (compression) {
  10705. case jsPDFAPI.image_compression.FAST:
  10706. predictor = 11;
  10707. break;
  10708. case jsPDFAPI.image_compression.MEDIUM:
  10709. predictor = 13;
  10710. break;
  10711. case jsPDFAPI.image_compression.SLOW:
  10712. predictor = 14;
  10713. break;
  10714. default:
  10715. predictor = 12;
  10716. break;
  10717. }
  10718. return predictor;
  10719. };
  10720. /**
  10721. *
  10722. * @name processPNG
  10723. * @function
  10724. * @ignore
  10725. */
  10726. jsPDFAPI.processPNG = function (imageData, imageIndex, alias, compression, dataAsBinaryString) {
  10727. var colorSpace = this.color_spaces.DEVICE_RGB,
  10728. decode = this.decode.FLATE_DECODE,
  10729. bpc = 8,
  10730. img,
  10731. dp,
  10732. trns,
  10733. colors,
  10734. pal,
  10735. smask;
  10736. /* if(this.isString(imageData)) {
  10737. }*/
  10738. if (this.isArrayBuffer(imageData)) imageData = new Uint8Array(imageData);
  10739. if (this.isArrayBufferView(imageData)) {
  10740. if (doesNotHavePngJS()) throw new Error("PNG support requires png.js and zlib.js");
  10741. img = new PNG(imageData);
  10742. imageData = img.imgData;
  10743. bpc = img.bits;
  10744. colorSpace = img.colorSpace;
  10745. colors = img.colors; //logImg(img);
  10746. /*
  10747. * colorType 6 - Each pixel is an R,G,B triple, followed by an alpha sample.
  10748. *
  10749. * colorType 4 - Each pixel is a grayscale sample, followed by an alpha sample.
  10750. *
  10751. * Extract alpha to create two separate images, using the alpha as a sMask
  10752. */
  10753. if ([4, 6].indexOf(img.colorType) !== -1) {
  10754. /*
  10755. * processes 8 bit RGBA and grayscale + alpha images
  10756. */
  10757. if (img.bits === 8) {
  10758. var pixels = img.pixelBitlength == 32 ? new Uint32Array(img.decodePixels().buffer) : img.pixelBitlength == 16 ? new Uint16Array(img.decodePixels().buffer) : new Uint8Array(img.decodePixels().buffer),
  10759. len = pixels.length,
  10760. imgData = new Uint8Array(len * img.colors),
  10761. alphaData = new Uint8Array(len),
  10762. pDiff = img.pixelBitlength - img.bits,
  10763. i = 0,
  10764. n = 0,
  10765. pixel,
  10766. pbl;
  10767. for (; i < len; i++) {
  10768. pixel = pixels[i];
  10769. pbl = 0;
  10770. while (pbl < pDiff) {
  10771. imgData[n++] = pixel >>> pbl & 0xff;
  10772. pbl = pbl + img.bits;
  10773. }
  10774. alphaData[i] = pixel >>> pbl & 0xff;
  10775. }
  10776. }
  10777. /*
  10778. * processes 16 bit RGBA and grayscale + alpha images
  10779. */
  10780. if (img.bits === 16) {
  10781. var pixels = new Uint32Array(img.decodePixels().buffer),
  10782. len = pixels.length,
  10783. imgData = new Uint8Array(len * (32 / img.pixelBitlength) * img.colors),
  10784. alphaData = new Uint8Array(len * (32 / img.pixelBitlength)),
  10785. hasColors = img.colors > 1,
  10786. i = 0,
  10787. n = 0,
  10788. a = 0,
  10789. pixel;
  10790. while (i < len) {
  10791. pixel = pixels[i++];
  10792. imgData[n++] = pixel >>> 0 & 0xff;
  10793. if (hasColors) {
  10794. imgData[n++] = pixel >>> 16 & 0xff;
  10795. pixel = pixels[i++];
  10796. imgData[n++] = pixel >>> 0 & 0xff;
  10797. }
  10798. alphaData[a++] = pixel >>> 16 & 0xff;
  10799. }
  10800. bpc = 8;
  10801. }
  10802. if (canCompress(compression)) {
  10803. imageData = compressBytes(imgData, img.width * img.colors, img.colors, compression);
  10804. smask = compressBytes(alphaData, img.width, 1, compression);
  10805. } else {
  10806. imageData = imgData;
  10807. smask = alphaData;
  10808. decode = null;
  10809. }
  10810. }
  10811. /*
  10812. * Indexed png. Each pixel is a palette index.
  10813. */
  10814. if (img.colorType === 3) {
  10815. colorSpace = this.color_spaces.INDEXED;
  10816. pal = img.palette;
  10817. if (img.transparency.indexed) {
  10818. var trans = img.transparency.indexed;
  10819. var total = 0,
  10820. i = 0,
  10821. len = trans.length;
  10822. for (; i < len; ++i) {
  10823. total += trans[i];
  10824. }
  10825. total = total / 255;
  10826. /*
  10827. * a single color is specified as 100% transparent (0),
  10828. * so we set trns to use a /Mask with that index
  10829. */
  10830. if (total === len - 1 && trans.indexOf(0) !== -1) {
  10831. trns = [trans.indexOf(0)];
  10832. /*
  10833. * there's more than one colour within the palette that specifies
  10834. * a transparency value less than 255, so we unroll the pixels to create an image sMask
  10835. */
  10836. } else if (total !== len) {
  10837. var pixels = img.decodePixels(),
  10838. alphaData = new Uint8Array(pixels.length),
  10839. i = 0,
  10840. len = pixels.length;
  10841. for (; i < len; i++) {
  10842. alphaData[i] = trans[pixels[i]];
  10843. }
  10844. smask = compressBytes(alphaData, img.width, 1);
  10845. }
  10846. }
  10847. }
  10848. var predictor = getPredictorFromCompression(compression);
  10849. if (decode === this.decode.FLATE_DECODE) dp = "/Predictor " + predictor + " /Colors " + colors + " /BitsPerComponent " + bpc + " /Columns " + img.width; //remove 'Predictor' as it applies to the type of png filter applied to its IDAT - we only apply with compression
  10850. else dp = "/Colors " + colors + " /BitsPerComponent " + bpc + " /Columns " + img.width;
  10851. if (this.isArrayBuffer(imageData) || this.isArrayBufferView(imageData)) imageData = this.arrayBufferToBinaryString(imageData);
  10852. if (smask && this.isArrayBuffer(smask) || this.isArrayBufferView(smask)) smask = this.arrayBufferToBinaryString(smask);
  10853. return this.createImageInfo(imageData, img.width, img.height, colorSpace, bpc, decode, imageIndex, alias, dp, trns, pal, smask, predictor);
  10854. }
  10855. throw new Error("Unsupported PNG image data, try using JPEG instead.");
  10856. };
  10857. })(jsPDF.API);
  10858. /**
  10859. * @license
  10860. * Copyright (c) 2017 Aras Abbasi
  10861. *
  10862. * Licensed under the MIT License.
  10863. * http://opensource.org/licenses/mit-license
  10864. */
  10865. /**
  10866. * jsPDF gif Support PlugIn
  10867. *
  10868. * @name gif_support
  10869. * @module
  10870. */
  10871. (function (jsPDFAPI) {
  10872. jsPDFAPI.processGIF89A = function (imageData, imageIndex, alias, compression, dataAsBinaryString) {
  10873. var reader = new GifReader(imageData);
  10874. var width = reader.width,
  10875. height = reader.height;
  10876. var qu = 100;
  10877. var pixels = [];
  10878. reader.decodeAndBlitFrameRGBA(0, pixels);
  10879. var rawImageData = {
  10880. data: pixels,
  10881. width: width,
  10882. height: height
  10883. };
  10884. var encoder = new JPEGEncoder(qu);
  10885. var data = encoder.encode(rawImageData, qu);
  10886. return jsPDFAPI.processJPEG.call(this, data, imageIndex, alias, compression);
  10887. };
  10888. jsPDFAPI.processGIF87A = jsPDFAPI.processGIF89A;
  10889. })(jsPDF.API);
  10890. /**
  10891. * Copyright (c) 2018 Aras Abbasi
  10892. *
  10893. * Licensed under the MIT License.
  10894. * http://opensource.org/licenses/mit-license
  10895. */
  10896. /**
  10897. * jsPDF bmp Support PlugIn
  10898. * @name bmp_support
  10899. * @module
  10900. */
  10901. (function (jsPDFAPI) {
  10902. jsPDFAPI.processBMP = function (imageData, imageIndex, alias, compression, dataAsBinaryString) {
  10903. var reader = new BmpDecoder(imageData, false);
  10904. var width = reader.width,
  10905. height = reader.height;
  10906. var qu = 100;
  10907. var pixels = reader.getData();
  10908. var rawImageData = {
  10909. data: pixels,
  10910. width: width,
  10911. height: height
  10912. };
  10913. var encoder = new JPEGEncoder(qu);
  10914. var data = encoder.encode(rawImageData, qu);
  10915. return jsPDFAPI.processJPEG.call(this, data, imageIndex, alias, compression);
  10916. };
  10917. })(jsPDF.API);
  10918. /**
  10919. * @license
  10920. * Licensed under the MIT License.
  10921. * http://opensource.org/licenses/mit-license
  10922. */
  10923. /**
  10924. * jsPDF setLanguage Plugin
  10925. *
  10926. * @name setLanguage
  10927. * @module
  10928. */
  10929. (function (jsPDFAPI) {
  10930. /**
  10931. * Add Language Tag to the generated PDF
  10932. *
  10933. * @name setLanguage
  10934. * @function
  10935. * @param {string} langCode The Language code as ISO-639-1 (e.g. 'en') or as country language code (e.g. 'en-GB').
  10936. * @returns {jsPDF}
  10937. * @example
  10938. * var doc = new jsPDF()
  10939. * doc.text(10, 10, 'This is a test')
  10940. * doc.setLanguage("en-US")
  10941. * doc.save('english.pdf')
  10942. */
  10943. jsPDFAPI.setLanguage = function (langCode) {
  10944. var langCodes = {
  10945. af: "Afrikaans",
  10946. sq: "Albanian",
  10947. ar: "Arabic (Standard)",
  10948. "ar-DZ": "Arabic (Algeria)",
  10949. "ar-BH": "Arabic (Bahrain)",
  10950. "ar-EG": "Arabic (Egypt)",
  10951. "ar-IQ": "Arabic (Iraq)",
  10952. "ar-JO": "Arabic (Jordan)",
  10953. "ar-KW": "Arabic (Kuwait)",
  10954. "ar-LB": "Arabic (Lebanon)",
  10955. "ar-LY": "Arabic (Libya)",
  10956. "ar-MA": "Arabic (Morocco)",
  10957. "ar-OM": "Arabic (Oman)",
  10958. "ar-QA": "Arabic (Qatar)",
  10959. "ar-SA": "Arabic (Saudi Arabia)",
  10960. "ar-SY": "Arabic (Syria)",
  10961. "ar-TN": "Arabic (Tunisia)",
  10962. "ar-AE": "Arabic (U.A.E.)",
  10963. "ar-YE": "Arabic (Yemen)",
  10964. an: "Aragonese",
  10965. hy: "Armenian",
  10966. as: "Assamese",
  10967. ast: "Asturian",
  10968. az: "Azerbaijani",
  10969. eu: "Basque",
  10970. be: "Belarusian",
  10971. bn: "Bengali",
  10972. bs: "Bosnian",
  10973. br: "Breton",
  10974. bg: "Bulgarian",
  10975. my: "Burmese",
  10976. ca: "Catalan",
  10977. ch: "Chamorro",
  10978. ce: "Chechen",
  10979. zh: "Chinese",
  10980. "zh-HK": "Chinese (Hong Kong)",
  10981. "zh-CN": "Chinese (PRC)",
  10982. "zh-SG": "Chinese (Singapore)",
  10983. "zh-TW": "Chinese (Taiwan)",
  10984. cv: "Chuvash",
  10985. co: "Corsican",
  10986. cr: "Cree",
  10987. hr: "Croatian",
  10988. cs: "Czech",
  10989. da: "Danish",
  10990. nl: "Dutch (Standard)",
  10991. "nl-BE": "Dutch (Belgian)",
  10992. en: "English",
  10993. "en-AU": "English (Australia)",
  10994. "en-BZ": "English (Belize)",
  10995. "en-CA": "English (Canada)",
  10996. "en-IE": "English (Ireland)",
  10997. "en-JM": "English (Jamaica)",
  10998. "en-NZ": "English (New Zealand)",
  10999. "en-PH": "English (Philippines)",
  11000. "en-ZA": "English (South Africa)",
  11001. "en-TT": "English (Trinidad & Tobago)",
  11002. "en-GB": "English (United Kingdom)",
  11003. "en-US": "English (United States)",
  11004. "en-ZW": "English (Zimbabwe)",
  11005. eo: "Esperanto",
  11006. et: "Estonian",
  11007. fo: "Faeroese",
  11008. fj: "Fijian",
  11009. fi: "Finnish",
  11010. fr: "French (Standard)",
  11011. "fr-BE": "French (Belgium)",
  11012. "fr-CA": "French (Canada)",
  11013. "fr-FR": "French (France)",
  11014. "fr-LU": "French (Luxembourg)",
  11015. "fr-MC": "French (Monaco)",
  11016. "fr-CH": "French (Switzerland)",
  11017. fy: "Frisian",
  11018. fur: "Friulian",
  11019. gd: "Gaelic (Scots)",
  11020. "gd-IE": "Gaelic (Irish)",
  11021. gl: "Galacian",
  11022. ka: "Georgian",
  11023. de: "German (Standard)",
  11024. "de-AT": "German (Austria)",
  11025. "de-DE": "German (Germany)",
  11026. "de-LI": "German (Liechtenstein)",
  11027. "de-LU": "German (Luxembourg)",
  11028. "de-CH": "German (Switzerland)",
  11029. el: "Greek",
  11030. gu: "Gujurati",
  11031. ht: "Haitian",
  11032. he: "Hebrew",
  11033. hi: "Hindi",
  11034. hu: "Hungarian",
  11035. is: "Icelandic",
  11036. id: "Indonesian",
  11037. iu: "Inuktitut",
  11038. ga: "Irish",
  11039. it: "Italian (Standard)",
  11040. "it-CH": "Italian (Switzerland)",
  11041. ja: "Japanese",
  11042. kn: "Kannada",
  11043. ks: "Kashmiri",
  11044. kk: "Kazakh",
  11045. km: "Khmer",
  11046. ky: "Kirghiz",
  11047. tlh: "Klingon",
  11048. ko: "Korean",
  11049. "ko-KP": "Korean (North Korea)",
  11050. "ko-KR": "Korean (South Korea)",
  11051. la: "Latin",
  11052. lv: "Latvian",
  11053. lt: "Lithuanian",
  11054. lb: "Luxembourgish",
  11055. mk: "FYRO Macedonian",
  11056. ms: "Malay",
  11057. ml: "Malayalam",
  11058. mt: "Maltese",
  11059. mi: "Maori",
  11060. mr: "Marathi",
  11061. mo: "Moldavian",
  11062. nv: "Navajo",
  11063. ng: "Ndonga",
  11064. ne: "Nepali",
  11065. no: "Norwegian",
  11066. nb: "Norwegian (Bokmal)",
  11067. nn: "Norwegian (Nynorsk)",
  11068. oc: "Occitan",
  11069. or: "Oriya",
  11070. om: "Oromo",
  11071. fa: "Persian",
  11072. "fa-IR": "Persian/Iran",
  11073. pl: "Polish",
  11074. pt: "Portuguese",
  11075. "pt-BR": "Portuguese (Brazil)",
  11076. pa: "Punjabi",
  11077. "pa-IN": "Punjabi (India)",
  11078. "pa-PK": "Punjabi (Pakistan)",
  11079. qu: "Quechua",
  11080. rm: "Rhaeto-Romanic",
  11081. ro: "Romanian",
  11082. "ro-MO": "Romanian (Moldavia)",
  11083. ru: "Russian",
  11084. "ru-MO": "Russian (Moldavia)",
  11085. sz: "Sami (Lappish)",
  11086. sg: "Sango",
  11087. sa: "Sanskrit",
  11088. sc: "Sardinian",
  11089. sd: "Sindhi",
  11090. si: "Singhalese",
  11091. sr: "Serbian",
  11092. sk: "Slovak",
  11093. sl: "Slovenian",
  11094. so: "Somani",
  11095. sb: "Sorbian",
  11096. es: "Spanish",
  11097. "es-AR": "Spanish (Argentina)",
  11098. "es-BO": "Spanish (Bolivia)",
  11099. "es-CL": "Spanish (Chile)",
  11100. "es-CO": "Spanish (Colombia)",
  11101. "es-CR": "Spanish (Costa Rica)",
  11102. "es-DO": "Spanish (Dominican Republic)",
  11103. "es-EC": "Spanish (Ecuador)",
  11104. "es-SV": "Spanish (El Salvador)",
  11105. "es-GT": "Spanish (Guatemala)",
  11106. "es-HN": "Spanish (Honduras)",
  11107. "es-MX": "Spanish (Mexico)",
  11108. "es-NI": "Spanish (Nicaragua)",
  11109. "es-PA": "Spanish (Panama)",
  11110. "es-PY": "Spanish (Paraguay)",
  11111. "es-PE": "Spanish (Peru)",
  11112. "es-PR": "Spanish (Puerto Rico)",
  11113. "es-ES": "Spanish (Spain)",
  11114. "es-UY": "Spanish (Uruguay)",
  11115. "es-VE": "Spanish (Venezuela)",
  11116. sx: "Sutu",
  11117. sw: "Swahili",
  11118. sv: "Swedish",
  11119. "sv-FI": "Swedish (Finland)",
  11120. "sv-SV": "Swedish (Sweden)",
  11121. ta: "Tamil",
  11122. tt: "Tatar",
  11123. te: "Teluga",
  11124. th: "Thai",
  11125. tig: "Tigre",
  11126. ts: "Tsonga",
  11127. tn: "Tswana",
  11128. tr: "Turkish",
  11129. tk: "Turkmen",
  11130. uk: "Ukrainian",
  11131. hsb: "Upper Sorbian",
  11132. ur: "Urdu",
  11133. ve: "Venda",
  11134. vi: "Vietnamese",
  11135. vo: "Volapuk",
  11136. wa: "Walloon",
  11137. cy: "Welsh",
  11138. xh: "Xhosa",
  11139. ji: "Yiddish",
  11140. zu: "Zulu"
  11141. };
  11142. if (this.internal.languageSettings === undefined) {
  11143. this.internal.languageSettings = {};
  11144. this.internal.languageSettings.isSubscribed = false;
  11145. }
  11146. if (langCodes[langCode] !== undefined) {
  11147. this.internal.languageSettings.languageCode = langCode;
  11148. if (this.internal.languageSettings.isSubscribed === false) {
  11149. this.internal.events.subscribe("putCatalog", function () {
  11150. this.internal.write("/Lang (" + this.internal.languageSettings.languageCode + ")");
  11151. });
  11152. this.internal.languageSettings.isSubscribed = true;
  11153. }
  11154. }
  11155. return this;
  11156. };
  11157. })(jsPDF.API);
  11158. /** @license
  11159. * MIT license.
  11160. * Copyright (c) 2012 Willow Systems Corporation, willow-systems.com
  11161. * 2014 Diego Casorran, https://github.com/diegocr
  11162. *
  11163. *
  11164. * ====================================================================
  11165. */
  11166. /**
  11167. * jsPDF split_text_to_size plugin
  11168. *
  11169. * @name split_text_to_size
  11170. * @module
  11171. */
  11172. (function (API) {
  11173. /**
  11174. * Returns an array of length matching length of the 'word' string, with each
  11175. * cell occupied by the width of the char in that position.
  11176. *
  11177. * @name getCharWidthsArray
  11178. * @function
  11179. * @param {string} text
  11180. * @param {Object} options
  11181. * @returns {Array}
  11182. */
  11183. var getCharWidthsArray = API.getCharWidthsArray = function (text, options) {
  11184. options = options || {};
  11185. var activeFont = options.font || this.internal.getFont();
  11186. var fontSize = options.fontSize || this.internal.getFontSize();
  11187. var charSpace = options.charSpace || this.internal.getCharSpace();
  11188. var widths = options.widths ? options.widths : activeFont.metadata.Unicode.widths;
  11189. var widthsFractionOf = widths.fof ? widths.fof : 1;
  11190. var kerning = options.kerning ? options.kerning : activeFont.metadata.Unicode.kerning;
  11191. var kerningFractionOf = kerning.fof ? kerning.fof : 1;
  11192. var i;
  11193. var l;
  11194. var char_code;
  11195. var prior_char_code = 0; //for kerning
  11196. var default_char_width = widths[0] || widthsFractionOf;
  11197. var output = [];
  11198. for (i = 0, l = text.length; i < l; i++) {
  11199. char_code = text.charCodeAt(i);
  11200. if (typeof activeFont.metadata.widthOfString === "function") {
  11201. output.push((activeFont.metadata.widthOfGlyph(activeFont.metadata.characterToGlyph(char_code)) + charSpace * (1000 / fontSize) || 0) / 1000);
  11202. } else {
  11203. output.push((widths[char_code] || default_char_width) / widthsFractionOf + (kerning[char_code] && kerning[char_code][prior_char_code] || 0) / kerningFractionOf);
  11204. }
  11205. prior_char_code = char_code;
  11206. }
  11207. return output;
  11208. };
  11209. /**
  11210. * Calculate the sum of a number-array
  11211. *
  11212. * @name getArraySum
  11213. * @public
  11214. * @function
  11215. * @param {Array} array Array of numbers
  11216. * @returns {number}
  11217. */
  11218. var getArraySum = API.getArraySum = function (array) {
  11219. var i = array.length,
  11220. output = 0;
  11221. while (i) {
  11222. i--;
  11223. output += array[i];
  11224. }
  11225. return output;
  11226. };
  11227. /**
  11228. * Returns a widths of string in a given font, if the font size is set as 1 point.
  11229. *
  11230. * In other words, this is "proportional" value. For 1 unit of font size, the length
  11231. * of the string will be that much.
  11232. *
  11233. * Multiply by font size to get actual width in *points*
  11234. * Then divide by 72 to get inches or divide by (72/25.6) to get 'mm' etc.
  11235. *
  11236. * @name getStringUnitWidth
  11237. * @public
  11238. * @function
  11239. * @param {string} text
  11240. * @param {string} options
  11241. * @returns {number} result
  11242. */
  11243. var getStringUnitWidth = API.getStringUnitWidth = function (text, options) {
  11244. options = options || {};
  11245. var fontSize = options.fontSize || this.internal.getFontSize();
  11246. var font = options.font || this.internal.getFont();
  11247. var charSpace = options.charSpace || this.internal.getCharSpace();
  11248. var result = 0;
  11249. if (typeof font.metadata.widthOfString === "function") {
  11250. result = font.metadata.widthOfString(text, fontSize, charSpace) / fontSize;
  11251. } else {
  11252. result = getArraySum(getCharWidthsArray.apply(this, arguments));
  11253. }
  11254. return result;
  11255. };
  11256. /**
  11257. returns array of lines
  11258. */
  11259. var splitLongWord = function splitLongWord(word, widths_array, firstLineMaxLen, maxLen) {
  11260. var answer = []; // 1st, chop off the piece that can fit on the hanging line.
  11261. var i = 0,
  11262. l = word.length,
  11263. workingLen = 0;
  11264. while (i !== l && workingLen + widths_array[i] < firstLineMaxLen) {
  11265. workingLen += widths_array[i];
  11266. i++;
  11267. } // this is first line.
  11268. answer.push(word.slice(0, i)); // 2nd. Split the rest into maxLen pieces.
  11269. var startOfLine = i;
  11270. workingLen = 0;
  11271. while (i !== l) {
  11272. if (workingLen + widths_array[i] > maxLen) {
  11273. answer.push(word.slice(startOfLine, i));
  11274. workingLen = 0;
  11275. startOfLine = i;
  11276. }
  11277. workingLen += widths_array[i];
  11278. i++;
  11279. }
  11280. if (startOfLine !== i) {
  11281. answer.push(word.slice(startOfLine, i));
  11282. }
  11283. return answer;
  11284. }; // Note, all sizing inputs for this function must be in "font measurement units"
  11285. // By default, for PDF, it's "point".
  11286. var splitParagraphIntoLines = function splitParagraphIntoLines(text, maxlen, options) {
  11287. // at this time works only on Western scripts, ones with space char
  11288. // separating the words. Feel free to expand.
  11289. if (!options) {
  11290. options = {};
  11291. }
  11292. var line = [],
  11293. lines = [line],
  11294. line_length = options.textIndent || 0,
  11295. separator_length = 0,
  11296. current_word_length = 0,
  11297. word,
  11298. widths_array,
  11299. words = text.split(" "),
  11300. spaceCharWidth = getCharWidthsArray.apply(this, [" ", options])[0],
  11301. i,
  11302. l,
  11303. tmp,
  11304. lineIndent;
  11305. if (options.lineIndent === -1) {
  11306. lineIndent = words[0].length + 2;
  11307. } else {
  11308. lineIndent = options.lineIndent || 0;
  11309. }
  11310. if (lineIndent) {
  11311. var pad = Array(lineIndent).join(" "),
  11312. wrds = [];
  11313. words.map(function (wrd) {
  11314. wrd = wrd.split(/\s*\n/);
  11315. if (wrd.length > 1) {
  11316. wrds = wrds.concat(wrd.map(function (wrd, idx) {
  11317. return (idx && wrd.length ? "\n" : "") + wrd;
  11318. }));
  11319. } else {
  11320. wrds.push(wrd[0]);
  11321. }
  11322. });
  11323. words = wrds;
  11324. lineIndent = getStringUnitWidth.apply(this, [pad, options]);
  11325. }
  11326. for (i = 0, l = words.length; i < l; i++) {
  11327. var force = 0;
  11328. word = words[i];
  11329. if (lineIndent && word[0] == "\n") {
  11330. word = word.substr(1);
  11331. force = 1;
  11332. }
  11333. widths_array = getCharWidthsArray.apply(this, [word, options]);
  11334. current_word_length = getArraySum(widths_array);
  11335. if (line_length + separator_length + current_word_length > maxlen || force) {
  11336. if (current_word_length > maxlen) {
  11337. // this happens when you have space-less long URLs for example.
  11338. // we just chop these to size. We do NOT insert hiphens
  11339. tmp = splitLongWord.apply(this, [word, widths_array, maxlen - (line_length + separator_length), maxlen]); // first line we add to existing line object
  11340. line.push(tmp.shift()); // it's ok to have extra space indicator there
  11341. // last line we make into new line object
  11342. line = [tmp.pop()]; // lines in the middle we apped to lines object as whole lines
  11343. while (tmp.length) {
  11344. lines.push([tmp.shift()]); // single fragment occupies whole line
  11345. }
  11346. current_word_length = getArraySum(widths_array.slice(word.length - (line[0] ? line[0].length : 0)));
  11347. } else {
  11348. // just put it on a new line
  11349. line = [word];
  11350. } // now we attach new line to lines
  11351. lines.push(line);
  11352. line_length = current_word_length + lineIndent;
  11353. separator_length = spaceCharWidth;
  11354. } else {
  11355. line.push(word);
  11356. line_length += separator_length + current_word_length;
  11357. separator_length = spaceCharWidth;
  11358. }
  11359. }
  11360. if (lineIndent) {
  11361. var postProcess = function postProcess(ln, idx) {
  11362. return (idx ? pad : "") + ln.join(" ");
  11363. };
  11364. } else {
  11365. var postProcess = function postProcess(ln) {
  11366. return ln.join(" ");
  11367. };
  11368. }
  11369. return lines.map(postProcess);
  11370. };
  11371. /**
  11372. * Splits a given string into an array of strings. Uses 'size' value
  11373. * (in measurement units declared as default for the jsPDF instance)
  11374. * and the font's "widths" and "Kerning" tables, where available, to
  11375. * determine display length of a given string for a given font.
  11376. *
  11377. * We use character's 100% of unit size (height) as width when Width
  11378. * table or other default width is not available.
  11379. *
  11380. * @name splitTextToSize
  11381. * @public
  11382. * @function
  11383. * @param {string} text Unencoded, regular JavaScript (Unicode, UTF-16 / UCS-2) string.
  11384. * @param {number} size Nominal number, measured in units default to this instance of jsPDF.
  11385. * @param {Object} options Optional flags needed for chopper to do the right thing.
  11386. * @returns {Array} array Array with strings chopped to size.
  11387. */
  11388. API.splitTextToSize = function (text, maxlen, options) {
  11389. options = options || {};
  11390. var fsize = options.fontSize || this.internal.getFontSize(),
  11391. newOptions = function (options) {
  11392. var widths = {
  11393. 0: 1
  11394. },
  11395. kerning = {};
  11396. if (!options.widths || !options.kerning) {
  11397. var f = this.internal.getFont(options.fontName, options.fontStyle),
  11398. encoding = "Unicode"; // NOT UTF8, NOT UTF16BE/LE, NOT UCS2BE/LE
  11399. // Actual JavaScript-native String's 16bit char codes used.
  11400. // no multi-byte logic here
  11401. if (f.metadata[encoding]) {
  11402. return {
  11403. widths: f.metadata[encoding].widths || widths,
  11404. kerning: f.metadata[encoding].kerning || kerning
  11405. };
  11406. } else {
  11407. return {
  11408. font: f.metadata,
  11409. fontSize: this.internal.getFontSize(),
  11410. charSpace: this.internal.getCharSpace()
  11411. };
  11412. }
  11413. } else {
  11414. return {
  11415. widths: options.widths,
  11416. kerning: options.kerning
  11417. };
  11418. } // then use default values
  11419. return {
  11420. widths: widths,
  11421. kerning: kerning
  11422. };
  11423. }.call(this, options); // first we split on end-of-line chars
  11424. var paragraphs;
  11425. if (Array.isArray(text)) {
  11426. paragraphs = text;
  11427. } else {
  11428. paragraphs = text.split(/\r?\n/);
  11429. } // now we convert size (max length of line) into "font size units"
  11430. // at present time, the "font size unit" is always 'point'
  11431. // 'proportional' means, "in proportion to font size"
  11432. var fontUnit_maxLen = 1.0 * this.internal.scaleFactor * maxlen / fsize; // at this time, fsize is always in "points" regardless of the default measurement unit of the doc.
  11433. // this may change in the future?
  11434. // until then, proportional_maxlen is likely to be in 'points'
  11435. // If first line is to be indented (shorter or longer) than maxLen
  11436. // we indicate that by using CSS-style "text-indent" option.
  11437. // here it's in font units too (which is likely 'points')
  11438. // it can be negative (which makes the first line longer than maxLen)
  11439. newOptions.textIndent = options.textIndent ? options.textIndent * 1.0 * this.internal.scaleFactor / fsize : 0;
  11440. newOptions.lineIndent = options.lineIndent;
  11441. var i,
  11442. l,
  11443. output = [];
  11444. for (i = 0, l = paragraphs.length; i < l; i++) {
  11445. output = output.concat(splitParagraphIntoLines.apply(this, [paragraphs[i], fontUnit_maxLen, newOptions]));
  11446. }
  11447. return output;
  11448. };
  11449. })(jsPDF.API);
  11450. /** @license
  11451. jsPDF standard_fonts_metrics plugin
  11452. * Copyright (c) 2012 Willow Systems Corporation, willow-systems.com
  11453. * MIT license.
  11454. *
  11455. * ====================================================================
  11456. */
  11457. /**
  11458. * This file adds the standard font metrics to jsPDF.
  11459. *
  11460. * Font metrics data is reprocessed derivative of contents of
  11461. * "Font Metrics for PDF Core 14 Fonts" package, which exhibits the following copyright and license:
  11462. *
  11463. * Copyright (c) 1989, 1990, 1991, 1992, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.
  11464. *
  11465. * This file and the 14 PostScript(R) AFM files it accompanies may be used,
  11466. * copied, and distributed for any purpose and without charge, with or without
  11467. * modification, provided that all copyright notices are retained; that the AFM
  11468. * files are not distributed without this file; that all modifications to this
  11469. * file or any of the AFM files are prominently noted in the modified file(s);
  11470. * and that this paragraph is not modified. Adobe Systems has no responsibility
  11471. * or obligation to support the use of the AFM files.
  11472. *
  11473. * @name standard_fonts_metrics
  11474. * @module
  11475. */
  11476. (function (API) {
  11477. /*
  11478. # reference (Python) versions of 'compress' and 'uncompress'
  11479. # only 'uncompress' function is featured lower as JavaScript
  11480. # if you want to unit test "roundtrip", just transcribe the reference
  11481. # 'compress' function from Python into JavaScript
  11482. def compress(data):
  11483. keys = '0123456789abcdef'
  11484. values = 'klmnopqrstuvwxyz'
  11485. mapping = dict(zip(keys, values))
  11486. vals = []
  11487. for key in data.keys():
  11488. value = data[key]
  11489. try:
  11490. keystring = hex(key)[2:]
  11491. keystring = keystring[:-1] + mapping[keystring[-1:]]
  11492. except:
  11493. keystring = key.join(["'","'"])
  11494. #print('Keystring is %s' % keystring)
  11495. try:
  11496. if value < 0:
  11497. valuestring = hex(value)[3:]
  11498. numberprefix = '-'
  11499. else:
  11500. valuestring = hex(value)[2:]
  11501. numberprefix = ''
  11502. valuestring = numberprefix + valuestring[:-1] + mapping[valuestring[-1:]]
  11503. except:
  11504. if type(value) == dict:
  11505. valuestring = compress(value)
  11506. else:
  11507. raise Exception("Don't know what to do with value type %s" % type(value))
  11508. vals.append(keystring+valuestring)
  11509. return '{' + ''.join(vals) + '}'
  11510. def uncompress(data):
  11511. decoded = '0123456789abcdef'
  11512. encoded = 'klmnopqrstuvwxyz'
  11513. mapping = dict(zip(encoded, decoded))
  11514. sign = +1
  11515. stringmode = False
  11516. stringparts = []
  11517. output = {}
  11518. activeobject = output
  11519. parentchain = []
  11520. keyparts = ''
  11521. valueparts = ''
  11522. key = None
  11523. ending = set(encoded)
  11524. i = 1
  11525. l = len(data) - 1 # stripping starting, ending {}
  11526. while i != l: # stripping {}
  11527. # -, {, }, ' are special.
  11528. ch = data[i]
  11529. i += 1
  11530. if ch == "'":
  11531. if stringmode:
  11532. # end of string mode
  11533. stringmode = False
  11534. key = ''.join(stringparts)
  11535. else:
  11536. # start of string mode
  11537. stringmode = True
  11538. stringparts = []
  11539. elif stringmode == True:
  11540. #print("Adding %s to stringpart" % ch)
  11541. stringparts.append(ch)
  11542. elif ch == '{':
  11543. # start of object
  11544. parentchain.append( [activeobject, key] )
  11545. activeobject = {}
  11546. key = None
  11547. #DEBUG = True
  11548. elif ch == '}':
  11549. # end of object
  11550. parent, key = parentchain.pop()
  11551. parent[key] = activeobject
  11552. key = None
  11553. activeobject = parent
  11554. #DEBUG = False
  11555. elif ch == '-':
  11556. sign = -1
  11557. else:
  11558. # must be number
  11559. if key == None:
  11560. #debug("In Key. It is '%s', ch is '%s'" % (keyparts, ch))
  11561. if ch in ending:
  11562. #debug("End of key")
  11563. keyparts += mapping[ch]
  11564. key = int(keyparts, 16) * sign
  11565. sign = +1
  11566. keyparts = ''
  11567. else:
  11568. keyparts += ch
  11569. else:
  11570. #debug("In value. It is '%s', ch is '%s'" % (valueparts, ch))
  11571. if ch in ending:
  11572. #debug("End of value")
  11573. valueparts += mapping[ch]
  11574. activeobject[key] = int(valueparts, 16) * sign
  11575. sign = +1
  11576. key = None
  11577. valueparts = ''
  11578. else:
  11579. valueparts += ch
  11580. #debug(activeobject)
  11581. return output
  11582. */
  11583. /**
  11584. Uncompresses data compressed into custom, base16-like format.
  11585. @public
  11586. @function
  11587. @param
  11588. @returns {Type}
  11589. */
  11590. var uncompress = function uncompress(data) {
  11591. var decoded = "0123456789abcdef",
  11592. encoded = "klmnopqrstuvwxyz",
  11593. mapping = {};
  11594. for (var i = 0; i < encoded.length; i++) {
  11595. mapping[encoded[i]] = decoded[i];
  11596. }
  11597. var undef,
  11598. output = {},
  11599. sign = 1,
  11600. stringparts,
  11601. // undef. will be [] in string mode
  11602. activeobject = output,
  11603. parentchain = [],
  11604. parent_key_pair,
  11605. keyparts = "",
  11606. valueparts = "",
  11607. key,
  11608. // undef. will be Truthy when Key is resolved.
  11609. datalen = data.length - 1,
  11610. // stripping ending }
  11611. ch;
  11612. i = 1; // stripping starting {
  11613. while (i != datalen) {
  11614. // - { } ' are special.
  11615. ch = data[i];
  11616. i += 1;
  11617. if (ch == "'") {
  11618. if (stringparts) {
  11619. // end of string mode
  11620. key = stringparts.join("");
  11621. stringparts = undef;
  11622. } else {
  11623. // start of string mode
  11624. stringparts = [];
  11625. }
  11626. } else if (stringparts) {
  11627. stringparts.push(ch);
  11628. } else if (ch == "{") {
  11629. // start of object
  11630. parentchain.push([activeobject, key]);
  11631. activeobject = {};
  11632. key = undef;
  11633. } else if (ch == "}") {
  11634. // end of object
  11635. parent_key_pair = parentchain.pop();
  11636. parent_key_pair[0][parent_key_pair[1]] = activeobject;
  11637. key = undef;
  11638. activeobject = parent_key_pair[0];
  11639. } else if (ch == "-") {
  11640. sign = -1;
  11641. } else {
  11642. // must be number
  11643. if (key === undef) {
  11644. if (mapping.hasOwnProperty(ch)) {
  11645. keyparts += mapping[ch];
  11646. key = parseInt(keyparts, 16) * sign;
  11647. sign = +1;
  11648. keyparts = "";
  11649. } else {
  11650. keyparts += ch;
  11651. }
  11652. } else {
  11653. if (mapping.hasOwnProperty(ch)) {
  11654. valueparts += mapping[ch];
  11655. activeobject[key] = parseInt(valueparts, 16) * sign;
  11656. sign = +1;
  11657. key = undef;
  11658. valueparts = "";
  11659. } else {
  11660. valueparts += ch;
  11661. }
  11662. }
  11663. }
  11664. } // end while
  11665. return output;
  11666. }; // encoding = 'Unicode'
  11667. // NOT UTF8, NOT UTF16BE/LE, NOT UCS2BE/LE. NO clever BOM behavior
  11668. // Actual 16bit char codes used.
  11669. // no multi-byte logic here
  11670. // Unicode characters to WinAnsiEncoding:
  11671. // {402: 131, 8211: 150, 8212: 151, 8216: 145, 8217: 146, 8218: 130, 8220: 147, 8221: 148, 8222: 132, 8224: 134, 8225: 135, 8226: 149, 8230: 133, 8364: 128, 8240:137, 8249: 139, 8250: 155, 710: 136, 8482: 153, 338: 140, 339: 156, 732: 152, 352: 138, 353: 154, 376: 159, 381: 142, 382: 158}
  11672. // as you can see, all Unicode chars are outside of 0-255 range. No char code conflicts.
  11673. // this means that you can give Win cp1252 encoded strings to jsPDF for rendering directly
  11674. // as well as give strings with some (supported by these fonts) Unicode characters and
  11675. // these will be mapped to win cp1252
  11676. // for example, you can send char code (cp1252) 0x80 or (unicode) 0x20AC, getting "Euro" glyph displayed in both cases.
  11677. var encodingBlock = {
  11678. codePages: ["WinAnsiEncoding"],
  11679. WinAnsiEncoding: uncompress("{19m8n201n9q201o9r201s9l201t9m201u8m201w9n201x9o201y8o202k8q202l8r202m9p202q8p20aw8k203k8t203t8v203u9v2cq8s212m9t15m8w15n9w2dw9s16k8u16l9u17s9z17x8y17y9y}")
  11680. },
  11681. encodings = {
  11682. Unicode: {
  11683. Courier: encodingBlock,
  11684. "Courier-Bold": encodingBlock,
  11685. "Courier-BoldOblique": encodingBlock,
  11686. "Courier-Oblique": encodingBlock,
  11687. Helvetica: encodingBlock,
  11688. "Helvetica-Bold": encodingBlock,
  11689. "Helvetica-BoldOblique": encodingBlock,
  11690. "Helvetica-Oblique": encodingBlock,
  11691. "Times-Roman": encodingBlock,
  11692. "Times-Bold": encodingBlock,
  11693. "Times-BoldItalic": encodingBlock,
  11694. "Times-Italic": encodingBlock // , 'Symbol'
  11695. // , 'ZapfDingbats'
  11696. }
  11697. },
  11698. fontMetrics = {
  11699. Unicode: {
  11700. // all sizing numbers are n/fontMetricsFractionOf = one font size unit
  11701. // this means that if fontMetricsFractionOf = 1000, and letter A's width is 476, it's
  11702. // width is 476/1000 or 47.6% of its height (regardless of font size)
  11703. // At this time this value applies to "widths" and "kerning" numbers.
  11704. // char code 0 represents "default" (average) width - use it for chars missing in this table.
  11705. // key 'fof' represents the "fontMetricsFractionOf" value
  11706. "Courier-Oblique": uncompress("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}"),
  11707. "Times-BoldItalic": uncompress("{'widths'{k3o2q4ycx2r201n3m201o6o201s2l201t2l201u2l201w3m201x3m201y3m2k1t2l2r202m2n2n3m2o3m2p5n202q6o2r1w2s2l2t2l2u3m2v3t2w1t2x2l2y1t2z1w3k3m3l3m3m3m3n3m3o3m3p3m3q3m3r3m3s3m203t2l203u2l3v2l3w3t3x3t3y3t3z3m4k5n4l4m4m4m4n4m4o4s4p4m4q4m4r4s4s4y4t2r4u3m4v4m4w3x4x5t4y4s4z4s5k3x5l4s5m4m5n3r5o3x5p4s5q4m5r5t5s4m5t3x5u3x5v2l5w1w5x2l5y3t5z3m6k2l6l3m6m3m6n2w6o3m6p2w6q2l6r3m6s3r6t1w6u1w6v3m6w1w6x4y6y3r6z3m7k3m7l3m7m2r7n2r7o1w7p3r7q2w7r4m7s3m7t2w7u2r7v2n7w1q7x2n7y3t202l3mcl4mal2ram3man3mao3map3mar3mas2lat4uau1uav3maw3way4uaz2lbk2sbl3t'fof'6obo2lbp3tbq3mbr1tbs2lbu1ybv3mbz3mck4m202k3mcm4mcn4mco4mcp4mcq5ycr4mcs4mct4mcu4mcv4mcw2r2m3rcy2rcz2rdl4sdm4sdn4sdo4sdp4sdq4sds4sdt4sdu4sdv4sdw4sdz3mek3mel3mem3men3meo3mep3meq4ser2wes2wet2weu2wev2wew1wex1wey1wez1wfl3rfm3mfn3mfo3mfp3mfq3mfr3tfs3mft3rfu3rfv3rfw3rfz2w203k6o212m6o2dw2l2cq2l3t3m3u2l17s3x19m3m}'kerning'{cl{4qu5kt5qt5rs17ss5ts}201s{201ss}201t{cks4lscmscnscoscpscls2wu2yu201ts}201x{2wu2yu}2k{201ts}2w{4qx5kx5ou5qx5rs17su5tu}2x{17su5tu5ou}2y{4qx5kx5ou5qx5rs17ss5ts}'fof'-6ofn{17sw5tw5ou5qw5rs}7t{cksclscmscnscoscps4ls}3u{17su5tu5os5qs}3v{17su5tu5os5qs}7p{17su5tu}ck{4qu5kt5qt5rs17ss5ts}4l{4qu5kt5qt5rs17ss5ts}cm{4qu5kt5qt5rs17ss5ts}cn{4qu5kt5qt5rs17ss5ts}co{4qu5kt5qt5rs17ss5ts}cp{4qu5kt5qt5rs17ss5ts}6l{4qu5ou5qw5rt17su5tu}5q{ckuclucmucnucoucpu4lu}5r{ckuclucmucnucoucpu4lu}7q{cksclscmscnscoscps4ls}6p{4qu5ou5qw5rt17sw5tw}ek{4qu5ou5qw5rt17su5tu}el{4qu5ou5qw5rt17su5tu}em{4qu5ou5qw5rt17su5tu}en{4qu5ou5qw5rt17su5tu}eo{4qu5ou5qw5rt17su5tu}ep{4qu5ou5qw5rt17su5tu}es{17ss5ts5qs4qu}et{4qu5ou5qw5rt17sw5tw}eu{4qu5ou5qw5rt17ss5ts}ev{17ss5ts5qs4qu}6z{17sw5tw5ou5qw5rs}fm{17sw5tw5ou5qw5rs}7n{201ts}fo{17sw5tw5ou5qw5rs}fp{17sw5tw5ou5qw5rs}fq{17sw5tw5ou5qw5rs}7r{cksclscmscnscoscps4ls}fs{17sw5tw5ou5qw5rs}ft{17su5tu}fu{17su5tu}fv{17su5tu}fw{17su5tu}fz{cksclscmscnscoscps4ls}}}"),
  11708. "Helvetica-Bold": uncompress("{'widths'{k3s2q4scx1w201n3r201o6o201s1w201t1w201u1w201w3m201x3m201y3m2k1w2l2l202m2n2n3r2o3r2p5t202q6o2r1s2s2l2t2l2u2r2v3u2w1w2x2l2y1w2z1w3k3r3l3r3m3r3n3r3o3r3p3r3q3r3r3r3s3r203t2l203u2l3v2l3w3u3x3u3y3u3z3x4k6l4l4s4m4s4n4s4o4s4p4m4q3x4r4y4s4s4t1w4u3r4v4s4w3x4x5n4y4s4z4y5k4m5l4y5m4s5n4m5o3x5p4s5q4m5r5y5s4m5t4m5u3x5v2l5w1w5x2l5y3u5z3r6k2l6l3r6m3x6n3r6o3x6p3r6q2l6r3x6s3x6t1w6u1w6v3r6w1w6x5t6y3x6z3x7k3x7l3x7m2r7n3r7o2l7p3x7q3r7r4y7s3r7t3r7u3m7v2r7w1w7x2r7y3u202l3rcl4sal2lam3ran3rao3rap3rar3ras2lat4tau2pav3raw3uay4taz2lbk2sbl3u'fof'6obo2lbp3xbq3rbr1wbs2lbu2obv3rbz3xck4s202k3rcm4scn4sco4scp4scq6ocr4scs4mct4mcu4mcv4mcw1w2m2zcy1wcz1wdl4sdm4ydn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3xek3rel3rem3ren3reo3rep3req5ter3res3ret3reu3rev3rew1wex1wey1wez1wfl3xfm3xfn3xfo3xfp3xfq3xfr3ufs3xft3xfu3xfv3xfw3xfz3r203k6o212m6o2dw2l2cq2l3t3r3u2l17s4m19m3r}'kerning'{cl{4qs5ku5ot5qs17sv5tv}201t{2ww4wy2yw}201w{2ks}201x{2ww4wy2yw}2k{201ts201xs}2w{7qs4qu5kw5os5qw5rs17su5tu7tsfzs}2x{5ow5qs}2y{7qs4qu5kw5os5qw5rs17su5tu7tsfzs}'fof'-6o7p{17su5tu5ot}ck{4qs5ku5ot5qs17sv5tv}4l{4qs5ku5ot5qs17sv5tv}cm{4qs5ku5ot5qs17sv5tv}cn{4qs5ku5ot5qs17sv5tv}co{4qs5ku5ot5qs17sv5tv}cp{4qs5ku5ot5qs17sv5tv}6l{17st5tt5os}17s{2kwclvcmvcnvcovcpv4lv4wwckv}5o{2kucltcmtcntcotcpt4lt4wtckt}5q{2ksclscmscnscoscps4ls4wvcks}5r{2ks4ws}5t{2kwclvcmvcnvcovcpv4lv4wwckv}eo{17st5tt5os}fu{17su5tu5ot}6p{17ss5ts}ek{17st5tt5os}el{17st5tt5os}em{17st5tt5os}en{17st5tt5os}6o{201ts}ep{17st5tt5os}es{17ss5ts}et{17ss5ts}eu{17ss5ts}ev{17ss5ts}6z{17su5tu5os5qt}fm{17su5tu5os5qt}fn{17su5tu5os5qt}fo{17su5tu5os5qt}fp{17su5tu5os5qt}fq{17su5tu5os5qt}fs{17su5tu5os5qt}ft{17su5tu5ot}7m{5os}fv{17su5tu5ot}fw{17su5tu5ot}}}"),
  11709. Courier: uncompress("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}"),
  11710. "Courier-BoldOblique": uncompress("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}"),
  11711. "Times-Bold": uncompress("{'widths'{k3q2q5ncx2r201n3m201o6o201s2l201t2l201u2l201w3m201x3m201y3m2k1t2l2l202m2n2n3m2o3m2p6o202q6o2r1w2s2l2t2l2u3m2v3t2w1t2x2l2y1t2z1w3k3m3l3m3m3m3n3m3o3m3p3m3q3m3r3m3s3m203t2l203u2l3v2l3w3t3x3t3y3t3z3m4k5x4l4s4m4m4n4s4o4s4p4m4q3x4r4y4s4y4t2r4u3m4v4y4w4m4x5y4y4s4z4y5k3x5l4y5m4s5n3r5o4m5p4s5q4s5r6o5s4s5t4s5u4m5v2l5w1w5x2l5y3u5z3m6k2l6l3m6m3r6n2w6o3r6p2w6q2l6r3m6s3r6t1w6u2l6v3r6w1w6x5n6y3r6z3m7k3r7l3r7m2w7n2r7o2l7p3r7q3m7r4s7s3m7t3m7u2w7v2r7w1q7x2r7y3o202l3mcl4sal2lam3man3mao3map3mar3mas2lat4uau1yav3maw3tay4uaz2lbk2sbl3t'fof'6obo2lbp3rbr1tbs2lbu2lbv3mbz3mck4s202k3mcm4scn4sco4scp4scq6ocr4scs4mct4mcu4mcv4mcw2r2m3rcy2rcz2rdl4sdm4ydn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3rek3mel3mem3men3meo3mep3meq4ser2wes2wet2weu2wev2wew1wex1wey1wez1wfl3rfm3mfn3mfo3mfp3mfq3mfr3tfs3mft3rfu3rfv3rfw3rfz3m203k6o212m6o2dw2l2cq2l3t3m3u2l17s4s19m3m}'kerning'{cl{4qt5ks5ot5qy5rw17sv5tv}201t{cks4lscmscnscoscpscls4wv}2k{201ts}2w{4qu5ku7mu5os5qx5ru17su5tu}2x{17su5tu5ou5qs}2y{4qv5kv7mu5ot5qz5ru17su5tu}'fof'-6o7t{cksclscmscnscoscps4ls}3u{17su5tu5os5qu}3v{17su5tu5os5qu}fu{17su5tu5ou5qu}7p{17su5tu5ou5qu}ck{4qt5ks5ot5qy5rw17sv5tv}4l{4qt5ks5ot5qy5rw17sv5tv}cm{4qt5ks5ot5qy5rw17sv5tv}cn{4qt5ks5ot5qy5rw17sv5tv}co{4qt5ks5ot5qy5rw17sv5tv}cp{4qt5ks5ot5qy5rw17sv5tv}6l{17st5tt5ou5qu}17s{ckuclucmucnucoucpu4lu4wu}5o{ckuclucmucnucoucpu4lu4wu}5q{ckzclzcmzcnzcozcpz4lz4wu}5r{ckxclxcmxcnxcoxcpx4lx4wu}5t{ckuclucmucnucoucpu4lu4wu}7q{ckuclucmucnucoucpu4lu}6p{17sw5tw5ou5qu}ek{17st5tt5qu}el{17st5tt5ou5qu}em{17st5tt5qu}en{17st5tt5qu}eo{17st5tt5qu}ep{17st5tt5ou5qu}es{17ss5ts5qu}et{17sw5tw5ou5qu}eu{17sw5tw5ou5qu}ev{17ss5ts5qu}6z{17sw5tw5ou5qu5rs}fm{17sw5tw5ou5qu5rs}fn{17sw5tw5ou5qu5rs}fo{17sw5tw5ou5qu5rs}fp{17sw5tw5ou5qu5rs}fq{17sw5tw5ou5qu5rs}7r{cktcltcmtcntcotcpt4lt5os}fs{17sw5tw5ou5qu5rs}ft{17su5tu5ou5qu}7m{5os}fv{17su5tu5ou5qu}fw{17su5tu5ou5qu}fz{cksclscmscnscoscps4ls}}}"),
  11712. Symbol: uncompress("{'widths'{k3uaw4r19m3m2k1t2l2l202m2y2n3m2p5n202q6o3k3m2s2l2t2l2v3r2w1t3m3m2y1t2z1wbk2sbl3r'fof'6o3n3m3o3m3p3m3q3m3r3m3s3m3t3m3u1w3v1w3w3r3x3r3y3r3z2wbp3t3l3m5v2l5x2l5z3m2q4yfr3r7v3k7w1o7x3k}'kerning'{'fof'-6o}}"),
  11713. Helvetica: uncompress("{'widths'{k3p2q4mcx1w201n3r201o6o201s1q201t1q201u1q201w2l201x2l201y2l2k1w2l1w202m2n2n3r2o3r2p5t202q6o2r1n2s2l2t2l2u2r2v3u2w1w2x2l2y1w2z1w3k3r3l3r3m3r3n3r3o3r3p3r3q3r3r3r3s3r203t2l203u2l3v1w3w3u3x3u3y3u3z3r4k6p4l4m4m4m4n4s4o4s4p4m4q3x4r4y4s4s4t1w4u3m4v4m4w3r4x5n4y4s4z4y5k4m5l4y5m4s5n4m5o3x5p4s5q4m5r5y5s4m5t4m5u3x5v1w5w1w5x1w5y2z5z3r6k2l6l3r6m3r6n3m6o3r6p3r6q1w6r3r6s3r6t1q6u1q6v3m6w1q6x5n6y3r6z3r7k3r7l3r7m2l7n3m7o1w7p3r7q3m7r4s7s3m7t3m7u3m7v2l7w1u7x2l7y3u202l3rcl4mal2lam3ran3rao3rap3rar3ras2lat4tau2pav3raw3uay4taz2lbk2sbl3u'fof'6obo2lbp3rbr1wbs2lbu2obv3rbz3xck4m202k3rcm4mcn4mco4mcp4mcq6ocr4scs4mct4mcu4mcv4mcw1w2m2ncy1wcz1wdl4sdm4ydn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3xek3rel3rem3ren3reo3rep3req5ter3mes3ret3reu3rev3rew1wex1wey1wez1wfl3rfm3rfn3rfo3rfp3rfq3rfr3ufs3xft3rfu3rfv3rfw3rfz3m203k6o212m6o2dw2l2cq2l3t3r3u1w17s4m19m3r}'kerning'{5q{4wv}cl{4qs5kw5ow5qs17sv5tv}201t{2wu4w1k2yu}201x{2wu4wy2yu}17s{2ktclucmucnu4otcpu4lu4wycoucku}2w{7qs4qz5k1m17sy5ow5qx5rsfsu5ty7tufzu}2x{17sy5ty5oy5qs}2y{7qs4qz5k1m17sy5ow5qx5rsfsu5ty7tufzu}'fof'-6o7p{17sv5tv5ow}ck{4qs5kw5ow5qs17sv5tv}4l{4qs5kw5ow5qs17sv5tv}cm{4qs5kw5ow5qs17sv5tv}cn{4qs5kw5ow5qs17sv5tv}co{4qs5kw5ow5qs17sv5tv}cp{4qs5kw5ow5qs17sv5tv}6l{17sy5ty5ow}do{17st5tt}4z{17st5tt}7s{fst}dm{17st5tt}dn{17st5tt}5o{ckwclwcmwcnwcowcpw4lw4wv}dp{17st5tt}dq{17st5tt}7t{5ow}ds{17st5tt}5t{2ktclucmucnu4otcpu4lu4wycoucku}fu{17sv5tv5ow}6p{17sy5ty5ow5qs}ek{17sy5ty5ow}el{17sy5ty5ow}em{17sy5ty5ow}en{5ty}eo{17sy5ty5ow}ep{17sy5ty5ow}es{17sy5ty5qs}et{17sy5ty5ow5qs}eu{17sy5ty5ow5qs}ev{17sy5ty5ow5qs}6z{17sy5ty5ow5qs}fm{17sy5ty5ow5qs}fn{17sy5ty5ow5qs}fo{17sy5ty5ow5qs}fp{17sy5ty5qs}fq{17sy5ty5ow5qs}7r{5ow}fs{17sy5ty5ow5qs}ft{17sv5tv5ow}7m{5ow}fv{17sv5tv5ow}fw{17sv5tv5ow}}}"),
  11714. "Helvetica-BoldOblique": uncompress("{'widths'{k3s2q4scx1w201n3r201o6o201s1w201t1w201u1w201w3m201x3m201y3m2k1w2l2l202m2n2n3r2o3r2p5t202q6o2r1s2s2l2t2l2u2r2v3u2w1w2x2l2y1w2z1w3k3r3l3r3m3r3n3r3o3r3p3r3q3r3r3r3s3r203t2l203u2l3v2l3w3u3x3u3y3u3z3x4k6l4l4s4m4s4n4s4o4s4p4m4q3x4r4y4s4s4t1w4u3r4v4s4w3x4x5n4y4s4z4y5k4m5l4y5m4s5n4m5o3x5p4s5q4m5r5y5s4m5t4m5u3x5v2l5w1w5x2l5y3u5z3r6k2l6l3r6m3x6n3r6o3x6p3r6q2l6r3x6s3x6t1w6u1w6v3r6w1w6x5t6y3x6z3x7k3x7l3x7m2r7n3r7o2l7p3x7q3r7r4y7s3r7t3r7u3m7v2r7w1w7x2r7y3u202l3rcl4sal2lam3ran3rao3rap3rar3ras2lat4tau2pav3raw3uay4taz2lbk2sbl3u'fof'6obo2lbp3xbq3rbr1wbs2lbu2obv3rbz3xck4s202k3rcm4scn4sco4scp4scq6ocr4scs4mct4mcu4mcv4mcw1w2m2zcy1wcz1wdl4sdm4ydn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3xek3rel3rem3ren3reo3rep3req5ter3res3ret3reu3rev3rew1wex1wey1wez1wfl3xfm3xfn3xfo3xfp3xfq3xfr3ufs3xft3xfu3xfv3xfw3xfz3r203k6o212m6o2dw2l2cq2l3t3r3u2l17s4m19m3r}'kerning'{cl{4qs5ku5ot5qs17sv5tv}201t{2ww4wy2yw}201w{2ks}201x{2ww4wy2yw}2k{201ts201xs}2w{7qs4qu5kw5os5qw5rs17su5tu7tsfzs}2x{5ow5qs}2y{7qs4qu5kw5os5qw5rs17su5tu7tsfzs}'fof'-6o7p{17su5tu5ot}ck{4qs5ku5ot5qs17sv5tv}4l{4qs5ku5ot5qs17sv5tv}cm{4qs5ku5ot5qs17sv5tv}cn{4qs5ku5ot5qs17sv5tv}co{4qs5ku5ot5qs17sv5tv}cp{4qs5ku5ot5qs17sv5tv}6l{17st5tt5os}17s{2kwclvcmvcnvcovcpv4lv4wwckv}5o{2kucltcmtcntcotcpt4lt4wtckt}5q{2ksclscmscnscoscps4ls4wvcks}5r{2ks4ws}5t{2kwclvcmvcnvcovcpv4lv4wwckv}eo{17st5tt5os}fu{17su5tu5ot}6p{17ss5ts}ek{17st5tt5os}el{17st5tt5os}em{17st5tt5os}en{17st5tt5os}6o{201ts}ep{17st5tt5os}es{17ss5ts}et{17ss5ts}eu{17ss5ts}ev{17ss5ts}6z{17su5tu5os5qt}fm{17su5tu5os5qt}fn{17su5tu5os5qt}fo{17su5tu5os5qt}fp{17su5tu5os5qt}fq{17su5tu5os5qt}fs{17su5tu5os5qt}ft{17su5tu5ot}7m{5os}fv{17su5tu5ot}fw{17su5tu5ot}}}"),
  11715. ZapfDingbats: uncompress("{'widths'{k4u2k1w'fof'6o}'kerning'{'fof'-6o}}"),
  11716. "Courier-Bold": uncompress("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}"),
  11717. "Times-Italic": uncompress("{'widths'{k3n2q4ycx2l201n3m201o5t201s2l201t2l201u2l201w3r201x3r201y3r2k1t2l2l202m2n2n3m2o3m2p5n202q5t2r1p2s2l2t2l2u3m2v4n2w1t2x2l2y1t2z1w3k3m3l3m3m3m3n3m3o3m3p3m3q3m3r3m3s3m203t2l203u2l3v2l3w4n3x4n3y4n3z3m4k5w4l3x4m3x4n4m4o4s4p3x4q3x4r4s4s4s4t2l4u2w4v4m4w3r4x5n4y4m4z4s5k3x5l4s5m3x5n3m5o3r5p4s5q3x5r5n5s3x5t3r5u3r5v2r5w1w5x2r5y2u5z3m6k2l6l3m6m3m6n2w6o3m6p2w6q1w6r3m6s3m6t1w6u1w6v2w6w1w6x4s6y3m6z3m7k3m7l3m7m2r7n2r7o1w7p3m7q2w7r4m7s2w7t2w7u2r7v2s7w1v7x2s7y3q202l3mcl3xal2ram3man3mao3map3mar3mas2lat4wau1vav3maw4nay4waz2lbk2sbl4n'fof'6obo2lbp3mbq3obr1tbs2lbu1zbv3mbz3mck3x202k3mcm3xcn3xco3xcp3xcq5tcr4mcs3xct3xcu3xcv3xcw2l2m2ucy2lcz2ldl4mdm4sdn4sdo4sdp4sdq4sds4sdt4sdu4sdv4sdw4sdz3mek3mel3mem3men3meo3mep3meq4mer2wes2wet2weu2wev2wew1wex1wey1wez1wfl3mfm3mfn3mfo3mfp3mfq3mfr4nfs3mft3mfu3mfv3mfw3mfz2w203k6o212m6m2dw2l2cq2l3t3m3u2l17s3r19m3m}'kerning'{cl{5kt4qw}201s{201sw}201t{201tw2wy2yy6q-t}201x{2wy2yy}2k{201tw}2w{7qs4qy7rs5ky7mw5os5qx5ru17su5tu}2x{17ss5ts5os}2y{7qs4qy7rs5ky7mw5os5qx5ru17su5tu}'fof'-6o6t{17ss5ts5qs}7t{5os}3v{5qs}7p{17su5tu5qs}ck{5kt4qw}4l{5kt4qw}cm{5kt4qw}cn{5kt4qw}co{5kt4qw}cp{5kt4qw}6l{4qs5ks5ou5qw5ru17su5tu}17s{2ks}5q{ckvclvcmvcnvcovcpv4lv}5r{ckuclucmucnucoucpu4lu}5t{2ks}6p{4qs5ks5ou5qw5ru17su5tu}ek{4qs5ks5ou5qw5ru17su5tu}el{4qs5ks5ou5qw5ru17su5tu}em{4qs5ks5ou5qw5ru17su5tu}en{4qs5ks5ou5qw5ru17su5tu}eo{4qs5ks5ou5qw5ru17su5tu}ep{4qs5ks5ou5qw5ru17su5tu}es{5ks5qs4qs}et{4qs5ks5ou5qw5ru17su5tu}eu{4qs5ks5qw5ru17su5tu}ev{5ks5qs4qs}ex{17ss5ts5qs}6z{4qv5ks5ou5qw5ru17su5tu}fm{4qv5ks5ou5qw5ru17su5tu}fn{4qv5ks5ou5qw5ru17su5tu}fo{4qv5ks5ou5qw5ru17su5tu}fp{4qv5ks5ou5qw5ru17su5tu}fq{4qv5ks5ou5qw5ru17su5tu}7r{5os}fs{4qv5ks5ou5qw5ru17su5tu}ft{17su5tu5qs}fu{17su5tu5qs}fv{17su5tu5qs}fw{17su5tu5qs}}}"),
  11718. "Times-Roman": uncompress("{'widths'{k3n2q4ycx2l201n3m201o6o201s2l201t2l201u2l201w2w201x2w201y2w2k1t2l2l202m2n2n3m2o3m2p5n202q6o2r1m2s2l2t2l2u3m2v3s2w1t2x2l2y1t2z1w3k3m3l3m3m3m3n3m3o3m3p3m3q3m3r3m3s3m203t2l203u2l3v1w3w3s3x3s3y3s3z2w4k5w4l4s4m4m4n4m4o4s4p3x4q3r4r4s4s4s4t2l4u2r4v4s4w3x4x5t4y4s4z4s5k3r5l4s5m4m5n3r5o3x5p4s5q4s5r5y5s4s5t4s5u3x5v2l5w1w5x2l5y2z5z3m6k2l6l2w6m3m6n2w6o3m6p2w6q2l6r3m6s3m6t1w6u1w6v3m6w1w6x4y6y3m6z3m7k3m7l3m7m2l7n2r7o1w7p3m7q3m7r4s7s3m7t3m7u2w7v3k7w1o7x3k7y3q202l3mcl4sal2lam3man3mao3map3mar3mas2lat4wau1vav3maw3say4waz2lbk2sbl3s'fof'6obo2lbp3mbq2xbr1tbs2lbu1zbv3mbz2wck4s202k3mcm4scn4sco4scp4scq5tcr4mcs3xct3xcu3xcv3xcw2l2m2tcy2lcz2ldl4sdm4sdn4sdo4sdp4sdq4sds4sdt4sdu4sdv4sdw4sdz3mek2wel2wem2wen2weo2wep2weq4mer2wes2wet2weu2wev2wew1wex1wey1wez1wfl3mfm3mfn3mfo3mfp3mfq3mfr3sfs3mft3mfu3mfv3mfw3mfz3m203k6o212m6m2dw2l2cq2l3t3m3u1w17s4s19m3m}'kerning'{cl{4qs5ku17sw5ou5qy5rw201ss5tw201ws}201s{201ss}201t{ckw4lwcmwcnwcowcpwclw4wu201ts}2k{201ts}2w{4qs5kw5os5qx5ru17sx5tx}2x{17sw5tw5ou5qu}2y{4qs5kw5os5qx5ru17sx5tx}'fof'-6o7t{ckuclucmucnucoucpu4lu5os5rs}3u{17su5tu5qs}3v{17su5tu5qs}7p{17sw5tw5qs}ck{4qs5ku17sw5ou5qy5rw201ss5tw201ws}4l{4qs5ku17sw5ou5qy5rw201ss5tw201ws}cm{4qs5ku17sw5ou5qy5rw201ss5tw201ws}cn{4qs5ku17sw5ou5qy5rw201ss5tw201ws}co{4qs5ku17sw5ou5qy5rw201ss5tw201ws}cp{4qs5ku17sw5ou5qy5rw201ss5tw201ws}6l{17su5tu5os5qw5rs}17s{2ktclvcmvcnvcovcpv4lv4wuckv}5o{ckwclwcmwcnwcowcpw4lw4wu}5q{ckyclycmycnycoycpy4ly4wu5ms}5r{cktcltcmtcntcotcpt4lt4ws}5t{2ktclvcmvcnvcovcpv4lv4wuckv}7q{cksclscmscnscoscps4ls}6p{17su5tu5qw5rs}ek{5qs5rs}el{17su5tu5os5qw5rs}em{17su5tu5os5qs5rs}en{17su5qs5rs}eo{5qs5rs}ep{17su5tu5os5qw5rs}es{5qs}et{17su5tu5qw5rs}eu{17su5tu5qs5rs}ev{5qs}6z{17sv5tv5os5qx5rs}fm{5os5qt5rs}fn{17sv5tv5os5qx5rs}fo{17sv5tv5os5qx5rs}fp{5os5qt5rs}fq{5os5qt5rs}7r{ckuclucmucnucoucpu4lu5os}fs{17sv5tv5os5qx5rs}ft{17ss5ts5qs}fu{17sw5tw5qs}fv{17sw5tw5qs}fw{17ss5ts5qs}fz{ckuclucmucnucoucpu4lu5os5rs}}}"),
  11719. "Helvetica-Oblique": uncompress("{'widths'{k3p2q4mcx1w201n3r201o6o201s1q201t1q201u1q201w2l201x2l201y2l2k1w2l1w202m2n2n3r2o3r2p5t202q6o2r1n2s2l2t2l2u2r2v3u2w1w2x2l2y1w2z1w3k3r3l3r3m3r3n3r3o3r3p3r3q3r3r3r3s3r203t2l203u2l3v1w3w3u3x3u3y3u3z3r4k6p4l4m4m4m4n4s4o4s4p4m4q3x4r4y4s4s4t1w4u3m4v4m4w3r4x5n4y4s4z4y5k4m5l4y5m4s5n4m5o3x5p4s5q4m5r5y5s4m5t4m5u3x5v1w5w1w5x1w5y2z5z3r6k2l6l3r6m3r6n3m6o3r6p3r6q1w6r3r6s3r6t1q6u1q6v3m6w1q6x5n6y3r6z3r7k3r7l3r7m2l7n3m7o1w7p3r7q3m7r4s7s3m7t3m7u3m7v2l7w1u7x2l7y3u202l3rcl4mal2lam3ran3rao3rap3rar3ras2lat4tau2pav3raw3uay4taz2lbk2sbl3u'fof'6obo2lbp3rbr1wbs2lbu2obv3rbz3xck4m202k3rcm4mcn4mco4mcp4mcq6ocr4scs4mct4mcu4mcv4mcw1w2m2ncy1wcz1wdl4sdm4ydn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3xek3rel3rem3ren3reo3rep3req5ter3mes3ret3reu3rev3rew1wex1wey1wez1wfl3rfm3rfn3rfo3rfp3rfq3rfr3ufs3xft3rfu3rfv3rfw3rfz3m203k6o212m6o2dw2l2cq2l3t3r3u1w17s4m19m3r}'kerning'{5q{4wv}cl{4qs5kw5ow5qs17sv5tv}201t{2wu4w1k2yu}201x{2wu4wy2yu}17s{2ktclucmucnu4otcpu4lu4wycoucku}2w{7qs4qz5k1m17sy5ow5qx5rsfsu5ty7tufzu}2x{17sy5ty5oy5qs}2y{7qs4qz5k1m17sy5ow5qx5rsfsu5ty7tufzu}'fof'-6o7p{17sv5tv5ow}ck{4qs5kw5ow5qs17sv5tv}4l{4qs5kw5ow5qs17sv5tv}cm{4qs5kw5ow5qs17sv5tv}cn{4qs5kw5ow5qs17sv5tv}co{4qs5kw5ow5qs17sv5tv}cp{4qs5kw5ow5qs17sv5tv}6l{17sy5ty5ow}do{17st5tt}4z{17st5tt}7s{fst}dm{17st5tt}dn{17st5tt}5o{ckwclwcmwcnwcowcpw4lw4wv}dp{17st5tt}dq{17st5tt}7t{5ow}ds{17st5tt}5t{2ktclucmucnu4otcpu4lu4wycoucku}fu{17sv5tv5ow}6p{17sy5ty5ow5qs}ek{17sy5ty5ow}el{17sy5ty5ow}em{17sy5ty5ow}en{5ty}eo{17sy5ty5ow}ep{17sy5ty5ow}es{17sy5ty5qs}et{17sy5ty5ow5qs}eu{17sy5ty5ow5qs}ev{17sy5ty5ow5qs}6z{17sy5ty5ow5qs}fm{17sy5ty5ow5qs}fn{17sy5ty5ow5qs}fo{17sy5ty5ow5qs}fp{17sy5ty5qs}fq{17sy5ty5ow5qs}7r{5ow}fs{17sy5ty5ow5qs}ft{17sv5tv5ow}7m{5ow}fv{17sv5tv5ow}fw{17sv5tv5ow}}}")
  11720. }
  11721. };
  11722. /*
  11723. This event handler is fired when a new jsPDF object is initialized
  11724. This event handler appends metrics data to standard fonts within
  11725. that jsPDF instance. The metrics are mapped over Unicode character
  11726. codes, NOT CIDs or other codes matching the StandardEncoding table of the
  11727. standard PDF fonts.
  11728. Future:
  11729. Also included is the encoding maping table, converting Unicode (UCS-2, UTF-16)
  11730. char codes to StandardEncoding character codes. The encoding table is to be used
  11731. somewhere around "pdfEscape" call.
  11732. */
  11733. API.events.push(["addFont", function (font) {
  11734. var metrics,
  11735. unicode_section,
  11736. encoding = "Unicode",
  11737. encodingBlock;
  11738. metrics = fontMetrics[encoding][font.postScriptName];
  11739. if (metrics) {
  11740. if (font.metadata[encoding]) {
  11741. unicode_section = font.metadata[encoding];
  11742. } else {
  11743. unicode_section = font.metadata[encoding] = {};
  11744. }
  11745. unicode_section.widths = metrics.widths;
  11746. unicode_section.kerning = metrics.kerning;
  11747. }
  11748. encodingBlock = encodings[encoding][font.postScriptName];
  11749. if (encodingBlock) {
  11750. if (font.metadata[encoding]) {
  11751. unicode_section = font.metadata[encoding];
  11752. } else {
  11753. unicode_section = font.metadata[encoding] = {};
  11754. }
  11755. unicode_section.encoding = encodingBlock;
  11756. if (encodingBlock.codePages && encodingBlock.codePages.length) {
  11757. font.encoding = encodingBlock.codePages[0];
  11758. }
  11759. }
  11760. }]); // end of adding event handler
  11761. })(jsPDF.API);
  11762. /**
  11763. * @license
  11764. * Licensed under the MIT License.
  11765. * http://opensource.org/licenses/mit-license
  11766. */
  11767. /**
  11768. * @name ttfsupport
  11769. * @module
  11770. */
  11771. (function (jsPDF, global) {
  11772. jsPDF.API.events.push(["addFont", function (font) {
  11773. if (jsPDF.API.existsFileInVFS(font.postScriptName)) {
  11774. font.metadata = jsPDF.API.TTFFont.open(font.postScriptName, font.fontName, jsPDF.API.getFileFromVFS(font.postScriptName), font.encoding);
  11775. font.metadata.Unicode = font.metadata.Unicode || {
  11776. encoding: {},
  11777. kerning: {},
  11778. widths: []
  11779. };
  11780. } else if (font.id.slice(1) > 14) {
  11781. console.error("Font does not exist in FileInVFS, import fonts or remove declaration doc.addFont('" + font.postScriptName + "').");
  11782. }
  11783. }]); // end of adding event handler
  11784. })(jsPDF, typeof self !== "undefined" && self || typeof global !== "undefined" && global || typeof window !== "undefined" && window || Function("return this")());
  11785. /** @license
  11786. * Copyright (c) 2012 Willow Systems Corporation, willow-systems.com
  11787. *
  11788. *
  11789. * ====================================================================
  11790. */
  11791. /**
  11792. * jsPDF SVG plugin
  11793. *
  11794. * @name svg
  11795. * @module
  11796. */
  11797. (function (jsPDFAPI) {
  11798. /**
  11799. * Parses SVG XML and converts only some of the SVG elements into
  11800. * PDF elements.
  11801. *
  11802. * Supports:
  11803. * paths
  11804. *
  11805. * @name addSvg
  11806. * @public
  11807. * @function
  11808. * @param {string} SVG-Data as Text
  11809. * @param {number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
  11810. * @param {number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
  11811. * @param {number} width of SVG (in units declared at inception of PDF document)
  11812. * @param {number} height of SVG (in units declared at inception of PDF document)
  11813. * @returns {Object} jsPDF-instance
  11814. */
  11815. jsPDFAPI.addSvg = function (svgtext, x, y, w, h) {
  11816. // 'this' is _jsPDF object returned when jsPDF is inited (new jsPDF())
  11817. var undef;
  11818. if (x === undef || y === undef) {
  11819. throw new Error("addSVG needs values for 'x' and 'y'");
  11820. }
  11821. function InjectCSS(cssbody, document) {
  11822. var styletag = document.createElement("style");
  11823. styletag.type = "text/css";
  11824. if (styletag.styleSheet) {
  11825. // ie
  11826. styletag.styleSheet.cssText = cssbody;
  11827. } else {
  11828. // others
  11829. styletag.appendChild(document.createTextNode(cssbody));
  11830. }
  11831. document.getElementsByTagName("head")[0].appendChild(styletag);
  11832. }
  11833. function createWorkerNode(document) {
  11834. var frameID = "childframe",
  11835. // Date.now().toString() + '_' + (Math.random() * 100).toString()
  11836. frame = document.createElement("iframe");
  11837. InjectCSS(".jsPDF_sillysvg_iframe {display:none;position:absolute;}", document);
  11838. frame.name = frameID;
  11839. frame.setAttribute("width", 0);
  11840. frame.setAttribute("height", 0);
  11841. frame.setAttribute("frameborder", "0");
  11842. frame.setAttribute("scrolling", "no");
  11843. frame.setAttribute("seamless", "seamless");
  11844. frame.setAttribute("class", "jsPDF_sillysvg_iframe");
  11845. document.body.appendChild(frame);
  11846. return frame;
  11847. }
  11848. function attachSVGToWorkerNode(svgtext, frame) {
  11849. var framedoc = (frame.contentWindow || frame.contentDocument).document;
  11850. framedoc.write(svgtext);
  11851. framedoc.close();
  11852. return framedoc.getElementsByTagName("svg")[0];
  11853. }
  11854. function convertPathToPDFLinesArgs(path) {
  11855. // - starting coordinate pair
  11856. // - array of arrays of vector shifts (2-len for line, 6 len for bezier)
  11857. // - scale array [horizontal, vertical] ratios
  11858. // - style (stroke, fill, both)
  11859. var x = parseFloat(path[1]),
  11860. y = parseFloat(path[2]),
  11861. vectors = [],
  11862. position = 3,
  11863. len = path.length;
  11864. while (position < len) {
  11865. if (path[position] === "c") {
  11866. vectors.push([parseFloat(path[position + 1]), parseFloat(path[position + 2]), parseFloat(path[position + 3]), parseFloat(path[position + 4]), parseFloat(path[position + 5]), parseFloat(path[position + 6])]);
  11867. position += 7;
  11868. } else if (path[position] === "l") {
  11869. vectors.push([parseFloat(path[position + 1]), parseFloat(path[position + 2])]);
  11870. position += 3;
  11871. } else {
  11872. position += 1;
  11873. }
  11874. }
  11875. return [x, y, vectors];
  11876. }
  11877. var workernode = createWorkerNode(document),
  11878. svgnode = attachSVGToWorkerNode(svgtext, workernode),
  11879. scale = [1, 1],
  11880. svgw = parseFloat(svgnode.getAttribute("width")),
  11881. svgh = parseFloat(svgnode.getAttribute("height"));
  11882. if (svgw && svgh) {
  11883. // setting both w and h makes image stretch to size.
  11884. // this may distort the image, but fits your demanded size
  11885. if (w && h) {
  11886. scale = [w / svgw, h / svgh];
  11887. } // if only one is set, that value is set as max and SVG
  11888. // is scaled proportionately.
  11889. else if (w) {
  11890. scale = [w / svgw, w / svgw];
  11891. } else if (h) {
  11892. scale = [h / svgh, h / svgh];
  11893. }
  11894. }
  11895. var i,
  11896. l,
  11897. tmp,
  11898. linesargs,
  11899. items = svgnode.childNodes;
  11900. for (i = 0, l = items.length; i < l; i++) {
  11901. tmp = items[i];
  11902. if (tmp.tagName && tmp.tagName.toUpperCase() === "PATH") {
  11903. linesargs = convertPathToPDFLinesArgs(tmp.getAttribute("d").split(" ")); // path start x coordinate
  11904. linesargs[0] = linesargs[0] * scale[0] + x; // where x is upper left X of image
  11905. // path start y coordinate
  11906. linesargs[1] = linesargs[1] * scale[1] + y; // where y is upper left Y of image
  11907. // the rest of lines are vectors. these will adjust with scale value auto.
  11908. this.lines.call(this, linesargs[2], // lines
  11909. linesargs[0], // starting x
  11910. linesargs[1], // starting y
  11911. scale);
  11912. }
  11913. } // clean up
  11914. // workernode.parentNode.removeChild(workernode)
  11915. return this;
  11916. }; //fallback
  11917. jsPDFAPI.addSVG = jsPDFAPI.addSvg;
  11918. /**
  11919. * Parses SVG XML and saves it as image into the PDF.
  11920. *
  11921. * Depends on canvas-element and canvg
  11922. *
  11923. * @name addSvgAsImage
  11924. * @public
  11925. * @function
  11926. * @param {string} SVG-Data as Text
  11927. * @param {number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
  11928. * @param {number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
  11929. * @param {number} width of SVG-Image (in units declared at inception of PDF document)
  11930. * @param {number} height of SVG-Image (in units declared at inception of PDF document)
  11931. * @param {string} alias of SVG-Image (if used multiple times)
  11932. * @param {string} compression of the generated JPEG, can have the values 'NONE', 'FAST', 'MEDIUM' and 'SLOW'
  11933. * @param {number} rotation of the image in degrees (0-359)
  11934. *
  11935. * @returns jsPDF jsPDF-instance
  11936. */
  11937. jsPDFAPI.addSvgAsImage = function (svg, x, y, w, h, alias, compression, rotation) {
  11938. if (isNaN(x) || isNaN(y)) {
  11939. console.error("jsPDF.addSvgAsImage: Invalid coordinates", arguments);
  11940. throw new Error("Invalid coordinates passed to jsPDF.addSvgAsImage");
  11941. }
  11942. if (isNaN(w) || isNaN(h)) {
  11943. console.error("jsPDF.addSvgAsImage: Invalid measurements", arguments);
  11944. throw new Error("Invalid measurements (width and/or height) passed to jsPDF.addSvgAsImage");
  11945. }
  11946. var canvas = document.createElement("canvas");
  11947. canvas.width = w;
  11948. canvas.height = h;
  11949. var ctx = canvas.getContext("2d");
  11950. ctx.fillStyle = "#fff"; /// set white fill style
  11951. ctx.fillRect(0, 0, canvas.width, canvas.height); //load a svg snippet in the canvas with id = 'drawingArea'
  11952. canvg(canvas, svg, {
  11953. ignoreMouse: true,
  11954. ignoreAnimation: true,
  11955. ignoreDimensions: true,
  11956. ignoreClear: true
  11957. });
  11958. this.addImage(canvas.toDataURL("image/jpeg", 1.0), x, y, w, h, compression, rotation);
  11959. return this;
  11960. };
  11961. })(jsPDF.API);
  11962. /**
  11963. * @license
  11964. * ====================================================================
  11965. * Copyright (c) 2013 Eduardo Menezes de Morais, eduardo.morais@usp.br
  11966. *
  11967. *
  11968. * ====================================================================
  11969. */
  11970. /**
  11971. * jsPDF total_pages plugin
  11972. * @name total_pages
  11973. * @module
  11974. */
  11975. (function (jsPDFAPI) {
  11976. /**
  11977. * @name putTotalPages
  11978. * @function
  11979. * @param {string} pageExpression Regular Expression
  11980. * @returns {jsPDF} jsPDF-instance
  11981. */
  11982. jsPDFAPI.putTotalPages = function (pageExpression) {
  11983. var replaceExpression = new RegExp(pageExpression, "g");
  11984. for (var n = 1; n <= this.internal.getNumberOfPages(); n++) {
  11985. for (var i = 0; i < this.internal.pages[n].length; i++) {
  11986. this.internal.pages[n][i] = this.internal.pages[n][i].replace(replaceExpression, this.internal.getNumberOfPages());
  11987. }
  11988. }
  11989. return this;
  11990. };
  11991. })(jsPDF.API);
  11992. /**
  11993. * jsPDF viewerPreferences Plugin
  11994. * @author Aras Abbasi (github.com/arasabbasi)
  11995. * Licensed under the MIT License.
  11996. * http://opensource.org/licenses/mit-license
  11997. */
  11998. /**
  11999. * Adds the ability to set ViewerPreferences and by thus
  12000. * controlling the way the document is to be presented on the
  12001. * screen or in print.
  12002. * @name viewerpreferences
  12003. * @module
  12004. */
  12005. (function (jsPDFAPI) {
  12006. /**
  12007. * Set the ViewerPreferences of the generated PDF
  12008. *
  12009. * @name viewerPreferences
  12010. * @function
  12011. * @public
  12012. * @param {Object} options Array with the ViewerPreferences<br />
  12013. * Example: doc.viewerPreferences({"FitWindow":true});<br />
  12014. * <br />
  12015. * You can set following preferences:<br />
  12016. * <br/>
  12017. * <b>HideToolbar</b> <i>(boolean)</i><br />
  12018. * Default value: false<br />
  12019. * <br />
  12020. * <b>HideMenubar</b> <i>(boolean)</i><br />
  12021. * Default value: false.<br />
  12022. * <br />
  12023. * <b>HideWindowUI</b> <i>(boolean)</i><br />
  12024. * Default value: false.<br />
  12025. * <br />
  12026. * <b>FitWindow</b> <i>(boolean)</i><br />
  12027. * Default value: false.<br />
  12028. * <br />
  12029. * <b>CenterWindow</b> <i>(boolean)</i><br />
  12030. * Default value: false<br />
  12031. * <br />
  12032. * <b>DisplayDocTitle</b> <i>(boolean)</i><br />
  12033. * Default value: false.<br />
  12034. * <br />
  12035. * <b>NonFullScreenPageMode</b> <i>(string)</i><br />
  12036. * Possible values: UseNone, UseOutlines, UseThumbs, UseOC<br />
  12037. * Default value: UseNone<br/>
  12038. * <br />
  12039. * <b>Direction</b> <i>(string)</i><br />
  12040. * Possible values: L2R, R2L<br />
  12041. * Default value: L2R.<br />
  12042. * <br />
  12043. * <b>ViewArea</b> <i>(string)</i><br />
  12044. * Possible values: MediaBox, CropBox, TrimBox, BleedBox, ArtBox<br />
  12045. * Default value: CropBox.<br />
  12046. * <br />
  12047. * <b>ViewClip</b> <i>(string)</i><br />
  12048. * Possible values: MediaBox, CropBox, TrimBox, BleedBox, ArtBox<br />
  12049. * Default value: CropBox<br />
  12050. * <br />
  12051. * <b>PrintArea</b> <i>(string)</i><br />
  12052. * Possible values: MediaBox, CropBox, TrimBox, BleedBox, ArtBox<br />
  12053. * Default value: CropBox<br />
  12054. * <br />
  12055. * <b>PrintClip</b> <i>(string)</i><br />
  12056. * Possible values: MediaBox, CropBox, TrimBox, BleedBox, ArtBox<br />
  12057. * Default value: CropBox.<br />
  12058. * <br />
  12059. * <b>PrintScaling</b> <i>(string)</i><br />
  12060. * Possible values: AppDefault, None<br />
  12061. * Default value: AppDefault.<br />
  12062. * <br />
  12063. * <b>Duplex</b> <i>(string)</i><br />
  12064. * Possible values: Simplex, DuplexFlipLongEdge, DuplexFlipShortEdge
  12065. * Default value: none<br />
  12066. * <br />
  12067. * <b>PickTrayByPDFSize</b> <i>(boolean)</i><br />
  12068. * Default value: false<br />
  12069. * <br />
  12070. * <b>PrintPageRange</b> <i>(Array)</i><br />
  12071. * Example: [[1,5], [7,9]]<br />
  12072. * Default value: as defined by PDF viewer application<br />
  12073. * <br />
  12074. * <b>NumCopies</b> <i>(Number)</i><br />
  12075. * Possible values: 1, 2, 3, 4, 5<br />
  12076. * Default value: 1<br />
  12077. * <br />
  12078. * For more information see the PDF Reference, sixth edition on Page 577
  12079. * @param {boolean} doReset True to reset the settings
  12080. * @function
  12081. * @returns jsPDF jsPDF-instance
  12082. * @example
  12083. * var doc = new jsPDF()
  12084. * doc.text('This is a test', 10, 10)
  12085. * doc.viewerPreferences({'FitWindow': true}, true)
  12086. * doc.save("viewerPreferences.pdf")
  12087. *
  12088. * // Example printing 10 copies, using cropbox, and hiding UI.
  12089. * doc.viewerPreferences({
  12090. * 'HideWindowUI': true,
  12091. * 'PrintArea': 'CropBox',
  12092. * 'NumCopies': 10
  12093. * })
  12094. */
  12095. jsPDFAPI.viewerPreferences = function (options, doReset) {
  12096. options = options || {};
  12097. doReset = doReset || false;
  12098. var configuration;
  12099. var configurationTemplate = {
  12100. HideToolbar: {
  12101. defaultValue: false,
  12102. value: false,
  12103. type: "boolean",
  12104. explicitSet: false,
  12105. valueSet: [true, false],
  12106. pdfVersion: 1.3
  12107. },
  12108. HideMenubar: {
  12109. defaultValue: false,
  12110. value: false,
  12111. type: "boolean",
  12112. explicitSet: false,
  12113. valueSet: [true, false],
  12114. pdfVersion: 1.3
  12115. },
  12116. HideWindowUI: {
  12117. defaultValue: false,
  12118. value: false,
  12119. type: "boolean",
  12120. explicitSet: false,
  12121. valueSet: [true, false],
  12122. pdfVersion: 1.3
  12123. },
  12124. FitWindow: {
  12125. defaultValue: false,
  12126. value: false,
  12127. type: "boolean",
  12128. explicitSet: false,
  12129. valueSet: [true, false],
  12130. pdfVersion: 1.3
  12131. },
  12132. CenterWindow: {
  12133. defaultValue: false,
  12134. value: false,
  12135. type: "boolean",
  12136. explicitSet: false,
  12137. valueSet: [true, false],
  12138. pdfVersion: 1.3
  12139. },
  12140. DisplayDocTitle: {
  12141. defaultValue: false,
  12142. value: false,
  12143. type: "boolean",
  12144. explicitSet: false,
  12145. valueSet: [true, false],
  12146. pdfVersion: 1.4
  12147. },
  12148. NonFullScreenPageMode: {
  12149. defaultValue: "UseNone",
  12150. value: "UseNone",
  12151. type: "name",
  12152. explicitSet: false,
  12153. valueSet: ["UseNone", "UseOutlines", "UseThumbs", "UseOC"],
  12154. pdfVersion: 1.3
  12155. },
  12156. Direction: {
  12157. defaultValue: "L2R",
  12158. value: "L2R",
  12159. type: "name",
  12160. explicitSet: false,
  12161. valueSet: ["L2R", "R2L"],
  12162. pdfVersion: 1.3
  12163. },
  12164. ViewArea: {
  12165. defaultValue: "CropBox",
  12166. value: "CropBox",
  12167. type: "name",
  12168. explicitSet: false,
  12169. valueSet: ["MediaBox", "CropBox", "TrimBox", "BleedBox", "ArtBox"],
  12170. pdfVersion: 1.4
  12171. },
  12172. ViewClip: {
  12173. defaultValue: "CropBox",
  12174. value: "CropBox",
  12175. type: "name",
  12176. explicitSet: false,
  12177. valueSet: ["MediaBox", "CropBox", "TrimBox", "BleedBox", "ArtBox"],
  12178. pdfVersion: 1.4
  12179. },
  12180. PrintArea: {
  12181. defaultValue: "CropBox",
  12182. value: "CropBox",
  12183. type: "name",
  12184. explicitSet: false,
  12185. valueSet: ["MediaBox", "CropBox", "TrimBox", "BleedBox", "ArtBox"],
  12186. pdfVersion: 1.4
  12187. },
  12188. PrintClip: {
  12189. defaultValue: "CropBox",
  12190. value: "CropBox",
  12191. type: "name",
  12192. explicitSet: false,
  12193. valueSet: ["MediaBox", "CropBox", "TrimBox", "BleedBox", "ArtBox"],
  12194. pdfVersion: 1.4
  12195. },
  12196. PrintScaling: {
  12197. defaultValue: "AppDefault",
  12198. value: "AppDefault",
  12199. type: "name",
  12200. explicitSet: false,
  12201. valueSet: ["AppDefault", "None"],
  12202. pdfVersion: 1.6
  12203. },
  12204. Duplex: {
  12205. defaultValue: "",
  12206. value: "none",
  12207. type: "name",
  12208. explicitSet: false,
  12209. valueSet: ["Simplex", "DuplexFlipShortEdge", "DuplexFlipLongEdge", "none"],
  12210. pdfVersion: 1.7
  12211. },
  12212. PickTrayByPDFSize: {
  12213. defaultValue: false,
  12214. value: false,
  12215. type: "boolean",
  12216. explicitSet: false,
  12217. valueSet: [true, false],
  12218. pdfVersion: 1.7
  12219. },
  12220. PrintPageRange: {
  12221. defaultValue: "",
  12222. value: "",
  12223. type: "array",
  12224. explicitSet: false,
  12225. valueSet: null,
  12226. pdfVersion: 1.7
  12227. },
  12228. NumCopies: {
  12229. defaultValue: 1,
  12230. value: 1,
  12231. type: "integer",
  12232. explicitSet: false,
  12233. valueSet: null,
  12234. pdfVersion: 1.7
  12235. }
  12236. };
  12237. var configurationKeys = Object.keys(configurationTemplate);
  12238. var rangeArray = [];
  12239. var i = 0;
  12240. var j = 0;
  12241. var k = 0;
  12242. var isValid = true;
  12243. var method;
  12244. var value;
  12245. function arrayContainsElement(array, element) {
  12246. var iterator;
  12247. var result = false;
  12248. for (iterator = 0; iterator < array.length; iterator += 1) {
  12249. if (array[iterator] === element) {
  12250. result = true;
  12251. }
  12252. }
  12253. return result;
  12254. }
  12255. if (this.internal.viewerpreferences === undefined) {
  12256. this.internal.viewerpreferences = {};
  12257. this.internal.viewerpreferences.configuration = JSON.parse(JSON.stringify(configurationTemplate));
  12258. this.internal.viewerpreferences.isSubscribed = false;
  12259. }
  12260. configuration = this.internal.viewerpreferences.configuration;
  12261. if (options === "reset" || doReset === true) {
  12262. var len = configurationKeys.length;
  12263. for (k = 0; k < len; k += 1) {
  12264. configuration[configurationKeys[k]].value = configuration[configurationKeys[k]].defaultValue;
  12265. configuration[configurationKeys[k]].explicitSet = false;
  12266. }
  12267. }
  12268. if (_typeof(options) === "object") {
  12269. for (method in options) {
  12270. value = options[method];
  12271. if (arrayContainsElement(configurationKeys, method) && value !== undefined) {
  12272. if (configuration[method].type === "boolean" && typeof value === "boolean") {
  12273. configuration[method].value = value;
  12274. } else if (configuration[method].type === "name" && arrayContainsElement(configuration[method].valueSet, value)) {
  12275. configuration[method].value = value;
  12276. } else if (configuration[method].type === "integer" && Number.isInteger(value)) {
  12277. configuration[method].value = value;
  12278. } else if (configuration[method].type === "array") {
  12279. for (i = 0; i < value.length; i += 1) {
  12280. isValid = true;
  12281. if (value[i].length === 1 && typeof value[i][0] === "number") {
  12282. rangeArray.push(String(value[i]));
  12283. } else if (value[i].length > 1) {
  12284. for (j = 0; j < value[i].length; j += 1) {
  12285. if (typeof value[i][j] !== "number") {
  12286. isValid = false;
  12287. }
  12288. }
  12289. if (isValid === true) {
  12290. rangeArray.push(String(value[i].join("-")));
  12291. }
  12292. }
  12293. }
  12294. configuration[method].value = String(rangeArray);
  12295. } else {
  12296. configuration[method].value = configuration[method].defaultValue;
  12297. }
  12298. configuration[method].explicitSet = true;
  12299. }
  12300. }
  12301. }
  12302. if (this.internal.viewerpreferences.isSubscribed === false) {
  12303. this.internal.events.subscribe("putCatalog", function () {
  12304. var pdfDict = [];
  12305. var vPref;
  12306. for (vPref in configuration) {
  12307. if (configuration[vPref].explicitSet === true) {
  12308. if (configuration[vPref].type === "name") {
  12309. pdfDict.push("/" + vPref + " /" + configuration[vPref].value);
  12310. } else {
  12311. pdfDict.push("/" + vPref + " " + configuration[vPref].value);
  12312. }
  12313. }
  12314. }
  12315. if (pdfDict.length !== 0) {
  12316. this.internal.write("/ViewerPreferences\n<<\n" + pdfDict.join("\n") + "\n>>");
  12317. }
  12318. });
  12319. this.internal.viewerpreferences.isSubscribed = true;
  12320. }
  12321. this.internal.viewerpreferences.configuration = configuration;
  12322. return this;
  12323. };
  12324. })(jsPDF.API);
  12325. /** ====================================================================
  12326. * jsPDF XMP metadata plugin
  12327. * Copyright (c) 2016 Jussi Utunen, u-jussi@suomi24.fi
  12328. *
  12329. *
  12330. * ====================================================================
  12331. */
  12332. /*global jsPDF */
  12333. /**
  12334. * @name xmp_metadata
  12335. * @module
  12336. */
  12337. (function (jsPDFAPI) {
  12338. var xmpmetadata = "";
  12339. var xmpnamespaceuri = "";
  12340. var metadata_object_number = "";
  12341. /**
  12342. * Adds XMP formatted metadata to PDF
  12343. *
  12344. * @name addMetadata
  12345. * @function
  12346. * @param {String} metadata The actual metadata to be added. The metadata shall be stored as XMP simple value. Note that if the metadata string contains XML markup characters "<", ">" or "&", those characters should be written using XML entities.
  12347. * @param {String} namespaceuri Sets the namespace URI for the metadata. Last character should be slash or hash.
  12348. * @returns {jsPDF} jsPDF-instance
  12349. */
  12350. jsPDFAPI.addMetadata = function (metadata, namespaceuri) {
  12351. xmpnamespaceuri = namespaceuri || "http://jspdf.default.namespaceuri/"; //The namespace URI for an XMP name shall not be empty
  12352. xmpmetadata = metadata;
  12353. this.internal.events.subscribe("postPutResources", function () {
  12354. if (!xmpmetadata) {
  12355. metadata_object_number = "";
  12356. } else {
  12357. var xmpmeta_beginning = '<x:xmpmeta xmlns:x="adobe:ns:meta/">';
  12358. var rdf_beginning = '<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><rdf:Description rdf:about="" xmlns:jspdf="' + xmpnamespaceuri + '"><jspdf:metadata>';
  12359. var rdf_ending = "</jspdf:metadata></rdf:Description></rdf:RDF>";
  12360. var xmpmeta_ending = "</x:xmpmeta>";
  12361. var utf8_xmpmeta_beginning = unescape(encodeURIComponent(xmpmeta_beginning));
  12362. var utf8_rdf_beginning = unescape(encodeURIComponent(rdf_beginning));
  12363. var utf8_metadata = unescape(encodeURIComponent(xmpmetadata));
  12364. var utf8_rdf_ending = unescape(encodeURIComponent(rdf_ending));
  12365. var utf8_xmpmeta_ending = unescape(encodeURIComponent(xmpmeta_ending));
  12366. var total_len = utf8_rdf_beginning.length + utf8_metadata.length + utf8_rdf_ending.length + utf8_xmpmeta_beginning.length + utf8_xmpmeta_ending.length;
  12367. metadata_object_number = this.internal.newObject();
  12368. this.internal.write("<< /Type /Metadata /Subtype /XML /Length " + total_len + " >>");
  12369. this.internal.write("stream");
  12370. this.internal.write(utf8_xmpmeta_beginning + utf8_rdf_beginning + utf8_metadata + utf8_rdf_ending + utf8_xmpmeta_ending);
  12371. this.internal.write("endstream");
  12372. this.internal.write("endobj");
  12373. }
  12374. });
  12375. this.internal.events.subscribe("putCatalog", function () {
  12376. if (metadata_object_number) {
  12377. this.internal.write("/Metadata " + metadata_object_number + " 0 R");
  12378. }
  12379. });
  12380. return this;
  12381. };
  12382. })(jsPDF.API);
  12383. /**
  12384. * @name utf8
  12385. * @module
  12386. */
  12387. (function (jsPDF, global) {
  12388. var jsPDFAPI = jsPDF.API;
  12389. var glyID = [0];
  12390. /**************************************************/
  12391. /* function : toHex */
  12392. /* comment : Replace str with a hex string. */
  12393. /**************************************************/
  12394. function toHex(str) {
  12395. var hex = "";
  12396. for (var i = 0; i < str.length; i++) {
  12397. hex += "" + str.charCodeAt(i).toString(16);
  12398. }
  12399. return hex;
  12400. }
  12401. /***************************************************************************************************/
  12402. /* function : pdfEscape16 */
  12403. /* comment : The character id of a 2-byte string is converted to a hexadecimal number by obtaining */
  12404. /* the corresponding glyph id and width, and then adding padding to the string. */
  12405. /***************************************************************************************************/
  12406. var pdfEscape16 = function pdfEscape16(text, font) {
  12407. var widths = font.metadata.Unicode.widths;
  12408. var padz = ["", "0", "00", "000", "0000"];
  12409. var ar = [""];
  12410. for (var i = 0, l = text.length, t; i < l; ++i) {
  12411. t = font.metadata.characterToGlyph(text.charCodeAt(i));
  12412. glyID.push(t);
  12413. if (widths.indexOf(t) == -1) {
  12414. widths.push(t);
  12415. widths.push([parseInt(font.metadata.widthOfGlyph(t), 10)]);
  12416. }
  12417. if (t == "0") {
  12418. //Spaces are not allowed in cmap.
  12419. return ar.join("");
  12420. } else {
  12421. t = t.toString(16);
  12422. ar.push(padz[4 - t.length], t);
  12423. }
  12424. }
  12425. return ar.join("");
  12426. };
  12427. var identityHFunction = function identityHFunction(font, out, newObject) {
  12428. if (font.metadata instanceof jsPDF.API.TTFFont && font.encoding === "Identity-H") {
  12429. //Tag with Identity-H
  12430. var widths = font.metadata.Unicode.widths;
  12431. var data = font.metadata.subset.encode(glyID);
  12432. var pdfOutput = data;
  12433. var pdfOutput2 = "";
  12434. for (var i = 0; i < pdfOutput.length; i++) {
  12435. pdfOutput2 += String.fromCharCode(pdfOutput[i]);
  12436. }
  12437. var fontTable = newObject();
  12438. out("<<");
  12439. out("/Length " + pdfOutput2.length);
  12440. out("/Length1 " + pdfOutput2.length);
  12441. out(">>");
  12442. out("stream");
  12443. out(pdfOutput2);
  12444. out("endstream");
  12445. out("endobj");
  12446. var fontDescriptor = newObject();
  12447. out("<<");
  12448. out("/Type /FontDescriptor");
  12449. out("/FontName /" + font.fontName);
  12450. out("/FontFile2 " + fontTable + " 0 R");
  12451. out("/FontBBox " + jsPDF.API.PDFObject.convert(font.metadata.bbox));
  12452. out("/Flags " + font.metadata.flags);
  12453. out("/StemV " + font.metadata.stemV);
  12454. out("/ItalicAngle " + font.metadata.italicAngle);
  12455. out("/Ascent " + font.metadata.ascender);
  12456. out("/Descent " + font.metadata.decender);
  12457. out("/CapHeight " + font.metadata.capHeight);
  12458. out(">>");
  12459. out("endobj");
  12460. var DescendantFont = newObject();
  12461. out("<<");
  12462. out("/Type /Font");
  12463. out("/BaseFont /" + font.fontName);
  12464. out("/FontDescriptor " + fontDescriptor + " 0 R");
  12465. out("/W " + jsPDF.API.PDFObject.convert(widths));
  12466. out("/CIDToGIDMap /Identity");
  12467. out("/DW 1000");
  12468. out("/Subtype /CIDFontType2");
  12469. out("/CIDSystemInfo");
  12470. out("<<");
  12471. out("/Supplement 0");
  12472. out("/Registry (Adobe)");
  12473. out("/Ordering (" + font.encoding + ")");
  12474. out(">>");
  12475. out(">>");
  12476. out("endobj");
  12477. font.objectNumber = newObject();
  12478. out("<<");
  12479. out("/Type /Font");
  12480. out("/Subtype /Type0");
  12481. out("/BaseFont /" + font.fontName);
  12482. out("/Encoding /" + font.encoding);
  12483. out("/DescendantFonts [" + DescendantFont + " 0 R]");
  12484. out(">>");
  12485. out("endobj");
  12486. font.isAlreadyPutted = true;
  12487. }
  12488. };
  12489. jsPDFAPI.events.push(["putFont", function (args) {
  12490. identityHFunction(args.font, args.out, args.newObject);
  12491. }]);
  12492. var winAnsiEncodingFunction = function winAnsiEncodingFunction(font, out, newObject) {
  12493. if (font.metadata instanceof jsPDF.API.TTFFont && font.encoding === "WinAnsiEncoding") {
  12494. //Tag with WinAnsi encoding
  12495. var widths = font.metadata.Unicode.widths;
  12496. var data = font.metadata.rawData;
  12497. var pdfOutput = data;
  12498. var pdfOutput2 = "";
  12499. for (var i = 0; i < pdfOutput.length; i++) {
  12500. pdfOutput2 += String.fromCharCode(pdfOutput[i]);
  12501. }
  12502. var fontTable = newObject();
  12503. out("<<");
  12504. out("/Length " + pdfOutput2.length);
  12505. out("/Length1 " + pdfOutput2.length);
  12506. out(">>");
  12507. out("stream");
  12508. out(pdfOutput2);
  12509. out("endstream");
  12510. out("endobj");
  12511. var fontDescriptor = newObject();
  12512. out("<<");
  12513. out("/Descent " + font.metadata.decender);
  12514. out("/CapHeight " + font.metadata.capHeight);
  12515. out("/StemV " + font.metadata.stemV);
  12516. out("/Type /FontDescriptor");
  12517. out("/FontFile2 " + fontTable + " 0 R");
  12518. out("/Flags 96");
  12519. out("/FontBBox " + jsPDF.API.PDFObject.convert(font.metadata.bbox));
  12520. out("/FontName /" + font.fontName);
  12521. out("/ItalicAngle " + font.metadata.italicAngle);
  12522. out("/Ascent " + font.metadata.ascender);
  12523. out(">>");
  12524. out("endobj");
  12525. font.objectNumber = newObject();
  12526. for (var i = 0; i < font.metadata.hmtx.widths.length; i++) {
  12527. font.metadata.hmtx.widths[i] = parseInt(font.metadata.hmtx.widths[i] * (1000 / font.metadata.head.unitsPerEm)); //Change the width of Em units to Point units.
  12528. }
  12529. out("<</Subtype/TrueType/Type/Font/BaseFont/" + font.fontName + "/FontDescriptor " + fontDescriptor + " 0 R" + "/Encoding/" + font.encoding + " /FirstChar 29 /LastChar 255 /Widths " + jsPDF.API.PDFObject.convert(font.metadata.hmtx.widths) + ">>");
  12530. out("endobj");
  12531. font.isAlreadyPutted = true;
  12532. }
  12533. };
  12534. jsPDFAPI.events.push(["putFont", function (args) {
  12535. winAnsiEncodingFunction(args.font, args.out, args.newObject);
  12536. }]);
  12537. var utf8TextFunction = function utf8TextFunction(args) {
  12538. var text = args.text || "";
  12539. var x = args.x;
  12540. var y = args.y;
  12541. var options = args.options || {};
  12542. var mutex = args.mutex || {};
  12543. var pdfEscape = mutex.pdfEscape;
  12544. var activeFontKey = mutex.activeFontKey;
  12545. var fonts = mutex.fonts;
  12546. var key,
  12547. fontSize = mutex.activeFontSize;
  12548. var str = "",
  12549. s = 0,
  12550. cmapConfirm;
  12551. var strText = "";
  12552. var key = activeFontKey;
  12553. var encoding = fonts[key].encoding;
  12554. if (fonts[key].encoding !== "Identity-H") {
  12555. return {
  12556. text: text,
  12557. x: x,
  12558. y: y,
  12559. options: options,
  12560. mutex: mutex
  12561. };
  12562. }
  12563. strText = text;
  12564. key = activeFontKey;
  12565. if (Object.prototype.toString.call(text) === "[object Array]") {
  12566. strText = text[0];
  12567. }
  12568. for (s = 0; s < strText.length; s += 1) {
  12569. if (fonts[key].metadata.hasOwnProperty("cmap")) {
  12570. cmapConfirm = fonts[key].metadata.cmap.unicode.codeMap[strText[s].charCodeAt(0)];
  12571. /*
  12572. if (Object.prototype.toString.call(text) === '[object Array]') {
  12573. var i = 0;
  12574. // for (i = 0; i < text.length; i += 1) {
  12575. if (Object.prototype.toString.call(text[s]) === '[object Array]') {
  12576. cmapConfirm = fonts[key].metadata.cmap.unicode.codeMap[strText[s][0].charCodeAt(0)]; //Make sure the cmap has the corresponding glyph id
  12577. } else {
  12578. }
  12579. //}
  12580. } else {
  12581. cmapConfirm = fonts[key].metadata.cmap.unicode.codeMap[strText[s].charCodeAt(0)]; //Make sure the cmap has the corresponding glyph id
  12582. }*/
  12583. }
  12584. if (!cmapConfirm) {
  12585. if (strText[s].charCodeAt(0) < 256 && fonts[key].metadata.hasOwnProperty("Unicode")) {
  12586. str += strText[s];
  12587. } else {
  12588. str += "";
  12589. }
  12590. } else {
  12591. str += strText[s];
  12592. }
  12593. }
  12594. var result = "";
  12595. if (parseInt(key.slice(1)) < 14 || encoding === "WinAnsiEncoding") {
  12596. //For the default 13 font
  12597. result = toHex(pdfEscape(str, key));
  12598. } else if (encoding === "Identity-H") {
  12599. result = pdfEscape16(str, fonts[key]);
  12600. }
  12601. mutex.isHex = true;
  12602. return {
  12603. text: result,
  12604. x: x,
  12605. y: y,
  12606. options: options,
  12607. mutex: mutex
  12608. };
  12609. };
  12610. var utf8EscapeFunction = function utf8EscapeFunction(parms) {
  12611. var text = parms.text || "",
  12612. x = parms.x,
  12613. y = parms.y,
  12614. options = parms.options,
  12615. mutex = parms.mutex;
  12616. var lang = options.lang;
  12617. var tmpText = [];
  12618. var args = {
  12619. text: text,
  12620. x: x,
  12621. y: y,
  12622. options: options,
  12623. mutex: mutex
  12624. };
  12625. if (Object.prototype.toString.call(text) === "[object Array]") {
  12626. var i = 0;
  12627. for (i = 0; i < text.length; i += 1) {
  12628. if (Object.prototype.toString.call(text[i]) === "[object Array]") {
  12629. if (text[i].length === 3) {
  12630. tmpText.push([utf8TextFunction(Object.assign({}, args, {
  12631. text: text[i][0]
  12632. })).text, text[i][1], text[i][2]]);
  12633. } else {
  12634. tmpText.push(utf8TextFunction(Object.assign({}, args, {
  12635. text: text[i]
  12636. })).text);
  12637. }
  12638. } else {
  12639. tmpText.push(utf8TextFunction(Object.assign({}, args, {
  12640. text: text[i]
  12641. })).text);
  12642. }
  12643. }
  12644. parms.text = tmpText;
  12645. } else {
  12646. parms.text = utf8TextFunction(Object.assign({}, args, {
  12647. text: text
  12648. })).text;
  12649. }
  12650. };
  12651. jsPDFAPI.events.push(["postProcessText", utf8EscapeFunction]);
  12652. })(jsPDF, typeof self !== "undefined" && self || typeof global !== "undefined" && global || typeof window !== "undefined" && window || Function("return this")());
  12653. /**
  12654. * jsPDF virtual FileSystem functionality
  12655. *
  12656. * Licensed under the MIT License.
  12657. * http://opensource.org/licenses/mit-license
  12658. */
  12659. /**
  12660. * Use the vFS to handle files
  12661. *
  12662. * @name vFS
  12663. * @module
  12664. */
  12665. (function (jsPDFAPI) {
  12666. var vFS = {};
  12667. /**
  12668. * Check if the file exists in the vFS
  12669. *
  12670. * @name existsFileInVFS
  12671. * @function
  12672. * @param {string} Possible filename in the vFS.
  12673. * @returns {boolean}
  12674. * @example
  12675. * doc.existsFileInVFS("someFile.txt");
  12676. */
  12677. jsPDFAPI.existsFileInVFS = function (filename) {
  12678. return vFS.hasOwnProperty(filename);
  12679. };
  12680. /**
  12681. * Add a file to the vFS
  12682. *
  12683. * @name addFileToVFS
  12684. * @function
  12685. * @param {string} filename The name of the file which should be added.
  12686. * @param {string} filecontent The content of the file.
  12687. * @returns {jsPDF}
  12688. * @example
  12689. * doc.addFileToVFS("someFile.txt", "BADFACE1");
  12690. */
  12691. jsPDFAPI.addFileToVFS = function (filename, filecontent) {
  12692. vFS[filename] = filecontent;
  12693. return this;
  12694. };
  12695. /**
  12696. * Get the file from the vFS
  12697. *
  12698. * @name getFileFromVFS
  12699. * @function
  12700. * @returns {string} The name of the file which gets requested.
  12701. * @example
  12702. * doc.getFileFromVFS("someFile.txt");
  12703. */
  12704. jsPDFAPI.getFileFromVFS = function (filename) {
  12705. if (vFS.hasOwnProperty(filename)) {
  12706. return vFS[filename];
  12707. }
  12708. return null;
  12709. };
  12710. })(jsPDF.API);
  12711. /* Blob.js
  12712. * A Blob implementation.
  12713. * 2014-07-24
  12714. *
  12715. * By Eli Grey, http://eligrey.com
  12716. * By Devin Samarin, https://github.com/dsamarin
  12717. * License: X11/MIT
  12718. * See https://github.com/eligrey/Blob.js/blob/master/LICENSE.md
  12719. */
  12720. /*global self, unescape */
  12721. /*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true,
  12722. plusplus: true */
  12723. /*! @source http://purl.eligrey.com/github/Blob.js/blob/master/Blob.js */
  12724. (function (view) {
  12725. view.URL = view.URL || view.webkitURL;
  12726. if (view.Blob && view.URL) {
  12727. try {
  12728. new Blob();
  12729. return;
  12730. } catch (e) {}
  12731. } // Internally we use a BlobBuilder implementation to base Blob off of
  12732. // in order to support older browsers that only have BlobBuilder
  12733. var BlobBuilder = view.BlobBuilder || view.WebKitBlobBuilder || view.MozBlobBuilder || function (view) {
  12734. var get_class = function (object) {
  12735. return Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1];
  12736. },
  12737. FakeBlobBuilder = function BlobBuilder() {
  12738. this.data = [];
  12739. },
  12740. FakeBlob = function Blob(data, type, encoding) {
  12741. this.data = data;
  12742. this.size = data.length;
  12743. this.type = type;
  12744. this.encoding = encoding;
  12745. },
  12746. FBB_proto = FakeBlobBuilder.prototype,
  12747. FB_proto = FakeBlob.prototype,
  12748. FileReaderSync = view.FileReaderSync,
  12749. FileException = function (type) {
  12750. this.code = this[this.name = type];
  12751. },
  12752. file_ex_codes = ("NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR " + "NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR").split(" "),
  12753. file_ex_code = file_ex_codes.length,
  12754. real_URL = view.URL || view.webkitURL || view,
  12755. real_create_object_URL = real_URL.createObjectURL,
  12756. real_revoke_object_URL = real_URL.revokeObjectURL,
  12757. URL = real_URL,
  12758. btoa = view.btoa,
  12759. atob = view.atob,
  12760. ArrayBuffer = view.ArrayBuffer,
  12761. Uint8Array = view.Uint8Array,
  12762. origin = /^[\w-]+:\/*\[?[\w\.:-]+\]?(?::[0-9]+)?/;
  12763. FakeBlob.fake = FB_proto.fake = true;
  12764. while (file_ex_code--) {
  12765. FileException.prototype[file_ex_codes[file_ex_code]] = file_ex_code + 1;
  12766. } // Polyfill URL
  12767. if (!real_URL.createObjectURL) {
  12768. URL = view.URL = function (uri) {
  12769. var uri_info = document.createElementNS("http://www.w3.org/1999/xhtml", "a"),
  12770. uri_origin;
  12771. uri_info.href = uri;
  12772. if (!("origin" in uri_info)) {
  12773. if (uri_info.protocol.toLowerCase() === "data:") {
  12774. uri_info.origin = null;
  12775. } else {
  12776. uri_origin = uri.match(origin);
  12777. uri_info.origin = uri_origin && uri_origin[1];
  12778. }
  12779. }
  12780. return uri_info;
  12781. };
  12782. }
  12783. URL.createObjectURL = function (blob) {
  12784. var type = blob.type,
  12785. data_URI_header;
  12786. if (type === null) {
  12787. type = "application/octet-stream";
  12788. }
  12789. if (blob instanceof FakeBlob) {
  12790. data_URI_header = "data:" + type;
  12791. if (blob.encoding === "base64") {
  12792. return data_URI_header + ";base64," + blob.data;
  12793. } else if (blob.encoding === "URI") {
  12794. return data_URI_header + "," + decodeURIComponent(blob.data);
  12795. }
  12796. if (btoa) {
  12797. return data_URI_header + ";base64," + btoa(blob.data);
  12798. } else {
  12799. return data_URI_header + "," + encodeURIComponent(blob.data);
  12800. }
  12801. } else if (real_create_object_URL) {
  12802. return real_create_object_URL.call(real_URL, blob);
  12803. }
  12804. };
  12805. URL.revokeObjectURL = function (object_URL) {
  12806. if (object_URL.substring(0, 5) !== "data:" && real_revoke_object_URL) {
  12807. real_revoke_object_URL.call(real_URL, object_URL);
  12808. }
  12809. };
  12810. FBB_proto.append = function (data
  12811. /*, endings*/
  12812. ) {
  12813. var bb = this.data; // decode data to a binary string
  12814. if (Uint8Array && (data instanceof ArrayBuffer || data instanceof Uint8Array)) {
  12815. var str = "",
  12816. buf = new Uint8Array(data),
  12817. i = 0,
  12818. buf_len = buf.length;
  12819. for (; i < buf_len; i++) {
  12820. str += String.fromCharCode(buf[i]);
  12821. }
  12822. bb.push(str);
  12823. } else if (get_class(data) === "Blob" || get_class(data) === "File") {
  12824. if (FileReaderSync) {
  12825. var fr = new FileReaderSync();
  12826. bb.push(fr.readAsBinaryString(data));
  12827. } else {
  12828. // async FileReader won't work as BlobBuilder is sync
  12829. throw new FileException("NOT_READABLE_ERR");
  12830. }
  12831. } else if (data instanceof FakeBlob) {
  12832. if (data.encoding === "base64" && atob) {
  12833. bb.push(atob(data.data));
  12834. } else if (data.encoding === "URI") {
  12835. bb.push(decodeURIComponent(data.data));
  12836. } else if (data.encoding === "raw") {
  12837. bb.push(data.data);
  12838. }
  12839. } else {
  12840. if (typeof data !== "string") {
  12841. data += ""; // convert unsupported types to strings
  12842. } // decode UTF-16 to binary string
  12843. bb.push(unescape(encodeURIComponent(data)));
  12844. }
  12845. };
  12846. FBB_proto.getBlob = function (type) {
  12847. if (!arguments.length) {
  12848. type = null;
  12849. }
  12850. return new FakeBlob(this.data.join(""), type, "raw");
  12851. };
  12852. FBB_proto.toString = function () {
  12853. return "[object BlobBuilder]";
  12854. };
  12855. FB_proto.slice = function (start, end, type) {
  12856. var args = arguments.length;
  12857. if (args < 3) {
  12858. type = null;
  12859. }
  12860. return new FakeBlob(this.data.slice(start, args > 1 ? end : this.data.length), type, this.encoding);
  12861. };
  12862. FB_proto.toString = function () {
  12863. return "[object Blob]";
  12864. };
  12865. FB_proto.close = function () {
  12866. this.size = 0;
  12867. delete this.data;
  12868. };
  12869. return FakeBlobBuilder;
  12870. }(view);
  12871. view.Blob = function (blobParts, options) {
  12872. var type = options ? options.type || "" : "";
  12873. var builder = new BlobBuilder();
  12874. if (blobParts) {
  12875. for (var i = 0, len = blobParts.length; i < len; i++) {
  12876. if (Uint8Array && blobParts[i] instanceof Uint8Array) {
  12877. builder.append(blobParts[i].buffer);
  12878. } else {
  12879. builder.append(blobParts[i]);
  12880. }
  12881. }
  12882. }
  12883. var blob = builder.getBlob(type);
  12884. if (!blob.slice && blob.webkitSlice) {
  12885. blob.slice = blob.webkitSlice;
  12886. }
  12887. return blob;
  12888. };
  12889. var getPrototypeOf = Object.getPrototypeOf || function (object) {
  12890. return object.__proto__;
  12891. };
  12892. view.Blob.prototype = getPrototypeOf(new view.Blob());
  12893. })(typeof self !== "undefined" && self || typeof window !== "undefined" && window || window.content || window);
  12894. /* FileSaver.js
  12895. * A saveAs() FileSaver implementation.
  12896. * 1.3.2
  12897. * 2016-06-16 18:25:19
  12898. *
  12899. * By Eli Grey, http://eligrey.com
  12900. * License: MIT
  12901. * See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md
  12902. */
  12903. /*global self */
  12904. /*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */
  12905. /*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */
  12906. var saveAs = saveAs || function (view) {
  12907. if (typeof view === "undefined" || typeof navigator !== "undefined" && /MSIE [1-9]\./.test(navigator.userAgent)) {
  12908. return;
  12909. }
  12910. var doc = view.document // only get URL when necessary in case Blob.js hasn't overridden it yet
  12911. ,
  12912. get_URL = function () {
  12913. return view.URL || view.webkitURL || view;
  12914. },
  12915. save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a"),
  12916. can_use_save_link = "download" in save_link,
  12917. click = function (node) {
  12918. var event = new MouseEvent("click");
  12919. node.dispatchEvent(event);
  12920. },
  12921. is_safari = /constructor/i.test(view.HTMLElement) || view.safari,
  12922. is_chrome_ios = /CriOS\/[\d]+/.test(navigator.userAgent),
  12923. throw_outside = function (ex) {
  12924. (view.setImmediate || view.setTimeout)(function () {
  12925. throw ex;
  12926. }, 0);
  12927. },
  12928. force_saveable_type = "application/octet-stream" // the Blob API is fundamentally broken as there is no "downloadfinished" event to subscribe to
  12929. ,
  12930. arbitrary_revoke_timeout = 1000 * 40 // in ms
  12931. ,
  12932. revoke = function (file) {
  12933. var revoker = function () {
  12934. if (typeof file === "string") {
  12935. // file is an object URL
  12936. get_URL().revokeObjectURL(file);
  12937. } else {
  12938. // file is a File
  12939. file.remove();
  12940. }
  12941. };
  12942. setTimeout(revoker, arbitrary_revoke_timeout);
  12943. },
  12944. dispatch = function (filesaver, event_types, event) {
  12945. event_types = [].concat(event_types);
  12946. var i = event_types.length;
  12947. while (i--) {
  12948. var listener = filesaver["on" + event_types[i]];
  12949. if (typeof listener === "function") {
  12950. try {
  12951. listener.call(filesaver, event || filesaver);
  12952. } catch (ex) {
  12953. throw_outside(ex);
  12954. }
  12955. }
  12956. }
  12957. },
  12958. auto_bom = function (blob) {
  12959. // prepend BOM for UTF-8 XML and text/* types (including HTML)
  12960. // note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF
  12961. if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) {
  12962. return new Blob([String.fromCharCode(0xFEFF), blob], {
  12963. type: blob.type
  12964. });
  12965. }
  12966. return blob;
  12967. },
  12968. FileSaver = function (blob, name, no_auto_bom) {
  12969. if (!no_auto_bom) {
  12970. blob = auto_bom(blob);
  12971. } // First try a.download, then web filesystem, then object URLs
  12972. var filesaver = this,
  12973. type = blob.type,
  12974. force = type === force_saveable_type,
  12975. object_url,
  12976. dispatch_all = function () {
  12977. dispatch(filesaver, "writestart progress write writeend".split(" "));
  12978. } // on any filesys errors revert to saving with object URLs
  12979. ,
  12980. fs_error = function () {
  12981. if ((is_chrome_ios || force && is_safari) && view.FileReader) {
  12982. // Safari doesn't allow downloading of blob urls
  12983. var reader = new FileReader();
  12984. reader.onloadend = function () {
  12985. var url = is_chrome_ios ? reader.result : reader.result.replace(/^data:[^;]*;/, 'data:attachment/file;');
  12986. var popup = view.open(url, '_blank');
  12987. if (!popup) view.location.href = url;
  12988. url = undefined; // release reference before dispatching
  12989. filesaver.readyState = filesaver.DONE;
  12990. dispatch_all();
  12991. };
  12992. reader.readAsDataURL(blob);
  12993. filesaver.readyState = filesaver.INIT;
  12994. return;
  12995. } // don't create more object URLs than needed
  12996. if (!object_url) {
  12997. object_url = get_URL().createObjectURL(blob);
  12998. }
  12999. if (force) {
  13000. view.location.href = object_url;
  13001. } else {
  13002. var opened = view.open(object_url, "_blank");
  13003. if (!opened) {
  13004. // Apple does not allow window.open, see https://developer.apple.com/library/safari/documentation/Tools/Conceptual/SafariExtensionGuide/WorkingwithWindowsandTabs/WorkingwithWindowsandTabs.html
  13005. view.location.href = object_url;
  13006. }
  13007. }
  13008. filesaver.readyState = filesaver.DONE;
  13009. dispatch_all();
  13010. revoke(object_url);
  13011. };
  13012. filesaver.readyState = filesaver.INIT;
  13013. if (can_use_save_link) {
  13014. object_url = get_URL().createObjectURL(blob);
  13015. setTimeout(function () {
  13016. save_link.href = object_url;
  13017. save_link.download = name;
  13018. click(save_link);
  13019. dispatch_all();
  13020. revoke(object_url);
  13021. filesaver.readyState = filesaver.DONE;
  13022. });
  13023. return;
  13024. }
  13025. fs_error();
  13026. },
  13027. FS_proto = FileSaver.prototype,
  13028. saveAs = function (blob, name, no_auto_bom) {
  13029. return new FileSaver(blob, name || blob.name || "download", no_auto_bom);
  13030. }; // IE 10+ (native saveAs)
  13031. if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) {
  13032. return function (blob, name, no_auto_bom) {
  13033. name = name || blob.name || "download";
  13034. if (!no_auto_bom) {
  13035. blob = auto_bom(blob);
  13036. }
  13037. return navigator.msSaveOrOpenBlob(blob, name);
  13038. };
  13039. }
  13040. FS_proto.abort = function () {};
  13041. FS_proto.readyState = FS_proto.INIT = 0;
  13042. FS_proto.WRITING = 1;
  13043. FS_proto.DONE = 2;
  13044. FS_proto.error = FS_proto.onwritestart = FS_proto.onprogress = FS_proto.onwrite = FS_proto.onabort = FS_proto.onerror = FS_proto.onwriteend = null;
  13045. return saveAs;
  13046. }(typeof self !== "undefined" && self || typeof window !== "undefined" && window || window.content); // `self` is undefined in Firefox for Android content script context
  13047. // while `this` is nsIContentFrameMessageManager
  13048. // with an attribute `content` that corresponds to the window
  13049. if (typeof module !== "undefined" && module.exports) {
  13050. module.exports.saveAs = saveAs;
  13051. } else if (typeof define !== "undefined" && define !== null && define.amd !== null) {
  13052. define("FileSaver.js", function () {
  13053. return saveAs;
  13054. });
  13055. }
  13056. // (c) Dean McNamee <dean@gmail.com>, 2013.
  13057. //
  13058. // https://github.com/deanm/omggif
  13059. //
  13060. //
  13061. //
  13062. // omggif is a JavaScript implementation of a GIF 89a encoder and decoder,
  13063. // including animation and compression. It does not rely on any specific
  13064. // underlying system, so should run in the browser, Node, or Plask.
  13065. function GifWriter(buf, width, height, gopts) {
  13066. var p = 0;
  13067. var gopts = gopts === undefined ? {} : gopts;
  13068. var loop_count = gopts.loop === undefined ? null : gopts.loop;
  13069. var global_palette = gopts.palette === undefined ? null : gopts.palette;
  13070. if (width <= 0 || height <= 0 || width > 65535 || height > 65535) throw "Width/Height invalid.";
  13071. function check_palette_and_num_colors(palette) {
  13072. var num_colors = palette.length;
  13073. if (num_colors < 2 || num_colors > 256 || num_colors & num_colors - 1) throw "Invalid code/color length, must be power of 2 and 2 .. 256.";
  13074. return num_colors;
  13075. } // - Header.
  13076. buf[p++] = 0x47;
  13077. buf[p++] = 0x49;
  13078. buf[p++] = 0x46; // GIF
  13079. buf[p++] = 0x38;
  13080. buf[p++] = 0x39;
  13081. buf[p++] = 0x61; // 89a
  13082. // Handling of Global Color Table (palette) and background index.
  13083. var gp_num_colors_pow2 = 0;
  13084. var background = 0;
  13085. if (global_palette !== null) {
  13086. var gp_num_colors = check_palette_and_num_colors(global_palette);
  13087. while (gp_num_colors >>= 1) ++gp_num_colors_pow2;
  13088. gp_num_colors = 1 << gp_num_colors_pow2;
  13089. --gp_num_colors_pow2;
  13090. if (gopts.background !== undefined) {
  13091. background = gopts.background;
  13092. if (background >= gp_num_colors) throw "Background index out of range."; // The GIF spec states that a background index of 0 should be ignored, so
  13093. // this is probably a mistake and you really want to set it to another
  13094. // slot in the palette. But actually in the end most browsers, etc end
  13095. // up ignoring this almost completely (including for dispose background).
  13096. if (background === 0) throw "Background index explicitly passed as 0.";
  13097. }
  13098. } // - Logical Screen Descriptor.
  13099. // NOTE(deanm): w/h apparently ignored by implementations, but set anyway.
  13100. buf[p++] = width & 0xff;
  13101. buf[p++] = width >> 8 & 0xff;
  13102. buf[p++] = height & 0xff;
  13103. buf[p++] = height >> 8 & 0xff; // NOTE: Indicates 0-bpp original color resolution (unused?).
  13104. buf[p++] = (global_palette !== null ? 0x80 : 0) | // Global Color Table Flag.
  13105. gp_num_colors_pow2; // NOTE: No sort flag (unused?).
  13106. buf[p++] = background; // Background Color Index.
  13107. buf[p++] = 0; // Pixel aspect ratio (unused?).
  13108. // - Global Color Table
  13109. if (global_palette !== null) {
  13110. for (var i = 0, il = global_palette.length; i < il; ++i) {
  13111. var rgb = global_palette[i];
  13112. buf[p++] = rgb >> 16 & 0xff;
  13113. buf[p++] = rgb >> 8 & 0xff;
  13114. buf[p++] = rgb & 0xff;
  13115. }
  13116. }
  13117. if (loop_count !== null) {
  13118. // Netscape block for looping.
  13119. if (loop_count < 0 || loop_count > 65535) throw "Loop count invalid."; // Extension code, label, and length.
  13120. buf[p++] = 0x21;
  13121. buf[p++] = 0xff;
  13122. buf[p++] = 0x0b; // NETSCAPE2.0
  13123. buf[p++] = 0x4e;
  13124. buf[p++] = 0x45;
  13125. buf[p++] = 0x54;
  13126. buf[p++] = 0x53;
  13127. buf[p++] = 0x43;
  13128. buf[p++] = 0x41;
  13129. buf[p++] = 0x50;
  13130. buf[p++] = 0x45;
  13131. buf[p++] = 0x32;
  13132. buf[p++] = 0x2e;
  13133. buf[p++] = 0x30; // Sub-block
  13134. buf[p++] = 0x03;
  13135. buf[p++] = 0x01;
  13136. buf[p++] = loop_count & 0xff;
  13137. buf[p++] = loop_count >> 8 & 0xff;
  13138. buf[p++] = 0x00; // Terminator.
  13139. }
  13140. var ended = false;
  13141. this.addFrame = function (x, y, w, h, indexed_pixels, opts) {
  13142. if (ended === true) {
  13143. --p;
  13144. ended = false;
  13145. } // Un-end.
  13146. opts = opts === undefined ? {} : opts; // TODO(deanm): Bounds check x, y. Do they need to be within the virtual
  13147. // canvas width/height, I imagine?
  13148. if (x < 0 || y < 0 || x > 65535 || y > 65535) throw "x/y invalid.";
  13149. if (w <= 0 || h <= 0 || w > 65535 || h > 65535) throw "Width/Height invalid.";
  13150. if (indexed_pixels.length < w * h) throw "Not enough pixels for the frame size.";
  13151. var using_local_palette = true;
  13152. var palette = opts.palette;
  13153. if (palette === undefined || palette === null) {
  13154. using_local_palette = false;
  13155. palette = global_palette;
  13156. }
  13157. if (palette === undefined || palette === null) throw "Must supply either a local or global palette.";
  13158. var num_colors = check_palette_and_num_colors(palette); // Compute the min_code_size (power of 2), destroying num_colors.
  13159. var min_code_size = 0;
  13160. while (num_colors >>= 1) ++min_code_size;
  13161. num_colors = 1 << min_code_size; // Now we can easily get it back.
  13162. var delay = opts.delay === undefined ? 0 : opts.delay; // From the spec:
  13163. // 0 - No disposal specified. The decoder is
  13164. // not required to take any action.
  13165. // 1 - Do not dispose. The graphic is to be left
  13166. // in place.
  13167. // 2 - Restore to background color. The area used by the
  13168. // graphic must be restored to the background color.
  13169. // 3 - Restore to previous. The decoder is required to
  13170. // restore the area overwritten by the graphic with
  13171. // what was there prior to rendering the graphic.
  13172. // 4-7 - To be defined.
  13173. // NOTE(deanm): Dispose background doesn't really work, apparently most
  13174. // browsers ignore the background palette index and clear to transparency.
  13175. var disposal = opts.disposal === undefined ? 0 : opts.disposal;
  13176. if (disposal < 0 || disposal > 3) // 4-7 is reserved.
  13177. throw "Disposal out of range.";
  13178. var use_transparency = false;
  13179. var transparent_index = 0;
  13180. if (opts.transparent !== undefined && opts.transparent !== null) {
  13181. use_transparency = true;
  13182. transparent_index = opts.transparent;
  13183. if (transparent_index < 0 || transparent_index >= num_colors) throw "Transparent color index.";
  13184. }
  13185. if (disposal !== 0 || use_transparency || delay !== 0) {
  13186. // - Graphics Control Extension
  13187. buf[p++] = 0x21;
  13188. buf[p++] = 0xf9; // Extension / Label.
  13189. buf[p++] = 4; // Byte size.
  13190. buf[p++] = disposal << 2 | (use_transparency === true ? 1 : 0);
  13191. buf[p++] = delay & 0xff;
  13192. buf[p++] = delay >> 8 & 0xff;
  13193. buf[p++] = transparent_index; // Transparent color index.
  13194. buf[p++] = 0; // Block Terminator.
  13195. } // - Image Descriptor
  13196. buf[p++] = 0x2c; // Image Seperator.
  13197. buf[p++] = x & 0xff;
  13198. buf[p++] = x >> 8 & 0xff; // Left.
  13199. buf[p++] = y & 0xff;
  13200. buf[p++] = y >> 8 & 0xff; // Top.
  13201. buf[p++] = w & 0xff;
  13202. buf[p++] = w >> 8 & 0xff;
  13203. buf[p++] = h & 0xff;
  13204. buf[p++] = h >> 8 & 0xff; // NOTE: No sort flag (unused?).
  13205. // TODO(deanm): Support interlace.
  13206. buf[p++] = using_local_palette === true ? 0x80 | min_code_size - 1 : 0; // - Local Color Table
  13207. if (using_local_palette === true) {
  13208. for (var i = 0, il = palette.length; i < il; ++i) {
  13209. var rgb = palette[i];
  13210. buf[p++] = rgb >> 16 & 0xff;
  13211. buf[p++] = rgb >> 8 & 0xff;
  13212. buf[p++] = rgb & 0xff;
  13213. }
  13214. }
  13215. p = GifWriterOutputLZWCodeStream(buf, p, min_code_size < 2 ? 2 : min_code_size, indexed_pixels);
  13216. };
  13217. this.end = function () {
  13218. if (ended === false) {
  13219. buf[p++] = 0x3b; // Trailer.
  13220. ended = true;
  13221. }
  13222. return p;
  13223. };
  13224. } // Main compression routine, palette indexes -> LZW code stream.
  13225. // |index_stream| must have at least one entry.
  13226. function GifWriterOutputLZWCodeStream(buf, p, min_code_size, index_stream) {
  13227. buf[p++] = min_code_size;
  13228. var cur_subblock = p++; // Pointing at the length field.
  13229. var clear_code = 1 << min_code_size;
  13230. var code_mask = clear_code - 1;
  13231. var eoi_code = clear_code + 1;
  13232. var next_code = eoi_code + 1;
  13233. var cur_code_size = min_code_size + 1; // Number of bits per code.
  13234. var cur_shift = 0; // We have at most 12-bit codes, so we should have to hold a max of 19
  13235. // bits here (and then we would write out).
  13236. var cur = 0;
  13237. function emit_bytes_to_buffer(bit_block_size) {
  13238. while (cur_shift >= bit_block_size) {
  13239. buf[p++] = cur & 0xff;
  13240. cur >>= 8;
  13241. cur_shift -= 8;
  13242. if (p === cur_subblock + 256) {
  13243. // Finished a subblock.
  13244. buf[cur_subblock] = 255;
  13245. cur_subblock = p++;
  13246. }
  13247. }
  13248. }
  13249. function emit_code(c) {
  13250. cur |= c << cur_shift;
  13251. cur_shift += cur_code_size;
  13252. emit_bytes_to_buffer(8);
  13253. } // I am not an expert on the topic, and I don't want to write a thesis.
  13254. // However, it is good to outline here the basic algorithm and the few data
  13255. // structures and optimizations here that make this implementation fast.
  13256. // The basic idea behind LZW is to build a table of previously seen runs
  13257. // addressed by a short id (herein called output code). All data is
  13258. // referenced by a code, which represents one or more values from the
  13259. // original input stream. All input bytes can be referenced as the same
  13260. // value as an output code. So if you didn't want any compression, you
  13261. // could more or less just output the original bytes as codes (there are
  13262. // some details to this, but it is the idea). In order to achieve
  13263. // compression, values greater then the input range (codes can be up to
  13264. // 12-bit while input only 8-bit) represent a sequence of previously seen
  13265. // inputs. The decompressor is able to build the same mapping while
  13266. // decoding, so there is always a shared common knowledge between the
  13267. // encoding and decoder, which is also important for "timing" aspects like
  13268. // how to handle variable bit width code encoding.
  13269. //
  13270. // One obvious but very important consequence of the table system is there
  13271. // is always a unique id (at most 12-bits) to map the runs. 'A' might be
  13272. // 4, then 'AA' might be 10, 'AAA' 11, 'AAAA' 12, etc. This relationship
  13273. // can be used for an effecient lookup strategy for the code mapping. We
  13274. // need to know if a run has been seen before, and be able to map that run
  13275. // to the output code. Since we start with known unique ids (input bytes),
  13276. // and then from those build more unique ids (table entries), we can
  13277. // continue this chain (almost like a linked list) to always have small
  13278. // integer values that represent the current byte chains in the encoder.
  13279. // This means instead of tracking the input bytes (AAAABCD) to know our
  13280. // current state, we can track the table entry for AAAABC (it is guaranteed
  13281. // to exist by the nature of the algorithm) and the next character D.
  13282. // Therefor the tuple of (table_entry, byte) is guaranteed to also be
  13283. // unique. This allows us to create a simple lookup key for mapping input
  13284. // sequences to codes (table indices) without having to store or search
  13285. // any of the code sequences. So if 'AAAA' has a table entry of 12, the
  13286. // tuple of ('AAAA', K) for any input byte K will be unique, and can be our
  13287. // key. This leads to a integer value at most 20-bits, which can always
  13288. // fit in an SMI value and be used as a fast sparse array / object key.
  13289. // Output code for the current contents of the index buffer.
  13290. var ib_code = index_stream[0] & code_mask; // Load first input index.
  13291. var code_table = {}; // Key'd on our 20-bit "tuple".
  13292. emit_code(clear_code); // Spec says first code should be a clear code.
  13293. // First index already loaded, process the rest of the stream.
  13294. for (var i = 1, il = index_stream.length; i < il; ++i) {
  13295. var k = index_stream[i] & code_mask;
  13296. var cur_key = ib_code << 8 | k; // (prev, k) unique tuple.
  13297. var cur_code = code_table[cur_key]; // buffer + k.
  13298. // Check if we have to create a new code table entry.
  13299. if (cur_code === undefined) {
  13300. // We don't have buffer + k.
  13301. // Emit index buffer (without k).
  13302. // This is an inline version of emit_code, because this is the core
  13303. // writing routine of the compressor (and V8 cannot inline emit_code
  13304. // because it is a closure here in a different context). Additionally
  13305. // we can call emit_byte_to_buffer less often, because we can have
  13306. // 30-bits (from our 31-bit signed SMI), and we know our codes will only
  13307. // be 12-bits, so can safely have 18-bits there without overflow.
  13308. // emit_code(ib_code);
  13309. cur |= ib_code << cur_shift;
  13310. cur_shift += cur_code_size;
  13311. while (cur_shift >= 8) {
  13312. buf[p++] = cur & 0xff;
  13313. cur >>= 8;
  13314. cur_shift -= 8;
  13315. if (p === cur_subblock + 256) {
  13316. // Finished a subblock.
  13317. buf[cur_subblock] = 255;
  13318. cur_subblock = p++;
  13319. }
  13320. }
  13321. if (next_code === 4096) {
  13322. // Table full, need a clear.
  13323. emit_code(clear_code);
  13324. next_code = eoi_code + 1;
  13325. cur_code_size = min_code_size + 1;
  13326. code_table = {};
  13327. } else {
  13328. // Table not full, insert a new entry.
  13329. // Increase our variable bit code sizes if necessary. This is a bit
  13330. // tricky as it is based on "timing" between the encoding and
  13331. // decoder. From the encoders perspective this should happen after
  13332. // we've already emitted the index buffer and are about to create the
  13333. // first table entry that would overflow our current code bit size.
  13334. if (next_code >= 1 << cur_code_size) ++cur_code_size;
  13335. code_table[cur_key] = next_code++; // Insert into code table.
  13336. }
  13337. ib_code = k; // Index buffer to single input k.
  13338. } else {
  13339. ib_code = cur_code; // Index buffer to sequence in code table.
  13340. }
  13341. }
  13342. emit_code(ib_code); // There will still be something in the index buffer.
  13343. emit_code(eoi_code); // End Of Information.
  13344. // Flush / finalize the sub-blocks stream to the buffer.
  13345. emit_bytes_to_buffer(1); // Finish the sub-blocks, writing out any unfinished lengths and
  13346. // terminating with a sub-block of length 0. If we have already started
  13347. // but not yet used a sub-block it can just become the terminator.
  13348. if (cur_subblock + 1 === p) {
  13349. // Started but unused.
  13350. buf[cur_subblock] = 0;
  13351. } else {
  13352. // Started and used, write length and additional terminator block.
  13353. buf[cur_subblock] = p - cur_subblock - 1;
  13354. buf[p++] = 0;
  13355. }
  13356. return p;
  13357. }
  13358. function GifReader(buf) {
  13359. var p = 0; // - Header (GIF87a or GIF89a).
  13360. if (buf[p++] !== 0x47 || buf[p++] !== 0x49 || buf[p++] !== 0x46 || buf[p++] !== 0x38 || (buf[p++] + 1 & 0xfd) !== 0x38 || buf[p++] !== 0x61) {
  13361. throw "Invalid GIF 87a/89a header.";
  13362. } // - Logical Screen Descriptor.
  13363. var width = buf[p++] | buf[p++] << 8;
  13364. var height = buf[p++] | buf[p++] << 8;
  13365. var pf0 = buf[p++]; // <Packed Fields>.
  13366. var global_palette_flag = pf0 >> 7;
  13367. var num_global_colors_pow2 = pf0 & 0x7;
  13368. var num_global_colors = 1 << num_global_colors_pow2 + 1;
  13369. var background = buf[p++];
  13370. buf[p++]; // Pixel aspect ratio (unused?).
  13371. var global_palette_offset = null;
  13372. if (global_palette_flag) {
  13373. global_palette_offset = p;
  13374. p += num_global_colors * 3; // Seek past palette.
  13375. }
  13376. var no_eof = true;
  13377. var frames = [];
  13378. var delay = 0;
  13379. var transparent_index = null;
  13380. var disposal = 0; // 0 - No disposal specified.
  13381. var loop_count = null;
  13382. this.width = width;
  13383. this.height = height;
  13384. while (no_eof && p < buf.length) {
  13385. switch (buf[p++]) {
  13386. case 0x21:
  13387. // Graphics Control Extension Block
  13388. switch (buf[p++]) {
  13389. case 0xff:
  13390. // Application specific block
  13391. // Try if it's a Netscape block (with animation loop counter).
  13392. if (buf[p] !== 0x0b || // 21 FF already read, check block size.
  13393. // NETSCAPE2.0
  13394. buf[p + 1] == 0x4e && buf[p + 2] == 0x45 && buf[p + 3] == 0x54 && buf[p + 4] == 0x53 && buf[p + 5] == 0x43 && buf[p + 6] == 0x41 && buf[p + 7] == 0x50 && buf[p + 8] == 0x45 && buf[p + 9] == 0x32 && buf[p + 10] == 0x2e && buf[p + 11] == 0x30 && // Sub-block
  13395. buf[p + 12] == 0x03 && buf[p + 13] == 0x01 && buf[p + 16] == 0) {
  13396. p += 14;
  13397. loop_count = buf[p++] | buf[p++] << 8;
  13398. p++; // Skip terminator.
  13399. } else {
  13400. // We don't know what it is, just try to get past it.
  13401. p += 12;
  13402. while (true) {
  13403. // Seek through subblocks.
  13404. var block_size = buf[p++];
  13405. if (block_size === 0) break;
  13406. p += block_size;
  13407. }
  13408. }
  13409. break;
  13410. case 0xf9:
  13411. // Graphics Control Extension
  13412. if (buf[p++] !== 0x4 || buf[p + 4] !== 0) throw "Invalid graphics extension block.";
  13413. var pf1 = buf[p++];
  13414. delay = buf[p++] | buf[p++] << 8;
  13415. transparent_index = buf[p++];
  13416. if ((pf1 & 1) === 0) transparent_index = null;
  13417. disposal = pf1 >> 2 & 0x7;
  13418. p++; // Skip terminator.
  13419. break;
  13420. case 0xfe:
  13421. // Comment Extension.
  13422. while (true) {
  13423. // Seek through subblocks.
  13424. var block_size = buf[p++];
  13425. if (block_size === 0) break; // console.log(buf.slice(p, p+block_size).toString('ascii'));
  13426. p += block_size;
  13427. }
  13428. break;
  13429. default:
  13430. throw "Unknown graphic control label: 0x" + buf[p - 1].toString(16);
  13431. }
  13432. break;
  13433. case 0x2c:
  13434. // Image Descriptor.
  13435. var x = buf[p++] | buf[p++] << 8;
  13436. var y = buf[p++] | buf[p++] << 8;
  13437. var w = buf[p++] | buf[p++] << 8;
  13438. var h = buf[p++] | buf[p++] << 8;
  13439. var pf2 = buf[p++];
  13440. var local_palette_flag = pf2 >> 7;
  13441. var interlace_flag = pf2 >> 6 & 1;
  13442. var num_local_colors_pow2 = pf2 & 0x7;
  13443. var num_local_colors = 1 << num_local_colors_pow2 + 1;
  13444. var palette_offset = global_palette_offset;
  13445. var has_local_palette = false;
  13446. if (local_palette_flag) {
  13447. var has_local_palette = true;
  13448. palette_offset = p; // Override with local palette.
  13449. p += num_local_colors * 3; // Seek past palette.
  13450. }
  13451. var data_offset = p;
  13452. p++; // codesize
  13453. while (true) {
  13454. var block_size = buf[p++];
  13455. if (block_size === 0) break;
  13456. p += block_size;
  13457. }
  13458. frames.push({
  13459. x: x,
  13460. y: y,
  13461. width: w,
  13462. height: h,
  13463. has_local_palette: has_local_palette,
  13464. palette_offset: palette_offset,
  13465. data_offset: data_offset,
  13466. data_length: p - data_offset,
  13467. transparent_index: transparent_index,
  13468. interlaced: !!interlace_flag,
  13469. delay: delay,
  13470. disposal: disposal
  13471. });
  13472. break;
  13473. case 0x3b:
  13474. // Trailer Marker (end of file).
  13475. no_eof = false;
  13476. break;
  13477. default:
  13478. throw "Unknown gif block: 0x" + buf[p - 1].toString(16);
  13479. break;
  13480. }
  13481. }
  13482. this.numFrames = function () {
  13483. return frames.length;
  13484. };
  13485. this.loopCount = function () {
  13486. return loop_count;
  13487. };
  13488. this.frameInfo = function (frame_num) {
  13489. if (frame_num < 0 || frame_num >= frames.length) throw "Frame index out of range.";
  13490. return frames[frame_num];
  13491. };
  13492. this.decodeAndBlitFrameBGRA = function (frame_num, pixels) {
  13493. var frame = this.frameInfo(frame_num);
  13494. var num_pixels = frame.width * frame.height;
  13495. var index_stream = new Uint8Array(num_pixels); // At most 8-bit indices.
  13496. GifReaderLZWOutputIndexStream(buf, frame.data_offset, index_stream, num_pixels);
  13497. var palette_offset = frame.palette_offset; // NOTE(deanm): It seems to be much faster to compare index to 256 than
  13498. // to === null. Not sure why, but CompareStub_EQ_STRICT shows up high in
  13499. // the profile, not sure if it's related to using a Uint8Array.
  13500. var trans = frame.transparent_index;
  13501. if (trans === null) trans = 256; // We are possibly just blitting to a portion of the entire frame.
  13502. // That is a subrect within the framerect, so the additional pixels
  13503. // must be skipped over after we finished a scanline.
  13504. var framewidth = frame.width;
  13505. var framestride = width - framewidth;
  13506. var xleft = framewidth; // Number of subrect pixels left in scanline.
  13507. // Output indicies of the top left and bottom right corners of the subrect.
  13508. var opbeg = (frame.y * width + frame.x) * 4;
  13509. var opend = ((frame.y + frame.height) * width + frame.x) * 4;
  13510. var op = opbeg;
  13511. var scanstride = framestride * 4; // Use scanstride to skip past the rows when interlacing. This is skipping
  13512. // 7 rows for the first two passes, then 3 then 1.
  13513. if (frame.interlaced === true) {
  13514. scanstride += (framewidth + framestride) * 4 * 7; // Pass 1.
  13515. }
  13516. var interlaceskip = 8; // Tracking the row interval in the current pass.
  13517. for (var i = 0, il = index_stream.length; i < il; ++i) {
  13518. var index = index_stream[i];
  13519. if (xleft === 0) {
  13520. // Beginning of new scan line
  13521. op += scanstride;
  13522. xleft = framewidth;
  13523. if (op >= opend) {
  13524. // Catch the wrap to switch passes when interlacing.
  13525. scanstride = framestride + (framewidth + framestride) * 4 * (interlaceskip - 1); // interlaceskip / 2 * 4 is interlaceskip << 1.
  13526. op = opbeg + (framewidth + framestride) * (interlaceskip << 1);
  13527. interlaceskip >>= 1;
  13528. }
  13529. }
  13530. if (index === trans) {
  13531. op += 4;
  13532. } else {
  13533. var r = buf[palette_offset + index * 3];
  13534. var g = buf[palette_offset + index * 3 + 1];
  13535. var b = buf[palette_offset + index * 3 + 2];
  13536. pixels[op++] = b;
  13537. pixels[op++] = g;
  13538. pixels[op++] = r;
  13539. pixels[op++] = 255;
  13540. }
  13541. --xleft;
  13542. }
  13543. }; // I will go to copy and paste hell one day...
  13544. this.decodeAndBlitFrameRGBA = function (frame_num, pixels) {
  13545. var frame = this.frameInfo(frame_num);
  13546. var num_pixels = frame.width * frame.height;
  13547. var index_stream = new Uint8Array(num_pixels); // At most 8-bit indices.
  13548. GifReaderLZWOutputIndexStream(buf, frame.data_offset, index_stream, num_pixels);
  13549. var palette_offset = frame.palette_offset; // NOTE(deanm): It seems to be much faster to compare index to 256 than
  13550. // to === null. Not sure why, but CompareStub_EQ_STRICT shows up high in
  13551. // the profile, not sure if it's related to using a Uint8Array.
  13552. var trans = frame.transparent_index;
  13553. if (trans === null) trans = 256; // We are possibly just blitting to a portion of the entire frame.
  13554. // That is a subrect within the framerect, so the additional pixels
  13555. // must be skipped over after we finished a scanline.
  13556. var framewidth = frame.width;
  13557. var framestride = width - framewidth;
  13558. var xleft = framewidth; // Number of subrect pixels left in scanline.
  13559. // Output indicies of the top left and bottom right corners of the subrect.
  13560. var opbeg = (frame.y * width + frame.x) * 4;
  13561. var opend = ((frame.y + frame.height) * width + frame.x) * 4;
  13562. var op = opbeg;
  13563. var scanstride = framestride * 4; // Use scanstride to skip past the rows when interlacing. This is skipping
  13564. // 7 rows for the first two passes, then 3 then 1.
  13565. if (frame.interlaced === true) {
  13566. scanstride += (framewidth + framestride) * 4 * 7; // Pass 1.
  13567. }
  13568. var interlaceskip = 8; // Tracking the row interval in the current pass.
  13569. for (var i = 0, il = index_stream.length; i < il; ++i) {
  13570. var index = index_stream[i];
  13571. if (xleft === 0) {
  13572. // Beginning of new scan line
  13573. op += scanstride;
  13574. xleft = framewidth;
  13575. if (op >= opend) {
  13576. // Catch the wrap to switch passes when interlacing.
  13577. scanstride = framestride + (framewidth + framestride) * 4 * (interlaceskip - 1); // interlaceskip / 2 * 4 is interlaceskip << 1.
  13578. op = opbeg + (framewidth + framestride) * (interlaceskip << 1);
  13579. interlaceskip >>= 1;
  13580. }
  13581. }
  13582. if (index === trans) {
  13583. op += 4;
  13584. } else {
  13585. var r = buf[palette_offset + index * 3];
  13586. var g = buf[palette_offset + index * 3 + 1];
  13587. var b = buf[palette_offset + index * 3 + 2];
  13588. pixels[op++] = r;
  13589. pixels[op++] = g;
  13590. pixels[op++] = b;
  13591. pixels[op++] = 255;
  13592. }
  13593. --xleft;
  13594. }
  13595. };
  13596. }
  13597. function GifReaderLZWOutputIndexStream(code_stream, p, output, output_length) {
  13598. var min_code_size = code_stream[p++];
  13599. var clear_code = 1 << min_code_size;
  13600. var eoi_code = clear_code + 1;
  13601. var next_code = eoi_code + 1;
  13602. var cur_code_size = min_code_size + 1; // Number of bits per code.
  13603. // NOTE: This shares the same name as the encoder, but has a different
  13604. // meaning here. Here this masks each code coming from the code stream.
  13605. var code_mask = (1 << cur_code_size) - 1;
  13606. var cur_shift = 0;
  13607. var cur = 0;
  13608. var op = 0; // Output pointer.
  13609. var subblock_size = code_stream[p++]; // TODO(deanm): Would using a TypedArray be any faster? At least it would
  13610. // solve the fast mode / backing store uncertainty.
  13611. // var code_table = Array(4096);
  13612. var code_table = new Int32Array(4096); // Can be signed, we only use 20 bits.
  13613. var prev_code = null; // Track code-1.
  13614. while (true) {
  13615. // Read up to two bytes, making sure we always 12-bits for max sized code.
  13616. while (cur_shift < 16) {
  13617. if (subblock_size === 0) break; // No more data to be read.
  13618. cur |= code_stream[p++] << cur_shift;
  13619. cur_shift += 8;
  13620. if (subblock_size === 1) {
  13621. // Never let it get to 0 to hold logic above.
  13622. subblock_size = code_stream[p++]; // Next subblock.
  13623. } else {
  13624. --subblock_size;
  13625. }
  13626. } // TODO(deanm): We should never really get here, we should have received
  13627. // and EOI.
  13628. if (cur_shift < cur_code_size) break;
  13629. var code = cur & code_mask;
  13630. cur >>= cur_code_size;
  13631. cur_shift -= cur_code_size; // TODO(deanm): Maybe should check that the first code was a clear code,
  13632. // at least this is what you're supposed to do. But actually our encoder
  13633. // now doesn't emit a clear code first anyway.
  13634. if (code === clear_code) {
  13635. // We don't actually have to clear the table. This could be a good idea
  13636. // for greater error checking, but we don't really do any anyway. We
  13637. // will just track it with next_code and overwrite old entries.
  13638. next_code = eoi_code + 1;
  13639. cur_code_size = min_code_size + 1;
  13640. code_mask = (1 << cur_code_size) - 1; // Don't update prev_code ?
  13641. prev_code = null;
  13642. continue;
  13643. } else if (code === eoi_code) {
  13644. break;
  13645. } // We have a similar situation as the decoder, where we want to store
  13646. // variable length entries (code table entries), but we want to do in a
  13647. // faster manner than an array of arrays. The code below stores sort of a
  13648. // linked list within the code table, and then "chases" through it to
  13649. // construct the dictionary entries. When a new entry is created, just the
  13650. // last byte is stored, and the rest (prefix) of the entry is only
  13651. // referenced by its table entry. Then the code chases through the
  13652. // prefixes until it reaches a single byte code. We have to chase twice,
  13653. // first to compute the length, and then to actually copy the data to the
  13654. // output (backwards, since we know the length). The alternative would be
  13655. // storing something in an intermediate stack, but that doesn't make any
  13656. // more sense. I implemented an approach where it also stored the length
  13657. // in the code table, although it's a bit tricky because you run out of
  13658. // bits (12 + 12 + 8), but I didn't measure much improvements (the table
  13659. // entries are generally not the long). Even when I created benchmarks for
  13660. // very long table entries the complexity did not seem worth it.
  13661. // The code table stores the prefix entry in 12 bits and then the suffix
  13662. // byte in 8 bits, so each entry is 20 bits.
  13663. var chase_code = code < next_code ? code : prev_code; // Chase what we will output, either {CODE} or {CODE-1}.
  13664. var chase_length = 0;
  13665. var chase = chase_code;
  13666. while (chase > clear_code) {
  13667. chase = code_table[chase] >> 8;
  13668. ++chase_length;
  13669. }
  13670. var k = chase;
  13671. var op_end = op + chase_length + (chase_code !== code ? 1 : 0);
  13672. if (op_end > output_length) {
  13673. console.log("Warning, gif stream longer than expected.");
  13674. return;
  13675. } // Already have the first byte from the chase, might as well write it fast.
  13676. output[op++] = k;
  13677. op += chase_length;
  13678. var b = op; // Track pointer, writing backwards.
  13679. if (chase_code !== code) // The case of emitting {CODE-1} + k.
  13680. output[op++] = k;
  13681. chase = chase_code;
  13682. while (chase_length--) {
  13683. chase = code_table[chase];
  13684. output[--b] = chase & 0xff; // Write backwards.
  13685. chase >>= 8; // Pull down to the prefix code.
  13686. }
  13687. if (prev_code !== null && next_code < 4096) {
  13688. code_table[next_code++] = prev_code << 8 | k; // TODO(deanm): Figure out this clearing vs code growth logic better. I
  13689. // have an feeling that it should just happen somewhere else, for now it
  13690. // is awkward between when we grow past the max and then hit a clear code.
  13691. // For now just check if we hit the max 12-bits (then a clear code should
  13692. // follow, also of course encoded in 12-bits).
  13693. if (next_code >= code_mask + 1 && cur_code_size < 12) {
  13694. ++cur_code_size;
  13695. code_mask = code_mask << 1 | 1;
  13696. }
  13697. }
  13698. prev_code = code;
  13699. }
  13700. if (op !== output_length) {
  13701. console.log("Warning, gif stream shorter than expected.");
  13702. }
  13703. return output;
  13704. }
  13705. try {
  13706. exports.GifWriter = GifWriter;
  13707. exports.GifReader = GifReader;
  13708. } catch (e) {} // CommonJS.
  13709. /*
  13710. * Copyright (c) 2012 chick307 <chick307@gmail.com>
  13711. *
  13712. * Licensed under the MIT License.
  13713. * http://opensource.org/licenses/mit-license
  13714. */
  13715. (function (jsPDF, callback) {
  13716. jsPDF.API.adler32cs = callback();
  13717. })(jsPDF, function () {
  13718. var _hasArrayBuffer = typeof ArrayBuffer === "function" && typeof Uint8Array === "function";
  13719. var _Buffer = null,
  13720. _isBuffer = function () {
  13721. if (!_hasArrayBuffer) return function _isBuffer() {
  13722. return false;
  13723. };
  13724. return function _isBuffer(value) {
  13725. return value instanceof ArrayBuffer || _Buffer !== null && value instanceof _Buffer;
  13726. };
  13727. }();
  13728. var _utf8ToBinary = function () {
  13729. if (_Buffer !== null) {
  13730. return function _utf8ToBinary(utf8String) {
  13731. return new _Buffer(utf8String, "utf8").toString("binary");
  13732. };
  13733. } else {
  13734. return function _utf8ToBinary(utf8String) {
  13735. return unescape(encodeURIComponent(utf8String));
  13736. };
  13737. }
  13738. }();
  13739. var MOD = 65521;
  13740. var _update = function _update(checksum, binaryString) {
  13741. var a = checksum & 0xffff,
  13742. b = checksum >>> 16;
  13743. for (var i = 0, length = binaryString.length; i < length; i++) {
  13744. a = (a + (binaryString.charCodeAt(i) & 0xff)) % MOD;
  13745. b = (b + a) % MOD;
  13746. }
  13747. return (b << 16 | a) >>> 0;
  13748. };
  13749. var _updateUint8Array = function _updateUint8Array(checksum, uint8Array) {
  13750. var a = checksum & 0xffff,
  13751. b = checksum >>> 16;
  13752. for (var i = 0, length = uint8Array.length; i < length; i++) {
  13753. a = (a + uint8Array[i]) % MOD;
  13754. b = (b + a) % MOD;
  13755. }
  13756. return (b << 16 | a) >>> 0;
  13757. };
  13758. var exports = {};
  13759. var Adler32 = exports.Adler32 = function () {
  13760. var ctor = function Adler32(checksum) {
  13761. if (!(this instanceof ctor)) {
  13762. throw new TypeError("Constructor cannot called be as a function.");
  13763. }
  13764. if (!isFinite(checksum = checksum == null ? 1 : +checksum)) {
  13765. throw new Error("First arguments needs to be a finite number.");
  13766. }
  13767. this.checksum = checksum >>> 0;
  13768. };
  13769. var proto = ctor.prototype = {};
  13770. proto.constructor = ctor;
  13771. ctor.from = function (from) {
  13772. from.prototype = proto;
  13773. return from;
  13774. }(function from(binaryString) {
  13775. if (!(this instanceof ctor)) {
  13776. throw new TypeError("Constructor cannot called be as a function.");
  13777. }
  13778. if (binaryString == null) throw new Error("First argument needs to be a string.");
  13779. this.checksum = _update(1, binaryString.toString());
  13780. });
  13781. ctor.fromUtf8 = function (fromUtf8) {
  13782. fromUtf8.prototype = proto;
  13783. return fromUtf8;
  13784. }(function fromUtf8(utf8String) {
  13785. if (!(this instanceof ctor)) {
  13786. throw new TypeError("Constructor cannot called be as a function.");
  13787. }
  13788. if (utf8String == null) throw new Error("First argument needs to be a string.");
  13789. var binaryString = _utf8ToBinary(utf8String.toString());
  13790. this.checksum = _update(1, binaryString);
  13791. });
  13792. if (_hasArrayBuffer) {
  13793. ctor.fromBuffer = function (fromBuffer) {
  13794. fromBuffer.prototype = proto;
  13795. return fromBuffer;
  13796. }(function fromBuffer(buffer) {
  13797. if (!(this instanceof ctor)) {
  13798. throw new TypeError("Constructor cannot called be as a function.");
  13799. }
  13800. if (!_isBuffer(buffer)) throw new Error("First argument needs to be ArrayBuffer.");
  13801. var array = new Uint8Array(buffer);
  13802. return this.checksum = _updateUint8Array(1, array);
  13803. });
  13804. }
  13805. proto.update = function update(binaryString) {
  13806. if (binaryString == null) throw new Error("First argument needs to be a string.");
  13807. binaryString = binaryString.toString();
  13808. return this.checksum = _update(this.checksum, binaryString);
  13809. };
  13810. proto.updateUtf8 = function updateUtf8(utf8String) {
  13811. if (utf8String == null) throw new Error("First argument needs to be a string.");
  13812. var binaryString = _utf8ToBinary(utf8String.toString());
  13813. return this.checksum = _update(this.checksum, binaryString);
  13814. };
  13815. if (_hasArrayBuffer) {
  13816. proto.updateBuffer = function updateBuffer(buffer) {
  13817. if (!_isBuffer(buffer)) throw new Error("First argument needs to be ArrayBuffer.");
  13818. var array = new Uint8Array(buffer);
  13819. return this.checksum = _updateUint8Array(this.checksum, array);
  13820. };
  13821. }
  13822. proto.clone = function clone() {
  13823. return new Adler32(this.checksum);
  13824. };
  13825. return ctor;
  13826. }();
  13827. exports.from = function from(binaryString) {
  13828. if (binaryString == null) throw new Error("First argument needs to be a string.");
  13829. return _update(1, binaryString.toString());
  13830. };
  13831. exports.fromUtf8 = function fromUtf8(utf8String) {
  13832. if (utf8String == null) throw new Error("First argument needs to be a string.");
  13833. var binaryString = _utf8ToBinary(utf8String.toString());
  13834. return _update(1, binaryString);
  13835. };
  13836. if (_hasArrayBuffer) {
  13837. exports.fromBuffer = function fromBuffer(buffer) {
  13838. if (!_isBuffer(buffer)) throw new Error("First argument need to be ArrayBuffer.");
  13839. var array = new Uint8Array(buffer);
  13840. return _updateUint8Array(1, array);
  13841. };
  13842. }
  13843. return exports;
  13844. });
  13845. /*
  13846. Copyright (c) 2008, Adobe Systems Incorporated
  13847. All rights reserved.
  13848. Redistribution and use in source and binary forms, with or without
  13849. modification, are permitted provided that the following conditions are
  13850. met:
  13851. * Redistributions of source code must retain the above copyright notice,
  13852. this list of conditions and the following disclaimer.
  13853. * Redistributions in binary form must reproduce the above copyright
  13854. notice, this list of conditions and the following disclaimer in the
  13855. documentation and/or other materials provided with the distribution.
  13856. * Neither the name of Adobe Systems Incorporated nor the names of its
  13857. contributors may be used to endorse or promote products derived from
  13858. this software without specific prior written permission.
  13859. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  13860. IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  13861. THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  13862. PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  13863. CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  13864. EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  13865. PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  13866. PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  13867. LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  13868. NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  13869. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  13870. */
  13871. /*
  13872. JPEG encoder ported to JavaScript and optimized by Andreas Ritter, www.bytestrom.eu, 11/2009
  13873. Basic GUI blocking jpeg encoder
  13874. */
  13875. function JPEGEncoder(quality) {
  13876. var ffloor = Math.floor;
  13877. var YTable = new Array(64);
  13878. var UVTable = new Array(64);
  13879. var fdtbl_Y = new Array(64);
  13880. var fdtbl_UV = new Array(64);
  13881. var YDC_HT;
  13882. var UVDC_HT;
  13883. var YAC_HT;
  13884. var UVAC_HT;
  13885. var bitcode = new Array(65535);
  13886. var category = new Array(65535);
  13887. var outputfDCTQuant = new Array(64);
  13888. var DU = new Array(64);
  13889. var byteout = [];
  13890. var bytenew = 0;
  13891. var bytepos = 7;
  13892. var YDU = new Array(64);
  13893. var UDU = new Array(64);
  13894. var VDU = new Array(64);
  13895. var clt = new Array(256);
  13896. var RGB_YUV_TABLE = new Array(2048);
  13897. var currentQuality;
  13898. var ZigZag = [0, 1, 5, 6, 14, 15, 27, 28, 2, 4, 7, 13, 16, 26, 29, 42, 3, 8, 12, 17, 25, 30, 41, 43, 9, 11, 18, 24, 31, 40, 44, 53, 10, 19, 23, 32, 39, 45, 52, 54, 20, 22, 33, 38, 46, 51, 55, 60, 21, 34, 37, 47, 50, 56, 59, 61, 35, 36, 48, 49, 57, 58, 62, 63];
  13899. var std_dc_luminance_nrcodes = [0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0];
  13900. var std_dc_luminance_values = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
  13901. var std_ac_luminance_nrcodes = [0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d];
  13902. var std_ac_luminance_values = [0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa];
  13903. var std_dc_chrominance_nrcodes = [0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0];
  13904. var std_dc_chrominance_values = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
  13905. var std_ac_chrominance_nrcodes = [0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77];
  13906. var std_ac_chrominance_values = [0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa];
  13907. function initQuantTables(sf) {
  13908. var YQT = [16, 11, 10, 16, 24, 40, 51, 61, 12, 12, 14, 19, 26, 58, 60, 55, 14, 13, 16, 24, 40, 57, 69, 56, 14, 17, 22, 29, 51, 87, 80, 62, 18, 22, 37, 56, 68, 109, 103, 77, 24, 35, 55, 64, 81, 104, 113, 92, 49, 64, 78, 87, 103, 121, 120, 101, 72, 92, 95, 98, 112, 100, 103, 99];
  13909. for (var i = 0; i < 64; i++) {
  13910. var t = ffloor((YQT[i] * sf + 50) / 100);
  13911. if (t < 1) {
  13912. t = 1;
  13913. } else if (t > 255) {
  13914. t = 255;
  13915. }
  13916. YTable[ZigZag[i]] = t;
  13917. }
  13918. var UVQT = [17, 18, 24, 47, 99, 99, 99, 99, 18, 21, 26, 66, 99, 99, 99, 99, 24, 26, 56, 99, 99, 99, 99, 99, 47, 66, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99];
  13919. for (var j = 0; j < 64; j++) {
  13920. var u = ffloor((UVQT[j] * sf + 50) / 100);
  13921. if (u < 1) {
  13922. u = 1;
  13923. } else if (u > 255) {
  13924. u = 255;
  13925. }
  13926. UVTable[ZigZag[j]] = u;
  13927. }
  13928. var aasf = [1.0, 1.387039845, 1.306562965, 1.175875602, 1.0, 0.785694958, 0.5411961, 0.275899379];
  13929. var k = 0;
  13930. for (var row = 0; row < 8; row++) {
  13931. for (var col = 0; col < 8; col++) {
  13932. fdtbl_Y[k] = 1.0 / (YTable[ZigZag[k]] * aasf[row] * aasf[col] * 8.0);
  13933. fdtbl_UV[k] = 1.0 / (UVTable[ZigZag[k]] * aasf[row] * aasf[col] * 8.0);
  13934. k++;
  13935. }
  13936. }
  13937. }
  13938. function computeHuffmanTbl(nrcodes, std_table) {
  13939. var codevalue = 0;
  13940. var pos_in_table = 0;
  13941. var HT = new Array();
  13942. for (var k = 1; k <= 16; k++) {
  13943. for (var j = 1; j <= nrcodes[k]; j++) {
  13944. HT[std_table[pos_in_table]] = [];
  13945. HT[std_table[pos_in_table]][0] = codevalue;
  13946. HT[std_table[pos_in_table]][1] = k;
  13947. pos_in_table++;
  13948. codevalue++;
  13949. }
  13950. codevalue *= 2;
  13951. }
  13952. return HT;
  13953. }
  13954. function initHuffmanTbl() {
  13955. YDC_HT = computeHuffmanTbl(std_dc_luminance_nrcodes, std_dc_luminance_values);
  13956. UVDC_HT = computeHuffmanTbl(std_dc_chrominance_nrcodes, std_dc_chrominance_values);
  13957. YAC_HT = computeHuffmanTbl(std_ac_luminance_nrcodes, std_ac_luminance_values);
  13958. UVAC_HT = computeHuffmanTbl(std_ac_chrominance_nrcodes, std_ac_chrominance_values);
  13959. }
  13960. function initCategoryNumber() {
  13961. var nrlower = 1;
  13962. var nrupper = 2;
  13963. for (var cat = 1; cat <= 15; cat++) {
  13964. //Positive numbers
  13965. for (var nr = nrlower; nr < nrupper; nr++) {
  13966. category[32767 + nr] = cat;
  13967. bitcode[32767 + nr] = [];
  13968. bitcode[32767 + nr][1] = cat;
  13969. bitcode[32767 + nr][0] = nr;
  13970. } //Negative numbers
  13971. for (var nrneg = -(nrupper - 1); nrneg <= -nrlower; nrneg++) {
  13972. category[32767 + nrneg] = cat;
  13973. bitcode[32767 + nrneg] = [];
  13974. bitcode[32767 + nrneg][1] = cat;
  13975. bitcode[32767 + nrneg][0] = nrupper - 1 + nrneg;
  13976. }
  13977. nrlower <<= 1;
  13978. nrupper <<= 1;
  13979. }
  13980. }
  13981. function initRGBYUVTable() {
  13982. for (var i = 0; i < 256; i++) {
  13983. RGB_YUV_TABLE[i] = 19595 * i;
  13984. RGB_YUV_TABLE[i + 256 >> 0] = 38470 * i;
  13985. RGB_YUV_TABLE[i + 512 >> 0] = 7471 * i + 0x8000;
  13986. RGB_YUV_TABLE[i + 768 >> 0] = -11059 * i;
  13987. RGB_YUV_TABLE[i + 1024 >> 0] = -21709 * i;
  13988. RGB_YUV_TABLE[i + 1280 >> 0] = 32768 * i + 0x807fff;
  13989. RGB_YUV_TABLE[i + 1536 >> 0] = -27439 * i;
  13990. RGB_YUV_TABLE[i + 1792 >> 0] = -5329 * i;
  13991. }
  13992. } // IO functions
  13993. function writeBits(bs) {
  13994. var value = bs[0];
  13995. var posval = bs[1] - 1;
  13996. while (posval >= 0) {
  13997. if (value & 1 << posval) {
  13998. bytenew |= 1 << bytepos;
  13999. }
  14000. posval--;
  14001. bytepos--;
  14002. if (bytepos < 0) {
  14003. if (bytenew == 0xff) {
  14004. writeByte(0xff);
  14005. writeByte(0);
  14006. } else {
  14007. writeByte(bytenew);
  14008. }
  14009. bytepos = 7;
  14010. bytenew = 0;
  14011. }
  14012. }
  14013. }
  14014. function writeByte(value) {
  14015. //byteout.push(clt[value]); // write char directly instead of converting later
  14016. byteout.push(value);
  14017. }
  14018. function writeWord(value) {
  14019. writeByte(value >> 8 & 0xff);
  14020. writeByte(value & 0xff);
  14021. } // DCT & quantization core
  14022. function fDCTQuant(data, fdtbl) {
  14023. var d0, d1, d2, d3, d4, d5, d6, d7;
  14024. /* Pass 1: process rows. */
  14025. var dataOff = 0;
  14026. var i;
  14027. var I8 = 8;
  14028. var I64 = 64;
  14029. for (i = 0; i < I8; ++i) {
  14030. d0 = data[dataOff];
  14031. d1 = data[dataOff + 1];
  14032. d2 = data[dataOff + 2];
  14033. d3 = data[dataOff + 3];
  14034. d4 = data[dataOff + 4];
  14035. d5 = data[dataOff + 5];
  14036. d6 = data[dataOff + 6];
  14037. d7 = data[dataOff + 7];
  14038. var tmp0 = d0 + d7;
  14039. var tmp7 = d0 - d7;
  14040. var tmp1 = d1 + d6;
  14041. var tmp6 = d1 - d6;
  14042. var tmp2 = d2 + d5;
  14043. var tmp5 = d2 - d5;
  14044. var tmp3 = d3 + d4;
  14045. var tmp4 = d3 - d4;
  14046. /* Even part */
  14047. var tmp10 = tmp0 + tmp3;
  14048. /* phase 2 */
  14049. var tmp13 = tmp0 - tmp3;
  14050. var tmp11 = tmp1 + tmp2;
  14051. var tmp12 = tmp1 - tmp2;
  14052. data[dataOff] = tmp10 + tmp11;
  14053. /* phase 3 */
  14054. data[dataOff + 4] = tmp10 - tmp11;
  14055. var z1 = (tmp12 + tmp13) * 0.707106781;
  14056. /* c4 */
  14057. data[dataOff + 2] = tmp13 + z1;
  14058. /* phase 5 */
  14059. data[dataOff + 6] = tmp13 - z1;
  14060. /* Odd part */
  14061. tmp10 = tmp4 + tmp5;
  14062. /* phase 2 */
  14063. tmp11 = tmp5 + tmp6;
  14064. tmp12 = tmp6 + tmp7;
  14065. /* The rotator is modified from fig 4-8 to avoid extra negations. */
  14066. var z5 = (tmp10 - tmp12) * 0.382683433;
  14067. /* c6 */
  14068. var z2 = 0.5411961 * tmp10 + z5;
  14069. /* c2-c6 */
  14070. var z4 = 1.306562965 * tmp12 + z5;
  14071. /* c2+c6 */
  14072. var z3 = tmp11 * 0.707106781;
  14073. /* c4 */
  14074. var z11 = tmp7 + z3;
  14075. /* phase 5 */
  14076. var z13 = tmp7 - z3;
  14077. data[dataOff + 5] = z13 + z2;
  14078. /* phase 6 */
  14079. data[dataOff + 3] = z13 - z2;
  14080. data[dataOff + 1] = z11 + z4;
  14081. data[dataOff + 7] = z11 - z4;
  14082. dataOff += 8;
  14083. /* advance pointer to next row */
  14084. }
  14085. /* Pass 2: process columns. */
  14086. dataOff = 0;
  14087. for (i = 0; i < I8; ++i) {
  14088. d0 = data[dataOff];
  14089. d1 = data[dataOff + 8];
  14090. d2 = data[dataOff + 16];
  14091. d3 = data[dataOff + 24];
  14092. d4 = data[dataOff + 32];
  14093. d5 = data[dataOff + 40];
  14094. d6 = data[dataOff + 48];
  14095. d7 = data[dataOff + 56];
  14096. var tmp0p2 = d0 + d7;
  14097. var tmp7p2 = d0 - d7;
  14098. var tmp1p2 = d1 + d6;
  14099. var tmp6p2 = d1 - d6;
  14100. var tmp2p2 = d2 + d5;
  14101. var tmp5p2 = d2 - d5;
  14102. var tmp3p2 = d3 + d4;
  14103. var tmp4p2 = d3 - d4;
  14104. /* Even part */
  14105. var tmp10p2 = tmp0p2 + tmp3p2;
  14106. /* phase 2 */
  14107. var tmp13p2 = tmp0p2 - tmp3p2;
  14108. var tmp11p2 = tmp1p2 + tmp2p2;
  14109. var tmp12p2 = tmp1p2 - tmp2p2;
  14110. data[dataOff] = tmp10p2 + tmp11p2;
  14111. /* phase 3 */
  14112. data[dataOff + 32] = tmp10p2 - tmp11p2;
  14113. var z1p2 = (tmp12p2 + tmp13p2) * 0.707106781;
  14114. /* c4 */
  14115. data[dataOff + 16] = tmp13p2 + z1p2;
  14116. /* phase 5 */
  14117. data[dataOff + 48] = tmp13p2 - z1p2;
  14118. /* Odd part */
  14119. tmp10p2 = tmp4p2 + tmp5p2;
  14120. /* phase 2 */
  14121. tmp11p2 = tmp5p2 + tmp6p2;
  14122. tmp12p2 = tmp6p2 + tmp7p2;
  14123. /* The rotator is modified from fig 4-8 to avoid extra negations. */
  14124. var z5p2 = (tmp10p2 - tmp12p2) * 0.382683433;
  14125. /* c6 */
  14126. var z2p2 = 0.5411961 * tmp10p2 + z5p2;
  14127. /* c2-c6 */
  14128. var z4p2 = 1.306562965 * tmp12p2 + z5p2;
  14129. /* c2+c6 */
  14130. var z3p2 = tmp11p2 * 0.707106781;
  14131. /* c4 */
  14132. var z11p2 = tmp7p2 + z3p2;
  14133. /* phase 5 */
  14134. var z13p2 = tmp7p2 - z3p2;
  14135. data[dataOff + 40] = z13p2 + z2p2;
  14136. /* phase 6 */
  14137. data[dataOff + 24] = z13p2 - z2p2;
  14138. data[dataOff + 8] = z11p2 + z4p2;
  14139. data[dataOff + 56] = z11p2 - z4p2;
  14140. dataOff++;
  14141. /* advance pointer to next column */
  14142. } // Quantize/descale the coefficients
  14143. var fDCTQuant;
  14144. for (i = 0; i < I64; ++i) {
  14145. // Apply the quantization and scaling factor & Round to nearest integer
  14146. fDCTQuant = data[i] * fdtbl[i];
  14147. outputfDCTQuant[i] = fDCTQuant > 0.0 ? fDCTQuant + 0.5 | 0 : fDCTQuant - 0.5 | 0; //outputfDCTQuant[i] = fround(fDCTQuant);
  14148. }
  14149. return outputfDCTQuant;
  14150. }
  14151. function writeAPP0() {
  14152. writeWord(0xffe0); // marker
  14153. writeWord(16); // length
  14154. writeByte(0x4a); // J
  14155. writeByte(0x46); // F
  14156. writeByte(0x49); // I
  14157. writeByte(0x46); // F
  14158. writeByte(0); // = "JFIF",'\0'
  14159. writeByte(1); // versionhi
  14160. writeByte(1); // versionlo
  14161. writeByte(0); // xyunits
  14162. writeWord(1); // xdensity
  14163. writeWord(1); // ydensity
  14164. writeByte(0); // thumbnwidth
  14165. writeByte(0); // thumbnheight
  14166. }
  14167. function writeSOF0(width, height) {
  14168. writeWord(0xffc0); // marker
  14169. writeWord(17); // length, truecolor YUV JPG
  14170. writeByte(8); // precision
  14171. writeWord(height);
  14172. writeWord(width);
  14173. writeByte(3); // nrofcomponents
  14174. writeByte(1); // IdY
  14175. writeByte(0x11); // HVY
  14176. writeByte(0); // QTY
  14177. writeByte(2); // IdU
  14178. writeByte(0x11); // HVU
  14179. writeByte(1); // QTU
  14180. writeByte(3); // IdV
  14181. writeByte(0x11); // HVV
  14182. writeByte(1); // QTV
  14183. }
  14184. function writeDQT() {
  14185. writeWord(0xffdb); // marker
  14186. writeWord(132); // length
  14187. writeByte(0);
  14188. for (var i = 0; i < 64; i++) {
  14189. writeByte(YTable[i]);
  14190. }
  14191. writeByte(1);
  14192. for (var j = 0; j < 64; j++) {
  14193. writeByte(UVTable[j]);
  14194. }
  14195. }
  14196. function writeDHT() {
  14197. writeWord(0xffc4); // marker
  14198. writeWord(0x01a2); // length
  14199. writeByte(0); // HTYDCinfo
  14200. for (var i = 0; i < 16; i++) {
  14201. writeByte(std_dc_luminance_nrcodes[i + 1]);
  14202. }
  14203. for (var j = 0; j <= 11; j++) {
  14204. writeByte(std_dc_luminance_values[j]);
  14205. }
  14206. writeByte(0x10); // HTYACinfo
  14207. for (var k = 0; k < 16; k++) {
  14208. writeByte(std_ac_luminance_nrcodes[k + 1]);
  14209. }
  14210. for (var l = 0; l <= 161; l++) {
  14211. writeByte(std_ac_luminance_values[l]);
  14212. }
  14213. writeByte(1); // HTUDCinfo
  14214. for (var m = 0; m < 16; m++) {
  14215. writeByte(std_dc_chrominance_nrcodes[m + 1]);
  14216. }
  14217. for (var n = 0; n <= 11; n++) {
  14218. writeByte(std_dc_chrominance_values[n]);
  14219. }
  14220. writeByte(0x11); // HTUACinfo
  14221. for (var o = 0; o < 16; o++) {
  14222. writeByte(std_ac_chrominance_nrcodes[o + 1]);
  14223. }
  14224. for (var p = 0; p <= 161; p++) {
  14225. writeByte(std_ac_chrominance_values[p]);
  14226. }
  14227. }
  14228. function writeSOS() {
  14229. writeWord(0xffda); // marker
  14230. writeWord(12); // length
  14231. writeByte(3); // nrofcomponents
  14232. writeByte(1); // IdY
  14233. writeByte(0); // HTY
  14234. writeByte(2); // IdU
  14235. writeByte(0x11); // HTU
  14236. writeByte(3); // IdV
  14237. writeByte(0x11); // HTV
  14238. writeByte(0); // Ss
  14239. writeByte(0x3f); // Se
  14240. writeByte(0); // Bf
  14241. }
  14242. function processDU(CDU, fdtbl, DC, HTDC, HTAC) {
  14243. var EOB = HTAC[0x00];
  14244. var M16zeroes = HTAC[0xf0];
  14245. var pos;
  14246. var I16 = 16;
  14247. var I63 = 63;
  14248. var I64 = 64;
  14249. var DU_DCT = fDCTQuant(CDU, fdtbl); //ZigZag reorder
  14250. for (var j = 0; j < I64; ++j) {
  14251. DU[ZigZag[j]] = DU_DCT[j];
  14252. }
  14253. var Diff = DU[0] - DC;
  14254. DC = DU[0]; //Encode DC
  14255. if (Diff == 0) {
  14256. writeBits(HTDC[0]); // Diff might be 0
  14257. } else {
  14258. pos = 32767 + Diff;
  14259. writeBits(HTDC[category[pos]]);
  14260. writeBits(bitcode[pos]);
  14261. } //Encode ACs
  14262. var end0pos = 63; // was const... which is crazy
  14263. for (; end0pos > 0 && DU[end0pos] == 0; end0pos--) {} //end0pos = first element in reverse order !=0
  14264. if (end0pos == 0) {
  14265. writeBits(EOB);
  14266. return DC;
  14267. }
  14268. var i = 1;
  14269. var lng;
  14270. while (i <= end0pos) {
  14271. var startpos = i;
  14272. for (; DU[i] == 0 && i <= end0pos; ++i) {}
  14273. var nrzeroes = i - startpos;
  14274. if (nrzeroes >= I16) {
  14275. lng = nrzeroes >> 4;
  14276. for (var nrmarker = 1; nrmarker <= lng; ++nrmarker) writeBits(M16zeroes);
  14277. nrzeroes = nrzeroes & 0xf;
  14278. }
  14279. pos = 32767 + DU[i];
  14280. writeBits(HTAC[(nrzeroes << 4) + category[pos]]);
  14281. writeBits(bitcode[pos]);
  14282. i++;
  14283. }
  14284. if (end0pos != I63) {
  14285. writeBits(EOB);
  14286. }
  14287. return DC;
  14288. }
  14289. function initCharLookupTable() {
  14290. var sfcc = String.fromCharCode;
  14291. for (var i = 0; i < 256; i++) {
  14292. ///// ACHTUNG // 255
  14293. clt[i] = sfcc(i);
  14294. }
  14295. }
  14296. this.encode = function (image, quality // image data object
  14297. ) {
  14298. var time_start = new Date().getTime();
  14299. if (quality) setQuality(quality); // Initialize bit writer
  14300. byteout = new Array();
  14301. bytenew = 0;
  14302. bytepos = 7; // Add JPEG headers
  14303. writeWord(0xffd8); // SOI
  14304. writeAPP0();
  14305. writeDQT();
  14306. writeSOF0(image.width, image.height);
  14307. writeDHT();
  14308. writeSOS(); // Encode 8x8 macroblocks
  14309. var DCY = 0;
  14310. var DCU = 0;
  14311. var DCV = 0;
  14312. bytenew = 0;
  14313. bytepos = 7;
  14314. this.encode.displayName = "_encode_";
  14315. var imageData = image.data;
  14316. var width = image.width;
  14317. var height = image.height;
  14318. var quadWidth = width * 4;
  14319. var x,
  14320. y = 0;
  14321. var r, g, b;
  14322. var start, p, col, row, pos;
  14323. while (y < height) {
  14324. x = 0;
  14325. while (x < quadWidth) {
  14326. start = quadWidth * y + x;
  14327. p = start;
  14328. col = -1;
  14329. row = 0;
  14330. for (pos = 0; pos < 64; pos++) {
  14331. row = pos >> 3; // /8
  14332. col = (pos & 7) * 4; // %8
  14333. p = start + row * quadWidth + col;
  14334. if (y + row >= height) {
  14335. // padding bottom
  14336. p -= quadWidth * (y + 1 + row - height);
  14337. }
  14338. if (x + col >= quadWidth) {
  14339. // padding right
  14340. p -= x + col - quadWidth + 4;
  14341. }
  14342. r = imageData[p++];
  14343. g = imageData[p++];
  14344. b = imageData[p++];
  14345. /* // calculate YUV values dynamically
  14346. YDU[pos]=((( 0.29900)*r+( 0.58700)*g+( 0.11400)*b))-128; //-0x80
  14347. UDU[pos]=(((-0.16874)*r+(-0.33126)*g+( 0.50000)*b));
  14348. VDU[pos]=((( 0.50000)*r+(-0.41869)*g+(-0.08131)*b));
  14349. */
  14350. // use lookup table (slightly faster)
  14351. YDU[pos] = (RGB_YUV_TABLE[r] + RGB_YUV_TABLE[g + 256 >> 0] + RGB_YUV_TABLE[b + 512 >> 0] >> 16) - 128;
  14352. UDU[pos] = (RGB_YUV_TABLE[r + 768 >> 0] + RGB_YUV_TABLE[g + 1024 >> 0] + RGB_YUV_TABLE[b + 1280 >> 0] >> 16) - 128;
  14353. VDU[pos] = (RGB_YUV_TABLE[r + 1280 >> 0] + RGB_YUV_TABLE[g + 1536 >> 0] + RGB_YUV_TABLE[b + 1792 >> 0] >> 16) - 128;
  14354. }
  14355. DCY = processDU(YDU, fdtbl_Y, DCY, YDC_HT, YAC_HT);
  14356. DCU = processDU(UDU, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
  14357. DCV = processDU(VDU, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
  14358. x += 32;
  14359. }
  14360. y += 8;
  14361. } ////////////////////////////////////////////////////////////////
  14362. // Do the bit alignment of the EOI marker
  14363. if (bytepos >= 0) {
  14364. var fillbits = [];
  14365. fillbits[1] = bytepos + 1;
  14366. fillbits[0] = (1 << bytepos + 1) - 1;
  14367. writeBits(fillbits);
  14368. }
  14369. writeWord(0xffd9); //EOI
  14370. return new Uint8Array(byteout); //return new Buffer(byteout);
  14371. var jpegDataUri = "data:image/jpeg;base64," + btoa(byteout.join(""));
  14372. byteout = []; // benchmarking
  14373. var duration = new Date().getTime() - time_start; //console.log('Encoding time: '+ duration + 'ms');
  14374. //
  14375. return jpegDataUri;
  14376. };
  14377. function setQuality(quality) {
  14378. if (quality <= 0) {
  14379. quality = 1;
  14380. }
  14381. if (quality > 100) {
  14382. quality = 100;
  14383. }
  14384. if (currentQuality == quality) return; // don't recalc if unchanged
  14385. var sf = 0;
  14386. if (quality < 50) {
  14387. sf = Math.floor(5000 / quality);
  14388. } else {
  14389. sf = Math.floor(200 - quality * 2);
  14390. }
  14391. initQuantTables(sf);
  14392. currentQuality = quality; //console.log('Quality set to: '+quality +'%');
  14393. }
  14394. function init() {
  14395. var time_start = new Date().getTime();
  14396. if (!quality) quality = 50; // Create tables
  14397. initCharLookupTable();
  14398. initHuffmanTbl();
  14399. initCategoryNumber();
  14400. initRGBYUVTable();
  14401. setQuality(quality);
  14402. var duration = new Date().getTime() - time_start; //console.log('Initialization '+ duration + 'ms');
  14403. }
  14404. init();
  14405. }
  14406. try {
  14407. module.exports = JPEGEncoder;
  14408. } catch (e) {} // CommonJS.
  14409. /**
  14410. * @author shaozilee
  14411. *
  14412. * Bmp format decoder,support 1bit 4bit 8bit 24bit bmp
  14413. *
  14414. */
  14415. function BmpDecoder(buffer, is_with_alpha) {
  14416. this.pos = 0;
  14417. this.buffer = buffer;
  14418. this.datav = new DataView(buffer.buffer);
  14419. this.is_with_alpha = !!is_with_alpha;
  14420. this.bottom_up = true;
  14421. this.flag = String.fromCharCode(this.buffer[0]) + String.fromCharCode(this.buffer[1]);
  14422. this.pos += 2;
  14423. if (["BM", "BA", "CI", "CP", "IC", "PT"].indexOf(this.flag) === -1) throw new Error("Invalid BMP File");
  14424. this.parseHeader();
  14425. this.parseBGR();
  14426. }
  14427. BmpDecoder.prototype.parseHeader = function () {
  14428. this.fileSize = this.datav.getUint32(this.pos, true);
  14429. this.pos += 4;
  14430. this.reserved = this.datav.getUint32(this.pos, true);
  14431. this.pos += 4;
  14432. this.offset = this.datav.getUint32(this.pos, true);
  14433. this.pos += 4;
  14434. this.headerSize = this.datav.getUint32(this.pos, true);
  14435. this.pos += 4;
  14436. this.width = this.datav.getUint32(this.pos, true);
  14437. this.pos += 4;
  14438. this.height = this.datav.getInt32(this.pos, true);
  14439. this.pos += 4;
  14440. this.planes = this.datav.getUint16(this.pos, true);
  14441. this.pos += 2;
  14442. this.bitPP = this.datav.getUint16(this.pos, true);
  14443. this.pos += 2;
  14444. this.compress = this.datav.getUint32(this.pos, true);
  14445. this.pos += 4;
  14446. this.rawSize = this.datav.getUint32(this.pos, true);
  14447. this.pos += 4;
  14448. this.hr = this.datav.getUint32(this.pos, true);
  14449. this.pos += 4;
  14450. this.vr = this.datav.getUint32(this.pos, true);
  14451. this.pos += 4;
  14452. this.colors = this.datav.getUint32(this.pos, true);
  14453. this.pos += 4;
  14454. this.importantColors = this.datav.getUint32(this.pos, true);
  14455. this.pos += 4;
  14456. if (this.bitPP === 16 && this.is_with_alpha) {
  14457. this.bitPP = 15;
  14458. }
  14459. if (this.bitPP < 15) {
  14460. var len = this.colors === 0 ? 1 << this.bitPP : this.colors;
  14461. this.palette = new Array(len);
  14462. for (var i = 0; i < len; i++) {
  14463. var blue = this.datav.getUint8(this.pos++, true);
  14464. var green = this.datav.getUint8(this.pos++, true);
  14465. var red = this.datav.getUint8(this.pos++, true);
  14466. var quad = this.datav.getUint8(this.pos++, true);
  14467. this.palette[i] = {
  14468. red: red,
  14469. green: green,
  14470. blue: blue,
  14471. quad: quad
  14472. };
  14473. }
  14474. }
  14475. if (this.height < 0) {
  14476. this.height *= -1;
  14477. this.bottom_up = false;
  14478. }
  14479. };
  14480. BmpDecoder.prototype.parseBGR = function () {
  14481. this.pos = this.offset;
  14482. try {
  14483. var bitn = "bit" + this.bitPP;
  14484. var len = this.width * this.height * 4;
  14485. this.data = new Uint8Array(len);
  14486. this[bitn]();
  14487. } catch (e) {
  14488. console.log("bit decode error:" + e);
  14489. }
  14490. };
  14491. BmpDecoder.prototype.bit1 = function () {
  14492. var xlen = Math.ceil(this.width / 8);
  14493. var mode = xlen % 4;
  14494. var y = this.height >= 0 ? this.height - 1 : -this.height;
  14495. for (var y = this.height - 1; y >= 0; y--) {
  14496. var line = this.bottom_up ? y : this.height - 1 - y;
  14497. for (var x = 0; x < xlen; x++) {
  14498. var b = this.datav.getUint8(this.pos++, true);
  14499. var location = line * this.width * 4 + x * 8 * 4;
  14500. for (var i = 0; i < 8; i++) {
  14501. if (x * 8 + i < this.width) {
  14502. var rgb = this.palette[b >> 7 - i & 0x1];
  14503. this.data[location + i * 4] = rgb.blue;
  14504. this.data[location + i * 4 + 1] = rgb.green;
  14505. this.data[location + i * 4 + 2] = rgb.red;
  14506. this.data[location + i * 4 + 3] = 0xff;
  14507. } else {
  14508. break;
  14509. }
  14510. }
  14511. }
  14512. if (mode != 0) {
  14513. this.pos += 4 - mode;
  14514. }
  14515. }
  14516. };
  14517. BmpDecoder.prototype.bit4 = function () {
  14518. var xlen = Math.ceil(this.width / 2);
  14519. var mode = xlen % 4;
  14520. for (var y = this.height - 1; y >= 0; y--) {
  14521. var line = this.bottom_up ? y : this.height - 1 - y;
  14522. for (var x = 0; x < xlen; x++) {
  14523. var b = this.datav.getUint8(this.pos++, true);
  14524. var location = line * this.width * 4 + x * 2 * 4;
  14525. var before = b >> 4;
  14526. var after = b & 0x0f;
  14527. var rgb = this.palette[before];
  14528. this.data[location] = rgb.blue;
  14529. this.data[location + 1] = rgb.green;
  14530. this.data[location + 2] = rgb.red;
  14531. this.data[location + 3] = 0xff;
  14532. if (x * 2 + 1 >= this.width) break;
  14533. rgb = this.palette[after];
  14534. this.data[location + 4] = rgb.blue;
  14535. this.data[location + 4 + 1] = rgb.green;
  14536. this.data[location + 4 + 2] = rgb.red;
  14537. this.data[location + 4 + 3] = 0xff;
  14538. }
  14539. if (mode != 0) {
  14540. this.pos += 4 - mode;
  14541. }
  14542. }
  14543. };
  14544. BmpDecoder.prototype.bit8 = function () {
  14545. var mode = this.width % 4;
  14546. for (var y = this.height - 1; y >= 0; y--) {
  14547. var line = this.bottom_up ? y : this.height - 1 - y;
  14548. for (var x = 0; x < this.width; x++) {
  14549. var b = this.datav.getUint8(this.pos++, true);
  14550. var location = line * this.width * 4 + x * 4;
  14551. if (b < this.palette.length) {
  14552. var rgb = this.palette[b];
  14553. this.data[location] = rgb.red;
  14554. this.data[location + 1] = rgb.green;
  14555. this.data[location + 2] = rgb.blue;
  14556. this.data[location + 3] = 0xff;
  14557. } else {
  14558. this.data[location] = 0xff;
  14559. this.data[location + 1] = 0xff;
  14560. this.data[location + 2] = 0xff;
  14561. this.data[location + 3] = 0xff;
  14562. }
  14563. }
  14564. if (mode != 0) {
  14565. this.pos += 4 - mode;
  14566. }
  14567. }
  14568. };
  14569. BmpDecoder.prototype.bit15 = function () {
  14570. var dif_w = this.width % 3;
  14571. var _11111 = parseInt("11111", 2),
  14572. _1_5 = _11111;
  14573. for (var y = this.height - 1; y >= 0; y--) {
  14574. var line = this.bottom_up ? y : this.height - 1 - y;
  14575. for (var x = 0; x < this.width; x++) {
  14576. var B = this.datav.getUint16(this.pos, true);
  14577. this.pos += 2;
  14578. var blue = (B & _1_5) / _1_5 * 255 | 0;
  14579. var green = (B >> 5 & _1_5) / _1_5 * 255 | 0;
  14580. var red = (B >> 10 & _1_5) / _1_5 * 255 | 0;
  14581. var alpha = B >> 15 ? 0xff : 0x00;
  14582. var location = line * this.width * 4 + x * 4;
  14583. this.data[location] = red;
  14584. this.data[location + 1] = green;
  14585. this.data[location + 2] = blue;
  14586. this.data[location + 3] = alpha;
  14587. } //skip extra bytes
  14588. this.pos += dif_w;
  14589. }
  14590. };
  14591. BmpDecoder.prototype.bit16 = function () {
  14592. var dif_w = this.width % 3;
  14593. var _11111 = parseInt("11111", 2),
  14594. _1_5 = _11111;
  14595. var _111111 = parseInt("111111", 2),
  14596. _1_6 = _111111;
  14597. for (var y = this.height - 1; y >= 0; y--) {
  14598. var line = this.bottom_up ? y : this.height - 1 - y;
  14599. for (var x = 0; x < this.width; x++) {
  14600. var B = this.datav.getUint16(this.pos, true);
  14601. this.pos += 2;
  14602. var alpha = 0xff;
  14603. var blue = (B & _1_5) / _1_5 * 255 | 0;
  14604. var green = (B >> 5 & _1_6) / _1_6 * 255 | 0;
  14605. var red = (B >> 11) / _1_5 * 255 | 0;
  14606. var location = line * this.width * 4 + x * 4;
  14607. this.data[location] = red;
  14608. this.data[location + 1] = green;
  14609. this.data[location + 2] = blue;
  14610. this.data[location + 3] = alpha;
  14611. } //skip extra bytes
  14612. this.pos += dif_w;
  14613. }
  14614. };
  14615. BmpDecoder.prototype.bit24 = function () {
  14616. //when height > 0
  14617. for (var y = this.height - 1; y >= 0; y--) {
  14618. var line = this.bottom_up ? y : this.height - 1 - y;
  14619. for (var x = 0; x < this.width; x++) {
  14620. var blue = this.datav.getUint8(this.pos++, true);
  14621. var green = this.datav.getUint8(this.pos++, true);
  14622. var red = this.datav.getUint8(this.pos++, true);
  14623. var location = line * this.width * 4 + x * 4;
  14624. this.data[location] = red;
  14625. this.data[location + 1] = green;
  14626. this.data[location + 2] = blue;
  14627. this.data[location + 3] = 0xff;
  14628. } //skip extra bytes
  14629. this.pos += this.width % 4;
  14630. }
  14631. };
  14632. /**
  14633. * add 32bit decode func
  14634. * @author soubok
  14635. */
  14636. BmpDecoder.prototype.bit32 = function () {
  14637. //when height > 0
  14638. for (var y = this.height - 1; y >= 0; y--) {
  14639. var line = this.bottom_up ? y : this.height - 1 - y;
  14640. for (var x = 0; x < this.width; x++) {
  14641. var blue = this.datav.getUint8(this.pos++, true);
  14642. var green = this.datav.getUint8(this.pos++, true);
  14643. var red = this.datav.getUint8(this.pos++, true);
  14644. var alpha = this.datav.getUint8(this.pos++, true);
  14645. var location = line * this.width * 4 + x * 4;
  14646. this.data[location] = red;
  14647. this.data[location + 1] = green;
  14648. this.data[location + 2] = blue;
  14649. this.data[location + 3] = alpha;
  14650. } //skip extra bytes
  14651. //this.pos += (this.width % 4);
  14652. }
  14653. };
  14654. BmpDecoder.prototype.getData = function () {
  14655. return this.data;
  14656. };
  14657. try {
  14658. module.exports = function (bmpData) {
  14659. var decoder = new BmpDecoder(bmpData);
  14660. return {
  14661. data: decoder.getData(),
  14662. width: decoder.width,
  14663. height: decoder.height
  14664. };
  14665. };
  14666. } catch (e) {} // CommonJS.
  14667. /*
  14668. Copyright (c) 2013 Gildas Lormeau. All rights reserved.
  14669. Redistribution and use in source and binary forms, with or without
  14670. modification, are permitted provided that the following conditions are met:
  14671. 1. Redistributions of source code must retain the above copyright notice,
  14672. this list of conditions and the following disclaimer.
  14673. 2. Redistributions in binary form must reproduce the above copyright
  14674. notice, this list of conditions and the following disclaimer in
  14675. the documentation and/or other materials provided with the distribution.
  14676. 3. The names of the authors may not be used to endorse or promote products
  14677. derived from this software without specific prior written permission.
  14678. THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
  14679. INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  14680. FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
  14681. INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
  14682. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  14683. LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
  14684. OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  14685. LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  14686. NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  14687. EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  14688. */
  14689. /*
  14690. * This program is based on JZlib 1.0.2 ymnk, JCraft,Inc.
  14691. * JZlib is based on zlib-1.1.3, so all credit should go authors
  14692. * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
  14693. * and contributors of zlib.
  14694. */
  14695. (function (global) {
  14696. var MAX_BITS = 15;
  14697. var D_CODES = 30;
  14698. var BL_CODES = 19;
  14699. var LENGTH_CODES = 29;
  14700. var LITERALS = 256;
  14701. var L_CODES = LITERALS + 1 + LENGTH_CODES;
  14702. var HEAP_SIZE = 2 * L_CODES + 1;
  14703. var END_BLOCK = 256; // Bit length codes must not exceed MAX_BL_BITS bits
  14704. var MAX_BL_BITS = 7; // repeat previous bit length 3-6 times (2 bits of repeat count)
  14705. var REP_3_6 = 16; // repeat a zero length 3-10 times (3 bits of repeat count)
  14706. var REPZ_3_10 = 17; // repeat a zero length 11-138 times (7 bits of repeat count)
  14707. var REPZ_11_138 = 18; // The lengths of the bit length codes are sent in order of decreasing
  14708. // probability, to avoid transmitting the lengths for unused bit
  14709. // length codes.
  14710. var Buf_size = 8 * 2; // JZlib version : "1.0.2"
  14711. var Z_DEFAULT_COMPRESSION = -1; // compression strategy
  14712. var Z_FILTERED = 1;
  14713. var Z_HUFFMAN_ONLY = 2;
  14714. var Z_DEFAULT_STRATEGY = 0;
  14715. var Z_NO_FLUSH = 0;
  14716. var Z_PARTIAL_FLUSH = 1;
  14717. var Z_FULL_FLUSH = 3;
  14718. var Z_FINISH = 4;
  14719. var Z_OK = 0;
  14720. var Z_STREAM_END = 1;
  14721. var Z_NEED_DICT = 2;
  14722. var Z_STREAM_ERROR = -2;
  14723. var Z_DATA_ERROR = -3;
  14724. var Z_BUF_ERROR = -5; // Tree
  14725. // see definition of array dist_code below
  14726. var _dist_code = [0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, 18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29];
  14727. function Tree() {
  14728. var that = this; // dyn_tree; // the dynamic tree
  14729. // max_code; // largest code with non zero frequency
  14730. // stat_desc; // the corresponding static tree
  14731. // Compute the optimal bit lengths for a tree and update the total bit
  14732. // length
  14733. // for the current block.
  14734. // IN assertion: the fields freq and dad are set, heap[heap_max] and
  14735. // above are the tree nodes sorted by increasing frequency.
  14736. // OUT assertions: the field len is set to the optimal bit length, the
  14737. // array bl_count contains the frequencies for each bit length.
  14738. // The length opt_len is updated; static_len is also updated if stree is
  14739. // not null.
  14740. function gen_bitlen(s) {
  14741. var tree = that.dyn_tree;
  14742. var stree = that.stat_desc.static_tree;
  14743. var extra = that.stat_desc.extra_bits;
  14744. var base = that.stat_desc.extra_base;
  14745. var max_length = that.stat_desc.max_length;
  14746. var h; // heap index
  14747. var n, m; // iterate over the tree elements
  14748. var bits; // bit length
  14749. var xbits; // extra bits
  14750. var f; // frequency
  14751. var overflow = 0; // number of elements with bit length too large
  14752. for (bits = 0; bits <= MAX_BITS; bits++) s.bl_count[bits] = 0; // In a first pass, compute the optimal bit lengths (which may
  14753. // overflow in the case of the bit length tree).
  14754. tree[s.heap[s.heap_max] * 2 + 1] = 0; // root of the heap
  14755. for (h = s.heap_max + 1; h < HEAP_SIZE; h++) {
  14756. n = s.heap[h];
  14757. bits = tree[tree[n * 2 + 1] * 2 + 1] + 1;
  14758. if (bits > max_length) {
  14759. bits = max_length;
  14760. overflow++;
  14761. }
  14762. tree[n * 2 + 1] = bits; // We overwrite tree[n*2+1] which is no longer needed
  14763. if (n > that.max_code) continue; // not a leaf node
  14764. s.bl_count[bits]++;
  14765. xbits = 0;
  14766. if (n >= base) xbits = extra[n - base];
  14767. f = tree[n * 2];
  14768. s.opt_len += f * (bits + xbits);
  14769. if (stree) s.static_len += f * (stree[n * 2 + 1] + xbits);
  14770. }
  14771. if (overflow === 0) return; // This happens for example on obj2 and pic of the Calgary corpus
  14772. // Find the first bit length which could increase:
  14773. do {
  14774. bits = max_length - 1;
  14775. while (s.bl_count[bits] === 0) bits--;
  14776. s.bl_count[bits]--; // move one leaf down the tree
  14777. s.bl_count[bits + 1] += 2; // move one overflow item as its brother
  14778. s.bl_count[max_length]--; // The brother of the overflow item also moves one step up,
  14779. // but this does not affect bl_count[max_length]
  14780. overflow -= 2;
  14781. } while (overflow > 0);
  14782. for (bits = max_length; bits !== 0; bits--) {
  14783. n = s.bl_count[bits];
  14784. while (n !== 0) {
  14785. m = s.heap[--h];
  14786. if (m > that.max_code) continue;
  14787. if (tree[m * 2 + 1] != bits) {
  14788. s.opt_len += (bits - tree[m * 2 + 1]) * tree[m * 2];
  14789. tree[m * 2 + 1] = bits;
  14790. }
  14791. n--;
  14792. }
  14793. }
  14794. } // Reverse the first len bits of a code, using straightforward code (a
  14795. // faster
  14796. // method would use a table)
  14797. // IN assertion: 1 <= len <= 15
  14798. function bi_reverse(code, // the value to invert
  14799. len // its bit length
  14800. ) {
  14801. var res = 0;
  14802. do {
  14803. res |= code & 1;
  14804. code >>>= 1;
  14805. res <<= 1;
  14806. } while (--len > 0);
  14807. return res >>> 1;
  14808. } // Generate the codes for a given tree and bit counts (which need not be
  14809. // optimal).
  14810. // IN assertion: the array bl_count contains the bit length statistics for
  14811. // the given tree and the field len is set for all tree elements.
  14812. // OUT assertion: the field code is set for all tree elements of non
  14813. // zero code length.
  14814. function gen_codes(tree, // the tree to decorate
  14815. max_code, // largest code with non zero frequency
  14816. bl_count // number of codes at each bit length
  14817. ) {
  14818. var next_code = []; // next code value for each
  14819. // bit length
  14820. var code = 0; // running code value
  14821. var bits; // bit index
  14822. var n; // code index
  14823. var len; // The distribution counts are first used to generate the code values
  14824. // without bit reversal.
  14825. for (bits = 1; bits <= MAX_BITS; bits++) {
  14826. next_code[bits] = code = code + bl_count[bits - 1] << 1;
  14827. } // Check that the bit counts in bl_count are consistent. The last code
  14828. // must be all ones.
  14829. // Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
  14830. // "inconsistent bit counts");
  14831. // Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
  14832. for (n = 0; n <= max_code; n++) {
  14833. len = tree[n * 2 + 1];
  14834. if (len === 0) continue; // Now reverse the bits
  14835. tree[n * 2] = bi_reverse(next_code[len]++, len);
  14836. }
  14837. } // Construct one Huffman tree and assigns the code bit strings and lengths.
  14838. // Update the total bit length for the current block.
  14839. // IN assertion: the field freq is set for all tree elements.
  14840. // OUT assertions: the fields len and code are set to the optimal bit length
  14841. // and corresponding code. The length opt_len is updated; static_len is
  14842. // also updated if stree is not null. The field max_code is set.
  14843. that.build_tree = function (s) {
  14844. var tree = that.dyn_tree;
  14845. var stree = that.stat_desc.static_tree;
  14846. var elems = that.stat_desc.elems;
  14847. var n, m; // iterate over heap elements
  14848. var max_code = -1; // largest code with non zero frequency
  14849. var node; // new node being created
  14850. // Construct the initial heap, with least frequent element in
  14851. // heap[1]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
  14852. // heap[0] is not used.
  14853. s.heap_len = 0;
  14854. s.heap_max = HEAP_SIZE;
  14855. for (n = 0; n < elems; n++) {
  14856. if (tree[n * 2] !== 0) {
  14857. s.heap[++s.heap_len] = max_code = n;
  14858. s.depth[n] = 0;
  14859. } else {
  14860. tree[n * 2 + 1] = 0;
  14861. }
  14862. } // The pkzip format requires that at least one distance code exists,
  14863. // and that at least one bit should be sent even if there is only one
  14864. // possible code. So to avoid special checks later on we force at least
  14865. // two codes of non zero frequency.
  14866. while (s.heap_len < 2) {
  14867. node = s.heap[++s.heap_len] = max_code < 2 ? ++max_code : 0;
  14868. tree[node * 2] = 1;
  14869. s.depth[node] = 0;
  14870. s.opt_len--;
  14871. if (stree) s.static_len -= stree[node * 2 + 1]; // node is 0 or 1 so it does not have extra bits
  14872. }
  14873. that.max_code = max_code; // The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
  14874. // establish sub-heaps of increasing lengths:
  14875. for (n = Math.floor(s.heap_len / 2); n >= 1; n--) s.pqdownheap(tree, n); // Construct the Huffman tree by repeatedly combining the least two
  14876. // frequent nodes.
  14877. node = elems; // next internal node of the tree
  14878. do {
  14879. // n = node of least frequency
  14880. n = s.heap[1];
  14881. s.heap[1] = s.heap[s.heap_len--];
  14882. s.pqdownheap(tree, 1);
  14883. m = s.heap[1]; // m = node of next least frequency
  14884. s.heap[--s.heap_max] = n; // keep the nodes sorted by frequency
  14885. s.heap[--s.heap_max] = m; // Create a new node father of n and m
  14886. tree[node * 2] = tree[n * 2] + tree[m * 2];
  14887. s.depth[node] = Math.max(s.depth[n], s.depth[m]) + 1;
  14888. tree[n * 2 + 1] = tree[m * 2 + 1] = node; // and insert the new node in the heap
  14889. s.heap[1] = node++;
  14890. s.pqdownheap(tree, 1);
  14891. } while (s.heap_len >= 2);
  14892. s.heap[--s.heap_max] = s.heap[1]; // At this point, the fields freq and dad are set. We can now
  14893. // generate the bit lengths.
  14894. gen_bitlen(s); // The field len is now set, we can generate the bit codes
  14895. gen_codes(tree, that.max_code, s.bl_count);
  14896. };
  14897. }
  14898. Tree._length_code = [0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28];
  14899. Tree.base_length = [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 0];
  14900. Tree.base_dist = [0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576]; // Mapping from a distance to a distance code. dist is the distance - 1 and
  14901. // must not have side effects. _dist_code[256] and _dist_code[257] are never
  14902. // used.
  14903. Tree.d_code = function (dist) {
  14904. return dist < 256 ? _dist_code[dist] : _dist_code[256 + (dist >>> 7)];
  14905. }; // extra bits for each length code
  14906. Tree.extra_lbits = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0]; // extra bits for each distance code
  14907. Tree.extra_dbits = [0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13]; // extra bits for each bit length code
  14908. Tree.extra_blbits = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7];
  14909. Tree.bl_order = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]; // StaticTree
  14910. function StaticTree(static_tree, extra_bits, extra_base, elems, max_length) {
  14911. var that = this;
  14912. that.static_tree = static_tree;
  14913. that.extra_bits = extra_bits;
  14914. that.extra_base = extra_base;
  14915. that.elems = elems;
  14916. that.max_length = max_length;
  14917. }
  14918. StaticTree.static_ltree = [12, 8, 140, 8, 76, 8, 204, 8, 44, 8, 172, 8, 108, 8, 236, 8, 28, 8, 156, 8, 92, 8, 220, 8, 60, 8, 188, 8, 124, 8, 252, 8, 2, 8, 130, 8, 66, 8, 194, 8, 34, 8, 162, 8, 98, 8, 226, 8, 18, 8, 146, 8, 82, 8, 210, 8, 50, 8, 178, 8, 114, 8, 242, 8, 10, 8, 138, 8, 74, 8, 202, 8, 42, 8, 170, 8, 106, 8, 234, 8, 26, 8, 154, 8, 90, 8, 218, 8, 58, 8, 186, 8, 122, 8, 250, 8, 6, 8, 134, 8, 70, 8, 198, 8, 38, 8, 166, 8, 102, 8, 230, 8, 22, 8, 150, 8, 86, 8, 214, 8, 54, 8, 182, 8, 118, 8, 246, 8, 14, 8, 142, 8, 78, 8, 206, 8, 46, 8, 174, 8, 110, 8, 238, 8, 30, 8, 158, 8, 94, 8, 222, 8, 62, 8, 190, 8, 126, 8, 254, 8, 1, 8, 129, 8, 65, 8, 193, 8, 33, 8, 161, 8, 97, 8, 225, 8, 17, 8, 145, 8, 81, 8, 209, 8, 49, 8, 177, 8, 113, 8, 241, 8, 9, 8, 137, 8, 73, 8, 201, 8, 41, 8, 169, 8, 105, 8, 233, 8, 25, 8, 153, 8, 89, 8, 217, 8, 57, 8, 185, 8, 121, 8, 249, 8, 5, 8, 133, 8, 69, 8, 197, 8, 37, 8, 165, 8, 101, 8, 229, 8, 21, 8, 149, 8, 85, 8, 213, 8, 53, 8, 181, 8, 117, 8, 245, 8, 13, 8, 141, 8, 77, 8, 205, 8, 45, 8, 173, 8, 109, 8, 237, 8, 29, 8, 157, 8, 93, 8, 221, 8, 61, 8, 189, 8, 125, 8, 253, 8, 19, 9, 275, 9, 147, 9, 403, 9, 83, 9, 339, 9, 211, 9, 467, 9, 51, 9, 307, 9, 179, 9, 435, 9, 115, 9, 371, 9, 243, 9, 499, 9, 11, 9, 267, 9, 139, 9, 395, 9, 75, 9, 331, 9, 203, 9, 459, 9, 43, 9, 299, 9, 171, 9, 427, 9, 107, 9, 363, 9, 235, 9, 491, 9, 27, 9, 283, 9, 155, 9, 411, 9, 91, 9, 347, 9, 219, 9, 475, 9, 59, 9, 315, 9, 187, 9, 443, 9, 123, 9, 379, 9, 251, 9, 507, 9, 7, 9, 263, 9, 135, 9, 391, 9, 71, 9, 327, 9, 199, 9, 455, 9, 39, 9, 295, 9, 167, 9, 423, 9, 103, 9, 359, 9, 231, 9, 487, 9, 23, 9, 279, 9, 151, 9, 407, 9, 87, 9, 343, 9, 215, 9, 471, 9, 55, 9, 311, 9, 183, 9, 439, 9, 119, 9, 375, 9, 247, 9, 503, 9, 15, 9, 271, 9, 143, 9, 399, 9, 79, 9, 335, 9, 207, 9, 463, 9, 47, 9, 303, 9, 175, 9, 431, 9, 111, 9, 367, 9, 239, 9, 495, 9, 31, 9, 287, 9, 159, 9, 415, 9, 95, 9, 351, 9, 223, 9, 479, 9, 63, 9, 319, 9, 191, 9, 447, 9, 127, 9, 383, 9, 255, 9, 511, 9, 0, 7, 64, 7, 32, 7, 96, 7, 16, 7, 80, 7, 48, 7, 112, 7, 8, 7, 72, 7, 40, 7, 104, 7, 24, 7, 88, 7, 56, 7, 120, 7, 4, 7, 68, 7, 36, 7, 100, 7, 20, 7, 84, 7, 52, 7, 116, 7, 3, 8, 131, 8, 67, 8, 195, 8, 35, 8, 163, 8, 99, 8, 227, 8];
  14919. StaticTree.static_dtree = [0, 5, 16, 5, 8, 5, 24, 5, 4, 5, 20, 5, 12, 5, 28, 5, 2, 5, 18, 5, 10, 5, 26, 5, 6, 5, 22, 5, 14, 5, 30, 5, 1, 5, 17, 5, 9, 5, 25, 5, 5, 5, 21, 5, 13, 5, 29, 5, 3, 5, 19, 5, 11, 5, 27, 5, 7, 5, 23, 5];
  14920. StaticTree.static_l_desc = new StaticTree(StaticTree.static_ltree, Tree.extra_lbits, LITERALS + 1, L_CODES, MAX_BITS);
  14921. StaticTree.static_d_desc = new StaticTree(StaticTree.static_dtree, Tree.extra_dbits, 0, D_CODES, MAX_BITS);
  14922. StaticTree.static_bl_desc = new StaticTree(null, Tree.extra_blbits, 0, BL_CODES, MAX_BL_BITS); // Deflate
  14923. var MAX_MEM_LEVEL = 9;
  14924. var DEF_MEM_LEVEL = 8;
  14925. function Config(good_length, max_lazy, nice_length, max_chain, func) {
  14926. var that = this;
  14927. that.good_length = good_length;
  14928. that.max_lazy = max_lazy;
  14929. that.nice_length = nice_length;
  14930. that.max_chain = max_chain;
  14931. that.func = func;
  14932. }
  14933. var STORED = 0;
  14934. var FAST = 1;
  14935. var SLOW = 2;
  14936. var config_table = [new Config(0, 0, 0, 0, STORED), new Config(4, 4, 8, 4, FAST), new Config(4, 5, 16, 8, FAST), new Config(4, 6, 32, 32, FAST), new Config(4, 4, 16, 16, SLOW), new Config(8, 16, 32, 32, SLOW), new Config(8, 16, 128, 128, SLOW), new Config(8, 32, 128, 256, SLOW), new Config(32, 128, 258, 1024, SLOW), new Config(32, 258, 258, 4096, SLOW)];
  14937. var z_errmsg = ["need dictionary", // Z_NEED_DICT
  14938. // 2
  14939. "stream end", // Z_STREAM_END 1
  14940. "", // Z_OK 0
  14941. "", // Z_ERRNO (-1)
  14942. "stream error", // Z_STREAM_ERROR (-2)
  14943. "data error", // Z_DATA_ERROR (-3)
  14944. "", // Z_MEM_ERROR (-4)
  14945. "buffer error", // Z_BUF_ERROR (-5)
  14946. "", // Z_VERSION_ERROR (-6)
  14947. ""]; // block not completed, need more input or more output
  14948. var NeedMore = 0; // block flush performed
  14949. var BlockDone = 1; // finish started, need only more output at next deflate
  14950. var FinishStarted = 2; // finish done, accept no more input or output
  14951. var FinishDone = 3; // preset dictionary flag in zlib header
  14952. var PRESET_DICT = 0x20;
  14953. var INIT_STATE = 42;
  14954. var BUSY_STATE = 113;
  14955. var FINISH_STATE = 666; // The deflate compression method
  14956. var Z_DEFLATED = 8;
  14957. var STORED_BLOCK = 0;
  14958. var STATIC_TREES = 1;
  14959. var DYN_TREES = 2;
  14960. var MIN_MATCH = 3;
  14961. var MAX_MATCH = 258;
  14962. var MIN_LOOKAHEAD = MAX_MATCH + MIN_MATCH + 1;
  14963. function smaller(tree, n, m, depth) {
  14964. var tn2 = tree[n * 2];
  14965. var tm2 = tree[m * 2];
  14966. return tn2 < tm2 || tn2 == tm2 && depth[n] <= depth[m];
  14967. }
  14968. function Deflate() {
  14969. var that = this;
  14970. var strm; // pointer back to this zlib stream
  14971. var status; // as the name implies
  14972. // pending_buf; // output still pending
  14973. var pending_buf_size; // size of pending_buf
  14974. var last_flush; // value of flush param for previous deflate call
  14975. var w_size; // LZ77 window size (32K by default)
  14976. var w_bits; // log2(w_size) (8..16)
  14977. var w_mask; // w_size - 1
  14978. var window; // Sliding window. Input bytes are read into the second half of the window,
  14979. // and move to the first half later to keep a dictionary of at least wSize
  14980. // bytes. With this organization, matches are limited to a distance of
  14981. // wSize-MAX_MATCH bytes, but this ensures that IO is always
  14982. // performed with a length multiple of the block size. Also, it limits
  14983. // the window size to 64K, which is quite useful on MSDOS.
  14984. // To do: use the user input buffer as sliding window.
  14985. var window_size; // Actual size of window: 2*wSize, except when the user input buffer
  14986. // is directly used as sliding window.
  14987. var prev; // Link to older string with same hash index. To limit the size of this
  14988. // array to 64K, this link is maintained only for the last 32K strings.
  14989. // An index in this array is thus a window index modulo 32K.
  14990. var head; // Heads of the hash chains or NIL.
  14991. var ins_h; // hash index of string to be inserted
  14992. var hash_size; // number of elements in hash table
  14993. var hash_bits; // log2(hash_size)
  14994. var hash_mask; // hash_size-1
  14995. // Number of bits by which ins_h must be shifted at each input
  14996. // step. It must be such that after MIN_MATCH steps, the oldest
  14997. // byte no longer takes part in the hash key, that is:
  14998. // hash_shift * MIN_MATCH >= hash_bits
  14999. var hash_shift; // Window position at the beginning of the current output block. Gets
  15000. // negative when the window is moved backwards.
  15001. var block_start;
  15002. var match_length; // length of best match
  15003. var prev_match; // previous match
  15004. var match_available; // set if previous match exists
  15005. var strstart; // start of string to insert
  15006. var match_start; // start of matching string
  15007. var lookahead; // number of valid bytes ahead in window
  15008. // Length of the best match at previous step. Matches not greater than this
  15009. // are discarded. This is used in the lazy match evaluation.
  15010. var prev_length; // To speed up deflation, hash chains are never searched beyond this
  15011. // length. A higher limit improves compression ratio but degrades the speed.
  15012. var max_chain_length; // Attempt to find a better match only when the current match is strictly
  15013. // smaller than this value. This mechanism is used only for compression
  15014. // levels >= 4.
  15015. var max_lazy_match; // Insert new strings in the hash table only if the match length is not
  15016. // greater than this length. This saves time but degrades compression.
  15017. // max_insert_length is used only for compression levels <= 3.
  15018. var level; // compression level (1..9)
  15019. var strategy; // favor or force Huffman coding
  15020. // Use a faster search when the previous match is longer than this
  15021. var good_match; // Stop searching when current match exceeds this
  15022. var nice_match;
  15023. var dyn_ltree; // literal and length tree
  15024. var dyn_dtree; // distance tree
  15025. var bl_tree; // Huffman tree for bit lengths
  15026. var l_desc = new Tree(); // desc for literal tree
  15027. var d_desc = new Tree(); // desc for distance tree
  15028. var bl_desc = new Tree(); // desc for bit length tree
  15029. // that.heap_len; // number of elements in the heap
  15030. // that.heap_max; // element of largest frequency
  15031. // The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
  15032. // The same heap array is used to build all trees.
  15033. // Depth of each subtree used as tie breaker for trees of equal frequency
  15034. that.depth = [];
  15035. var l_buf; // index for literals or lengths */
  15036. // Size of match buffer for literals/lengths. There are 4 reasons for
  15037. // limiting lit_bufsize to 64K:
  15038. // - frequencies can be kept in 16 bit counters
  15039. // - if compression is not successful for the first block, all input
  15040. // data is still in the window so we can still emit a stored block even
  15041. // when input comes from standard input. (This can also be done for
  15042. // all blocks if lit_bufsize is not greater than 32K.)
  15043. // - if compression is not successful for a file smaller than 64K, we can
  15044. // even emit a stored file instead of a stored block (saving 5 bytes).
  15045. // This is applicable only for zip (not gzip or zlib).
  15046. // - creating new Huffman trees less frequently may not provide fast
  15047. // adaptation to changes in the input data statistics. (Take for
  15048. // example a binary file with poorly compressible code followed by
  15049. // a highly compressible string table.) Smaller buffer sizes give
  15050. // fast adaptation but have of course the overhead of transmitting
  15051. // trees more frequently.
  15052. // - I can't count above 4
  15053. var lit_bufsize;
  15054. var last_lit; // running index in l_buf
  15055. // Buffer for distances. To simplify the code, d_buf and l_buf have
  15056. // the same number of elements. To use different lengths, an extra flag
  15057. // array would be necessary.
  15058. var d_buf; // index of pendig_buf
  15059. // that.opt_len; // bit length of current block with optimal trees
  15060. // that.static_len; // bit length of current block with static trees
  15061. var matches; // number of string matches in current block
  15062. var last_eob_len; // bit length of EOB code for last block
  15063. // Output buffer. bits are inserted starting at the bottom (least
  15064. // significant bits).
  15065. var bi_buf; // Number of valid bits in bi_buf. All bits above the last valid bit
  15066. // are always zero.
  15067. var bi_valid; // number of codes at each bit length for an optimal tree
  15068. that.bl_count = []; // heap used to build the Huffman trees
  15069. that.heap = [];
  15070. dyn_ltree = [];
  15071. dyn_dtree = [];
  15072. bl_tree = [];
  15073. function lm_init() {
  15074. var i;
  15075. window_size = 2 * w_size;
  15076. head[hash_size - 1] = 0;
  15077. for (i = 0; i < hash_size - 1; i++) {
  15078. head[i] = 0;
  15079. } // Set the default configuration parameters:
  15080. max_lazy_match = config_table[level].max_lazy;
  15081. good_match = config_table[level].good_length;
  15082. nice_match = config_table[level].nice_length;
  15083. max_chain_length = config_table[level].max_chain;
  15084. strstart = 0;
  15085. block_start = 0;
  15086. lookahead = 0;
  15087. match_length = prev_length = MIN_MATCH - 1;
  15088. match_available = 0;
  15089. ins_h = 0;
  15090. }
  15091. function init_block() {
  15092. var i; // Initialize the trees.
  15093. for (i = 0; i < L_CODES; i++) dyn_ltree[i * 2] = 0;
  15094. for (i = 0; i < D_CODES; i++) dyn_dtree[i * 2] = 0;
  15095. for (i = 0; i < BL_CODES; i++) bl_tree[i * 2] = 0;
  15096. dyn_ltree[END_BLOCK * 2] = 1;
  15097. that.opt_len = that.static_len = 0;
  15098. last_lit = matches = 0;
  15099. } // Initialize the tree data structures for a new zlib stream.
  15100. function tr_init() {
  15101. l_desc.dyn_tree = dyn_ltree;
  15102. l_desc.stat_desc = StaticTree.static_l_desc;
  15103. d_desc.dyn_tree = dyn_dtree;
  15104. d_desc.stat_desc = StaticTree.static_d_desc;
  15105. bl_desc.dyn_tree = bl_tree;
  15106. bl_desc.stat_desc = StaticTree.static_bl_desc;
  15107. bi_buf = 0;
  15108. bi_valid = 0;
  15109. last_eob_len = 8; // enough lookahead for inflate
  15110. // Initialize the first block of the first file:
  15111. init_block();
  15112. } // Restore the heap property by moving down the tree starting at node k,
  15113. // exchanging a node with the smallest of its two sons if necessary,
  15114. // stopping
  15115. // when the heap property is re-established (each father smaller than its
  15116. // two sons).
  15117. that.pqdownheap = function (tree, // the tree to restore
  15118. k // node to move down
  15119. ) {
  15120. var heap = that.heap;
  15121. var v = heap[k];
  15122. var j = k << 1; // left son of k
  15123. while (j <= that.heap_len) {
  15124. // Set j to the smallest of the two sons:
  15125. if (j < that.heap_len && smaller(tree, heap[j + 1], heap[j], that.depth)) {
  15126. j++;
  15127. } // Exit if v is smaller than both sons
  15128. if (smaller(tree, v, heap[j], that.depth)) break; // Exchange v with the smallest son
  15129. heap[k] = heap[j];
  15130. k = j; // And continue down the tree, setting j to the left son of k
  15131. j <<= 1;
  15132. }
  15133. heap[k] = v;
  15134. }; // Scan a literal or distance tree to determine the frequencies of the codes
  15135. // in the bit length tree.
  15136. function scan_tree(tree, // the tree to be scanned
  15137. max_code // and its largest code of non zero frequency
  15138. ) {
  15139. var n; // iterates over all tree elements
  15140. var prevlen = -1; // last emitted length
  15141. var curlen; // length of current code
  15142. var nextlen = tree[0 * 2 + 1]; // length of next code
  15143. var count = 0; // repeat count of the current code
  15144. var max_count = 7; // max repeat count
  15145. var min_count = 4; // min repeat count
  15146. if (nextlen === 0) {
  15147. max_count = 138;
  15148. min_count = 3;
  15149. }
  15150. tree[(max_code + 1) * 2 + 1] = 0xffff; // guard
  15151. for (n = 0; n <= max_code; n++) {
  15152. curlen = nextlen;
  15153. nextlen = tree[(n + 1) * 2 + 1];
  15154. if (++count < max_count && curlen == nextlen) {
  15155. continue;
  15156. } else if (count < min_count) {
  15157. bl_tree[curlen * 2] += count;
  15158. } else if (curlen !== 0) {
  15159. if (curlen != prevlen) bl_tree[curlen * 2]++;
  15160. bl_tree[REP_3_6 * 2]++;
  15161. } else if (count <= 10) {
  15162. bl_tree[REPZ_3_10 * 2]++;
  15163. } else {
  15164. bl_tree[REPZ_11_138 * 2]++;
  15165. }
  15166. count = 0;
  15167. prevlen = curlen;
  15168. if (nextlen === 0) {
  15169. max_count = 138;
  15170. min_count = 3;
  15171. } else if (curlen == nextlen) {
  15172. max_count = 6;
  15173. min_count = 3;
  15174. } else {
  15175. max_count = 7;
  15176. min_count = 4;
  15177. }
  15178. }
  15179. } // Construct the Huffman tree for the bit lengths and return the index in
  15180. // bl_order of the last bit length code to send.
  15181. function build_bl_tree() {
  15182. var max_blindex; // index of last bit length code of non zero freq
  15183. // Determine the bit length frequencies for literal and distance trees
  15184. scan_tree(dyn_ltree, l_desc.max_code);
  15185. scan_tree(dyn_dtree, d_desc.max_code); // Build the bit length tree:
  15186. bl_desc.build_tree(that); // opt_len now includes the length of the tree representations, except
  15187. // the lengths of the bit lengths codes and the 5+5+4 bits for the
  15188. // counts.
  15189. // Determine the number of bit length codes to send. The pkzip format
  15190. // requires that at least 4 bit length codes be sent. (appnote.txt says
  15191. // 3 but the actual value used is 4.)
  15192. for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) {
  15193. if (bl_tree[Tree.bl_order[max_blindex] * 2 + 1] !== 0) break;
  15194. } // Update opt_len to include the bit length tree and counts
  15195. that.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4;
  15196. return max_blindex;
  15197. } // Output a byte on the stream.
  15198. // IN assertion: there is enough room in pending_buf.
  15199. function put_byte(p) {
  15200. that.pending_buf[that.pending++] = p;
  15201. }
  15202. function put_short(w) {
  15203. put_byte(w & 0xff);
  15204. put_byte(w >>> 8 & 0xff);
  15205. }
  15206. function putShortMSB(b) {
  15207. put_byte(b >> 8 & 0xff);
  15208. put_byte(b & 0xff & 0xff);
  15209. }
  15210. function send_bits(value, length) {
  15211. var val,
  15212. len = length;
  15213. if (bi_valid > Buf_size - len) {
  15214. val = value; // bi_buf |= (val << bi_valid);
  15215. bi_buf |= val << bi_valid & 0xffff;
  15216. put_short(bi_buf);
  15217. bi_buf = val >>> Buf_size - bi_valid;
  15218. bi_valid += len - Buf_size;
  15219. } else {
  15220. // bi_buf |= (value) << bi_valid;
  15221. bi_buf |= value << bi_valid & 0xffff;
  15222. bi_valid += len;
  15223. }
  15224. }
  15225. function send_code(c, tree) {
  15226. var c2 = c * 2;
  15227. send_bits(tree[c2] & 0xffff, tree[c2 + 1] & 0xffff);
  15228. } // Send a literal or distance tree in compressed form, using the codes in
  15229. // bl_tree.
  15230. function send_tree(tree, // the tree to be sent
  15231. max_code // and its largest code of non zero frequency
  15232. ) {
  15233. var n; // iterates over all tree elements
  15234. var prevlen = -1; // last emitted length
  15235. var curlen; // length of current code
  15236. var nextlen = tree[0 * 2 + 1]; // length of next code
  15237. var count = 0; // repeat count of the current code
  15238. var max_count = 7; // max repeat count
  15239. var min_count = 4; // min repeat count
  15240. if (nextlen === 0) {
  15241. max_count = 138;
  15242. min_count = 3;
  15243. }
  15244. for (n = 0; n <= max_code; n++) {
  15245. curlen = nextlen;
  15246. nextlen = tree[(n + 1) * 2 + 1];
  15247. if (++count < max_count && curlen == nextlen) {
  15248. continue;
  15249. } else if (count < min_count) {
  15250. do {
  15251. send_code(curlen, bl_tree);
  15252. } while (--count !== 0);
  15253. } else if (curlen !== 0) {
  15254. if (curlen != prevlen) {
  15255. send_code(curlen, bl_tree);
  15256. count--;
  15257. }
  15258. send_code(REP_3_6, bl_tree);
  15259. send_bits(count - 3, 2);
  15260. } else if (count <= 10) {
  15261. send_code(REPZ_3_10, bl_tree);
  15262. send_bits(count - 3, 3);
  15263. } else {
  15264. send_code(REPZ_11_138, bl_tree);
  15265. send_bits(count - 11, 7);
  15266. }
  15267. count = 0;
  15268. prevlen = curlen;
  15269. if (nextlen === 0) {
  15270. max_count = 138;
  15271. min_count = 3;
  15272. } else if (curlen == nextlen) {
  15273. max_count = 6;
  15274. min_count = 3;
  15275. } else {
  15276. max_count = 7;
  15277. min_count = 4;
  15278. }
  15279. }
  15280. } // Send the header for a block using dynamic Huffman trees: the counts, the
  15281. // lengths of the bit length codes, the literal tree and the distance tree.
  15282. // IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
  15283. function send_all_trees(lcodes, dcodes, blcodes) {
  15284. var rank; // index in bl_order
  15285. send_bits(lcodes - 257, 5); // not +255 as stated in appnote.txt
  15286. send_bits(dcodes - 1, 5);
  15287. send_bits(blcodes - 4, 4); // not -3 as stated in appnote.txt
  15288. for (rank = 0; rank < blcodes; rank++) {
  15289. send_bits(bl_tree[Tree.bl_order[rank] * 2 + 1], 3);
  15290. }
  15291. send_tree(dyn_ltree, lcodes - 1); // literal tree
  15292. send_tree(dyn_dtree, dcodes - 1); // distance tree
  15293. } // Flush the bit buffer, keeping at most 7 bits in it.
  15294. function bi_flush() {
  15295. if (bi_valid == 16) {
  15296. put_short(bi_buf);
  15297. bi_buf = 0;
  15298. bi_valid = 0;
  15299. } else if (bi_valid >= 8) {
  15300. put_byte(bi_buf & 0xff);
  15301. bi_buf >>>= 8;
  15302. bi_valid -= 8;
  15303. }
  15304. } // Send one empty static block to give enough lookahead for inflate.
  15305. // This takes 10 bits, of which 7 may remain in the bit buffer.
  15306. // The current inflate code requires 9 bits of lookahead. If the
  15307. // last two codes for the previous block (real code plus EOB) were coded
  15308. // on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
  15309. // the last real code. In this case we send two empty static blocks instead
  15310. // of one. (There are no problems if the previous block is stored or fixed.)
  15311. // To simplify the code, we assume the worst case of last real code encoded
  15312. // on one bit only.
  15313. function _tr_align() {
  15314. send_bits(STATIC_TREES << 1, 3);
  15315. send_code(END_BLOCK, StaticTree.static_ltree);
  15316. bi_flush(); // Of the 10 bits for the empty block, we have already sent
  15317. // (10 - bi_valid) bits. The lookahead for the last real code (before
  15318. // the EOB of the previous block) was thus at least one plus the length
  15319. // of the EOB plus what we have just sent of the empty static block.
  15320. if (1 + last_eob_len + 10 - bi_valid < 9) {
  15321. send_bits(STATIC_TREES << 1, 3);
  15322. send_code(END_BLOCK, StaticTree.static_ltree);
  15323. bi_flush();
  15324. }
  15325. last_eob_len = 7;
  15326. } // Save the match info and tally the frequency counts. Return true if
  15327. // the current block must be flushed.
  15328. function _tr_tally(dist, // distance of matched string
  15329. lc // match length-MIN_MATCH or unmatched char (if dist==0)
  15330. ) {
  15331. var out_length, in_length, dcode;
  15332. that.pending_buf[d_buf + last_lit * 2] = dist >>> 8 & 0xff;
  15333. that.pending_buf[d_buf + last_lit * 2 + 1] = dist & 0xff;
  15334. that.pending_buf[l_buf + last_lit] = lc & 0xff;
  15335. last_lit++;
  15336. if (dist === 0) {
  15337. // lc is the unmatched char
  15338. dyn_ltree[lc * 2]++;
  15339. } else {
  15340. matches++; // Here, lc is the match length - MIN_MATCH
  15341. dist--; // dist = match distance - 1
  15342. dyn_ltree[(Tree._length_code[lc] + LITERALS + 1) * 2]++;
  15343. dyn_dtree[Tree.d_code(dist) * 2]++;
  15344. }
  15345. if ((last_lit & 0x1fff) === 0 && level > 2) {
  15346. // Compute an upper bound for the compressed length
  15347. out_length = last_lit * 8;
  15348. in_length = strstart - block_start;
  15349. for (dcode = 0; dcode < D_CODES; dcode++) {
  15350. out_length += dyn_dtree[dcode * 2] * (5 + Tree.extra_dbits[dcode]);
  15351. }
  15352. out_length >>>= 3;
  15353. if (matches < Math.floor(last_lit / 2) && out_length < Math.floor(in_length / 2)) return true;
  15354. }
  15355. return last_lit == lit_bufsize - 1; // We avoid equality with lit_bufsize because of wraparound at 64K
  15356. // on 16 bit machines and because stored blocks are restricted to
  15357. // 64K-1 bytes.
  15358. } // Send the block data compressed using the given Huffman trees
  15359. function compress_block(ltree, dtree) {
  15360. var dist; // distance of matched string
  15361. var lc; // match length or unmatched char (if dist === 0)
  15362. var lx = 0; // running index in l_buf
  15363. var code; // the code to send
  15364. var extra; // number of extra bits to send
  15365. if (last_lit !== 0) {
  15366. do {
  15367. dist = that.pending_buf[d_buf + lx * 2] << 8 & 0xff00 | that.pending_buf[d_buf + lx * 2 + 1] & 0xff;
  15368. lc = that.pending_buf[l_buf + lx] & 0xff;
  15369. lx++;
  15370. if (dist === 0) {
  15371. send_code(lc, ltree); // send a literal byte
  15372. } else {
  15373. // Here, lc is the match length - MIN_MATCH
  15374. code = Tree._length_code[lc];
  15375. send_code(code + LITERALS + 1, ltree); // send the length
  15376. // code
  15377. extra = Tree.extra_lbits[code];
  15378. if (extra !== 0) {
  15379. lc -= Tree.base_length[code];
  15380. send_bits(lc, extra); // send the extra length bits
  15381. }
  15382. dist--; // dist is now the match distance - 1
  15383. code = Tree.d_code(dist);
  15384. send_code(code, dtree); // send the distance code
  15385. extra = Tree.extra_dbits[code];
  15386. if (extra !== 0) {
  15387. dist -= Tree.base_dist[code];
  15388. send_bits(dist, extra); // send the extra distance bits
  15389. }
  15390. } // literal or match pair ?
  15391. // Check that the overlay between pending_buf and d_buf+l_buf is
  15392. // ok:
  15393. } while (lx < last_lit);
  15394. }
  15395. send_code(END_BLOCK, ltree);
  15396. last_eob_len = ltree[END_BLOCK * 2 + 1];
  15397. } // Flush the bit buffer and align the output on a byte boundary
  15398. function bi_windup() {
  15399. if (bi_valid > 8) {
  15400. put_short(bi_buf);
  15401. } else if (bi_valid > 0) {
  15402. put_byte(bi_buf & 0xff);
  15403. }
  15404. bi_buf = 0;
  15405. bi_valid = 0;
  15406. } // Copy a stored block, storing first the length and its
  15407. // one's complement if requested.
  15408. function copy_block(buf, // the input data
  15409. len, // its length
  15410. header // true if block header must be written
  15411. ) {
  15412. bi_windup(); // align on byte boundary
  15413. last_eob_len = 8; // enough lookahead for inflate
  15414. if (header) {
  15415. put_short(len);
  15416. put_short(~len);
  15417. }
  15418. that.pending_buf.set(window.subarray(buf, buf + len), that.pending);
  15419. that.pending += len;
  15420. } // Send a stored block
  15421. function _tr_stored_block(buf, // input block
  15422. stored_len, // length of input block
  15423. eof // true if this is the last block for a file
  15424. ) {
  15425. send_bits((STORED_BLOCK << 1) + (eof ? 1 : 0), 3); // send block type
  15426. copy_block(buf, stored_len, true); // with header
  15427. } // Determine the best encoding for the current block: dynamic trees, static
  15428. // trees or store, and output the encoded block to the zip file.
  15429. function _tr_flush_block(buf, // input block, or NULL if too old
  15430. stored_len, // length of input block
  15431. eof // true if this is the last block for a file
  15432. ) {
  15433. var opt_lenb, static_lenb; // opt_len and static_len in bytes
  15434. var max_blindex = 0; // index of last bit length code of non zero freq
  15435. // Build the Huffman trees unless a stored block is forced
  15436. if (level > 0) {
  15437. // Construct the literal and distance trees
  15438. l_desc.build_tree(that);
  15439. d_desc.build_tree(that); // At this point, opt_len and static_len are the total bit lengths
  15440. // of
  15441. // the compressed block data, excluding the tree representations.
  15442. // Build the bit length tree for the above two trees, and get the
  15443. // index
  15444. // in bl_order of the last bit length code to send.
  15445. max_blindex = build_bl_tree(); // Determine the best encoding. Compute first the block length in
  15446. // bytes
  15447. opt_lenb = that.opt_len + 3 + 7 >>> 3;
  15448. static_lenb = that.static_len + 3 + 7 >>> 3;
  15449. if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
  15450. } else {
  15451. opt_lenb = static_lenb = stored_len + 5; // force a stored block
  15452. }
  15453. if (stored_len + 4 <= opt_lenb && buf != -1) {
  15454. // 4: two words for the lengths
  15455. // The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
  15456. // Otherwise we can't have processed more than WSIZE input bytes
  15457. // since
  15458. // the last block flush, because compression would have been
  15459. // successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
  15460. // transform a block into a stored block.
  15461. _tr_stored_block(buf, stored_len, eof);
  15462. } else if (static_lenb == opt_lenb) {
  15463. send_bits((STATIC_TREES << 1) + (eof ? 1 : 0), 3);
  15464. compress_block(StaticTree.static_ltree, StaticTree.static_dtree);
  15465. } else {
  15466. send_bits((DYN_TREES << 1) + (eof ? 1 : 0), 3);
  15467. send_all_trees(l_desc.max_code + 1, d_desc.max_code + 1, max_blindex + 1);
  15468. compress_block(dyn_ltree, dyn_dtree);
  15469. } // The above check is made mod 2^32, for files larger than 512 MB
  15470. // and uLong implemented on 32 bits.
  15471. init_block();
  15472. if (eof) {
  15473. bi_windup();
  15474. }
  15475. }
  15476. function flush_block_only(eof) {
  15477. _tr_flush_block(block_start >= 0 ? block_start : -1, strstart - block_start, eof);
  15478. block_start = strstart;
  15479. strm.flush_pending();
  15480. } // Fill the window when the lookahead becomes insufficient.
  15481. // Updates strstart and lookahead.
  15482. //
  15483. // IN assertion: lookahead < MIN_LOOKAHEAD
  15484. // OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
  15485. // At least one byte has been read, or avail_in === 0; reads are
  15486. // performed for at least two bytes (required for the zip translate_eol
  15487. // option -- not supported here).
  15488. function fill_window() {
  15489. var n, m;
  15490. var p;
  15491. var more; // Amount of free space at the end of the window.
  15492. do {
  15493. more = window_size - lookahead - strstart; // Deal with !@#$% 64K limit:
  15494. if (more === 0 && strstart === 0 && lookahead === 0) {
  15495. more = w_size;
  15496. } else if (more == -1) {
  15497. // Very unlikely, but possible on 16 bit machine if strstart ==
  15498. // 0
  15499. // and lookahead == 1 (input done one byte at time)
  15500. more--; // If the window is almost full and there is insufficient
  15501. // lookahead,
  15502. // move the upper half to the lower one to make room in the
  15503. // upper half.
  15504. } else if (strstart >= w_size + w_size - MIN_LOOKAHEAD) {
  15505. window.set(window.subarray(w_size, w_size + w_size), 0);
  15506. match_start -= w_size;
  15507. strstart -= w_size; // we now have strstart >= MAX_DIST
  15508. block_start -= w_size; // Slide the hash table (could be avoided with 32 bit values
  15509. // at the expense of memory usage). We slide even when level ==
  15510. // 0
  15511. // to keep the hash table consistent if we switch back to level
  15512. // > 0
  15513. // later. (Using level 0 permanently is not an optimal usage of
  15514. // zlib, so we don't care about this pathological case.)
  15515. n = hash_size;
  15516. p = n;
  15517. do {
  15518. m = head[--p] & 0xffff;
  15519. head[p] = m >= w_size ? m - w_size : 0;
  15520. } while (--n !== 0);
  15521. n = w_size;
  15522. p = n;
  15523. do {
  15524. m = prev[--p] & 0xffff;
  15525. prev[p] = m >= w_size ? m - w_size : 0; // If n is not on any hash chain, prev[n] is garbage but
  15526. // its value will never be used.
  15527. } while (--n !== 0);
  15528. more += w_size;
  15529. }
  15530. if (strm.avail_in === 0) return; // If there was no sliding:
  15531. // strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
  15532. // more == window_size - lookahead - strstart
  15533. // => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
  15534. // => more >= window_size - 2*WSIZE + 2
  15535. // In the BIG_MEM or MMAP case (not yet supported),
  15536. // window_size == input_size + MIN_LOOKAHEAD &&
  15537. // strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
  15538. // Otherwise, window_size == 2*WSIZE so more >= 2.
  15539. // If there was sliding, more >= WSIZE. So in all cases, more >= 2.
  15540. n = strm.read_buf(window, strstart + lookahead, more);
  15541. lookahead += n; // Initialize the hash value now that we have some input:
  15542. if (lookahead >= MIN_MATCH) {
  15543. ins_h = window[strstart] & 0xff;
  15544. ins_h = (ins_h << hash_shift ^ window[strstart + 1] & 0xff) & hash_mask;
  15545. } // If the whole input has less than MIN_MATCH bytes, ins_h is
  15546. // garbage,
  15547. // but this is not important since only literal bytes will be
  15548. // emitted.
  15549. } while (lookahead < MIN_LOOKAHEAD && strm.avail_in !== 0);
  15550. } // Copy without compression as much as possible from the input stream,
  15551. // return
  15552. // the current block state.
  15553. // This function does not insert new strings in the dictionary since
  15554. // uncompressible data is probably not useful. This function is used
  15555. // only for the level=0 compression option.
  15556. // NOTE: this function should be optimized to avoid extra copying from
  15557. // window to pending_buf.
  15558. function deflate_stored(flush) {
  15559. // Stored blocks are limited to 0xffff bytes, pending_buf is limited
  15560. // to pending_buf_size, and each stored block has a 5 byte header:
  15561. var max_block_size = 0xffff;
  15562. var max_start;
  15563. if (max_block_size > pending_buf_size - 5) {
  15564. max_block_size = pending_buf_size - 5;
  15565. } // Copy as much as possible from input to output:
  15566. while (true) {
  15567. // Fill the window as much as possible:
  15568. if (lookahead <= 1) {
  15569. fill_window();
  15570. if (lookahead === 0 && flush == Z_NO_FLUSH) return NeedMore;
  15571. if (lookahead === 0) break; // flush the current block
  15572. }
  15573. strstart += lookahead;
  15574. lookahead = 0; // Emit a stored block if pending_buf will be full:
  15575. max_start = block_start + max_block_size;
  15576. if (strstart === 0 || strstart >= max_start) {
  15577. // strstart === 0 is possible when wraparound on 16-bit machine
  15578. lookahead = strstart - max_start;
  15579. strstart = max_start;
  15580. flush_block_only(false);
  15581. if (strm.avail_out === 0) return NeedMore;
  15582. } // Flush if we may have to slide, otherwise block_start may become
  15583. // negative and the data will be gone:
  15584. if (strstart - block_start >= w_size - MIN_LOOKAHEAD) {
  15585. flush_block_only(false);
  15586. if (strm.avail_out === 0) return NeedMore;
  15587. }
  15588. }
  15589. flush_block_only(flush == Z_FINISH);
  15590. if (strm.avail_out === 0) return flush == Z_FINISH ? FinishStarted : NeedMore;
  15591. return flush == Z_FINISH ? FinishDone : BlockDone;
  15592. }
  15593. function longest_match(cur_match) {
  15594. var chain_length = max_chain_length; // max hash chain length
  15595. var scan = strstart; // current string
  15596. var match; // matched string
  15597. var len; // length of current match
  15598. var best_len = prev_length; // best match length so far
  15599. var limit = strstart > w_size - MIN_LOOKAHEAD ? strstart - (w_size - MIN_LOOKAHEAD) : 0;
  15600. var _nice_match = nice_match; // Stop when cur_match becomes <= limit. To simplify the code,
  15601. // we prevent matches with the string of window index 0.
  15602. var wmask = w_mask;
  15603. var strend = strstart + MAX_MATCH;
  15604. var scan_end1 = window[scan + best_len - 1];
  15605. var scan_end = window[scan + best_len]; // The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of
  15606. // 16.
  15607. // It is easy to get rid of this optimization if necessary.
  15608. // Do not waste too much time if we already have a good match:
  15609. if (prev_length >= good_match) {
  15610. chain_length >>= 2;
  15611. } // Do not look for matches beyond the end of the input. This is
  15612. // necessary
  15613. // to make deflate deterministic.
  15614. if (_nice_match > lookahead) _nice_match = lookahead;
  15615. do {
  15616. match = cur_match; // Skip to next match if the match length cannot increase
  15617. // or if the match length is less than 2:
  15618. if (window[match + best_len] != scan_end || window[match + best_len - 1] != scan_end1 || window[match] != window[scan] || window[++match] != window[scan + 1]) continue; // The check at best_len-1 can be removed because it will be made
  15619. // again later. (This heuristic is not always a win.)
  15620. // It is not necessary to compare scan[2] and match[2] since they
  15621. // are always equal when the other bytes match, given that
  15622. // the hash keys are equal and that HASH_BITS >= 8.
  15623. scan += 2;
  15624. match++; // We check for insufficient lookahead only every 8th comparison;
  15625. // the 256th check will be made at strstart+258.
  15626. do {} while (window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match] && scan < strend);
  15627. len = MAX_MATCH - (strend - scan);
  15628. scan = strend - MAX_MATCH;
  15629. if (len > best_len) {
  15630. match_start = cur_match;
  15631. best_len = len;
  15632. if (len >= _nice_match) break;
  15633. scan_end1 = window[scan + best_len - 1];
  15634. scan_end = window[scan + best_len];
  15635. }
  15636. } while ((cur_match = prev[cur_match & wmask] & 0xffff) > limit && --chain_length !== 0);
  15637. if (best_len <= lookahead) return best_len;
  15638. return lookahead;
  15639. } // Compress as much as possible from the input stream, return the current
  15640. // block state.
  15641. // This function does not perform lazy evaluation of matches and inserts
  15642. // new strings in the dictionary only for unmatched strings or for short
  15643. // matches. It is used only for the fast compression options.
  15644. function deflate_fast(flush) {
  15645. // short hash_head = 0; // head of the hash chain
  15646. var hash_head = 0; // head of the hash chain
  15647. var bflush; // set if current block must be flushed
  15648. while (true) {
  15649. // Make sure that we always have enough lookahead, except
  15650. // at the end of the input file. We need MAX_MATCH bytes
  15651. // for the next match, plus MIN_MATCH bytes to insert the
  15652. // string following the next match.
  15653. if (lookahead < MIN_LOOKAHEAD) {
  15654. fill_window();
  15655. if (lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
  15656. return NeedMore;
  15657. }
  15658. if (lookahead === 0) break; // flush the current block
  15659. } // Insert the string window[strstart .. strstart+2] in the
  15660. // dictionary, and set hash_head to the head of the hash chain:
  15661. if (lookahead >= MIN_MATCH) {
  15662. ins_h = (ins_h << hash_shift ^ window[strstart + (MIN_MATCH - 1)] & 0xff) & hash_mask; // prev[strstart&w_mask]=hash_head=head[ins_h];
  15663. hash_head = head[ins_h] & 0xffff;
  15664. prev[strstart & w_mask] = head[ins_h];
  15665. head[ins_h] = strstart;
  15666. } // Find the longest match, discarding those <= prev_length.
  15667. // At this point we have always match_length < MIN_MATCH
  15668. if (hash_head !== 0 && (strstart - hash_head & 0xffff) <= w_size - MIN_LOOKAHEAD) {
  15669. // To simplify the code, we prevent matches with the string
  15670. // of window index 0 (in particular we have to avoid a match
  15671. // of the string with itself at the start of the input file).
  15672. if (strategy != Z_HUFFMAN_ONLY) {
  15673. match_length = longest_match(hash_head);
  15674. } // longest_match() sets match_start
  15675. }
  15676. if (match_length >= MIN_MATCH) {
  15677. // check_match(strstart, match_start, match_length);
  15678. bflush = _tr_tally(strstart - match_start, match_length - MIN_MATCH);
  15679. lookahead -= match_length; // Insert new strings in the hash table only if the match length
  15680. // is not too large. This saves time but degrades compression.
  15681. if (match_length <= max_lazy_match && lookahead >= MIN_MATCH) {
  15682. match_length--; // string at strstart already in hash table
  15683. do {
  15684. strstart++;
  15685. ins_h = (ins_h << hash_shift ^ window[strstart + (MIN_MATCH - 1)] & 0xff) & hash_mask; // prev[strstart&w_mask]=hash_head=head[ins_h];
  15686. hash_head = head[ins_h] & 0xffff;
  15687. prev[strstart & w_mask] = head[ins_h];
  15688. head[ins_h] = strstart; // strstart never exceeds WSIZE-MAX_MATCH, so there are
  15689. // always MIN_MATCH bytes ahead.
  15690. } while (--match_length !== 0);
  15691. strstart++;
  15692. } else {
  15693. strstart += match_length;
  15694. match_length = 0;
  15695. ins_h = window[strstart] & 0xff;
  15696. ins_h = (ins_h << hash_shift ^ window[strstart + 1] & 0xff) & hash_mask; // If lookahead < MIN_MATCH, ins_h is garbage, but it does
  15697. // not
  15698. // matter since it will be recomputed at next deflate call.
  15699. }
  15700. } else {
  15701. // No match, output a literal byte
  15702. bflush = _tr_tally(0, window[strstart] & 0xff);
  15703. lookahead--;
  15704. strstart++;
  15705. }
  15706. if (bflush) {
  15707. flush_block_only(false);
  15708. if (strm.avail_out === 0) return NeedMore;
  15709. }
  15710. }
  15711. flush_block_only(flush == Z_FINISH);
  15712. if (strm.avail_out === 0) {
  15713. if (flush == Z_FINISH) return FinishStarted;else return NeedMore;
  15714. }
  15715. return flush == Z_FINISH ? FinishDone : BlockDone;
  15716. } // Same as above, but achieves better compression. We use a lazy
  15717. // evaluation for matches: a match is finally adopted only if there is
  15718. // no better match at the next window position.
  15719. function deflate_slow(flush) {
  15720. // short hash_head = 0; // head of hash chain
  15721. var hash_head = 0; // head of hash chain
  15722. var bflush; // set if current block must be flushed
  15723. var max_insert; // Process the input block.
  15724. while (true) {
  15725. // Make sure that we always have enough lookahead, except
  15726. // at the end of the input file. We need MAX_MATCH bytes
  15727. // for the next match, plus MIN_MATCH bytes to insert the
  15728. // string following the next match.
  15729. if (lookahead < MIN_LOOKAHEAD) {
  15730. fill_window();
  15731. if (lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
  15732. return NeedMore;
  15733. }
  15734. if (lookahead === 0) break; // flush the current block
  15735. } // Insert the string window[strstart .. strstart+2] in the
  15736. // dictionary, and set hash_head to the head of the hash chain:
  15737. if (lookahead >= MIN_MATCH) {
  15738. ins_h = (ins_h << hash_shift ^ window[strstart + (MIN_MATCH - 1)] & 0xff) & hash_mask; // prev[strstart&w_mask]=hash_head=head[ins_h];
  15739. hash_head = head[ins_h] & 0xffff;
  15740. prev[strstart & w_mask] = head[ins_h];
  15741. head[ins_h] = strstart;
  15742. } // Find the longest match, discarding those <= prev_length.
  15743. prev_length = match_length;
  15744. prev_match = match_start;
  15745. match_length = MIN_MATCH - 1;
  15746. if (hash_head !== 0 && prev_length < max_lazy_match && (strstart - hash_head & 0xffff) <= w_size - MIN_LOOKAHEAD) {
  15747. // To simplify the code, we prevent matches with the string
  15748. // of window index 0 (in particular we have to avoid a match
  15749. // of the string with itself at the start of the input file).
  15750. if (strategy != Z_HUFFMAN_ONLY) {
  15751. match_length = longest_match(hash_head);
  15752. } // longest_match() sets match_start
  15753. if (match_length <= 5 && (strategy == Z_FILTERED || match_length == MIN_MATCH && strstart - match_start > 4096)) {
  15754. // If prev_match is also MIN_MATCH, match_start is garbage
  15755. // but we will ignore the current match anyway.
  15756. match_length = MIN_MATCH - 1;
  15757. }
  15758. } // If there was a match at the previous step and the current
  15759. // match is not better, output the previous match:
  15760. if (prev_length >= MIN_MATCH && match_length <= prev_length) {
  15761. max_insert = strstart + lookahead - MIN_MATCH; // Do not insert strings in hash table beyond this.
  15762. // check_match(strstart-1, prev_match, prev_length);
  15763. bflush = _tr_tally(strstart - 1 - prev_match, prev_length - MIN_MATCH); // Insert in hash table all strings up to the end of the match.
  15764. // strstart-1 and strstart are already inserted. If there is not
  15765. // enough lookahead, the last two strings are not inserted in
  15766. // the hash table.
  15767. lookahead -= prev_length - 1;
  15768. prev_length -= 2;
  15769. do {
  15770. if (++strstart <= max_insert) {
  15771. ins_h = (ins_h << hash_shift ^ window[strstart + (MIN_MATCH - 1)] & 0xff) & hash_mask; // prev[strstart&w_mask]=hash_head=head[ins_h];
  15772. hash_head = head[ins_h] & 0xffff;
  15773. prev[strstart & w_mask] = head[ins_h];
  15774. head[ins_h] = strstart;
  15775. }
  15776. } while (--prev_length !== 0);
  15777. match_available = 0;
  15778. match_length = MIN_MATCH - 1;
  15779. strstart++;
  15780. if (bflush) {
  15781. flush_block_only(false);
  15782. if (strm.avail_out === 0) return NeedMore;
  15783. }
  15784. } else if (match_available !== 0) {
  15785. // If there was no match at the previous position, output a
  15786. // single literal. If there was a match but the current match
  15787. // is longer, truncate the previous match to a single literal.
  15788. bflush = _tr_tally(0, window[strstart - 1] & 0xff);
  15789. if (bflush) {
  15790. flush_block_only(false);
  15791. }
  15792. strstart++;
  15793. lookahead--;
  15794. if (strm.avail_out === 0) return NeedMore;
  15795. } else {
  15796. // There is no previous match to compare with, wait for
  15797. // the next step to decide.
  15798. match_available = 1;
  15799. strstart++;
  15800. lookahead--;
  15801. }
  15802. }
  15803. if (match_available !== 0) {
  15804. bflush = _tr_tally(0, window[strstart - 1] & 0xff);
  15805. match_available = 0;
  15806. }
  15807. flush_block_only(flush == Z_FINISH);
  15808. if (strm.avail_out === 0) {
  15809. if (flush == Z_FINISH) return FinishStarted;else return NeedMore;
  15810. }
  15811. return flush == Z_FINISH ? FinishDone : BlockDone;
  15812. }
  15813. function deflateReset(strm) {
  15814. strm.total_in = strm.total_out = 0;
  15815. strm.msg = null; //
  15816. that.pending = 0;
  15817. that.pending_out = 0;
  15818. status = BUSY_STATE;
  15819. last_flush = Z_NO_FLUSH;
  15820. tr_init();
  15821. lm_init();
  15822. return Z_OK;
  15823. }
  15824. that.deflateInit = function (strm, _level, bits, _method, memLevel, _strategy) {
  15825. if (!_method) _method = Z_DEFLATED;
  15826. if (!memLevel) memLevel = DEF_MEM_LEVEL;
  15827. if (!_strategy) _strategy = Z_DEFAULT_STRATEGY; // byte[] my_version=ZLIB_VERSION;
  15828. //
  15829. // if (!version || version[0] != my_version[0]
  15830. // || stream_size != sizeof(z_stream)) {
  15831. // return Z_VERSION_ERROR;
  15832. // }
  15833. strm.msg = null;
  15834. if (_level == Z_DEFAULT_COMPRESSION) _level = 6;
  15835. if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || _method != Z_DEFLATED || bits < 9 || bits > 15 || _level < 0 || _level > 9 || _strategy < 0 || _strategy > Z_HUFFMAN_ONLY) {
  15836. return Z_STREAM_ERROR;
  15837. }
  15838. strm.dstate = that;
  15839. w_bits = bits;
  15840. w_size = 1 << w_bits;
  15841. w_mask = w_size - 1;
  15842. hash_bits = memLevel + 7;
  15843. hash_size = 1 << hash_bits;
  15844. hash_mask = hash_size - 1;
  15845. hash_shift = Math.floor((hash_bits + MIN_MATCH - 1) / MIN_MATCH);
  15846. window = new Uint8Array(w_size * 2);
  15847. prev = [];
  15848. head = [];
  15849. lit_bufsize = 1 << memLevel + 6; // 16K elements by default
  15850. // We overlay pending_buf and d_buf+l_buf. This works since the average
  15851. // output size for (length,distance) codes is <= 24 bits.
  15852. that.pending_buf = new Uint8Array(lit_bufsize * 4);
  15853. pending_buf_size = lit_bufsize * 4;
  15854. d_buf = Math.floor(lit_bufsize / 2);
  15855. l_buf = (1 + 2) * lit_bufsize;
  15856. level = _level;
  15857. strategy = _strategy;
  15858. return deflateReset(strm);
  15859. };
  15860. that.deflateEnd = function () {
  15861. if (status != INIT_STATE && status != BUSY_STATE && status != FINISH_STATE) {
  15862. return Z_STREAM_ERROR;
  15863. } // Deallocate in reverse order of allocations:
  15864. that.pending_buf = null;
  15865. head = null;
  15866. prev = null;
  15867. window = null; // free
  15868. that.dstate = null;
  15869. return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
  15870. };
  15871. that.deflateParams = function (strm, _level, _strategy) {
  15872. var err = Z_OK;
  15873. if (_level == Z_DEFAULT_COMPRESSION) {
  15874. _level = 6;
  15875. }
  15876. if (_level < 0 || _level > 9 || _strategy < 0 || _strategy > Z_HUFFMAN_ONLY) {
  15877. return Z_STREAM_ERROR;
  15878. }
  15879. if (config_table[level].func != config_table[_level].func && strm.total_in !== 0) {
  15880. // Flush the last buffer:
  15881. err = strm.deflate(Z_PARTIAL_FLUSH);
  15882. }
  15883. if (level != _level) {
  15884. level = _level;
  15885. max_lazy_match = config_table[level].max_lazy;
  15886. good_match = config_table[level].good_length;
  15887. nice_match = config_table[level].nice_length;
  15888. max_chain_length = config_table[level].max_chain;
  15889. }
  15890. strategy = _strategy;
  15891. return err;
  15892. };
  15893. that.deflateSetDictionary = function (strm, dictionary, dictLength) {
  15894. var length = dictLength;
  15895. var n,
  15896. index = 0;
  15897. if (!dictionary || status != INIT_STATE) return Z_STREAM_ERROR;
  15898. if (length < MIN_MATCH) return Z_OK;
  15899. if (length > w_size - MIN_LOOKAHEAD) {
  15900. length = w_size - MIN_LOOKAHEAD;
  15901. index = dictLength - length; // use the tail of the dictionary
  15902. }
  15903. window.set(dictionary.subarray(index, index + length), 0);
  15904. strstart = length;
  15905. block_start = length; // Insert all strings in the hash table (except for the last two bytes).
  15906. // s->lookahead stays null, so s->ins_h will be recomputed at the next
  15907. // call of fill_window.
  15908. ins_h = window[0] & 0xff;
  15909. ins_h = (ins_h << hash_shift ^ window[1] & 0xff) & hash_mask;
  15910. for (n = 0; n <= length - MIN_MATCH; n++) {
  15911. ins_h = (ins_h << hash_shift ^ window[n + (MIN_MATCH - 1)] & 0xff) & hash_mask;
  15912. prev[n & w_mask] = head[ins_h];
  15913. head[ins_h] = n;
  15914. }
  15915. return Z_OK;
  15916. };
  15917. that.deflate = function (_strm, flush) {
  15918. var i, header, level_flags, old_flush, bstate;
  15919. if (flush > Z_FINISH || flush < 0) {
  15920. return Z_STREAM_ERROR;
  15921. }
  15922. if (!_strm.next_out || !_strm.next_in && _strm.avail_in !== 0 || status == FINISH_STATE && flush != Z_FINISH) {
  15923. _strm.msg = z_errmsg[Z_NEED_DICT - Z_STREAM_ERROR];
  15924. return Z_STREAM_ERROR;
  15925. }
  15926. if (_strm.avail_out === 0) {
  15927. _strm.msg = z_errmsg[Z_NEED_DICT - Z_BUF_ERROR];
  15928. return Z_BUF_ERROR;
  15929. }
  15930. strm = _strm; // just in case
  15931. old_flush = last_flush;
  15932. last_flush = flush; // Write the zlib header
  15933. if (status == INIT_STATE) {
  15934. header = Z_DEFLATED + (w_bits - 8 << 4) << 8;
  15935. level_flags = (level - 1 & 0xff) >> 1;
  15936. if (level_flags > 3) level_flags = 3;
  15937. header |= level_flags << 6;
  15938. if (strstart !== 0) header |= PRESET_DICT;
  15939. header += 31 - header % 31;
  15940. status = BUSY_STATE;
  15941. putShortMSB(header);
  15942. } // Flush as much pending output as possible
  15943. if (that.pending !== 0) {
  15944. strm.flush_pending();
  15945. if (strm.avail_out === 0) {
  15946. // console.log(" avail_out==0");
  15947. // Since avail_out is 0, deflate will be called again with
  15948. // more output space, but possibly with both pending and
  15949. // avail_in equal to zero. There won't be anything to do,
  15950. // but this is not an error situation so make sure we
  15951. // return OK instead of BUF_ERROR at next call of deflate:
  15952. last_flush = -1;
  15953. return Z_OK;
  15954. } // Make sure there is something to do and avoid duplicate
  15955. // consecutive
  15956. // flushes. For repeated and useless calls with Z_FINISH, we keep
  15957. // returning Z_STREAM_END instead of Z_BUFF_ERROR.
  15958. } else if (strm.avail_in === 0 && flush <= old_flush && flush != Z_FINISH) {
  15959. strm.msg = z_errmsg[Z_NEED_DICT - Z_BUF_ERROR];
  15960. return Z_BUF_ERROR;
  15961. } // User must not provide more input after the first FINISH:
  15962. if (status == FINISH_STATE && strm.avail_in !== 0) {
  15963. _strm.msg = z_errmsg[Z_NEED_DICT - Z_BUF_ERROR];
  15964. return Z_BUF_ERROR;
  15965. } // Start a new block or continue the current one.
  15966. if (strm.avail_in !== 0 || lookahead !== 0 || flush != Z_NO_FLUSH && status != FINISH_STATE) {
  15967. bstate = -1;
  15968. switch (config_table[level].func) {
  15969. case STORED:
  15970. bstate = deflate_stored(flush);
  15971. break;
  15972. case FAST:
  15973. bstate = deflate_fast(flush);
  15974. break;
  15975. case SLOW:
  15976. bstate = deflate_slow(flush);
  15977. break;
  15978. default:
  15979. }
  15980. if (bstate == FinishStarted || bstate == FinishDone) {
  15981. status = FINISH_STATE;
  15982. }
  15983. if (bstate == NeedMore || bstate == FinishStarted) {
  15984. if (strm.avail_out === 0) {
  15985. last_flush = -1; // avoid BUF_ERROR next call, see above
  15986. }
  15987. return Z_OK; // If flush != Z_NO_FLUSH && avail_out === 0, the next call
  15988. // of deflate should use the same flush parameter to make sure
  15989. // that the flush is complete. So we don't have to output an
  15990. // empty block here, this will be done at next call. This also
  15991. // ensures that for a very small output buffer, we emit at most
  15992. // one empty block.
  15993. }
  15994. if (bstate == BlockDone) {
  15995. if (flush == Z_PARTIAL_FLUSH) {
  15996. _tr_align();
  15997. } else {
  15998. // FULL_FLUSH or SYNC_FLUSH
  15999. _tr_stored_block(0, 0, false); // For a full flush, this empty block will be recognized
  16000. // as a special marker by inflate_sync().
  16001. if (flush == Z_FULL_FLUSH) {
  16002. // state.head[s.hash_size-1]=0;
  16003. for (i = 0; i < hash_size
  16004. /*-1*/
  16005. ; i++) // forget history
  16006. head[i] = 0;
  16007. }
  16008. }
  16009. strm.flush_pending();
  16010. if (strm.avail_out === 0) {
  16011. last_flush = -1; // avoid BUF_ERROR at next call, see above
  16012. return Z_OK;
  16013. }
  16014. }
  16015. }
  16016. if (flush != Z_FINISH) return Z_OK;
  16017. return Z_STREAM_END;
  16018. };
  16019. } // ZStream
  16020. function ZStream() {
  16021. var that = this;
  16022. that.next_in_index = 0;
  16023. that.next_out_index = 0; // that.next_in; // next input byte
  16024. that.avail_in = 0; // number of bytes available at next_in
  16025. that.total_in = 0; // total nb of input bytes read so far
  16026. // that.next_out; // next output byte should be put there
  16027. that.avail_out = 0; // remaining free space at next_out
  16028. that.total_out = 0; // total nb of bytes output so far
  16029. // that.msg;
  16030. // that.dstate;
  16031. }
  16032. ZStream.prototype = {
  16033. deflateInit: function (level, bits) {
  16034. var that = this;
  16035. that.dstate = new Deflate();
  16036. if (!bits) bits = MAX_BITS;
  16037. return that.dstate.deflateInit(that, level, bits);
  16038. },
  16039. deflate: function (flush) {
  16040. var that = this;
  16041. if (!that.dstate) {
  16042. return Z_STREAM_ERROR;
  16043. }
  16044. return that.dstate.deflate(that, flush);
  16045. },
  16046. deflateEnd: function () {
  16047. var that = this;
  16048. if (!that.dstate) return Z_STREAM_ERROR;
  16049. var ret = that.dstate.deflateEnd();
  16050. that.dstate = null;
  16051. return ret;
  16052. },
  16053. deflateParams: function (level, strategy) {
  16054. var that = this;
  16055. if (!that.dstate) return Z_STREAM_ERROR;
  16056. return that.dstate.deflateParams(that, level, strategy);
  16057. },
  16058. deflateSetDictionary: function (dictionary, dictLength) {
  16059. var that = this;
  16060. if (!that.dstate) return Z_STREAM_ERROR;
  16061. return that.dstate.deflateSetDictionary(that, dictionary, dictLength);
  16062. },
  16063. // Read a new buffer from the current input stream, update the
  16064. // total number of bytes read. All deflate() input goes through
  16065. // this function so some applications may wish to modify it to avoid
  16066. // allocating a large strm->next_in buffer and copying from it.
  16067. // (See also flush_pending()).
  16068. read_buf: function (buf, start, size) {
  16069. var that = this;
  16070. var len = that.avail_in;
  16071. if (len > size) len = size;
  16072. if (len === 0) return 0;
  16073. that.avail_in -= len;
  16074. buf.set(that.next_in.subarray(that.next_in_index, that.next_in_index + len), start);
  16075. that.next_in_index += len;
  16076. that.total_in += len;
  16077. return len;
  16078. },
  16079. // Flush as much pending output as possible. All deflate() output goes
  16080. // through this function so some applications may wish to modify it
  16081. // to avoid allocating a large strm->next_out buffer and copying into it.
  16082. // (See also read_buf()).
  16083. flush_pending: function () {
  16084. var that = this;
  16085. var len = that.dstate.pending;
  16086. if (len > that.avail_out) len = that.avail_out;
  16087. if (len === 0) return; // if (that.dstate.pending_buf.length <= that.dstate.pending_out || that.next_out.length <= that.next_out_index
  16088. // || that.dstate.pending_buf.length < (that.dstate.pending_out + len) || that.next_out.length < (that.next_out_index +
  16089. // len)) {
  16090. // console.log(that.dstate.pending_buf.length + ", " + that.dstate.pending_out + ", " + that.next_out.length + ", " +
  16091. // that.next_out_index + ", " + len);
  16092. // console.log("avail_out=" + that.avail_out);
  16093. // }
  16094. that.next_out.set(that.dstate.pending_buf.subarray(that.dstate.pending_out, that.dstate.pending_out + len), that.next_out_index);
  16095. that.next_out_index += len;
  16096. that.dstate.pending_out += len;
  16097. that.total_out += len;
  16098. that.avail_out -= len;
  16099. that.dstate.pending -= len;
  16100. if (that.dstate.pending === 0) {
  16101. that.dstate.pending_out = 0;
  16102. }
  16103. }
  16104. }; // Deflater
  16105. function Deflater(options) {
  16106. var that = this;
  16107. var z = new ZStream();
  16108. var bufsize = 512;
  16109. var flush = Z_NO_FLUSH;
  16110. var buf = new Uint8Array(bufsize);
  16111. var level = options ? options.level : Z_DEFAULT_COMPRESSION;
  16112. if (typeof level == "undefined") level = Z_DEFAULT_COMPRESSION;
  16113. z.deflateInit(level);
  16114. z.next_out = buf;
  16115. that.append = function (data, onprogress) {
  16116. var err,
  16117. buffers = [],
  16118. lastIndex = 0,
  16119. bufferIndex = 0,
  16120. bufferSize = 0,
  16121. array;
  16122. if (!data.length) return;
  16123. z.next_in_index = 0;
  16124. z.next_in = data;
  16125. z.avail_in = data.length;
  16126. do {
  16127. z.next_out_index = 0;
  16128. z.avail_out = bufsize;
  16129. err = z.deflate(flush);
  16130. if (err != Z_OK) throw new Error("deflating: " + z.msg);
  16131. if (z.next_out_index) if (z.next_out_index == bufsize) buffers.push(new Uint8Array(buf));else buffers.push(new Uint8Array(buf.subarray(0, z.next_out_index)));
  16132. bufferSize += z.next_out_index;
  16133. if (onprogress && z.next_in_index > 0 && z.next_in_index != lastIndex) {
  16134. onprogress(z.next_in_index);
  16135. lastIndex = z.next_in_index;
  16136. }
  16137. } while (z.avail_in > 0 || z.avail_out === 0);
  16138. array = new Uint8Array(bufferSize);
  16139. buffers.forEach(function (chunk) {
  16140. array.set(chunk, bufferIndex);
  16141. bufferIndex += chunk.length;
  16142. });
  16143. return array;
  16144. };
  16145. that.flush = function () {
  16146. var err,
  16147. buffers = [],
  16148. bufferIndex = 0,
  16149. bufferSize = 0,
  16150. array;
  16151. do {
  16152. z.next_out_index = 0;
  16153. z.avail_out = bufsize;
  16154. err = z.deflate(Z_FINISH);
  16155. if (err != Z_STREAM_END && err != Z_OK) throw new Error("deflating: " + z.msg);
  16156. if (bufsize - z.avail_out > 0) buffers.push(new Uint8Array(buf.subarray(0, z.next_out_index)));
  16157. bufferSize += z.next_out_index;
  16158. } while (z.avail_in > 0 || z.avail_out === 0);
  16159. z.deflateEnd();
  16160. array = new Uint8Array(bufferSize);
  16161. buffers.forEach(function (chunk) {
  16162. array.set(chunk, bufferIndex);
  16163. bufferIndex += chunk.length;
  16164. });
  16165. return array;
  16166. };
  16167. } // 'zip' may not be defined in z-worker and some tests
  16168. var env = global.zip || global;
  16169. env.Deflater = env._jzlib_Deflater = Deflater;
  16170. })(typeof self !== "undefined" && self || typeof window !== "undefined" && window || typeof global !== "undefined" && global || Function('return typeof this === "object" && this.content')() || Function("return this")()); // `self` is undefined in Firefox for Android content script context
  16171. // while `this` is nsIContentFrameMessageManager
  16172. // with an attribute `content` that corresponds to the window
  16173. /**
  16174. * A class to parse color values
  16175. * @author Stoyan Stefanov <sstoo@gmail.com>
  16176. * @link http://www.phpied.com/rgb-color-parser-in-javascript/
  16177. * @license Use it if you like it
  16178. */
  16179. (function (global) {
  16180. function RGBColor(color_string) {
  16181. this.ok = false; // strip any leading #
  16182. if (color_string.charAt(0) == "#") {
  16183. // remove # if any
  16184. color_string = color_string.substr(1, 6);
  16185. }
  16186. color_string = color_string.replace(/ /g, "");
  16187. color_string = color_string.toLowerCase();
  16188. var channels; // before getting into regexps, try simple matches
  16189. // and overwrite the input
  16190. var simple_colors = {
  16191. aliceblue: "f0f8ff",
  16192. antiquewhite: "faebd7",
  16193. aqua: "00ffff",
  16194. aquamarine: "7fffd4",
  16195. azure: "f0ffff",
  16196. beige: "f5f5dc",
  16197. bisque: "ffe4c4",
  16198. black: "000000",
  16199. blanchedalmond: "ffebcd",
  16200. blue: "0000ff",
  16201. blueviolet: "8a2be2",
  16202. brown: "a52a2a",
  16203. burlywood: "deb887",
  16204. cadetblue: "5f9ea0",
  16205. chartreuse: "7fff00",
  16206. chocolate: "d2691e",
  16207. coral: "ff7f50",
  16208. cornflowerblue: "6495ed",
  16209. cornsilk: "fff8dc",
  16210. crimson: "dc143c",
  16211. cyan: "00ffff",
  16212. darkblue: "00008b",
  16213. darkcyan: "008b8b",
  16214. darkgoldenrod: "b8860b",
  16215. darkgray: "a9a9a9",
  16216. darkgreen: "006400",
  16217. darkkhaki: "bdb76b",
  16218. darkmagenta: "8b008b",
  16219. darkolivegreen: "556b2f",
  16220. darkorange: "ff8c00",
  16221. darkorchid: "9932cc",
  16222. darkred: "8b0000",
  16223. darksalmon: "e9967a",
  16224. darkseagreen: "8fbc8f",
  16225. darkslateblue: "483d8b",
  16226. darkslategray: "2f4f4f",
  16227. darkturquoise: "00ced1",
  16228. darkviolet: "9400d3",
  16229. deeppink: "ff1493",
  16230. deepskyblue: "00bfff",
  16231. dimgray: "696969",
  16232. dodgerblue: "1e90ff",
  16233. feldspar: "d19275",
  16234. firebrick: "b22222",
  16235. floralwhite: "fffaf0",
  16236. forestgreen: "228b22",
  16237. fuchsia: "ff00ff",
  16238. gainsboro: "dcdcdc",
  16239. ghostwhite: "f8f8ff",
  16240. gold: "ffd700",
  16241. goldenrod: "daa520",
  16242. gray: "808080",
  16243. green: "008000",
  16244. greenyellow: "adff2f",
  16245. honeydew: "f0fff0",
  16246. hotpink: "ff69b4",
  16247. indianred: "cd5c5c",
  16248. indigo: "4b0082",
  16249. ivory: "fffff0",
  16250. khaki: "f0e68c",
  16251. lavender: "e6e6fa",
  16252. lavenderblush: "fff0f5",
  16253. lawngreen: "7cfc00",
  16254. lemonchiffon: "fffacd",
  16255. lightblue: "add8e6",
  16256. lightcoral: "f08080",
  16257. lightcyan: "e0ffff",
  16258. lightgoldenrodyellow: "fafad2",
  16259. lightgrey: "d3d3d3",
  16260. lightgreen: "90ee90",
  16261. lightpink: "ffb6c1",
  16262. lightsalmon: "ffa07a",
  16263. lightseagreen: "20b2aa",
  16264. lightskyblue: "87cefa",
  16265. lightslateblue: "8470ff",
  16266. lightslategray: "778899",
  16267. lightsteelblue: "b0c4de",
  16268. lightyellow: "ffffe0",
  16269. lime: "00ff00",
  16270. limegreen: "32cd32",
  16271. linen: "faf0e6",
  16272. magenta: "ff00ff",
  16273. maroon: "800000",
  16274. mediumaquamarine: "66cdaa",
  16275. mediumblue: "0000cd",
  16276. mediumorchid: "ba55d3",
  16277. mediumpurple: "9370d8",
  16278. mediumseagreen: "3cb371",
  16279. mediumslateblue: "7b68ee",
  16280. mediumspringgreen: "00fa9a",
  16281. mediumturquoise: "48d1cc",
  16282. mediumvioletred: "c71585",
  16283. midnightblue: "191970",
  16284. mintcream: "f5fffa",
  16285. mistyrose: "ffe4e1",
  16286. moccasin: "ffe4b5",
  16287. navajowhite: "ffdead",
  16288. navy: "000080",
  16289. oldlace: "fdf5e6",
  16290. olive: "808000",
  16291. olivedrab: "6b8e23",
  16292. orange: "ffa500",
  16293. orangered: "ff4500",
  16294. orchid: "da70d6",
  16295. palegoldenrod: "eee8aa",
  16296. palegreen: "98fb98",
  16297. paleturquoise: "afeeee",
  16298. palevioletred: "d87093",
  16299. papayawhip: "ffefd5",
  16300. peachpuff: "ffdab9",
  16301. peru: "cd853f",
  16302. pink: "ffc0cb",
  16303. plum: "dda0dd",
  16304. powderblue: "b0e0e6",
  16305. purple: "800080",
  16306. red: "ff0000",
  16307. rosybrown: "bc8f8f",
  16308. royalblue: "4169e1",
  16309. saddlebrown: "8b4513",
  16310. salmon: "fa8072",
  16311. sandybrown: "f4a460",
  16312. seagreen: "2e8b57",
  16313. seashell: "fff5ee",
  16314. sienna: "a0522d",
  16315. silver: "c0c0c0",
  16316. skyblue: "87ceeb",
  16317. slateblue: "6a5acd",
  16318. slategray: "708090",
  16319. snow: "fffafa",
  16320. springgreen: "00ff7f",
  16321. steelblue: "4682b4",
  16322. tan: "d2b48c",
  16323. teal: "008080",
  16324. thistle: "d8bfd8",
  16325. tomato: "ff6347",
  16326. turquoise: "40e0d0",
  16327. violet: "ee82ee",
  16328. violetred: "d02090",
  16329. wheat: "f5deb3",
  16330. white: "ffffff",
  16331. whitesmoke: "f5f5f5",
  16332. yellow: "ffff00",
  16333. yellowgreen: "9acd32"
  16334. };
  16335. for (var key in simple_colors) {
  16336. if (color_string == key) {
  16337. color_string = simple_colors[key];
  16338. }
  16339. } // emd of simple type-in colors
  16340. // array of color definition objects
  16341. var color_defs = [{
  16342. re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,
  16343. example: ["rgb(123, 234, 45)", "rgb(255,234,245)"],
  16344. process: function (bits) {
  16345. return [parseInt(bits[1]), parseInt(bits[2]), parseInt(bits[3])];
  16346. }
  16347. }, {
  16348. re: /^(\w{2})(\w{2})(\w{2})$/,
  16349. example: ["#00ff00", "336699"],
  16350. process: function (bits) {
  16351. return [parseInt(bits[1], 16), parseInt(bits[2], 16), parseInt(bits[3], 16)];
  16352. }
  16353. }, {
  16354. re: /^(\w{1})(\w{1})(\w{1})$/,
  16355. example: ["#fb0", "f0f"],
  16356. process: function (bits) {
  16357. return [parseInt(bits[1] + bits[1], 16), parseInt(bits[2] + bits[2], 16), parseInt(bits[3] + bits[3], 16)];
  16358. }
  16359. }]; // search through the definitions to find a match
  16360. for (var i = 0; i < color_defs.length; i++) {
  16361. var re = color_defs[i].re;
  16362. var processor = color_defs[i].process;
  16363. var bits = re.exec(color_string);
  16364. if (bits) {
  16365. channels = processor(bits);
  16366. this.r = channels[0];
  16367. this.g = channels[1];
  16368. this.b = channels[2];
  16369. this.ok = true;
  16370. }
  16371. } // validate/cleanup values
  16372. this.r = this.r < 0 || isNaN(this.r) ? 0 : this.r > 255 ? 255 : this.r;
  16373. this.g = this.g < 0 || isNaN(this.g) ? 0 : this.g > 255 ? 255 : this.g;
  16374. this.b = this.b < 0 || isNaN(this.b) ? 0 : this.b > 255 ? 255 : this.b; // some getters
  16375. this.toRGB = function () {
  16376. return "rgb(" + this.r + ", " + this.g + ", " + this.b + ")";
  16377. };
  16378. this.toHex = function () {
  16379. var r = this.r.toString(16);
  16380. var g = this.g.toString(16);
  16381. var b = this.b.toString(16);
  16382. if (r.length == 1) r = "0" + r;
  16383. if (g.length == 1) g = "0" + g;
  16384. if (b.length == 1) b = "0" + b;
  16385. return "#" + r + g + b;
  16386. }; // help
  16387. this.getHelpXML = function () {
  16388. var examples = new Array(); // add regexps
  16389. for (var i = 0; i < color_defs.length; i++) {
  16390. var example = color_defs[i].example;
  16391. for (var j = 0; j < example.length; j++) {
  16392. examples[examples.length] = example[j];
  16393. }
  16394. } // add type-in colors
  16395. for (var sc in simple_colors) {
  16396. examples[examples.length] = sc;
  16397. }
  16398. var xml = document.createElement("ul");
  16399. xml.setAttribute("id", "rgbcolor-examples");
  16400. for (var i = 0; i < examples.length; i++) {
  16401. try {
  16402. var list_item = document.createElement("li");
  16403. var list_color = new RGBColor(examples[i]);
  16404. var example_div = document.createElement("div");
  16405. example_div.style.cssText = "margin: 3px; " + "border: 1px solid black; " + "background:" + list_color.toHex() + "; " + "color:" + list_color.toHex();
  16406. example_div.appendChild(document.createTextNode("test"));
  16407. var list_item_value = document.createTextNode(" " + examples[i] + " -> " + list_color.toRGB() + " -> " + list_color.toHex());
  16408. list_item.appendChild(example_div);
  16409. list_item.appendChild(list_item_value);
  16410. xml.appendChild(list_item);
  16411. } catch (e) {}
  16412. }
  16413. return xml;
  16414. };
  16415. } // export as AMD...
  16416. if (typeof define !== "undefined" && define.amd) {
  16417. define("RGBColor", function () {
  16418. return RGBColor;
  16419. });
  16420. } // ...or as browserify
  16421. else if (typeof module !== "undefined" && module.exports) {
  16422. module.exports = RGBColor;
  16423. }
  16424. global.RGBColor = RGBColor;
  16425. })(typeof self !== "undefined" && self || typeof window !== "undefined" && window || typeof global !== "undefined" && global || Function('return typeof this === "object" && this.content')() || Function("return this")()); // `self` is undefined in Firefox for Android content script context
  16426. // while `this` is nsIContentFrameMessageManager
  16427. // with an attribute `content` that corresponds to the window
  16428. /************************************************
  16429. * Title : custom font *
  16430. * Start Data : 2017. 01. 22. *
  16431. * Comment : TEXT API *
  16432. ************************************************/
  16433. /******************************
  16434. * jsPDF extension API Design *
  16435. * ****************************/
  16436. (function (jsPDF) {
  16437. var PLUS = "+".charCodeAt(0);
  16438. var SLASH = "/".charCodeAt(0);
  16439. var NUMBER = "0".charCodeAt(0);
  16440. var LOWER = "a".charCodeAt(0);
  16441. var UPPER = "A".charCodeAt(0);
  16442. var PLUS_URL_SAFE = "-".charCodeAt(0);
  16443. var SLASH_URL_SAFE = "_".charCodeAt(0);
  16444. /*****************************************************************/
  16445. /* function : b64ToByteArray */
  16446. /* comment : Base64 encoded TTF file contents (b64) are decoded */
  16447. /* by Byte array and stored. */
  16448. /*****************************************************************/
  16449. var b64ToByteArray = function (b64) {
  16450. var i, j, l, tmp, placeHolders, arr;
  16451. if (b64.length % 4 > 0) {
  16452. throw new Error("Invalid string. Length must be a multiple of 4");
  16453. } // the number of equal signs (place holders)
  16454. // if there are two placeholders, than the two characters before it
  16455. // represent one byte
  16456. // if there is only one, then the three characters before it represent 2 bytes
  16457. // this is just a cheap hack to not do indexOf twice
  16458. var len = b64.length;
  16459. placeHolders = "=" === b64.charAt(len - 2) ? 2 : "=" === b64.charAt(len - 1) ? 1 : 0; // base64 is 4/3 + up to two characters of the original data
  16460. arr = new Uint8Array(b64.length * 3 / 4 - placeHolders); // if there are placeholders, only get up to the last complete 4 chars
  16461. l = placeHolders > 0 ? b64.length - 4 : b64.length;
  16462. var L = 0;
  16463. function push(v) {
  16464. arr[L++] = v;
  16465. }
  16466. for (i = 0, j = 0; i < l; i += 4, j += 3) {
  16467. tmp = decode(b64.charAt(i)) << 18 | decode(b64.charAt(i + 1)) << 12 | decode(b64.charAt(i + 2)) << 6 | decode(b64.charAt(i + 3));
  16468. push((tmp & 0xff0000) >> 16);
  16469. push((tmp & 0xff00) >> 8);
  16470. push(tmp & 0xff);
  16471. }
  16472. if (placeHolders === 2) {
  16473. tmp = decode(b64.charAt(i)) << 2 | decode(b64.charAt(i + 1)) >> 4;
  16474. push(tmp & 0xff);
  16475. } else if (placeHolders === 1) {
  16476. tmp = decode(b64.charAt(i)) << 10 | decode(b64.charAt(i + 1)) << 4 | decode(b64.charAt(i + 2)) >> 2;
  16477. push(tmp >> 8 & 0xff);
  16478. push(tmp & 0xff);
  16479. }
  16480. return arr;
  16481. };
  16482. /***************************************************************/
  16483. /* function : decode */
  16484. /* comment : Change the base64 encoded font's content to match */
  16485. /* the base64 index value. */
  16486. /***************************************************************/
  16487. var decode = function (elt) {
  16488. var code = elt.charCodeAt(0);
  16489. if (code === PLUS || code === PLUS_URL_SAFE) return 62; // '+'
  16490. if (code === SLASH || code === SLASH_URL_SAFE) return 63; // '/'
  16491. if (code < NUMBER) return -1; //no match
  16492. if (code < NUMBER + 10) return code - NUMBER + 26 + 26;
  16493. if (code < UPPER + 26) return code - UPPER;
  16494. if (code < LOWER + 26) return code - LOWER + 26;
  16495. };
  16496. jsPDF.API.TTFFont = function () {
  16497. /************************************************************************/
  16498. /* function : open */
  16499. /* comment : Decode the encoded ttf content and create a TTFFont object. */
  16500. /************************************************************************/
  16501. TTFFont.open = function (filename, name, vfs, encoding) {
  16502. var contents;
  16503. contents = b64ToByteArray(vfs);
  16504. return new TTFFont(contents, name, encoding);
  16505. };
  16506. /***************************************************************/
  16507. /* function : TTFFont gernerator */
  16508. /* comment : Decode TTF contents are parsed, Data, */
  16509. /* Subset object is created, and registerTTF function is called.*/
  16510. /***************************************************************/
  16511. function TTFFont(rawData, name, encoding) {
  16512. var data;
  16513. this.rawData = rawData;
  16514. data = this.contents = new Data(rawData);
  16515. this.contents.pos = 4;
  16516. if (data.readString(4) === "ttcf") {
  16517. if (!name) {
  16518. throw new Error("Must specify a font name for TTC files.");
  16519. }
  16520. throw new Error("Font " + name + " not found in TTC file.");
  16521. } else {
  16522. data.pos = 0;
  16523. this.parse();
  16524. this.subset = new Subset(this);
  16525. this.registerTTF();
  16526. }
  16527. }
  16528. /********************************************************/
  16529. /* function : parse */
  16530. /* comment : TTF Parses the file contents by each table.*/
  16531. /********************************************************/
  16532. TTFFont.prototype.parse = function () {
  16533. this.directory = new Directory(this.contents);
  16534. this.head = new HeadTable(this);
  16535. this.name = new NameTable(this);
  16536. this.cmap = new CmapTable(this);
  16537. this.hhea = new HheaTable(this);
  16538. this.maxp = new MaxpTable(this);
  16539. this.hmtx = new HmtxTable(this);
  16540. this.post = new PostTable(this);
  16541. this.os2 = new OS2Table(this);
  16542. this.loca = new LocaTable(this);
  16543. this.glyf = new GlyfTable(this);
  16544. this.ascender = this.os2.exists && this.os2.ascender || this.hhea.ascender;
  16545. this.decender = this.os2.exists && this.os2.decender || this.hhea.decender;
  16546. this.lineGap = this.os2.exists && this.os2.lineGap || this.hhea.lineGap;
  16547. return this.bbox = [this.head.xMin, this.head.yMin, this.head.xMax, this.head.yMax];
  16548. };
  16549. /***************************************************************/
  16550. /* function : registerTTF */
  16551. /* comment : Get the value to assign pdf font descriptors. */
  16552. /***************************************************************/
  16553. TTFFont.prototype.registerTTF = function () {
  16554. var e, hi, low, raw, _ref;
  16555. this.scaleFactor = 1000.0 / this.head.unitsPerEm;
  16556. this.bbox = function () {
  16557. var _i, _len, _ref, _results;
  16558. _ref = this.bbox;
  16559. _results = [];
  16560. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  16561. e = _ref[_i];
  16562. _results.push(Math.round(e * this.scaleFactor));
  16563. }
  16564. return _results;
  16565. }.call(this);
  16566. this.stemV = 0;
  16567. if (this.post.exists) {
  16568. raw = this.post.italic_angle;
  16569. hi = raw >> 16;
  16570. low = raw & 0xff;
  16571. if (hi & 0x8000 !== 0) {
  16572. hi = -((hi ^ 0xffff) + 1);
  16573. }
  16574. this.italicAngle = +("" + hi + "." + low);
  16575. } else {
  16576. this.italicAngle = 0;
  16577. }
  16578. this.ascender = Math.round(this.ascender * this.scaleFactor);
  16579. this.decender = Math.round(this.decender * this.scaleFactor);
  16580. this.lineGap = Math.round(this.lineGap * this.scaleFactor);
  16581. this.capHeight = this.os2.exists && this.os2.capHeight || this.ascender;
  16582. this.xHeight = this.os2.exists && this.os2.xHeight || 0;
  16583. this.familyClass = (this.os2.exists && this.os2.familyClass || 0) >> 8;
  16584. this.isSerif = (_ref = this.familyClass) === 1 || _ref === 2 || _ref === 3 || _ref === 4 || _ref === 5 || _ref === 7;
  16585. this.isScript = this.familyClass === 10;
  16586. this.flags = 0;
  16587. if (this.post.isFixedPitch) {
  16588. this.flags |= 1 << 0;
  16589. }
  16590. if (this.isSerif) {
  16591. this.flags |= 1 << 1;
  16592. }
  16593. if (this.isScript) {
  16594. this.flags |= 1 << 3;
  16595. }
  16596. if (this.italicAngle !== 0) {
  16597. this.flags |= 1 << 6;
  16598. }
  16599. this.flags |= 1 << 5;
  16600. if (!this.cmap.unicode) {
  16601. throw new Error("No unicode cmap for font");
  16602. }
  16603. };
  16604. TTFFont.prototype.characterToGlyph = function (character) {
  16605. var _ref;
  16606. return ((_ref = this.cmap.unicode) != null ? _ref.codeMap[character] : void 0) || 0;
  16607. };
  16608. TTFFont.prototype.widthOfGlyph = function (glyph) {
  16609. var scale;
  16610. scale = 1000.0 / this.head.unitsPerEm;
  16611. return this.hmtx.forGlyph(glyph).advance * scale;
  16612. };
  16613. TTFFont.prototype.widthOfString = function (string, size, charSpace) {
  16614. var charCode, i, scale, width, _i, _ref, charSpace;
  16615. string = "" + string;
  16616. width = 0;
  16617. for (i = _i = 0, _ref = string.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
  16618. charCode = string.charCodeAt(i);
  16619. width += this.widthOfGlyph(this.characterToGlyph(charCode)) + charSpace * (1000 / size) || 0;
  16620. }
  16621. scale = size / 1000;
  16622. return width * scale;
  16623. };
  16624. TTFFont.prototype.lineHeight = function (size, includeGap) {
  16625. var gap;
  16626. if (includeGap == null) {
  16627. includeGap = false;
  16628. }
  16629. gap = includeGap ? this.lineGap : 0;
  16630. return (this.ascender + gap - this.decender) / 1000 * size;
  16631. };
  16632. return TTFFont;
  16633. }();
  16634. /************************************************************************************************/
  16635. /* function : Data */
  16636. /* comment : The ttf data decoded and stored in an array is read and written to the Data object.*/
  16637. /************************************************************************************************/
  16638. var Data = function () {
  16639. function Data(data) {
  16640. this.data = data != null ? data : [];
  16641. this.pos = 0;
  16642. this.length = this.data.length;
  16643. }
  16644. Data.prototype.readByte = function () {
  16645. return this.data[this.pos++];
  16646. };
  16647. Data.prototype.writeByte = function (byte) {
  16648. return this.data[this.pos++] = byte;
  16649. };
  16650. Data.prototype.readUInt32 = function () {
  16651. var b1, b2, b3, b4;
  16652. b1 = this.readByte() * 0x1000000;
  16653. b2 = this.readByte() << 16;
  16654. b3 = this.readByte() << 8;
  16655. b4 = this.readByte();
  16656. return b1 + b2 + b3 + b4;
  16657. };
  16658. Data.prototype.writeUInt32 = function (val) {
  16659. this.writeByte(val >>> 24 & 0xff);
  16660. this.writeByte(val >> 16 & 0xff);
  16661. this.writeByte(val >> 8 & 0xff);
  16662. return this.writeByte(val & 0xff);
  16663. };
  16664. Data.prototype.readInt32 = function () {
  16665. var int;
  16666. int = this.readUInt32();
  16667. if (int >= 0x80000000) {
  16668. return int - 0x100000000;
  16669. } else {
  16670. return int;
  16671. }
  16672. };
  16673. Data.prototype.writeInt32 = function (val) {
  16674. if (val < 0) {
  16675. val += 0x100000000;
  16676. }
  16677. return this.writeUInt32(val);
  16678. };
  16679. Data.prototype.readUInt16 = function () {
  16680. var b1, b2;
  16681. b1 = this.readByte() << 8;
  16682. b2 = this.readByte();
  16683. return b1 | b2;
  16684. };
  16685. Data.prototype.writeUInt16 = function (val) {
  16686. this.writeByte(val >> 8 & 0xff);
  16687. return this.writeByte(val & 0xff);
  16688. };
  16689. Data.prototype.readInt16 = function () {
  16690. var int;
  16691. int = this.readUInt16();
  16692. if (int >= 0x8000) {
  16693. return int - 0x10000;
  16694. } else {
  16695. return int;
  16696. }
  16697. };
  16698. Data.prototype.writeInt16 = function (val) {
  16699. if (val < 0) {
  16700. val += 0x10000;
  16701. }
  16702. return this.writeUInt16(val);
  16703. };
  16704. Data.prototype.readString = function (length) {
  16705. var i, ret, _i;
  16706. ret = [];
  16707. for (i = _i = 0; 0 <= length ? _i < length : _i > length; i = 0 <= length ? ++_i : --_i) {
  16708. ret[i] = String.fromCharCode(this.readByte());
  16709. }
  16710. return ret.join("");
  16711. };
  16712. Data.prototype.writeString = function (val) {
  16713. var i, _i, _ref, _results;
  16714. _results = [];
  16715. for (i = _i = 0, _ref = val.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
  16716. _results.push(this.writeByte(val.charCodeAt(i)));
  16717. }
  16718. return _results;
  16719. };
  16720. /*Data.prototype.stringAt = function (pos, length) {
  16721. this.pos = pos;
  16722. return this.readString(length);
  16723. };*/
  16724. Data.prototype.readShort = function () {
  16725. return this.readInt16();
  16726. };
  16727. Data.prototype.writeShort = function (val) {
  16728. return this.writeInt16(val);
  16729. };
  16730. Data.prototype.readLongLong = function () {
  16731. var b1, b2, b3, b4, b5, b6, b7, b8;
  16732. b1 = this.readByte();
  16733. b2 = this.readByte();
  16734. b3 = this.readByte();
  16735. b4 = this.readByte();
  16736. b5 = this.readByte();
  16737. b6 = this.readByte();
  16738. b7 = this.readByte();
  16739. b8 = this.readByte();
  16740. if (b1 & 0x80) {
  16741. return ((b1 ^ 0xff) * 0x100000000000000 + (b2 ^ 0xff) * 0x1000000000000 + (b3 ^ 0xff) * 0x10000000000 + (b4 ^ 0xff) * 0x100000000 + (b5 ^ 0xff) * 0x1000000 + (b6 ^ 0xff) * 0x10000 + (b7 ^ 0xff) * 0x100 + (b8 ^ 0xff) + 1) * -1;
  16742. }
  16743. return b1 * 0x100000000000000 + b2 * 0x1000000000000 + b3 * 0x10000000000 + b4 * 0x100000000 + b5 * 0x1000000 + b6 * 0x10000 + b7 * 0x100 + b8;
  16744. };
  16745. /*Data.prototype.writeLongLong = function (val) {
  16746. var high, low;
  16747. high = Math.floor(val / 0x100000000);
  16748. low = val & 0xffffffff;
  16749. this.writeByte((high >> 24) & 0xff);
  16750. this.writeByte((high >> 16) & 0xff);
  16751. this.writeByte((high >> 8) & 0xff);
  16752. this.writeByte(high & 0xff);
  16753. this.writeByte((low >> 24) & 0xff);
  16754. this.writeByte((low >> 16) & 0xff);
  16755. this.writeByte((low >> 8) & 0xff);
  16756. return this.writeByte(low & 0xff);
  16757. };*/
  16758. Data.prototype.readInt = function () {
  16759. return this.readInt32();
  16760. };
  16761. Data.prototype.writeInt = function (val) {
  16762. return this.writeInt32(val);
  16763. };
  16764. /*Data.prototype.slice = function (start, end) {
  16765. return this.data.slice(start, end);
  16766. };*/
  16767. Data.prototype.read = function (bytes) {
  16768. var buf, i, _i;
  16769. buf = [];
  16770. for (i = _i = 0; 0 <= bytes ? _i < bytes : _i > bytes; i = 0 <= bytes ? ++_i : --_i) {
  16771. buf.push(this.readByte());
  16772. }
  16773. return buf;
  16774. };
  16775. Data.prototype.write = function (bytes) {
  16776. var byte, _i, _len, _results;
  16777. _results = [];
  16778. for (_i = 0, _len = bytes.length; _i < _len; _i++) {
  16779. byte = bytes[_i];
  16780. _results.push(this.writeByte(byte));
  16781. }
  16782. return _results;
  16783. };
  16784. return Data;
  16785. }();
  16786. var Directory = function () {
  16787. var checksum;
  16788. /*****************************************************************************************************/
  16789. /* function : Directory generator */
  16790. /* comment : Initialize the offset, tag, length, and checksum for each table for the font to be used.*/
  16791. /*****************************************************************************************************/
  16792. function Directory(data) {
  16793. var entry, i, _i, _ref;
  16794. this.scalarType = data.readInt();
  16795. this.tableCount = data.readShort();
  16796. this.searchRange = data.readShort();
  16797. this.entrySelector = data.readShort();
  16798. this.rangeShift = data.readShort();
  16799. this.tables = {};
  16800. for (i = _i = 0, _ref = this.tableCount; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
  16801. entry = {
  16802. tag: data.readString(4),
  16803. checksum: data.readInt(),
  16804. offset: data.readInt(),
  16805. length: data.readInt()
  16806. };
  16807. this.tables[entry.tag] = entry;
  16808. }
  16809. }
  16810. /********************************************************************************************************/
  16811. /* function : encode */
  16812. /* comment : It encodes and stores the font table object and information used for the directory object. */
  16813. /********************************************************************************************************/
  16814. Directory.prototype.encode = function (tables) {
  16815. var adjustment, directory, directoryLength, entrySelector, headOffset, log2, offset, rangeShift, searchRange, sum, table, tableCount, tableData, tag;
  16816. tableCount = Object.keys(tables).length;
  16817. log2 = Math.log(2);
  16818. searchRange = Math.floor(Math.log(tableCount) / log2) * 16;
  16819. entrySelector = Math.floor(searchRange / log2);
  16820. rangeShift = tableCount * 16 - searchRange;
  16821. directory = new Data();
  16822. directory.writeInt(this.scalarType);
  16823. directory.writeShort(tableCount);
  16824. directory.writeShort(searchRange);
  16825. directory.writeShort(entrySelector);
  16826. directory.writeShort(rangeShift);
  16827. directoryLength = tableCount * 16;
  16828. offset = directory.pos + directoryLength;
  16829. headOffset = null;
  16830. tableData = [];
  16831. for (tag in tables) {
  16832. table = tables[tag];
  16833. directory.writeString(tag);
  16834. directory.writeInt(checksum(table));
  16835. directory.writeInt(offset);
  16836. directory.writeInt(table.length);
  16837. tableData = tableData.concat(table);
  16838. if (tag === "head") {
  16839. headOffset = offset;
  16840. }
  16841. offset += table.length;
  16842. while (offset % 4) {
  16843. tableData.push(0);
  16844. offset++;
  16845. }
  16846. }
  16847. directory.write(tableData);
  16848. sum = checksum(directory.data);
  16849. adjustment = 0xb1b0afba - sum;
  16850. directory.pos = headOffset + 8;
  16851. directory.writeUInt32(adjustment);
  16852. return directory.data;
  16853. };
  16854. /***************************************************************/
  16855. /* function : checksum */
  16856. /* comment : Duplicate the table for the tag. */
  16857. /***************************************************************/
  16858. checksum = function (data) {
  16859. var i, sum, tmp, _i, _ref;
  16860. data = __slice.call(data);
  16861. while (data.length % 4) {
  16862. data.push(0);
  16863. }
  16864. tmp = new Data(data);
  16865. sum = 0;
  16866. for (i = _i = 0, _ref = data.length; _i < _ref; i = _i += 4) {
  16867. sum += tmp.readUInt32();
  16868. }
  16869. return sum & 0xffffffff;
  16870. };
  16871. return Directory;
  16872. }();
  16873. var Table,
  16874. __hasProp = {}.hasOwnProperty,
  16875. __extends = function (child, parent) {
  16876. for (var key in parent) {
  16877. if (__hasProp.call(parent, key)) child[key] = parent[key];
  16878. }
  16879. function ctor() {
  16880. this.constructor = child;
  16881. }
  16882. ctor.prototype = parent.prototype;
  16883. child.prototype = new ctor();
  16884. child.__super__ = parent.prototype;
  16885. return child;
  16886. };
  16887. /***************************************************************/
  16888. /* function : Table */
  16889. /* comment : Save info for each table, and parse the table. */
  16890. /***************************************************************/
  16891. Table = function () {
  16892. function Table(file) {
  16893. var info;
  16894. this.file = file;
  16895. info = this.file.directory.tables[this.tag];
  16896. this.exists = !!info;
  16897. if (info) {
  16898. this.offset = info.offset, this.length = info.length;
  16899. this.parse(this.file.contents);
  16900. }
  16901. }
  16902. Table.prototype.parse = function () {};
  16903. Table.prototype.encode = function () {};
  16904. Table.prototype.raw = function () {
  16905. if (!this.exists) {
  16906. return null;
  16907. }
  16908. this.file.contents.pos = this.offset;
  16909. return this.file.contents.read(this.length);
  16910. };
  16911. return Table;
  16912. }();
  16913. var HeadTable = function (_super) {
  16914. __extends(HeadTable, _super);
  16915. function HeadTable() {
  16916. return HeadTable.__super__.constructor.apply(this, arguments);
  16917. }
  16918. HeadTable.prototype.tag = "head";
  16919. HeadTable.prototype.parse = function (data) {
  16920. data.pos = this.offset;
  16921. this.version = data.readInt();
  16922. this.revision = data.readInt();
  16923. this.checkSumAdjustment = data.readInt();
  16924. this.magicNumber = data.readInt();
  16925. this.flags = data.readShort();
  16926. this.unitsPerEm = data.readShort();
  16927. this.created = data.readLongLong();
  16928. this.modified = data.readLongLong();
  16929. this.xMin = data.readShort();
  16930. this.yMin = data.readShort();
  16931. this.xMax = data.readShort();
  16932. this.yMax = data.readShort();
  16933. this.macStyle = data.readShort();
  16934. this.lowestRecPPEM = data.readShort();
  16935. this.fontDirectionHint = data.readShort();
  16936. this.indexToLocFormat = data.readShort();
  16937. return this.glyphDataFormat = data.readShort();
  16938. };
  16939. /*HeadTable.prototype.encode = function (loca) {
  16940. var table;
  16941. table = new Data;
  16942. table.writeInt(this.version);
  16943. table.writeInt(this.revision);
  16944. table.writeInt(this.checkSumAdjustment);
  16945. table.writeInt(this.magicNumber);
  16946. table.writeShort(this.flags);
  16947. table.writeShort(this.unitsPerEm);
  16948. table.writeLongLong(this.created);
  16949. table.writeLongLong(this.modified);
  16950. table.writeShort(this.xMin);
  16951. table.writeShort(this.yMin);
  16952. table.writeShort(this.xMax);
  16953. table.writeShort(this.yMax);
  16954. table.writeShort(this.macStyle);
  16955. table.writeShort(this.lowestRecPPEM);
  16956. table.writeShort(this.fontDirectionHint);
  16957. table.writeShort(loca.type);
  16958. table.writeShort(this.glyphDataFormat);
  16959. return table.data;
  16960. };*/
  16961. return HeadTable;
  16962. }(Table);
  16963. /************************************************************************************/
  16964. /* function : CmapEntry */
  16965. /* comment : Cmap Initializes and encodes object information (required by pdf spec).*/
  16966. /************************************************************************************/
  16967. var CmapEntry = function () {
  16968. function CmapEntry(data, offset) {
  16969. var code, count, endCode, glyphId, glyphIds, i, idDelta, idRangeOffset, index, saveOffset, segCount, segCountX2, start, startCode, tail, _i, _j, _k, _len;
  16970. this.platformID = data.readUInt16();
  16971. this.encodingID = data.readShort();
  16972. this.offset = offset + data.readInt();
  16973. saveOffset = data.pos;
  16974. data.pos = this.offset;
  16975. this.format = data.readUInt16();
  16976. this.length = data.readUInt16();
  16977. this.language = data.readUInt16();
  16978. this.isUnicode = this.platformID === 3 && this.encodingID === 1 && this.format === 4 || this.platformID === 0 && this.format === 4;
  16979. this.codeMap = {};
  16980. switch (this.format) {
  16981. case 0:
  16982. for (i = _i = 0; _i < 256; i = ++_i) {
  16983. this.codeMap[i] = data.readByte();
  16984. }
  16985. break;
  16986. case 4:
  16987. segCountX2 = data.readUInt16();
  16988. segCount = segCountX2 / 2;
  16989. data.pos += 6;
  16990. endCode = function () {
  16991. var _j, _results;
  16992. _results = [];
  16993. for (i = _j = 0; 0 <= segCount ? _j < segCount : _j > segCount; i = 0 <= segCount ? ++_j : --_j) {
  16994. _results.push(data.readUInt16());
  16995. }
  16996. return _results;
  16997. }();
  16998. data.pos += 2;
  16999. startCode = function () {
  17000. var _j, _results;
  17001. _results = [];
  17002. for (i = _j = 0; 0 <= segCount ? _j < segCount : _j > segCount; i = 0 <= segCount ? ++_j : --_j) {
  17003. _results.push(data.readUInt16());
  17004. }
  17005. return _results;
  17006. }();
  17007. idDelta = function () {
  17008. var _j, _results;
  17009. _results = [];
  17010. for (i = _j = 0; 0 <= segCount ? _j < segCount : _j > segCount; i = 0 <= segCount ? ++_j : --_j) {
  17011. _results.push(data.readUInt16());
  17012. }
  17013. return _results;
  17014. }();
  17015. idRangeOffset = function () {
  17016. var _j, _results;
  17017. _results = [];
  17018. for (i = _j = 0; 0 <= segCount ? _j < segCount : _j > segCount; i = 0 <= segCount ? ++_j : --_j) {
  17019. _results.push(data.readUInt16());
  17020. }
  17021. return _results;
  17022. }();
  17023. count = (this.length - data.pos + this.offset) / 2;
  17024. glyphIds = function () {
  17025. var _j, _results;
  17026. _results = [];
  17027. for (i = _j = 0; 0 <= count ? _j < count : _j > count; i = 0 <= count ? ++_j : --_j) {
  17028. _results.push(data.readUInt16());
  17029. }
  17030. return _results;
  17031. }();
  17032. for (i = _j = 0, _len = endCode.length; _j < _len; i = ++_j) {
  17033. tail = endCode[i];
  17034. start = startCode[i];
  17035. for (code = _k = start; start <= tail ? _k <= tail : _k >= tail; code = start <= tail ? ++_k : --_k) {
  17036. if (idRangeOffset[i] === 0) {
  17037. glyphId = code + idDelta[i];
  17038. } else {
  17039. index = idRangeOffset[i] / 2 + (code - start) - (segCount - i);
  17040. glyphId = glyphIds[index] || 0;
  17041. if (glyphId !== 0) {
  17042. glyphId += idDelta[i];
  17043. }
  17044. }
  17045. this.codeMap[code] = glyphId & 0xffff;
  17046. }
  17047. }
  17048. }
  17049. data.pos = saveOffset;
  17050. }
  17051. CmapEntry.encode = function (charmap, encoding) {
  17052. var charMap, code, codeMap, codes, delta, deltas, diff, endCode, endCodes, entrySelector, glyphIDs, i, id, indexes, last, map, nextID, offset, old, rangeOffsets, rangeShift, result, searchRange, segCount, segCountX2, startCode, startCodes, startGlyph, subtable, _i, _j, _k, _l, _len, _len1, _len2, _len3, _len4, _len5, _len6, _len7, _m, _n, _name, _o, _p, _q;
  17053. subtable = new Data();
  17054. codes = Object.keys(charmap).sort(function (a, b) {
  17055. return a - b;
  17056. });
  17057. switch (encoding) {
  17058. case "macroman":
  17059. id = 0;
  17060. indexes = function () {
  17061. var _i, _results;
  17062. _results = [];
  17063. for (i = _i = 0; _i < 256; i = ++_i) {
  17064. _results.push(0);
  17065. }
  17066. return _results;
  17067. }();
  17068. map = {
  17069. 0: 0
  17070. };
  17071. codeMap = {};
  17072. for (_i = 0, _len = codes.length; _i < _len; _i++) {
  17073. code = codes[_i];
  17074. if (map[_name = charmap[code]] == null) {
  17075. map[_name] = ++id;
  17076. }
  17077. codeMap[code] = {
  17078. old: charmap[code],
  17079. new: map[charmap[code]]
  17080. };
  17081. indexes[code] = map[charmap[code]];
  17082. }
  17083. subtable.writeUInt16(1);
  17084. subtable.writeUInt16(0);
  17085. subtable.writeUInt32(12);
  17086. subtable.writeUInt16(0);
  17087. subtable.writeUInt16(262);
  17088. subtable.writeUInt16(0);
  17089. subtable.write(indexes);
  17090. return result = {
  17091. charMap: codeMap,
  17092. subtable: subtable.data,
  17093. maxGlyphID: id + 1
  17094. };
  17095. case "unicode":
  17096. startCodes = [];
  17097. endCodes = [];
  17098. nextID = 0;
  17099. map = {};
  17100. charMap = {};
  17101. last = diff = null;
  17102. for (_j = 0, _len1 = codes.length; _j < _len1; _j++) {
  17103. code = codes[_j];
  17104. old = charmap[code];
  17105. if (map[old] == null) {
  17106. map[old] = ++nextID;
  17107. }
  17108. charMap[code] = {
  17109. old: old,
  17110. new: map[old]
  17111. };
  17112. delta = map[old] - code;
  17113. if (last == null || delta !== diff) {
  17114. if (last) {
  17115. endCodes.push(last);
  17116. }
  17117. startCodes.push(code);
  17118. diff = delta;
  17119. }
  17120. last = code;
  17121. }
  17122. if (last) {
  17123. endCodes.push(last);
  17124. }
  17125. endCodes.push(0xffff);
  17126. startCodes.push(0xffff);
  17127. segCount = startCodes.length;
  17128. segCountX2 = segCount * 2;
  17129. searchRange = 2 * Math.pow(Math.log(segCount) / Math.LN2, 2);
  17130. entrySelector = Math.log(searchRange / 2) / Math.LN2;
  17131. rangeShift = 2 * segCount - searchRange;
  17132. deltas = [];
  17133. rangeOffsets = [];
  17134. glyphIDs = [];
  17135. for (i = _k = 0, _len2 = startCodes.length; _k < _len2; i = ++_k) {
  17136. startCode = startCodes[i];
  17137. endCode = endCodes[i];
  17138. if (startCode === 0xffff) {
  17139. deltas.push(0);
  17140. rangeOffsets.push(0);
  17141. break;
  17142. }
  17143. startGlyph = charMap[startCode]["new"];
  17144. if (startCode - startGlyph >= 0x8000) {
  17145. deltas.push(0);
  17146. rangeOffsets.push(2 * (glyphIDs.length + segCount - i));
  17147. for (code = _l = startCode; startCode <= endCode ? _l <= endCode : _l >= endCode; code = startCode <= endCode ? ++_l : --_l) {
  17148. glyphIDs.push(charMap[code]["new"]);
  17149. }
  17150. } else {
  17151. deltas.push(startGlyph - startCode);
  17152. rangeOffsets.push(0);
  17153. }
  17154. }
  17155. subtable.writeUInt16(3);
  17156. subtable.writeUInt16(1);
  17157. subtable.writeUInt32(12);
  17158. subtable.writeUInt16(4);
  17159. subtable.writeUInt16(16 + segCount * 8 + glyphIDs.length * 2);
  17160. subtable.writeUInt16(0);
  17161. subtable.writeUInt16(segCountX2);
  17162. subtable.writeUInt16(searchRange);
  17163. subtable.writeUInt16(entrySelector);
  17164. subtable.writeUInt16(rangeShift);
  17165. for (_m = 0, _len3 = endCodes.length; _m < _len3; _m++) {
  17166. code = endCodes[_m];
  17167. subtable.writeUInt16(code);
  17168. }
  17169. subtable.writeUInt16(0);
  17170. for (_n = 0, _len4 = startCodes.length; _n < _len4; _n++) {
  17171. code = startCodes[_n];
  17172. subtable.writeUInt16(code);
  17173. }
  17174. for (_o = 0, _len5 = deltas.length; _o < _len5; _o++) {
  17175. delta = deltas[_o];
  17176. subtable.writeUInt16(delta);
  17177. }
  17178. for (_p = 0, _len6 = rangeOffsets.length; _p < _len6; _p++) {
  17179. offset = rangeOffsets[_p];
  17180. subtable.writeUInt16(offset);
  17181. }
  17182. for (_q = 0, _len7 = glyphIDs.length; _q < _len7; _q++) {
  17183. id = glyphIDs[_q];
  17184. subtable.writeUInt16(id);
  17185. }
  17186. return result = {
  17187. charMap: charMap,
  17188. subtable: subtable.data,
  17189. maxGlyphID: nextID + 1
  17190. };
  17191. }
  17192. };
  17193. return CmapEntry;
  17194. }();
  17195. var CmapTable = function (_super) {
  17196. __extends(CmapTable, _super);
  17197. function CmapTable() {
  17198. return CmapTable.__super__.constructor.apply(this, arguments);
  17199. }
  17200. CmapTable.prototype.tag = "cmap";
  17201. CmapTable.prototype.parse = function (data) {
  17202. var entry, i, tableCount, _i;
  17203. data.pos = this.offset;
  17204. this.version = data.readUInt16();
  17205. tableCount = data.readUInt16();
  17206. this.tables = [];
  17207. this.unicode = null;
  17208. for (i = _i = 0; 0 <= tableCount ? _i < tableCount : _i > tableCount; i = 0 <= tableCount ? ++_i : --_i) {
  17209. entry = new CmapEntry(data, this.offset);
  17210. this.tables.push(entry);
  17211. if (entry.isUnicode) {
  17212. if (this.unicode == null) {
  17213. this.unicode = entry;
  17214. }
  17215. }
  17216. }
  17217. return true;
  17218. };
  17219. /*************************************************************************/
  17220. /* function : encode */
  17221. /* comment : Encode the cmap table corresponding to the input character. */
  17222. /*************************************************************************/
  17223. CmapTable.encode = function (charmap, encoding) {
  17224. var result, table;
  17225. if (encoding == null) {
  17226. encoding = "macroman";
  17227. }
  17228. result = CmapEntry.encode(charmap, encoding);
  17229. table = new Data();
  17230. table.writeUInt16(0);
  17231. table.writeUInt16(1);
  17232. result.table = table.data.concat(result.subtable);
  17233. return result;
  17234. };
  17235. return CmapTable;
  17236. }(Table);
  17237. var HheaTable = function (_super) {
  17238. __extends(HheaTable, _super);
  17239. function HheaTable() {
  17240. return HheaTable.__super__.constructor.apply(this, arguments);
  17241. }
  17242. HheaTable.prototype.tag = "hhea";
  17243. HheaTable.prototype.parse = function (data) {
  17244. data.pos = this.offset;
  17245. this.version = data.readInt();
  17246. this.ascender = data.readShort();
  17247. this.decender = data.readShort();
  17248. this.lineGap = data.readShort();
  17249. this.advanceWidthMax = data.readShort();
  17250. this.minLeftSideBearing = data.readShort();
  17251. this.minRightSideBearing = data.readShort();
  17252. this.xMaxExtent = data.readShort();
  17253. this.caretSlopeRise = data.readShort();
  17254. this.caretSlopeRun = data.readShort();
  17255. this.caretOffset = data.readShort();
  17256. data.pos += 4 * 2;
  17257. this.metricDataFormat = data.readShort();
  17258. return this.numberOfMetrics = data.readUInt16();
  17259. };
  17260. /*HheaTable.prototype.encode = function (ids) {
  17261. var i, table, _i, _ref;
  17262. table = new Data;
  17263. table.writeInt(this.version);
  17264. table.writeShort(this.ascender);
  17265. table.writeShort(this.decender);
  17266. table.writeShort(this.lineGap);
  17267. table.writeShort(this.advanceWidthMax);
  17268. table.writeShort(this.minLeftSideBearing);
  17269. table.writeShort(this.minRightSideBearing);
  17270. table.writeShort(this.xMaxExtent);
  17271. table.writeShort(this.caretSlopeRise);
  17272. table.writeShort(this.caretSlopeRun);
  17273. table.writeShort(this.caretOffset);
  17274. for (i = _i = 0, _ref = 4 * 2; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
  17275. table.writeByte(0);
  17276. }
  17277. table.writeShort(this.metricDataFormat);
  17278. table.writeUInt16(ids.length);
  17279. return table.data;
  17280. };*/
  17281. return HheaTable;
  17282. }(Table);
  17283. var OS2Table = function (_super) {
  17284. __extends(OS2Table, _super);
  17285. function OS2Table() {
  17286. return OS2Table.__super__.constructor.apply(this, arguments);
  17287. }
  17288. OS2Table.prototype.tag = "OS/2";
  17289. OS2Table.prototype.parse = function (data) {
  17290. var i;
  17291. data.pos = this.offset;
  17292. this.version = data.readUInt16();
  17293. this.averageCharWidth = data.readShort();
  17294. this.weightClass = data.readUInt16();
  17295. this.widthClass = data.readUInt16();
  17296. this.type = data.readShort();
  17297. this.ySubscriptXSize = data.readShort();
  17298. this.ySubscriptYSize = data.readShort();
  17299. this.ySubscriptXOffset = data.readShort();
  17300. this.ySubscriptYOffset = data.readShort();
  17301. this.ySuperscriptXSize = data.readShort();
  17302. this.ySuperscriptYSize = data.readShort();
  17303. this.ySuperscriptXOffset = data.readShort();
  17304. this.ySuperscriptYOffset = data.readShort();
  17305. this.yStrikeoutSize = data.readShort();
  17306. this.yStrikeoutPosition = data.readShort();
  17307. this.familyClass = data.readShort();
  17308. this.panose = function () {
  17309. var _i, _results;
  17310. _results = [];
  17311. for (i = _i = 0; _i < 10; i = ++_i) {
  17312. _results.push(data.readByte());
  17313. }
  17314. return _results;
  17315. }();
  17316. this.charRange = function () {
  17317. var _i, _results;
  17318. _results = [];
  17319. for (i = _i = 0; _i < 4; i = ++_i) {
  17320. _results.push(data.readInt());
  17321. }
  17322. return _results;
  17323. }();
  17324. this.vendorID = data.readString(4);
  17325. this.selection = data.readShort();
  17326. this.firstCharIndex = data.readShort();
  17327. this.lastCharIndex = data.readShort();
  17328. if (this.version > 0) {
  17329. this.ascent = data.readShort();
  17330. this.descent = data.readShort();
  17331. this.lineGap = data.readShort();
  17332. this.winAscent = data.readShort();
  17333. this.winDescent = data.readShort();
  17334. this.codePageRange = function () {
  17335. var _i, _results;
  17336. _results = [];
  17337. for (i = _i = 0; _i < 2; i = ++_i) {
  17338. _results.push(data.readInt());
  17339. }
  17340. return _results;
  17341. }();
  17342. if (this.version > 1) {
  17343. this.xHeight = data.readShort();
  17344. this.capHeight = data.readShort();
  17345. this.defaultChar = data.readShort();
  17346. this.breakChar = data.readShort();
  17347. return this.maxContext = data.readShort();
  17348. }
  17349. }
  17350. };
  17351. /*OS2Table.prototype.encode = function () {
  17352. return this.raw();
  17353. };*/
  17354. return OS2Table;
  17355. }(Table);
  17356. var PostTable = function (_super) {
  17357. __extends(PostTable, _super);
  17358. function PostTable() {
  17359. return PostTable.__super__.constructor.apply(this, arguments);
  17360. }
  17361. PostTable.prototype.tag = "post";
  17362. PostTable.prototype.parse = function (data) {
  17363. var i, length, numberOfGlyphs, _i, _results;
  17364. data.pos = this.offset;
  17365. this.format = data.readInt();
  17366. this.italicAngle = data.readInt();
  17367. this.underlinePosition = data.readShort();
  17368. this.underlineThickness = data.readShort();
  17369. this.isFixedPitch = data.readInt();
  17370. this.minMemType42 = data.readInt();
  17371. this.maxMemType42 = data.readInt();
  17372. this.minMemType1 = data.readInt();
  17373. this.maxMemType1 = data.readInt();
  17374. switch (this.format) {
  17375. case 0x00010000:
  17376. break;
  17377. case 0x00020000:
  17378. numberOfGlyphs = data.readUInt16();
  17379. this.glyphNameIndex = [];
  17380. for (i = _i = 0; 0 <= numberOfGlyphs ? _i < numberOfGlyphs : _i > numberOfGlyphs; i = 0 <= numberOfGlyphs ? ++_i : --_i) {
  17381. this.glyphNameIndex.push(data.readUInt16());
  17382. }
  17383. this.names = [];
  17384. _results = [];
  17385. while (data.pos < this.offset + this.length) {
  17386. length = data.readByte();
  17387. _results.push(this.names.push(data.readString(length)));
  17388. }
  17389. return _results;
  17390. break;
  17391. case 0x00025000:
  17392. numberOfGlyphs = data.readUInt16();
  17393. return this.offsets = data.read(numberOfGlyphs);
  17394. case 0x00030000:
  17395. break;
  17396. case 0x00040000:
  17397. return this.map = function () {
  17398. var _j, _ref, _results1;
  17399. _results1 = [];
  17400. for (i = _j = 0, _ref = this.file.maxp.numGlyphs; 0 <= _ref ? _j < _ref : _j > _ref; i = 0 <= _ref ? ++_j : --_j) {
  17401. _results1.push(data.readUInt32());
  17402. }
  17403. return _results1;
  17404. }.call(this);
  17405. }
  17406. };
  17407. return PostTable;
  17408. }(Table);
  17409. /*********************************************************************************************************/
  17410. /* function : NameEntry */
  17411. /* comment : Store copyright information, platformID, encodingID, and languageID in the NameEntry object.*/
  17412. /*********************************************************************************************************/
  17413. var NameEntry = function () {
  17414. function NameEntry(raw, entry) {
  17415. this.raw = raw;
  17416. this.length = raw.length;
  17417. this.platformID = entry.platformID;
  17418. this.encodingID = entry.encodingID;
  17419. this.languageID = entry.languageID;
  17420. }
  17421. return NameEntry;
  17422. }();
  17423. var NameTable = function (_super) {
  17424. __extends(NameTable, _super);
  17425. function NameTable() {
  17426. return NameTable.__super__.constructor.apply(this, arguments);
  17427. }
  17428. NameTable.prototype.tag = "name";
  17429. NameTable.prototype.parse = function (data) {
  17430. var count, entries, entry, format, i, name, stringOffset, strings, text, _i, _j, _len, _name;
  17431. data.pos = this.offset;
  17432. format = data.readShort();
  17433. count = data.readShort();
  17434. stringOffset = data.readShort();
  17435. entries = [];
  17436. for (i = _i = 0; 0 <= count ? _i < count : _i > count; i = 0 <= count ? ++_i : --_i) {
  17437. entries.push({
  17438. platformID: data.readShort(),
  17439. encodingID: data.readShort(),
  17440. languageID: data.readShort(),
  17441. nameID: data.readShort(),
  17442. length: data.readShort(),
  17443. offset: this.offset + stringOffset + data.readShort()
  17444. });
  17445. }
  17446. strings = {};
  17447. for (i = _j = 0, _len = entries.length; _j < _len; i = ++_j) {
  17448. entry = entries[i];
  17449. data.pos = entry.offset;
  17450. text = data.readString(entry.length);
  17451. name = new NameEntry(text, entry);
  17452. if (strings[_name = entry.nameID] == null) {
  17453. strings[_name] = [];
  17454. }
  17455. strings[entry.nameID].push(name);
  17456. }
  17457. this.strings = strings;
  17458. this.copyright = strings[0];
  17459. this.fontFamily = strings[1];
  17460. this.fontSubfamily = strings[2];
  17461. this.uniqueSubfamily = strings[3];
  17462. this.fontName = strings[4];
  17463. this.version = strings[5];
  17464. this.postscriptName = strings[6][0].raw.replace(/[\x00-\x19\x80-\xff]/g, "");
  17465. this.trademark = strings[7];
  17466. this.manufacturer = strings[8];
  17467. this.designer = strings[9];
  17468. this.description = strings[10];
  17469. this.vendorUrl = strings[11];
  17470. this.designerUrl = strings[12];
  17471. this.license = strings[13];
  17472. this.licenseUrl = strings[14];
  17473. this.preferredFamily = strings[15];
  17474. this.preferredSubfamily = strings[17];
  17475. this.compatibleFull = strings[18];
  17476. return this.sampleText = strings[19];
  17477. };
  17478. /*NameTable.prototype.encode = function () {
  17479. var id, list, nameID, nameTable, postscriptName, strCount, strTable, string, strings, table, val, _i, _len, _ref;
  17480. strings = {};
  17481. _ref = this.strings;
  17482. for (id in _ref) {
  17483. val = _ref[id];
  17484. strings[id] = val;
  17485. }
  17486. postscriptName = new NameEntry("" + subsetTag + "+" + this.postscriptName, {
  17487. platformID: 1
  17488. , encodingID: 0
  17489. , languageID: 0
  17490. });
  17491. strings[6] = [postscriptName];
  17492. subsetTag = successorOf(subsetTag);
  17493. strCount = 0;
  17494. for (id in strings) {
  17495. list = strings[id];
  17496. if (list != null) {
  17497. strCount += list.length;
  17498. }
  17499. }
  17500. table = new Data;
  17501. strTable = new Data;
  17502. table.writeShort(0);
  17503. table.writeShort(strCount);
  17504. table.writeShort(6 + 12 * strCount);
  17505. for (nameID in strings) {
  17506. list = strings[nameID];
  17507. if (list != null) {
  17508. for (_i = 0, _len = list.length; _i < _len; _i++) {
  17509. string = list[_i];
  17510. table.writeShort(string.platformID);
  17511. table.writeShort(string.encodingID);
  17512. table.writeShort(string.languageID);
  17513. table.writeShort(nameID);
  17514. table.writeShort(string.length);
  17515. table.writeShort(strTable.pos);
  17516. strTable.writeString(string.raw);
  17517. }
  17518. }
  17519. }
  17520. return nameTable = {
  17521. postscriptName: postscriptName.raw
  17522. , table: table.data.concat(strTable.data)
  17523. };
  17524. };*/
  17525. return NameTable;
  17526. }(Table);
  17527. var MaxpTable = function (_super) {
  17528. __extends(MaxpTable, _super);
  17529. function MaxpTable() {
  17530. return MaxpTable.__super__.constructor.apply(this, arguments);
  17531. }
  17532. MaxpTable.prototype.tag = "maxp";
  17533. MaxpTable.prototype.parse = function (data) {
  17534. data.pos = this.offset;
  17535. this.version = data.readInt();
  17536. this.numGlyphs = data.readUInt16();
  17537. this.maxPoints = data.readUInt16();
  17538. this.maxContours = data.readUInt16();
  17539. this.maxCompositePoints = data.readUInt16();
  17540. this.maxComponentContours = data.readUInt16();
  17541. this.maxZones = data.readUInt16();
  17542. this.maxTwilightPoints = data.readUInt16();
  17543. this.maxStorage = data.readUInt16();
  17544. this.maxFunctionDefs = data.readUInt16();
  17545. this.maxInstructionDefs = data.readUInt16();
  17546. this.maxStackElements = data.readUInt16();
  17547. this.maxSizeOfInstructions = data.readUInt16();
  17548. this.maxComponentElements = data.readUInt16();
  17549. return this.maxComponentDepth = data.readUInt16();
  17550. };
  17551. /*MaxpTable.prototype.encode = function (ids) {
  17552. var table;
  17553. table = new Data;
  17554. table.writeInt(this.version);
  17555. table.writeUInt16(ids.length);
  17556. table.writeUInt16(this.maxPoints);
  17557. table.writeUInt16(this.maxContours);
  17558. table.writeUInt16(this.maxCompositePoints);
  17559. table.writeUInt16(this.maxComponentContours);
  17560. table.writeUInt16(this.maxZones);
  17561. table.writeUInt16(this.maxTwilightPoints);
  17562. table.writeUInt16(this.maxStorage);
  17563. table.writeUInt16(this.maxFunctionDefs);
  17564. table.writeUInt16(this.maxInstructionDefs);
  17565. table.writeUInt16(this.maxStackElements);
  17566. table.writeUInt16(this.maxSizeOfInstructions);
  17567. table.writeUInt16(this.maxComponentElements);
  17568. table.writeUInt16(this.maxComponentDepth);
  17569. return table.data;
  17570. };*/
  17571. return MaxpTable;
  17572. }(Table);
  17573. var HmtxTable = function (_super) {
  17574. __extends(HmtxTable, _super);
  17575. function HmtxTable() {
  17576. return HmtxTable.__super__.constructor.apply(this, arguments);
  17577. }
  17578. HmtxTable.prototype.tag = "hmtx";
  17579. HmtxTable.prototype.parse = function (data) {
  17580. var i, last, lsbCount, m, _i, _j, _ref, _results;
  17581. data.pos = this.offset;
  17582. this.metrics = [];
  17583. for (i = _i = 0, _ref = this.file.hhea.numberOfMetrics; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
  17584. this.metrics.push({
  17585. advance: data.readUInt16(),
  17586. lsb: data.readInt16()
  17587. });
  17588. }
  17589. lsbCount = this.file.maxp.numGlyphs - this.file.hhea.numberOfMetrics;
  17590. this.leftSideBearings = function () {
  17591. var _j, _results;
  17592. _results = [];
  17593. for (i = _j = 0; 0 <= lsbCount ? _j < lsbCount : _j > lsbCount; i = 0 <= lsbCount ? ++_j : --_j) {
  17594. _results.push(data.readInt16());
  17595. }
  17596. return _results;
  17597. }();
  17598. this.widths = function () {
  17599. var _j, _len, _ref1, _results;
  17600. _ref1 = this.metrics;
  17601. _results = [];
  17602. for (_j = 0, _len = _ref1.length; _j < _len; _j++) {
  17603. m = _ref1[_j];
  17604. _results.push(m.advance);
  17605. }
  17606. return _results;
  17607. }.call(this);
  17608. last = this.widths[this.widths.length - 1];
  17609. _results = [];
  17610. for (i = _j = 0; 0 <= lsbCount ? _j < lsbCount : _j > lsbCount; i = 0 <= lsbCount ? ++_j : --_j) {
  17611. _results.push(this.widths.push(last));
  17612. }
  17613. return _results;
  17614. };
  17615. /***************************************************************/
  17616. /* function : forGlyph */
  17617. /* comment : Returns the advance width and lsb for this glyph. */
  17618. /***************************************************************/
  17619. HmtxTable.prototype.forGlyph = function (id) {
  17620. var metrics;
  17621. if (id in this.metrics) {
  17622. return this.metrics[id];
  17623. }
  17624. return metrics = {
  17625. advance: this.metrics[this.metrics.length - 1].advance,
  17626. lsb: this.leftSideBearings[id - this.metrics.length]
  17627. };
  17628. };
  17629. /*HmtxTable.prototype.encode = function (mapping) {
  17630. var id, metric, table, _i, _len;
  17631. table = new Data;
  17632. for (_i = 0, _len = mapping.length; _i < _len; _i++) {
  17633. id = mapping[_i];
  17634. metric = this.forGlyph(id);
  17635. table.writeUInt16(metric.advance);
  17636. table.writeUInt16(metric.lsb);
  17637. }
  17638. return table.data;
  17639. };*/
  17640. return HmtxTable;
  17641. }(Table);
  17642. var __slice = [].slice;
  17643. var GlyfTable = function (_super) {
  17644. __extends(GlyfTable, _super);
  17645. function GlyfTable() {
  17646. return GlyfTable.__super__.constructor.apply(this, arguments);
  17647. }
  17648. GlyfTable.prototype.tag = "glyf";
  17649. GlyfTable.prototype.parse = function (data) {
  17650. return this.cache = {};
  17651. };
  17652. GlyfTable.prototype.glyphFor = function (id) {
  17653. id = id;
  17654. var data, index, length, loca, numberOfContours, raw, xMax, xMin, yMax, yMin;
  17655. if (id in this.cache) {
  17656. return this.cache[id];
  17657. }
  17658. loca = this.file.loca;
  17659. data = this.file.contents;
  17660. index = loca.indexOf(id);
  17661. length = loca.lengthOf(id);
  17662. if (length === 0) {
  17663. return this.cache[id] = null;
  17664. }
  17665. data.pos = this.offset + index;
  17666. raw = new Data(data.read(length));
  17667. numberOfContours = raw.readShort();
  17668. xMin = raw.readShort();
  17669. yMin = raw.readShort();
  17670. xMax = raw.readShort();
  17671. yMax = raw.readShort();
  17672. if (numberOfContours === -1) {
  17673. this.cache[id] = new CompoundGlyph(raw, xMin, yMin, xMax, yMax);
  17674. } else {
  17675. this.cache[id] = new SimpleGlyph(raw, numberOfContours, xMin, yMin, xMax, yMax);
  17676. }
  17677. return this.cache[id];
  17678. };
  17679. GlyfTable.prototype.encode = function (glyphs, mapping, old2new) {
  17680. var glyph, id, offsets, table, _i, _len;
  17681. table = [];
  17682. offsets = [];
  17683. for (_i = 0, _len = mapping.length; _i < _len; _i++) {
  17684. id = mapping[_i];
  17685. glyph = glyphs[id];
  17686. offsets.push(table.length);
  17687. if (glyph) {
  17688. table = table.concat(glyph.encode(old2new));
  17689. }
  17690. }
  17691. offsets.push(table.length);
  17692. return {
  17693. table: table,
  17694. offsets: offsets
  17695. };
  17696. };
  17697. return GlyfTable;
  17698. }(Table);
  17699. var SimpleGlyph = function () {
  17700. /**************************************************************************/
  17701. /* function : SimpleGlyph */
  17702. /* comment : Stores raw, xMin, yMin, xMax, and yMax values for this glyph.*/
  17703. /**************************************************************************/
  17704. function SimpleGlyph(raw, numberOfContours, xMin, yMin, xMax, yMax) {
  17705. this.raw = raw;
  17706. this.numberOfContours = numberOfContours;
  17707. this.xMin = xMin;
  17708. this.yMin = yMin;
  17709. this.xMax = xMax;
  17710. this.yMax = yMax;
  17711. this.compound = false;
  17712. }
  17713. SimpleGlyph.prototype.encode = function () {
  17714. return this.raw.data;
  17715. };
  17716. return SimpleGlyph;
  17717. }();
  17718. var CompoundGlyph = function () {
  17719. var ARG_1_AND_2_ARE_WORDS, MORE_COMPONENTS, WE_HAVE_AN_X_AND_Y_SCALE, WE_HAVE_A_SCALE, WE_HAVE_A_TWO_BY_TWO;
  17720. ARG_1_AND_2_ARE_WORDS = 0x0001;
  17721. WE_HAVE_A_SCALE = 0x0008;
  17722. MORE_COMPONENTS = 0x0020;
  17723. WE_HAVE_AN_X_AND_Y_SCALE = 0x0040;
  17724. WE_HAVE_A_TWO_BY_TWO = 0x0080;
  17725. /********************************************************************************************************************/
  17726. /* function : CompoundGlypg generator */
  17727. /* comment : It stores raw, xMin, yMin, xMax, yMax, glyph id, and glyph offset for the corresponding compound glyph.*/
  17728. /********************************************************************************************************************/
  17729. function CompoundGlyph(raw, xMin, yMin, xMax, yMax) {
  17730. var data, flags;
  17731. this.raw = raw;
  17732. this.xMin = xMin;
  17733. this.yMin = yMin;
  17734. this.xMax = xMax;
  17735. this.yMax = yMax;
  17736. this.compound = true;
  17737. this.glyphIDs = [];
  17738. this.glyphOffsets = [];
  17739. data = this.raw;
  17740. while (true) {
  17741. flags = data.readShort();
  17742. this.glyphOffsets.push(data.pos);
  17743. this.glyphIDs.push(data.readShort());
  17744. if (!(flags & MORE_COMPONENTS)) {
  17745. break;
  17746. }
  17747. if (flags & ARG_1_AND_2_ARE_WORDS) {
  17748. data.pos += 4;
  17749. } else {
  17750. data.pos += 2;
  17751. }
  17752. if (flags & WE_HAVE_A_TWO_BY_TWO) {
  17753. data.pos += 8;
  17754. } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) {
  17755. data.pos += 4;
  17756. } else if (flags & WE_HAVE_A_SCALE) {
  17757. data.pos += 2;
  17758. }
  17759. }
  17760. }
  17761. /****************************************************************************************************************/
  17762. /* function : CompoundGlypg encode */
  17763. /* comment : After creating a table for the characters you typed, you call directory.encode to encode the table.*/
  17764. /****************************************************************************************************************/
  17765. CompoundGlyph.prototype.encode = function (mapping) {
  17766. var i, id, result, _i, _len, _ref;
  17767. result = new Data(__slice.call(this.raw.data));
  17768. _ref = this.glyphIDs;
  17769. for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
  17770. id = _ref[i];
  17771. result.pos = this.glyphOffsets[i];
  17772. }
  17773. return result.data;
  17774. };
  17775. return CompoundGlyph;
  17776. }();
  17777. var LocaTable = function (_super) {
  17778. __extends(LocaTable, _super);
  17779. function LocaTable() {
  17780. return LocaTable.__super__.constructor.apply(this, arguments);
  17781. }
  17782. LocaTable.prototype.tag = "loca";
  17783. LocaTable.prototype.parse = function (data) {
  17784. var format, i;
  17785. data.pos = this.offset;
  17786. format = this.file.head.indexToLocFormat;
  17787. if (format === 0) {
  17788. return this.offsets = function () {
  17789. var _i, _ref, _results;
  17790. _results = [];
  17791. for (i = _i = 0, _ref = this.length; _i < _ref; i = _i += 2) {
  17792. _results.push(data.readUInt16() * 2);
  17793. }
  17794. return _results;
  17795. }.call(this);
  17796. } else {
  17797. return this.offsets = function () {
  17798. var _i, _ref, _results;
  17799. _results = [];
  17800. for (i = _i = 0, _ref = this.length; _i < _ref; i = _i += 4) {
  17801. _results.push(data.readUInt32());
  17802. }
  17803. return _results;
  17804. }.call(this);
  17805. }
  17806. };
  17807. LocaTable.prototype.indexOf = function (id) {
  17808. return this.offsets[id];
  17809. };
  17810. LocaTable.prototype.lengthOf = function (id) {
  17811. return this.offsets[id + 1] - this.offsets[id];
  17812. };
  17813. LocaTable.prototype.encode = function (offsets, activeGlyphs) {
  17814. var LocaTable = new Uint32Array(this.offsets.length);
  17815. var glyfPtr = 0;
  17816. var listGlyf = 0;
  17817. for (var k = 0; k < LocaTable.length; ++k) {
  17818. LocaTable[k] = glyfPtr;
  17819. if (listGlyf < activeGlyphs.length && activeGlyphs[listGlyf] == k) {
  17820. ++listGlyf;
  17821. LocaTable[k] = glyfPtr;
  17822. var start = this.offsets[k];
  17823. var len = this.offsets[k + 1] - start;
  17824. if (len > 0) {
  17825. glyfPtr += len;
  17826. }
  17827. }
  17828. }
  17829. var newLocaTable = new Array(LocaTable.length * 4);
  17830. for (var j = 0; j < LocaTable.length; ++j) {
  17831. newLocaTable[4 * j + 3] = LocaTable[j] & 0x000000ff;
  17832. newLocaTable[4 * j + 2] = (LocaTable[j] & 0x0000ff00) >> 8;
  17833. newLocaTable[4 * j + 1] = (LocaTable[j] & 0x00ff0000) >> 16;
  17834. newLocaTable[4 * j] = (LocaTable[j] & 0xff000000) >> 24;
  17835. }
  17836. return newLocaTable;
  17837. };
  17838. return LocaTable;
  17839. }(Table);
  17840. /************************************************************************************/
  17841. /* function : invert */
  17842. /* comment : Change the object's (key: value) to create an object with (value: key).*/
  17843. /************************************************************************************/
  17844. var invert = function (object) {
  17845. var key, ret, val;
  17846. ret = {};
  17847. for (key in object) {
  17848. val = object[key];
  17849. ret[val] = key;
  17850. }
  17851. return ret;
  17852. };
  17853. /*var successorOf = function (input) {
  17854. var added, alphabet, carry, i, index, isUpperCase, last, length, next, result;
  17855. alphabet = 'abcdefghijklmnopqrstuvwxyz';
  17856. length = alphabet.length;
  17857. result = input;
  17858. i = input.length;
  17859. while (i >= 0) {
  17860. last = input.charAt(--i);
  17861. if (isNaN(last)) {
  17862. index = alphabet.indexOf(last.toLowerCase());
  17863. if (index === -1) {
  17864. next = last;
  17865. carry = true;
  17866. }
  17867. else {
  17868. next = alphabet.charAt((index + 1) % length);
  17869. isUpperCase = last === last.toUpperCase();
  17870. if (isUpperCase) {
  17871. next = next.toUpperCase();
  17872. }
  17873. carry = index + 1 >= length;
  17874. if (carry && i === 0) {
  17875. added = isUpperCase ? 'A' : 'a';
  17876. result = added + next + result.slice(1);
  17877. break;
  17878. }
  17879. }
  17880. }
  17881. else {
  17882. next = +last + 1;
  17883. carry = next > 9;
  17884. if (carry) {
  17885. next = 0;
  17886. }
  17887. if (carry && i === 0) {
  17888. result = '1' + next + result.slice(1);
  17889. break;
  17890. }
  17891. }
  17892. result = result.slice(0, i) + next + result.slice(i + 1);
  17893. if (!carry) {
  17894. break;
  17895. }
  17896. }
  17897. return result;
  17898. };*/
  17899. var Subset = function () {
  17900. function Subset(font) {
  17901. this.font = font;
  17902. this.subset = {};
  17903. this.unicodes = {};
  17904. this.next = 33;
  17905. }
  17906. /*Subset.prototype.use = function (character) {
  17907. var i, _i, _ref;
  17908. if (typeof character === 'string') {
  17909. for (i = _i = 0, _ref = character.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
  17910. this.use(character.charCodeAt(i));
  17911. }
  17912. return;
  17913. }
  17914. if (!this.unicodes[character]) {
  17915. this.subset[this.next] = character;
  17916. return this.unicodes[character] = this.next++;
  17917. }
  17918. };*/
  17919. /*Subset.prototype.encodeText = function (text) {
  17920. var char, i, string, _i, _ref;
  17921. string = '';
  17922. for (i = _i = 0, _ref = text.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
  17923. char = this.unicodes[text.charCodeAt(i)];
  17924. string += String.fromCharCode(char);
  17925. }
  17926. return string;
  17927. };*/
  17928. /***************************************************************/
  17929. /* function : generateCmap */
  17930. /* comment : Returns the unicode cmap for this font. */
  17931. /***************************************************************/
  17932. Subset.prototype.generateCmap = function () {
  17933. var mapping, roman, unicode, unicodeCmap, _ref;
  17934. unicodeCmap = this.font.cmap.tables[0].codeMap;
  17935. mapping = {};
  17936. _ref = this.subset;
  17937. for (roman in _ref) {
  17938. unicode = _ref[roman];
  17939. mapping[roman] = unicodeCmap[unicode];
  17940. }
  17941. return mapping;
  17942. };
  17943. /*Subset.prototype.glyphIDs = function () {
  17944. var ret, roman, unicode, unicodeCmap, val, _ref;
  17945. unicodeCmap = this.font.cmap.tables[0].codeMap;
  17946. ret = [0];
  17947. _ref = this.subset;
  17948. for (roman in _ref) {
  17949. unicode = _ref[roman];
  17950. val = unicodeCmap[unicode];
  17951. if ((val != null) && __indexOf.call(ret, val) < 0) {
  17952. ret.push(val);
  17953. }
  17954. }
  17955. return ret.sort();
  17956. };*/
  17957. /******************************************************************/
  17958. /* function : glyphsFor */
  17959. /* comment : Returns simple glyph objects for the input character.*/
  17960. /******************************************************************/
  17961. Subset.prototype.glyphsFor = function (glyphIDs) {
  17962. var additionalIDs, glyph, glyphs, id, _i, _len, _ref;
  17963. glyphs = {};
  17964. for (_i = 0, _len = glyphIDs.length; _i < _len; _i++) {
  17965. id = glyphIDs[_i];
  17966. glyphs[id] = this.font.glyf.glyphFor(id);
  17967. }
  17968. additionalIDs = [];
  17969. for (id in glyphs) {
  17970. glyph = glyphs[id];
  17971. if (glyph != null ? glyph.compound : void 0) {
  17972. additionalIDs.push.apply(additionalIDs, glyph.glyphIDs);
  17973. }
  17974. }
  17975. if (additionalIDs.length > 0) {
  17976. _ref = this.glyphsFor(additionalIDs);
  17977. for (id in _ref) {
  17978. glyph = _ref[id];
  17979. glyphs[id] = glyph;
  17980. }
  17981. }
  17982. return glyphs;
  17983. };
  17984. /***************************************************************/
  17985. /* function : encode */
  17986. /* comment : Encode various tables for the characters you use. */
  17987. /***************************************************************/
  17988. Subset.prototype.encode = function (glyID) {
  17989. var cmap, code, glyf, glyphs, id, ids, loca, new2old, newIDs, nextGlyphID, old2new, oldID, oldIDs, tables, _ref;
  17990. cmap = CmapTable.encode(this.generateCmap(), "unicode");
  17991. glyphs = this.glyphsFor(glyID);
  17992. old2new = {
  17993. 0: 0
  17994. };
  17995. _ref = cmap.charMap;
  17996. for (code in _ref) {
  17997. ids = _ref[code];
  17998. old2new[ids.old] = ids["new"];
  17999. }
  18000. nextGlyphID = cmap.maxGlyphID;
  18001. for (oldID in glyphs) {
  18002. if (!(oldID in old2new)) {
  18003. old2new[oldID] = nextGlyphID++;
  18004. }
  18005. }
  18006. new2old = invert(old2new);
  18007. newIDs = Object.keys(new2old).sort(function (a, b) {
  18008. return a - b;
  18009. });
  18010. oldIDs = function () {
  18011. var _i, _len, _results;
  18012. _results = [];
  18013. for (_i = 0, _len = newIDs.length; _i < _len; _i++) {
  18014. id = newIDs[_i];
  18015. _results.push(new2old[id]);
  18016. }
  18017. return _results;
  18018. }();
  18019. glyf = this.font.glyf.encode(glyphs, oldIDs, old2new);
  18020. loca = this.font.loca.encode(glyf.offsets, oldIDs);
  18021. tables = {
  18022. cmap: this.font.cmap.raw(),
  18023. glyf: glyf.table,
  18024. loca: loca,
  18025. hmtx: this.font.hmtx.raw(),
  18026. hhea: this.font.hhea.raw(),
  18027. maxp: this.font.maxp.raw(),
  18028. post: this.font.post.raw(),
  18029. name: this.font.name.raw(),
  18030. head: this.font.head.raw()
  18031. };
  18032. if (this.font.os2.exists) {
  18033. tables["OS/2"] = this.font.os2.raw();
  18034. }
  18035. return this.font.directory.encode(tables);
  18036. };
  18037. return Subset;
  18038. }();
  18039. jsPDF.API.PDFObject = function () {
  18040. var pad;
  18041. function PDFObject() {}
  18042. pad = function (str, length) {
  18043. return (Array(length + 1).join("0") + str).slice(-length);
  18044. };
  18045. /*****************************************************************************/
  18046. /* function : convert */
  18047. /* comment :Converts pdf tag's / FontBBox and array values in / W to strings */
  18048. /*****************************************************************************/
  18049. PDFObject.convert = function (object) {
  18050. var e, items, key, out, val;
  18051. if (Array.isArray(object)) {
  18052. items = function () {
  18053. var _i, _len, _results;
  18054. _results = [];
  18055. for (_i = 0, _len = object.length; _i < _len; _i++) {
  18056. e = object[_i];
  18057. _results.push(PDFObject.convert(e));
  18058. }
  18059. return _results;
  18060. }().join(" ");
  18061. return "[" + items + "]";
  18062. } else if (typeof object === "string") {
  18063. return "/" + object;
  18064. } else if (object != null ? object.isString : void 0) {
  18065. return "(" + object + ")";
  18066. } else if (object instanceof Date) {
  18067. return "(D:" + pad(object.getUTCFullYear(), 4) + pad(object.getUTCMonth(), 2) + pad(object.getUTCDate(), 2) + pad(object.getUTCHours(), 2) + pad(object.getUTCMinutes(), 2) + pad(object.getUTCSeconds(), 2) + "Z)";
  18068. } else if ({}.toString.call(object) === "[object Object]") {
  18069. out = ["<<"];
  18070. for (key in object) {
  18071. val = object[key];
  18072. out.push("/" + key + " " + PDFObject.convert(val));
  18073. }
  18074. out.push(">>");
  18075. return out.join("\n");
  18076. } else {
  18077. return "" + object;
  18078. }
  18079. };
  18080. return PDFObject;
  18081. }();
  18082. })(jsPDF);
  18083. // Generated by CoffeeScript 1.4.0
  18084. /*
  18085. # PNG.js
  18086. # Copyright (c) 2011 Devon Govett
  18087. # MIT LICENSE
  18088. #
  18089. #
  18090. */
  18091. (function (global) {
  18092. var PNG;
  18093. PNG = function () {
  18094. var APNG_BLEND_OP_SOURCE, APNG_DISPOSE_OP_BACKGROUND, APNG_DISPOSE_OP_PREVIOUS, makeImage, scratchCanvas, scratchCtx;
  18095. PNG.load = function (url, canvas, callback) {
  18096. var xhr;
  18097. if (typeof canvas === "function") {
  18098. callback = canvas;
  18099. }
  18100. xhr = new XMLHttpRequest();
  18101. xhr.open("GET", url, true);
  18102. xhr.responseType = "arraybuffer";
  18103. xhr.onload = function () {
  18104. var data, png;
  18105. data = new Uint8Array(xhr.response || xhr.mozResponseArrayBuffer);
  18106. png = new PNG(data);
  18107. if (typeof (canvas != null ? canvas.getContext : void 0) === "function") {
  18108. png.render(canvas);
  18109. }
  18110. return typeof callback === "function" ? callback(png) : void 0;
  18111. };
  18112. return xhr.send(null);
  18113. };
  18114. APNG_DISPOSE_OP_BACKGROUND = 1;
  18115. APNG_DISPOSE_OP_PREVIOUS = 2;
  18116. APNG_BLEND_OP_SOURCE = 0;
  18117. function PNG(data) {
  18118. var chunkSize, colors, palLen, delayDen, delayNum, frame, i, index, key, section, palShort, text, _i, _j, _ref;
  18119. this.data = data;
  18120. this.pos = 8;
  18121. this.palette = [];
  18122. this.imgData = [];
  18123. this.transparency = {};
  18124. this.animation = null;
  18125. this.text = {};
  18126. frame = null;
  18127. while (true) {
  18128. chunkSize = this.readUInt32();
  18129. section = function () {
  18130. var _i, _results;
  18131. _results = [];
  18132. for (i = _i = 0; _i < 4; i = ++_i) {
  18133. _results.push(String.fromCharCode(this.data[this.pos++]));
  18134. }
  18135. return _results;
  18136. }.call(this).join("");
  18137. switch (section) {
  18138. case "IHDR":
  18139. this.width = this.readUInt32();
  18140. this.height = this.readUInt32();
  18141. this.bits = this.data[this.pos++];
  18142. this.colorType = this.data[this.pos++];
  18143. this.compressionMethod = this.data[this.pos++];
  18144. this.filterMethod = this.data[this.pos++];
  18145. this.interlaceMethod = this.data[this.pos++];
  18146. break;
  18147. case "acTL":
  18148. this.animation = {
  18149. numFrames: this.readUInt32(),
  18150. numPlays: this.readUInt32() || Infinity,
  18151. frames: []
  18152. };
  18153. break;
  18154. case "PLTE":
  18155. this.palette = this.read(chunkSize);
  18156. break;
  18157. case "fcTL":
  18158. if (frame) {
  18159. this.animation.frames.push(frame);
  18160. }
  18161. this.pos += 4;
  18162. frame = {
  18163. width: this.readUInt32(),
  18164. height: this.readUInt32(),
  18165. xOffset: this.readUInt32(),
  18166. yOffset: this.readUInt32()
  18167. };
  18168. delayNum = this.readUInt16();
  18169. delayDen = this.readUInt16() || 100;
  18170. frame.delay = 1000 * delayNum / delayDen;
  18171. frame.disposeOp = this.data[this.pos++];
  18172. frame.blendOp = this.data[this.pos++];
  18173. frame.data = [];
  18174. break;
  18175. case "IDAT":
  18176. case "fdAT":
  18177. if (section === "fdAT") {
  18178. this.pos += 4;
  18179. chunkSize -= 4;
  18180. }
  18181. data = (frame != null ? frame.data : void 0) || this.imgData;
  18182. for (i = _i = 0; 0 <= chunkSize ? _i < chunkSize : _i > chunkSize; i = 0 <= chunkSize ? ++_i : --_i) {
  18183. data.push(this.data[this.pos++]);
  18184. }
  18185. break;
  18186. case "tRNS":
  18187. this.transparency = {};
  18188. switch (this.colorType) {
  18189. case 3:
  18190. palLen = this.palette.length / 3;
  18191. this.transparency.indexed = this.read(chunkSize);
  18192. if (this.transparency.indexed.length > palLen) throw new Error("More transparent colors than palette size");
  18193. /*
  18194. * According to the PNG spec trns should be increased to the same size as palette if shorter
  18195. */
  18196. //palShort = 255 - this.transparency.indexed.length;
  18197. palShort = palLen - this.transparency.indexed.length;
  18198. if (palShort > 0) {
  18199. for (i = _j = 0; 0 <= palShort ? _j < palShort : _j > palShort; i = 0 <= palShort ? ++_j : --_j) {
  18200. this.transparency.indexed.push(255);
  18201. }
  18202. }
  18203. break;
  18204. case 0:
  18205. this.transparency.grayscale = this.read(chunkSize)[0];
  18206. break;
  18207. case 2:
  18208. this.transparency.rgb = this.read(chunkSize);
  18209. }
  18210. break;
  18211. case "tEXt":
  18212. text = this.read(chunkSize);
  18213. index = text.indexOf(0);
  18214. key = String.fromCharCode.apply(String, text.slice(0, index));
  18215. this.text[key] = String.fromCharCode.apply(String, text.slice(index + 1));
  18216. break;
  18217. case "IEND":
  18218. if (frame) {
  18219. this.animation.frames.push(frame);
  18220. }
  18221. this.colors = function () {
  18222. switch (this.colorType) {
  18223. case 0:
  18224. case 3:
  18225. case 4:
  18226. return 1;
  18227. case 2:
  18228. case 6:
  18229. return 3;
  18230. }
  18231. }.call(this);
  18232. this.hasAlphaChannel = (_ref = this.colorType) === 4 || _ref === 6;
  18233. colors = this.colors + (this.hasAlphaChannel ? 1 : 0);
  18234. this.pixelBitlength = this.bits * colors;
  18235. this.colorSpace = function () {
  18236. switch (this.colors) {
  18237. case 1:
  18238. return "DeviceGray";
  18239. case 3:
  18240. return "DeviceRGB";
  18241. }
  18242. }.call(this);
  18243. this.imgData = new Uint8Array(this.imgData);
  18244. return;
  18245. default:
  18246. this.pos += chunkSize;
  18247. }
  18248. this.pos += 4;
  18249. if (this.pos > this.data.length) {
  18250. throw new Error("Incomplete or corrupt PNG file");
  18251. }
  18252. }
  18253. return;
  18254. }
  18255. PNG.prototype.read = function (bytes) {
  18256. var i, _i, _results;
  18257. _results = [];
  18258. for (i = _i = 0; 0 <= bytes ? _i < bytes : _i > bytes; i = 0 <= bytes ? ++_i : --_i) {
  18259. _results.push(this.data[this.pos++]);
  18260. }
  18261. return _results;
  18262. };
  18263. PNG.prototype.readUInt32 = function () {
  18264. var b1, b2, b3, b4;
  18265. b1 = this.data[this.pos++] << 24;
  18266. b2 = this.data[this.pos++] << 16;
  18267. b3 = this.data[this.pos++] << 8;
  18268. b4 = this.data[this.pos++];
  18269. return b1 | b2 | b3 | b4;
  18270. };
  18271. PNG.prototype.readUInt16 = function () {
  18272. var b1, b2;
  18273. b1 = this.data[this.pos++] << 8;
  18274. b2 = this.data[this.pos++];
  18275. return b1 | b2;
  18276. };
  18277. PNG.prototype.decodePixels = function (data) {
  18278. var pixelBytes = this.pixelBitlength / 8;
  18279. var fullPixels = new Uint8Array(this.width * this.height * pixelBytes);
  18280. var pos = 0;
  18281. var _this = this;
  18282. if (data == null) {
  18283. data = this.imgData;
  18284. }
  18285. if (data.length === 0) {
  18286. return new Uint8Array(0);
  18287. }
  18288. data = new FlateStream(data);
  18289. data = data.getBytes();
  18290. function pass(x0, y0, dx, dy) {
  18291. var abyte, c, col, i, left, length, p, pa, paeth, pb, pc, pixels, row, scanlineLength, upper, upperLeft, _i, _j, _k, _l, _m;
  18292. var w = Math.ceil((_this.width - x0) / dx),
  18293. h = Math.ceil((_this.height - y0) / dy);
  18294. var isFull = _this.width == w && _this.height == h;
  18295. scanlineLength = pixelBytes * w;
  18296. pixels = isFull ? fullPixels : new Uint8Array(scanlineLength * h);
  18297. length = data.length;
  18298. row = 0;
  18299. c = 0;
  18300. while (row < h && pos < length) {
  18301. switch (data[pos++]) {
  18302. case 0:
  18303. for (i = _i = 0; _i < scanlineLength; i = _i += 1) {
  18304. pixels[c++] = data[pos++];
  18305. }
  18306. break;
  18307. case 1:
  18308. for (i = _j = 0; _j < scanlineLength; i = _j += 1) {
  18309. abyte = data[pos++];
  18310. left = i < pixelBytes ? 0 : pixels[c - pixelBytes];
  18311. pixels[c++] = (abyte + left) % 256;
  18312. }
  18313. break;
  18314. case 2:
  18315. for (i = _k = 0; _k < scanlineLength; i = _k += 1) {
  18316. abyte = data[pos++];
  18317. col = (i - i % pixelBytes) / pixelBytes;
  18318. upper = row && pixels[(row - 1) * scanlineLength + col * pixelBytes + i % pixelBytes];
  18319. pixels[c++] = (upper + abyte) % 256;
  18320. }
  18321. break;
  18322. case 3:
  18323. for (i = _l = 0; _l < scanlineLength; i = _l += 1) {
  18324. abyte = data[pos++];
  18325. col = (i - i % pixelBytes) / pixelBytes;
  18326. left = i < pixelBytes ? 0 : pixels[c - pixelBytes];
  18327. upper = row && pixels[(row - 1) * scanlineLength + col * pixelBytes + i % pixelBytes];
  18328. pixels[c++] = (abyte + Math.floor((left + upper) / 2)) % 256;
  18329. }
  18330. break;
  18331. case 4:
  18332. for (i = _m = 0; _m < scanlineLength; i = _m += 1) {
  18333. abyte = data[pos++];
  18334. col = (i - i % pixelBytes) / pixelBytes;
  18335. left = i < pixelBytes ? 0 : pixels[c - pixelBytes];
  18336. if (row === 0) {
  18337. upper = upperLeft = 0;
  18338. } else {
  18339. upper = pixels[(row - 1) * scanlineLength + col * pixelBytes + i % pixelBytes];
  18340. upperLeft = col && pixels[(row - 1) * scanlineLength + (col - 1) * pixelBytes + i % pixelBytes];
  18341. }
  18342. p = left + upper - upperLeft;
  18343. pa = Math.abs(p - left);
  18344. pb = Math.abs(p - upper);
  18345. pc = Math.abs(p - upperLeft);
  18346. if (pa <= pb && pa <= pc) {
  18347. paeth = left;
  18348. } else if (pb <= pc) {
  18349. paeth = upper;
  18350. } else {
  18351. paeth = upperLeft;
  18352. }
  18353. pixels[c++] = (abyte + paeth) % 256;
  18354. }
  18355. break;
  18356. default:
  18357. throw new Error("Invalid filter algorithm: " + data[pos - 1]);
  18358. }
  18359. if (!isFull) {
  18360. var fullPos = ((y0 + row * dy) * _this.width + x0) * pixelBytes;
  18361. var partPos = row * scanlineLength;
  18362. for (i = 0; i < w; i += 1) {
  18363. for (var j = 0; j < pixelBytes; j += 1) fullPixels[fullPos++] = pixels[partPos++];
  18364. fullPos += (dx - 1) * pixelBytes;
  18365. }
  18366. }
  18367. row++;
  18368. }
  18369. }
  18370. if (_this.interlaceMethod == 1) {
  18371. /*
  18372. 1 6 4 6 2 6 4 6
  18373. 7 7 7 7 7 7 7 7
  18374. 5 6 5 6 5 6 5 6
  18375. 7 7 7 7 7 7 7 7
  18376. 3 6 4 6 3 6 4 6
  18377. 7 7 7 7 7 7 7 7
  18378. 5 6 5 6 5 6 5 6
  18379. 7 7 7 7 7 7 7 7
  18380. */
  18381. pass(0, 0, 8, 8); // 1
  18382. /* NOTE these seem to follow the pattern:
  18383. * pass(x, 0, 2*x, 2*x);
  18384. * pass(0, x, x, 2*x);
  18385. * with x being 4, 2, 1.
  18386. */
  18387. pass(4, 0, 8, 8); // 2
  18388. pass(0, 4, 4, 8); // 3
  18389. pass(2, 0, 4, 4); // 4
  18390. pass(0, 2, 2, 4); // 5
  18391. pass(1, 0, 2, 2); // 6
  18392. pass(0, 1, 1, 2); // 7
  18393. } else {
  18394. pass(0, 0, 1, 1);
  18395. }
  18396. return fullPixels;
  18397. };
  18398. PNG.prototype.decodePalette = function () {
  18399. var c, i, length, palette, pos, ret, transparency, _i, _ref, _ref1;
  18400. palette = this.palette;
  18401. transparency = this.transparency.indexed || [];
  18402. ret = new Uint8Array((transparency.length || 0) + palette.length);
  18403. pos = 0;
  18404. length = palette.length;
  18405. c = 0;
  18406. for (i = _i = 0, _ref = palette.length; _i < _ref; i = _i += 3) {
  18407. ret[pos++] = palette[i];
  18408. ret[pos++] = palette[i + 1];
  18409. ret[pos++] = palette[i + 2];
  18410. ret[pos++] = (_ref1 = transparency[c++]) != null ? _ref1 : 255;
  18411. }
  18412. return ret;
  18413. };
  18414. PNG.prototype.copyToImageData = function (imageData, pixels) {
  18415. var alpha, colors, data, i, input, j, k, length, palette, v, _ref;
  18416. colors = this.colors;
  18417. palette = null;
  18418. alpha = this.hasAlphaChannel;
  18419. if (this.palette.length) {
  18420. palette = (_ref = this._decodedPalette) != null ? _ref : this._decodedPalette = this.decodePalette();
  18421. colors = 4;
  18422. alpha = true;
  18423. }
  18424. data = imageData.data || imageData;
  18425. length = data.length;
  18426. input = palette || pixels;
  18427. i = j = 0;
  18428. if (colors === 1) {
  18429. while (i < length) {
  18430. k = palette ? pixels[i / 4] * 4 : j;
  18431. v = input[k++];
  18432. data[i++] = v;
  18433. data[i++] = v;
  18434. data[i++] = v;
  18435. data[i++] = alpha ? input[k++] : 255;
  18436. j = k;
  18437. }
  18438. } else {
  18439. while (i < length) {
  18440. k = palette ? pixels[i / 4] * 4 : j;
  18441. data[i++] = input[k++];
  18442. data[i++] = input[k++];
  18443. data[i++] = input[k++];
  18444. data[i++] = alpha ? input[k++] : 255;
  18445. j = k;
  18446. }
  18447. }
  18448. };
  18449. PNG.prototype.decode = function () {
  18450. var ret;
  18451. ret = new Uint8Array(this.width * this.height * 4);
  18452. this.copyToImageData(ret, this.decodePixels());
  18453. return ret;
  18454. };
  18455. try {
  18456. scratchCanvas = global.document.createElement("canvas");
  18457. scratchCtx = scratchCanvas.getContext("2d");
  18458. } catch (e) {
  18459. return -1;
  18460. }
  18461. makeImage = function (imageData) {
  18462. var img;
  18463. scratchCtx.width = imageData.width;
  18464. scratchCtx.height = imageData.height;
  18465. scratchCtx.clearRect(0, 0, imageData.width, imageData.height);
  18466. scratchCtx.putImageData(imageData, 0, 0);
  18467. img = new Image();
  18468. img.src = scratchCanvas.toDataURL();
  18469. return img;
  18470. };
  18471. PNG.prototype.decodeFrames = function (ctx) {
  18472. var frame, i, imageData, pixels, _i, _len, _ref, _results;
  18473. if (!this.animation) {
  18474. return;
  18475. }
  18476. _ref = this.animation.frames;
  18477. _results = [];
  18478. for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
  18479. frame = _ref[i];
  18480. imageData = ctx.createImageData(frame.width, frame.height);
  18481. pixels = this.decodePixels(new Uint8Array(frame.data));
  18482. this.copyToImageData(imageData, pixels);
  18483. frame.imageData = imageData;
  18484. _results.push(frame.image = makeImage(imageData));
  18485. }
  18486. return _results;
  18487. };
  18488. PNG.prototype.renderFrame = function (ctx, number) {
  18489. var frame, frames, prev;
  18490. frames = this.animation.frames;
  18491. frame = frames[number];
  18492. prev = frames[number - 1];
  18493. if (number === 0) {
  18494. ctx.clearRect(0, 0, this.width, this.height);
  18495. }
  18496. if ((prev != null ? prev.disposeOp : void 0) === APNG_DISPOSE_OP_BACKGROUND) {
  18497. ctx.clearRect(prev.xOffset, prev.yOffset, prev.width, prev.height);
  18498. } else if ((prev != null ? prev.disposeOp : void 0) === APNG_DISPOSE_OP_PREVIOUS) {
  18499. ctx.putImageData(prev.imageData, prev.xOffset, prev.yOffset);
  18500. }
  18501. if (frame.blendOp === APNG_BLEND_OP_SOURCE) {
  18502. ctx.clearRect(frame.xOffset, frame.yOffset, frame.width, frame.height);
  18503. }
  18504. return ctx.drawImage(frame.image, frame.xOffset, frame.yOffset);
  18505. };
  18506. PNG.prototype.animate = function (ctx) {
  18507. var doFrame,
  18508. frameNumber,
  18509. frames,
  18510. numFrames,
  18511. numPlays,
  18512. _ref,
  18513. _this = this;
  18514. frameNumber = 0;
  18515. _ref = this.animation, numFrames = _ref.numFrames, frames = _ref.frames, numPlays = _ref.numPlays;
  18516. return (doFrame = function () {
  18517. var f, frame;
  18518. f = frameNumber++ % numFrames;
  18519. frame = frames[f];
  18520. _this.renderFrame(ctx, f);
  18521. if (numFrames > 1 && frameNumber / numFrames < numPlays) {
  18522. return _this.animation._timeout = setTimeout(doFrame, frame.delay);
  18523. }
  18524. })();
  18525. };
  18526. PNG.prototype.stopAnimation = function () {
  18527. var _ref;
  18528. return clearTimeout((_ref = this.animation) != null ? _ref._timeout : void 0);
  18529. };
  18530. PNG.prototype.render = function (canvas) {
  18531. var ctx, data;
  18532. if (canvas._png) {
  18533. canvas._png.stopAnimation();
  18534. }
  18535. canvas._png = this;
  18536. canvas.width = this.width;
  18537. canvas.height = this.height;
  18538. ctx = canvas.getContext("2d");
  18539. if (this.animation) {
  18540. this.decodeFrames(ctx);
  18541. return this.animate(ctx);
  18542. } else {
  18543. data = ctx.createImageData(this.width, this.height);
  18544. this.copyToImageData(data, this.decodePixels());
  18545. return ctx.putImageData(data, 0, 0);
  18546. }
  18547. };
  18548. return PNG;
  18549. }();
  18550. global.PNG = PNG;
  18551. })(typeof self !== "undefined" && self || typeof window !== "undefined" && window || typeof global !== "undefined" && global || Function('return typeof this === "object" && this.content')() || Function("return this")()); // `self` is undefined in Firefox for Android content script context
  18552. // while `this` is nsIContentFrameMessageManager
  18553. // with an attribute `content` that corresponds to the window
  18554. /*
  18555. * Extracted from pdf.js
  18556. * https://github.com/andreasgal/pdf.js
  18557. *
  18558. * Copyright (c) 2011 Mozilla Foundation
  18559. *
  18560. * Contributors: Andreas Gal <gal@mozilla.com>
  18561. * Chris G Jones <cjones@mozilla.com>
  18562. * Shaon Barman <shaon.barman@gmail.com>
  18563. * Vivien Nicolas <21@vingtetun.org>
  18564. * Justin D'Arcangelo <justindarc@gmail.com>
  18565. * Yury Delendik
  18566. *
  18567. *
  18568. */
  18569. var DecodeStream = function () {
  18570. function constructor() {
  18571. this.pos = 0;
  18572. this.bufferLength = 0;
  18573. this.eof = false;
  18574. this.buffer = null;
  18575. }
  18576. constructor.prototype = {
  18577. ensureBuffer: function decodestream_ensureBuffer(requested) {
  18578. var buffer = this.buffer;
  18579. var current = buffer ? buffer.byteLength : 0;
  18580. if (requested < current) return buffer;
  18581. var size = 512;
  18582. while (size < requested) size <<= 1;
  18583. var buffer2 = new Uint8Array(size);
  18584. for (var i = 0; i < current; ++i) buffer2[i] = buffer[i];
  18585. return this.buffer = buffer2;
  18586. },
  18587. getByte: function decodestream_getByte() {
  18588. var pos = this.pos;
  18589. while (this.bufferLength <= pos) {
  18590. if (this.eof) return null;
  18591. this.readBlock();
  18592. }
  18593. return this.buffer[this.pos++];
  18594. },
  18595. getBytes: function decodestream_getBytes(length) {
  18596. var pos = this.pos;
  18597. if (length) {
  18598. this.ensureBuffer(pos + length);
  18599. var end = pos + length;
  18600. while (!this.eof && this.bufferLength < end) this.readBlock();
  18601. var bufEnd = this.bufferLength;
  18602. if (end > bufEnd) end = bufEnd;
  18603. } else {
  18604. while (!this.eof) this.readBlock();
  18605. var end = this.bufferLength;
  18606. }
  18607. this.pos = end;
  18608. return this.buffer.subarray(pos, end);
  18609. },
  18610. lookChar: function decodestream_lookChar() {
  18611. var pos = this.pos;
  18612. while (this.bufferLength <= pos) {
  18613. if (this.eof) return null;
  18614. this.readBlock();
  18615. }
  18616. return String.fromCharCode(this.buffer[this.pos]);
  18617. },
  18618. getChar: function decodestream_getChar() {
  18619. var pos = this.pos;
  18620. while (this.bufferLength <= pos) {
  18621. if (this.eof) return null;
  18622. this.readBlock();
  18623. }
  18624. return String.fromCharCode(this.buffer[this.pos++]);
  18625. },
  18626. makeSubStream: function decodestream_makeSubstream(start, length, dict) {
  18627. var end = start + length;
  18628. while (this.bufferLength <= end && !this.eof) this.readBlock();
  18629. return new Stream(this.buffer, start, length, dict);
  18630. },
  18631. skip: function decodestream_skip(n) {
  18632. if (!n) n = 1;
  18633. this.pos += n;
  18634. },
  18635. reset: function decodestream_reset() {
  18636. this.pos = 0;
  18637. }
  18638. };
  18639. return constructor;
  18640. }();
  18641. var FlateStream = function () {
  18642. if (typeof Uint32Array === "undefined") {
  18643. return undefined;
  18644. }
  18645. var codeLenCodeMap = new Uint32Array([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]);
  18646. var lengthDecode = new Uint32Array([0x00003, 0x00004, 0x00005, 0x00006, 0x00007, 0x00008, 0x00009, 0x0000a, 0x1000b, 0x1000d, 0x1000f, 0x10011, 0x20013, 0x20017, 0x2001b, 0x2001f, 0x30023, 0x3002b, 0x30033, 0x3003b, 0x40043, 0x40053, 0x40063, 0x40073, 0x50083, 0x500a3, 0x500c3, 0x500e3, 0x00102, 0x00102, 0x00102]);
  18647. var distDecode = new Uint32Array([0x00001, 0x00002, 0x00003, 0x00004, 0x10005, 0x10007, 0x20009, 0x2000d, 0x30011, 0x30019, 0x40021, 0x40031, 0x50041, 0x50061, 0x60081, 0x600c1, 0x70101, 0x70181, 0x80201, 0x80301, 0x90401, 0x90601, 0xa0801, 0xa0c01, 0xb1001, 0xb1801, 0xc2001, 0xc3001, 0xd4001, 0xd6001]);
  18648. var fixedLitCodeTab = [new Uint32Array([0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c0, 0x70108, 0x80060, 0x80020, 0x900a0, 0x80000, 0x80080, 0x80040, 0x900e0, 0x70104, 0x80058, 0x80018, 0x90090, 0x70114, 0x80078, 0x80038, 0x900d0, 0x7010c, 0x80068, 0x80028, 0x900b0, 0x80008, 0x80088, 0x80048, 0x900f0, 0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074, 0x80034, 0x900c8, 0x7010a, 0x80064, 0x80024, 0x900a8, 0x80004, 0x80084, 0x80044, 0x900e8, 0x70106, 0x8005c, 0x8001c, 0x90098, 0x70116, 0x8007c, 0x8003c, 0x900d8, 0x7010e, 0x8006c, 0x8002c, 0x900b8, 0x8000c, 0x8008c, 0x8004c, 0x900f8, 0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c4, 0x70109, 0x80062, 0x80022, 0x900a4, 0x80002, 0x80082, 0x80042, 0x900e4, 0x70105, 0x8005a, 0x8001a, 0x90094, 0x70115, 0x8007a, 0x8003a, 0x900d4, 0x7010d, 0x8006a, 0x8002a, 0x900b4, 0x8000a, 0x8008a, 0x8004a, 0x900f4, 0x70103, 0x80056, 0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cc, 0x7010b, 0x80066, 0x80026, 0x900ac, 0x80006, 0x80086, 0x80046, 0x900ec, 0x70107, 0x8005e, 0x8001e, 0x9009c, 0x70117, 0x8007e, 0x8003e, 0x900dc, 0x7010f, 0x8006e, 0x8002e, 0x900bc, 0x8000e, 0x8008e, 0x8004e, 0x900fc, 0x70100, 0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c2, 0x70108, 0x80061, 0x80021, 0x900a2, 0x80001, 0x80081, 0x80041, 0x900e2, 0x70104, 0x80059, 0x80019, 0x90092, 0x70114, 0x80079, 0x80039, 0x900d2, 0x7010c, 0x80069, 0x80029, 0x900b2, 0x80009, 0x80089, 0x80049, 0x900f2, 0x70102, 0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900ca, 0x7010a, 0x80065, 0x80025, 0x900aa, 0x80005, 0x80085, 0x80045, 0x900ea, 0x70106, 0x8005d, 0x8001d, 0x9009a, 0x70116, 0x8007d, 0x8003d, 0x900da, 0x7010e, 0x8006d, 0x8002d, 0x900ba, 0x8000d, 0x8008d, 0x8004d, 0x900fa, 0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033, 0x900c6, 0x70109, 0x80063, 0x80023, 0x900a6, 0x80003, 0x80083, 0x80043, 0x900e6, 0x70105, 0x8005b, 0x8001b, 0x90096, 0x70115, 0x8007b, 0x8003b, 0x900d6, 0x7010d, 0x8006b, 0x8002b, 0x900b6, 0x8000b, 0x8008b, 0x8004b, 0x900f6, 0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037, 0x900ce, 0x7010b, 0x80067, 0x80027, 0x900ae, 0x80007, 0x80087, 0x80047, 0x900ee, 0x70107, 0x8005f, 0x8001f, 0x9009e, 0x70117, 0x8007f, 0x8003f, 0x900de, 0x7010f, 0x8006f, 0x8002f, 0x900be, 0x8000f, 0x8008f, 0x8004f, 0x900fe, 0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c1, 0x70108, 0x80060, 0x80020, 0x900a1, 0x80000, 0x80080, 0x80040, 0x900e1, 0x70104, 0x80058, 0x80018, 0x90091, 0x70114, 0x80078, 0x80038, 0x900d1, 0x7010c, 0x80068, 0x80028, 0x900b1, 0x80008, 0x80088, 0x80048, 0x900f1, 0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074, 0x80034, 0x900c9, 0x7010a, 0x80064, 0x80024, 0x900a9, 0x80004, 0x80084, 0x80044, 0x900e9, 0x70106, 0x8005c, 0x8001c, 0x90099, 0x70116, 0x8007c, 0x8003c, 0x900d9, 0x7010e, 0x8006c, 0x8002c, 0x900b9, 0x8000c, 0x8008c, 0x8004c, 0x900f9, 0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c5, 0x70109, 0x80062, 0x80022, 0x900a5, 0x80002, 0x80082, 0x80042, 0x900e5, 0x70105, 0x8005a, 0x8001a, 0x90095, 0x70115, 0x8007a, 0x8003a, 0x900d5, 0x7010d, 0x8006a, 0x8002a, 0x900b5, 0x8000a, 0x8008a, 0x8004a, 0x900f5, 0x70103, 0x80056, 0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cd, 0x7010b, 0x80066, 0x80026, 0x900ad, 0x80006, 0x80086, 0x80046, 0x900ed, 0x70107, 0x8005e, 0x8001e, 0x9009d, 0x70117, 0x8007e, 0x8003e, 0x900dd, 0x7010f, 0x8006e, 0x8002e, 0x900bd, 0x8000e, 0x8008e, 0x8004e, 0x900fd, 0x70100, 0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c3, 0x70108, 0x80061, 0x80021, 0x900a3, 0x80001, 0x80081, 0x80041, 0x900e3, 0x70104, 0x80059, 0x80019, 0x90093, 0x70114, 0x80079, 0x80039, 0x900d3, 0x7010c, 0x80069, 0x80029, 0x900b3, 0x80009, 0x80089, 0x80049, 0x900f3, 0x70102, 0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900cb, 0x7010a, 0x80065, 0x80025, 0x900ab, 0x80005, 0x80085, 0x80045, 0x900eb, 0x70106, 0x8005d, 0x8001d, 0x9009b, 0x70116, 0x8007d, 0x8003d, 0x900db, 0x7010e, 0x8006d, 0x8002d, 0x900bb, 0x8000d, 0x8008d, 0x8004d, 0x900fb, 0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033, 0x900c7, 0x70109, 0x80063, 0x80023, 0x900a7, 0x80003, 0x80083, 0x80043, 0x900e7, 0x70105, 0x8005b, 0x8001b, 0x90097, 0x70115, 0x8007b, 0x8003b, 0x900d7, 0x7010d, 0x8006b, 0x8002b, 0x900b7, 0x8000b, 0x8008b, 0x8004b, 0x900f7, 0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037, 0x900cf, 0x7010b, 0x80067, 0x80027, 0x900af, 0x80007, 0x80087, 0x80047, 0x900ef, 0x70107, 0x8005f, 0x8001f, 0x9009f, 0x70117, 0x8007f, 0x8003f, 0x900df, 0x7010f, 0x8006f, 0x8002f, 0x900bf, 0x8000f, 0x8008f, 0x8004f, 0x900ff]), 9];
  18649. var fixedDistCodeTab = [new Uint32Array([0x50000, 0x50010, 0x50008, 0x50018, 0x50004, 0x50014, 0x5000c, 0x5001c, 0x50002, 0x50012, 0x5000a, 0x5001a, 0x50006, 0x50016, 0x5000e, 0x00000, 0x50001, 0x50011, 0x50009, 0x50019, 0x50005, 0x50015, 0x5000d, 0x5001d, 0x50003, 0x50013, 0x5000b, 0x5001b, 0x50007, 0x50017, 0x5000f, 0x00000]), 5];
  18650. function error(e) {
  18651. throw new Error(e);
  18652. }
  18653. function constructor(bytes) {
  18654. //var bytes = stream.getBytes();
  18655. var bytesPos = 0;
  18656. var cmf = bytes[bytesPos++];
  18657. var flg = bytes[bytesPos++];
  18658. if (cmf == -1 || flg == -1) error("Invalid header in flate stream");
  18659. if ((cmf & 0x0f) != 0x08) error("Unknown compression method in flate stream");
  18660. if (((cmf << 8) + flg) % 31 != 0) error("Bad FCHECK in flate stream");
  18661. if (flg & 0x20) error("FDICT bit set in flate stream");
  18662. this.bytes = bytes;
  18663. this.bytesPos = bytesPos;
  18664. this.codeSize = 0;
  18665. this.codeBuf = 0;
  18666. DecodeStream.call(this);
  18667. }
  18668. constructor.prototype = Object.create(DecodeStream.prototype);
  18669. constructor.prototype.getBits = function (bits) {
  18670. var codeSize = this.codeSize;
  18671. var codeBuf = this.codeBuf;
  18672. var bytes = this.bytes;
  18673. var bytesPos = this.bytesPos;
  18674. var b;
  18675. while (codeSize < bits) {
  18676. if (typeof (b = bytes[bytesPos++]) == "undefined") error("Bad encoding in flate stream");
  18677. codeBuf |= b << codeSize;
  18678. codeSize += 8;
  18679. }
  18680. b = codeBuf & (1 << bits) - 1;
  18681. this.codeBuf = codeBuf >> bits;
  18682. this.codeSize = codeSize -= bits;
  18683. this.bytesPos = bytesPos;
  18684. return b;
  18685. };
  18686. constructor.prototype.getCode = function (table) {
  18687. var codes = table[0];
  18688. var maxLen = table[1];
  18689. var codeSize = this.codeSize;
  18690. var codeBuf = this.codeBuf;
  18691. var bytes = this.bytes;
  18692. var bytesPos = this.bytesPos;
  18693. while (codeSize < maxLen) {
  18694. var b;
  18695. if (typeof (b = bytes[bytesPos++]) == "undefined") error("Bad encoding in flate stream");
  18696. codeBuf |= b << codeSize;
  18697. codeSize += 8;
  18698. }
  18699. var code = codes[codeBuf & (1 << maxLen) - 1];
  18700. var codeLen = code >> 16;
  18701. var codeVal = code & 0xffff;
  18702. if (codeSize == 0 || codeSize < codeLen || codeLen == 0) error("Bad encoding in flate stream");
  18703. this.codeBuf = codeBuf >> codeLen;
  18704. this.codeSize = codeSize - codeLen;
  18705. this.bytesPos = bytesPos;
  18706. return codeVal;
  18707. };
  18708. constructor.prototype.generateHuffmanTable = function (lengths) {
  18709. var n = lengths.length; // find max code length
  18710. var maxLen = 0;
  18711. for (var i = 0; i < n; ++i) {
  18712. if (lengths[i] > maxLen) maxLen = lengths[i];
  18713. } // build the table
  18714. var size = 1 << maxLen;
  18715. var codes = new Uint32Array(size);
  18716. for (var len = 1, code = 0, skip = 2; len <= maxLen; ++len, code <<= 1, skip <<= 1) {
  18717. for (var val = 0; val < n; ++val) {
  18718. if (lengths[val] == len) {
  18719. // bit-reverse the code
  18720. var code2 = 0;
  18721. var t = code;
  18722. for (var i = 0; i < len; ++i) {
  18723. code2 = code2 << 1 | t & 1;
  18724. t >>= 1;
  18725. } // fill the table entries
  18726. for (var i = code2; i < size; i += skip) codes[i] = len << 16 | val;
  18727. ++code;
  18728. }
  18729. }
  18730. }
  18731. return [codes, maxLen];
  18732. };
  18733. constructor.prototype.readBlock = function () {
  18734. function repeat(stream, array, len, offset, what) {
  18735. var repeat = stream.getBits(len) + offset;
  18736. while (repeat-- > 0) array[i++] = what;
  18737. } // read block header
  18738. var hdr = this.getBits(3);
  18739. if (hdr & 1) this.eof = true;
  18740. hdr >>= 1;
  18741. if (hdr == 0) {
  18742. // uncompressed block
  18743. var bytes = this.bytes;
  18744. var bytesPos = this.bytesPos;
  18745. var b;
  18746. if (typeof (b = bytes[bytesPos++]) == "undefined") error("Bad block header in flate stream");
  18747. var blockLen = b;
  18748. if (typeof (b = bytes[bytesPos++]) == "undefined") error("Bad block header in flate stream");
  18749. blockLen |= b << 8;
  18750. if (typeof (b = bytes[bytesPos++]) == "undefined") error("Bad block header in flate stream");
  18751. var check = b;
  18752. if (typeof (b = bytes[bytesPos++]) == "undefined") error("Bad block header in flate stream");
  18753. check |= b << 8;
  18754. if (check != (~blockLen & 0xffff)) error("Bad uncompressed block length in flate stream");
  18755. this.codeBuf = 0;
  18756. this.codeSize = 0;
  18757. var bufferLength = this.bufferLength;
  18758. var buffer = this.ensureBuffer(bufferLength + blockLen);
  18759. var end = bufferLength + blockLen;
  18760. this.bufferLength = end;
  18761. for (var n = bufferLength; n < end; ++n) {
  18762. if (typeof (b = bytes[bytesPos++]) == "undefined") {
  18763. this.eof = true;
  18764. break;
  18765. }
  18766. buffer[n] = b;
  18767. }
  18768. this.bytesPos = bytesPos;
  18769. return;
  18770. }
  18771. var litCodeTable;
  18772. var distCodeTable;
  18773. if (hdr == 1) {
  18774. // compressed block, fixed codes
  18775. litCodeTable = fixedLitCodeTab;
  18776. distCodeTable = fixedDistCodeTab;
  18777. } else if (hdr == 2) {
  18778. // compressed block, dynamic codes
  18779. var numLitCodes = this.getBits(5) + 257;
  18780. var numDistCodes = this.getBits(5) + 1;
  18781. var numCodeLenCodes = this.getBits(4) + 4; // build the code lengths code table
  18782. var codeLenCodeLengths = Array(codeLenCodeMap.length);
  18783. var i = 0;
  18784. while (i < numCodeLenCodes) codeLenCodeLengths[codeLenCodeMap[i++]] = this.getBits(3);
  18785. var codeLenCodeTab = this.generateHuffmanTable(codeLenCodeLengths); // build the literal and distance code tables
  18786. var len = 0;
  18787. var i = 0;
  18788. var codes = numLitCodes + numDistCodes;
  18789. var codeLengths = new Array(codes);
  18790. while (i < codes) {
  18791. var code = this.getCode(codeLenCodeTab);
  18792. if (code == 16) {
  18793. repeat(this, codeLengths, 2, 3, len);
  18794. } else if (code == 17) {
  18795. repeat(this, codeLengths, 3, 3, len = 0);
  18796. } else if (code == 18) {
  18797. repeat(this, codeLengths, 7, 11, len = 0);
  18798. } else {
  18799. codeLengths[i++] = len = code;
  18800. }
  18801. }
  18802. litCodeTable = this.generateHuffmanTable(codeLengths.slice(0, numLitCodes));
  18803. distCodeTable = this.generateHuffmanTable(codeLengths.slice(numLitCodes, codes));
  18804. } else {
  18805. error("Unknown block type in flate stream");
  18806. }
  18807. var buffer = this.buffer;
  18808. var limit = buffer ? buffer.length : 0;
  18809. var pos = this.bufferLength;
  18810. while (true) {
  18811. var code1 = this.getCode(litCodeTable);
  18812. if (code1 < 256) {
  18813. if (pos + 1 >= limit) {
  18814. buffer = this.ensureBuffer(pos + 1);
  18815. limit = buffer.length;
  18816. }
  18817. buffer[pos++] = code1;
  18818. continue;
  18819. }
  18820. if (code1 == 256) {
  18821. this.bufferLength = pos;
  18822. return;
  18823. }
  18824. code1 -= 257;
  18825. code1 = lengthDecode[code1];
  18826. var code2 = code1 >> 16;
  18827. if (code2 > 0) code2 = this.getBits(code2);
  18828. var len = (code1 & 0xffff) + code2;
  18829. code1 = this.getCode(distCodeTable);
  18830. code1 = distDecode[code1];
  18831. code2 = code1 >> 16;
  18832. if (code2 > 0) code2 = this.getBits(code2);
  18833. var dist = (code1 & 0xffff) + code2;
  18834. if (pos + len >= limit) {
  18835. buffer = this.ensureBuffer(pos + len);
  18836. limit = buffer.length;
  18837. }
  18838. for (var k = 0; k < len; ++k, ++pos) buffer[pos] = buffer[pos - dist];
  18839. }
  18840. };
  18841. return constructor;
  18842. }();
  18843. exports.default = jsPDF;
  18844. var _default2 = exports.default;
  18845. function rewire($stub) {
  18846. exports.default = $stub;
  18847. }
  18848. function restore() {
  18849. exports.default = _default2;
  18850. }
  18851. exports.rewire = rewire;
  18852. exports.restore = restore;
  18853. Object.defineProperty(exports, '__esModule', { value: true });
  18854. })));