jspdf.src.js 723 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195151961519715198151991520015201152021520315204152051520615207152081520915210152111521215213152141521515216152171521815219152201522115222152231522415225152261522715228152291523015231152321523315234152351523615237152381523915240152411524215243152441524515246152471524815249152501525115252152531525415255152561525715258152591526015261152621526315264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532315324153251532615327153281532915330153311533215333153341533515336153371533815339153401534115342153431534415345153461534715348153491535015351153521535315354153551535615357153581535915360153611536215363153641536515366153671536815369153701537115372153731537415375153761537715378153791538015381153821538315384153851538615387153881538915390153911539215393153941539515396153971539815399154001540115402154031540415405154061540715408154091541015411154121541315414154151541615417154181541915420154211542215423154241542515426154271542815429154301543115432154331543415435154361543715438154391544015441154421544315444154451544615447154481544915450154511545215453154541545515456154571545815459154601546115462154631546415465154661546715468154691547015471154721547315474154751547615477154781547915480154811548215483154841548515486154871548815489154901549115492154931549415495154961549715498154991550015501155021550315504155051550615507155081550915510155111551215513155141551515516155171551815519155201552115522155231552415525155261552715528155291553015531155321553315534155351553615537155381553915540155411554215543155441554515546155471554815549155501555115552155531555415555155561555715558155591556015561155621556315564155651556615567155681556915570155711557215573155741557515576155771557815579155801558115582155831558415585155861558715588155891559015591155921559315594155951559615597155981559915600156011560215603156041560515606156071560815609156101561115612156131561415615156161561715618156191562015621156221562315624156251562615627156281562915630156311563215633156341563515636156371563815639156401564115642156431564415645156461564715648156491565015651156521565315654156551565615657156581565915660156611566215663156641566515666156671566815669156701567115672156731567415675156761567715678156791568015681156821568315684156851568615687156881568915690156911569215693156941569515696156971569815699157001570115702157031570415705157061570715708157091571015711157121571315714157151571615717157181571915720157211572215723157241572515726157271572815729157301573115732157331573415735157361573715738157391574015741157421574315744157451574615747157481574915750157511575215753157541575515756157571575815759157601576115762157631576415765157661576715768157691577015771157721577315774157751577615777157781577915780157811578215783157841578515786157871578815789157901579115792157931579415795157961579715798157991580015801158021580315804158051580615807158081580915810158111581215813158141581515816158171581815819158201582115822158231582415825158261582715828158291583015831158321583315834158351583615837158381583915840158411584215843158441584515846158471584815849158501585115852158531585415855158561585715858158591586015861158621586315864158651586615867158681586915870158711587215873158741587515876158771587815879158801588115882158831588415885158861588715888158891589015891158921589315894158951589615897158981589915900159011590215903159041590515906159071590815909159101591115912159131591415915159161591715918159191592015921159221592315924159251592615927159281592915930159311593215933159341593515936159371593815939159401594115942159431594415945159461594715948159491595015951159521595315954159551595615957159581595915960159611596215963159641596515966159671596815969159701597115972159731597415975159761597715978159791598015981159821598315984159851598615987159881598915990159911599215993159941599515996159971599815999160001600116002160031600416005160061600716008160091601016011160121601316014160151601616017160181601916020160211602216023160241602516026160271602816029160301603116032160331603416035160361603716038160391604016041160421604316044160451604616047160481604916050160511605216053160541605516056160571605816059160601606116062160631606416065160661606716068160691607016071160721607316074160751607616077160781607916080160811608216083160841608516086160871608816089160901609116092160931609416095160961609716098160991610016101161021610316104161051610616107161081610916110161111611216113161141611516116161171611816119161201612116122161231612416125161261612716128161291613016131161321613316134161351613616137161381613916140161411614216143161441614516146161471614816149161501615116152161531615416155161561615716158161591616016161161621616316164161651616616167161681616916170161711617216173161741617516176161771617816179161801618116182161831618416185161861618716188161891619016191161921619316194161951619616197161981619916200162011620216203162041620516206162071620816209162101621116212162131621416215162161621716218162191622016221162221622316224162251622616227162281622916230162311623216233162341623516236162371623816239162401624116242162431624416245162461624716248162491625016251162521625316254162551625616257162581625916260162611626216263162641626516266162671626816269162701627116272162731627416275162761627716278162791628016281162821628316284162851628616287162881628916290162911629216293162941629516296162971629816299163001630116302163031630416305163061630716308163091631016311163121631316314163151631616317163181631916320163211632216323163241632516326163271632816329163301633116332163331633416335163361633716338163391634016341163421634316344163451634616347163481634916350163511635216353163541635516356163571635816359163601636116362163631636416365163661636716368163691637016371163721637316374163751637616377163781637916380163811638216383163841638516386163871638816389163901639116392163931639416395163961639716398163991640016401164021640316404164051640616407164081640916410164111641216413164141641516416164171641816419164201642116422164231642416425164261642716428164291643016431164321643316434164351643616437164381643916440164411644216443164441644516446164471644816449164501645116452164531645416455164561645716458164591646016461164621646316464164651646616467164681646916470164711647216473164741647516476164771647816479164801648116482164831648416485164861648716488164891649016491164921649316494164951649616497164981649916500165011650216503165041650516506165071650816509165101651116512165131651416515165161651716518165191652016521165221652316524165251652616527165281652916530165311653216533165341653516536165371653816539165401654116542165431654416545165461654716548165491655016551165521655316554165551655616557165581655916560165611656216563165641656516566165671656816569165701657116572165731657416575165761657716578165791658016581165821658316584165851658616587165881658916590165911659216593165941659516596165971659816599166001660116602166031660416605166061660716608166091661016611166121661316614166151661616617166181661916620166211662216623166241662516626166271662816629166301663116632166331663416635166361663716638166391664016641166421664316644166451664616647166481664916650166511665216653166541665516656166571665816659166601666116662166631666416665166661666716668166691667016671166721667316674166751667616677166781667916680166811668216683166841668516686166871668816689166901669116692166931669416695166961669716698166991670016701167021670316704167051670616707167081670916710167111671216713167141671516716167171671816719167201672116722167231672416725167261672716728167291673016731167321673316734167351673616737167381673916740167411674216743167441674516746167471674816749167501675116752167531675416755167561675716758167591676016761167621676316764167651676616767167681676916770167711677216773167741677516776167771677816779167801678116782167831678416785167861678716788167891679016791167921679316794167951679616797167981679916800168011680216803168041680516806168071680816809168101681116812168131681416815168161681716818168191682016821168221682316824168251682616827168281682916830168311683216833168341683516836168371683816839168401684116842168431684416845168461684716848168491685016851168521685316854168551685616857168581685916860168611686216863168641686516866168671686816869168701687116872168731687416875168761687716878168791688016881168821688316884168851688616887168881688916890168911689216893168941689516896168971689816899169001690116902169031690416905169061690716908169091691016911169121691316914169151691616917169181691916920169211692216923169241692516926169271692816929169301693116932169331693416935169361693716938169391694016941169421694316944169451694616947169481694916950169511695216953169541695516956169571695816959169601696116962169631696416965169661696716968169691697016971169721697316974169751697616977169781697916980169811698216983169841698516986169871698816989169901699116992169931699416995169961699716998169991700017001170021700317004170051700617007170081700917010170111701217013170141701517016170171701817019170201702117022170231702417025170261702717028170291703017031170321703317034170351703617037170381703917040170411704217043170441704517046170471704817049170501705117052170531705417055170561705717058170591706017061170621706317064170651706617067170681706917070170711707217073170741707517076170771707817079170801708117082170831708417085170861708717088170891709017091170921709317094170951709617097170981709917100171011710217103171041710517106171071710817109171101711117112171131711417115171161711717118171191712017121171221712317124171251712617127171281712917130171311713217133171341713517136171371713817139171401714117142171431714417145171461714717148171491715017151171521715317154171551715617157171581715917160171611716217163171641716517166171671716817169171701717117172171731717417175171761717717178171791718017181171821718317184171851718617187171881718917190171911719217193171941719517196171971719817199172001720117202172031720417205172061720717208172091721017211172121721317214172151721617217172181721917220172211722217223172241722517226172271722817229172301723117232172331723417235172361723717238172391724017241172421724317244172451724617247172481724917250172511725217253172541725517256172571725817259172601726117262172631726417265172661726717268172691727017271172721727317274172751727617277172781727917280172811728217283172841728517286172871728817289172901729117292172931729417295172961729717298172991730017301173021730317304173051730617307173081730917310173111731217313173141731517316173171731817319173201732117322173231732417325173261732717328173291733017331173321733317334173351733617337173381733917340173411734217343173441734517346173471734817349173501735117352173531735417355173561735717358173591736017361173621736317364173651736617367173681736917370173711737217373173741737517376173771737817379173801738117382173831738417385173861738717388173891739017391173921739317394173951739617397173981739917400174011740217403174041740517406174071740817409174101741117412174131741417415174161741717418174191742017421174221742317424174251742617427174281742917430174311743217433174341743517436174371743817439174401744117442174431744417445174461744717448174491745017451174521745317454174551745617457174581745917460174611746217463174641746517466174671746817469174701747117472174731747417475174761747717478174791748017481174821748317484174851748617487174881748917490174911749217493174941749517496174971749817499175001750117502175031750417505175061750717508175091751017511175121751317514175151751617517175181751917520175211752217523175241752517526175271752817529175301753117532175331753417535175361753717538175391754017541175421754317544175451754617547175481754917550175511755217553175541755517556175571755817559175601756117562175631756417565175661756717568175691757017571175721757317574175751757617577175781757917580175811758217583175841758517586175871758817589175901759117592175931759417595175961759717598175991760017601176021760317604176051760617607176081760917610176111761217613176141761517616176171761817619176201762117622176231762417625176261762717628176291763017631176321763317634176351763617637176381763917640176411764217643176441764517646176471764817649176501765117652176531765417655176561765717658176591766017661176621766317664176651766617667176681766917670176711767217673176741767517676176771767817679176801768117682176831768417685176861768717688176891769017691176921769317694176951769617697176981769917700177011770217703177041770517706177071770817709177101771117712177131771417715177161771717718177191772017721177221772317724177251772617727177281772917730177311773217733177341773517736177371773817739177401774117742177431774417745177461774717748177491775017751177521775317754177551775617757177581775917760177611776217763177641776517766177671776817769177701777117772177731777417775177761777717778177791778017781177821778317784177851778617787177881778917790177911779217793177941779517796177971779817799178001780117802178031780417805178061780717808178091781017811178121781317814178151781617817178181781917820178211782217823178241782517826178271782817829178301783117832178331783417835178361783717838178391784017841178421784317844178451784617847178481784917850178511785217853178541785517856178571785817859178601786117862178631786417865178661786717868178691787017871178721787317874178751787617877178781787917880178811788217883178841788517886178871788817889178901789117892178931789417895178961789717898178991790017901179021790317904179051790617907179081790917910179111791217913179141791517916179171791817919179201792117922179231792417925179261792717928179291793017931179321793317934179351793617937179381793917940179411794217943179441794517946179471794817949179501795117952179531795417955179561795717958179591796017961179621796317964179651796617967179681796917970179711797217973179741797517976179771797817979179801798117982179831798417985179861798717988179891799017991179921799317994179951799617997179981799918000180011800218003180041800518006180071800818009180101801118012180131801418015180161801718018180191802018021180221802318024180251802618027180281802918030180311803218033180341803518036180371803818039180401804118042180431804418045180461804718048180491805018051180521805318054180551805618057180581805918060180611806218063180641806518066180671806818069180701807118072180731807418075180761807718078180791808018081180821808318084180851808618087180881808918090180911809218093180941809518096180971809818099181001810118102181031810418105181061810718108181091811018111181121811318114181151811618117181181811918120181211812218123181241812518126181271812818129181301813118132181331813418135181361813718138181391814018141181421814318144181451814618147181481814918150181511815218153181541815518156181571815818159181601816118162181631816418165181661816718168181691817018171181721817318174181751817618177181781817918180181811818218183181841818518186181871818818189181901819118192181931819418195181961819718198181991820018201182021820318204182051820618207182081820918210182111821218213182141821518216182171821818219182201822118222182231822418225182261822718228182291823018231182321823318234182351823618237182381823918240182411824218243182441824518246182471824818249182501825118252182531825418255182561825718258182591826018261182621826318264182651826618267182681826918270182711827218273182741827518276182771827818279182801828118282182831828418285182861828718288182891829018291182921829318294182951829618297182981829918300183011830218303183041830518306183071830818309183101831118312183131831418315183161831718318183191832018321183221832318324183251832618327183281832918330183311833218333183341833518336183371833818339183401834118342183431834418345183461834718348183491835018351183521835318354183551835618357183581835918360183611836218363183641836518366183671836818369183701837118372183731837418375183761837718378183791838018381183821838318384183851838618387183881838918390183911839218393183941839518396183971839818399184001840118402184031840418405184061840718408184091841018411184121841318414184151841618417184181841918420184211842218423184241842518426184271842818429184301843118432184331843418435184361843718438184391844018441184421844318444184451844618447184481844918450184511845218453184541845518456184571845818459184601846118462184631846418465184661846718468184691847018471184721847318474184751847618477184781847918480184811848218483184841848518486184871848818489184901849118492184931849418495184961849718498184991850018501185021850318504185051850618507185081850918510185111851218513185141851518516185171851818519185201852118522185231852418525185261852718528185291853018531185321853318534185351853618537185381853918540185411854218543185441854518546185471854818549185501855118552185531855418555185561855718558185591856018561185621856318564185651856618567185681856918570185711857218573185741857518576185771857818579185801858118582185831858418585185861858718588185891859018591185921859318594185951859618597185981859918600186011860218603186041860518606186071860818609186101861118612186131861418615186161861718618186191862018621186221862318624186251862618627186281862918630186311863218633186341863518636186371863818639186401864118642186431864418645186461864718648186491865018651186521865318654186551865618657186581865918660186611866218663186641866518666186671866818669186701867118672186731867418675186761867718678186791868018681186821868318684186851868618687186881868918690186911869218693186941869518696186971869818699187001870118702187031870418705187061870718708187091871018711187121871318714187151871618717187181871918720187211872218723187241872518726187271872818729187301873118732187331873418735187361873718738187391874018741187421874318744187451874618747187481874918750187511875218753187541875518756187571875818759187601876118762187631876418765187661876718768187691877018771187721877318774187751877618777187781877918780187811878218783187841878518786187871878818789187901879118792187931879418795187961879718798187991880018801188021880318804188051880618807188081880918810188111881218813188141881518816188171881818819188201882118822188231882418825188261882718828188291883018831188321883318834188351883618837188381883918840188411884218843188441884518846188471884818849188501885118852188531885418855188561885718858188591886018861188621886318864188651886618867188681886918870188711887218873188741887518876188771887818879188801888118882188831888418885188861888718888188891889018891188921889318894188951889618897188981889918900189011890218903189041890518906189071890818909189101891118912189131891418915189161891718918189191892018921189221892318924189251892618927189281892918930189311893218933189341893518936189371893818939189401894118942189431894418945189461894718948189491895018951189521895318954189551895618957189581895918960189611896218963189641896518966189671896818969189701897118972189731897418975189761897718978189791898018981189821898318984189851898618987189881898918990189911899218993189941899518996189971899818999190001900119002190031900419005190061900719008190091901019011190121901319014190151901619017190181901919020190211902219023190241902519026190271902819029190301903119032190331903419035190361903719038190391904019041190421904319044190451904619047190481904919050190511905219053190541905519056190571905819059190601906119062190631906419065190661906719068190691907019071190721907319074190751907619077190781907919080190811908219083190841908519086190871908819089190901909119092190931909419095190961909719098190991910019101191021910319104191051910619107191081910919110191111911219113191141911519116191171911819119191201912119122191231912419125191261912719128191291913019131191321913319134191351913619137191381913919140191411914219143191441914519146191471914819149191501915119152191531915419155191561915719158191591916019161191621916319164191651916619167191681916919170191711917219173191741917519176191771917819179191801918119182191831918419185191861918719188191891919019191191921919319194191951919619197191981919919200192011920219203192041920519206192071920819209192101921119212192131921419215192161921719218192191922019221192221922319224192251922619227192281922919230192311923219233192341923519236192371923819239192401924119242192431924419245192461924719248192491925019251192521925319254192551925619257192581925919260192611926219263192641926519266192671926819269192701927119272192731927419275192761927719278192791928019281192821928319284192851928619287192881928919290192911929219293192941929519296192971929819299193001930119302193031930419305193061930719308193091931019311193121931319314193151931619317193181931919320193211932219323193241932519326193271932819329193301933119332193331933419335193361933719338193391934019341193421934319344193451934619347193481934919350193511935219353193541935519356193571935819359193601936119362193631936419365193661936719368193691937019371193721937319374193751937619377193781937919380193811938219383193841938519386193871938819389193901939119392193931939419395193961939719398193991940019401194021940319404194051940619407194081940919410194111941219413194141941519416194171941819419194201942119422194231942419425194261942719428194291943019431194321943319434194351943619437194381943919440194411944219443194441944519446194471944819449194501945119452194531945419455194561945719458194591946019461194621946319464194651946619467194681946919470194711947219473194741947519476194771947819479194801948119482194831948419485194861948719488194891949019491194921949319494194951949619497194981949919500195011950219503195041950519506195071950819509195101951119512195131951419515195161951719518195191952019521195221952319524195251952619527195281952919530195311953219533195341953519536195371953819539195401954119542195431954419545195461954719548195491955019551195521955319554195551955619557195581955919560195611956219563195641956519566195671956819569195701957119572195731957419575195761957719578195791958019581195821958319584195851958619587195881958919590195911959219593195941959519596195971959819599196001960119602196031960419605196061960719608196091961019611196121961319614196151961619617196181961919620196211962219623196241962519626196271962819629196301963119632196331963419635196361963719638196391964019641196421964319644196451964619647196481964919650196511965219653196541965519656196571965819659196601966119662196631966419665196661966719668196691967019671196721967319674196751967619677196781967919680196811968219683196841968519686196871968819689196901969119692196931969419695196961969719698196991970019701197021970319704197051970619707197081970919710197111971219713197141971519716197171971819719197201972119722197231972419725197261972719728197291973019731197321973319734197351973619737197381973919740197411974219743197441974519746197471974819749197501975119752197531975419755197561975719758197591976019761197621976319764197651976619767197681976919770197711977219773197741977519776197771977819779197801978119782197831978419785197861978719788197891979019791197921979319794197951979619797197981979919800198011980219803198041980519806198071980819809198101981119812198131981419815198161981719818198191982019821198221982319824198251982619827198281982919830198311983219833198341983519836198371983819839198401984119842198431984419845198461984719848198491985019851198521985319854198551985619857198581985919860198611986219863198641986519866198671986819869198701987119872198731987419875198761987719878198791988019881198821988319884198851988619887198881988919890198911989219893198941989519896198971989819899199001990119902199031990419905199061990719908199091991019911199121991319914199151991619917199181991919920199211992219923199241992519926199271992819929199301993119932199331993419935199361993719938199391994019941199421994319944199451994619947199481994919950199511995219953199541995519956199571995819959199601996119962199631996419965199661996719968199691997019971199721997319974199751997619977199781997919980199811998219983199841998519986199871998819989199901999119992199931999419995199961999719998199992000020001200022000320004200052000620007200082000920010200112001220013200142001520016200172001820019200202002120022200232002420025200262002720028200292003020031200322003320034200352003620037200382003920040200412004220043200442004520046200472004820049200502005120052200532005420055200562005720058200592006020061200622006320064200652006620067200682006920070200712007220073200742007520076200772007820079200802008120082200832008420085200862008720088200892009020091200922009320094200952009620097200982009920100201012010220103201042010520106201072010820109201102011120112201132011420115201162011720118201192012020121201222012320124201252012620127201282012920130201312013220133201342013520136201372013820139201402014120142201432014420145201462014720148201492015020151201522015320154201552015620157201582015920160201612016220163201642016520166201672016820169201702017120172201732017420175201762017720178201792018020181201822018320184201852018620187201882018920190201912019220193201942019520196201972019820199202002020120202202032020420205202062020720208202092021020211202122021320214202152021620217202182021920220202212022220223202242022520226202272022820229202302023120232202332023420235202362023720238202392024020241202422024320244202452024620247202482024920250202512025220253202542025520256202572025820259202602026120262202632026420265202662026720268202692027020271202722027320274202752027620277202782027920280202812028220283202842028520286202872028820289202902029120292202932029420295202962029720298202992030020301203022030320304203052030620307203082030920310203112031220313203142031520316203172031820319203202032120322203232032420325203262032720328203292033020331203322033320334203352033620337203382033920340203412034220343203442034520346203472034820349203502035120352203532035420355203562035720358203592036020361203622036320364203652036620367203682036920370203712037220373203742037520376203772037820379203802038120382203832038420385203862038720388203892039020391203922039320394203952039620397203982039920400204012040220403204042040520406204072040820409204102041120412204132041420415204162041720418204192042020421204222042320424204252042620427204282042920430204312043220433204342043520436204372043820439204402044120442204432044420445204462044720448204492045020451204522045320454204552045620457204582045920460204612046220463204642046520466204672046820469204702047120472204732047420475204762047720478204792048020481204822048320484204852048620487204882048920490204912049220493204942049520496204972049820499205002050120502205032050420505205062050720508205092051020511205122051320514205152051620517205182051920520205212052220523205242052520526205272052820529205302053120532205332053420535205362053720538205392054020541205422054320544205452054620547205482054920550205512055220553205542055520556205572055820559205602056120562205632056420565205662056720568205692057020571205722057320574205752057620577205782057920580205812058220583205842058520586205872058820589205902059120592205932059420595205962059720598205992060020601206022060320604206052060620607206082060920610206112061220613206142061520616206172061820619206202062120622206232062420625206262062720628206292063020631206322063320634206352063620637206382063920640206412064220643206442064520646206472064820649206502065120652206532065420655206562065720658206592066020661206622066320664206652066620667206682066920670206712067220673206742067520676206772067820679206802068120682206832068420685206862068720688206892069020691206922069320694206952069620697206982069920700207012070220703207042070520706207072070820709207102071120712207132071420715207162071720718207192072020721207222072320724207252072620727207282072920730207312073220733207342073520736207372073820739207402074120742207432074420745207462074720748207492075020751207522075320754207552075620757207582075920760207612076220763207642076520766207672076820769207702077120772207732077420775207762077720778207792078020781207822078320784207852078620787207882078920790207912079220793207942079520796207972079820799208002080120802208032080420805208062080720808208092081020811208122081320814208152081620817208182081920820208212082220823208242082520826208272082820829208302083120832208332083420835208362083720838208392084020841208422084320844208452084620847208482084920850208512085220853208542085520856208572085820859208602086120862208632086420865208662086720868208692087020871208722087320874208752087620877208782087920880208812088220883208842088520886208872088820889208902089120892208932089420895208962089720898208992090020901209022090320904209052090620907209082090920910209112091220913209142091520916209172091820919209202092120922209232092420925209262092720928209292093020931209322093320934209352093620937209382093920940209412094220943209442094520946209472094820949209502095120952209532095420955209562095720958209592096020961209622096320964209652096620967209682096920970209712097220973209742097520976209772097820979209802098120982209832098420985209862098720988209892099020991209922099320994209952099620997209982099921000210012100221003210042100521006210072100821009210102101121012210132101421015210162101721018210192102021021210222102321024210252102621027210282102921030210312103221033210342103521036210372103821039210402104121042210432104421045210462104721048210492105021051210522105321054210552105621057210582105921060210612106221063210642106521066210672106821069210702107121072210732107421075210762107721078210792108021081210822108321084210852108621087210882108921090210912109221093210942109521096210972109821099211002110121102211032110421105211062110721108211092111021111211122111321114211152111621117211182111921120211212112221123211242112521126211272112821129211302113121132211332113421135211362113721138211392114021141211422114321144211452114621147211482114921150211512115221153211542115521156211572115821159211602116121162211632116421165211662116721168211692117021171211722117321174211752117621177211782117921180211812118221183211842118521186211872118821189211902119121192211932119421195211962119721198211992120021201212022120321204212052120621207212082120921210212112121221213212142121521216212172121821219212202122121222212232122421225212262122721228212292123021231212322123321234212352123621237212382123921240212412124221243212442124521246212472124821249212502125121252212532125421255212562125721258212592126021261212622126321264212652126621267212682126921270212712127221273212742127521276212772127821279212802128121282212832128421285212862128721288212892129021291212922129321294212952129621297212982129921300213012130221303213042130521306213072130821309213102131121312213132131421315213162131721318213192132021321213222132321324213252132621327213282132921330213312133221333213342133521336213372133821339213402134121342213432134421345213462134721348213492135021351213522135321354213552135621357213582135921360213612136221363213642136521366213672136821369213702137121372213732137421375213762137721378213792138021381213822138321384213852138621387213882138921390213912139221393213942139521396213972139821399214002140121402214032140421405214062140721408214092141021411214122141321414214152141621417214182141921420214212142221423214242142521426214272142821429214302143121432214332143421435214362143721438214392144021441214422144321444214452144621447214482144921450214512145221453214542145521456214572145821459214602146121462214632146421465214662146721468214692147021471214722147321474214752147621477214782147921480214812148221483214842148521486214872148821489214902149121492214932149421495214962149721498214992150021501215022150321504215052150621507215082150921510215112151221513215142151521516215172151821519215202152121522215232152421525215262152721528215292153021531215322153321534215352153621537215382153921540215412154221543215442154521546215472154821549215502155121552215532155421555215562155721558215592156021561215622156321564215652156621567215682156921570215712157221573215742157521576215772157821579215802158121582215832158421585215862158721588215892159021591215922159321594215952159621597215982159921600216012160221603216042160521606216072160821609216102161121612216132161421615216162161721618216192162021621216222162321624216252162621627
  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 2019-01-22T15:32:38.220Z
  473. * CommitID 0110a2202b
  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. appendBuffer = function appendBuffer(buffer1, buffer2) {
  929. var tmp = new Uint8Array(buffer1.byteLength + buffer2.byteLength);
  930. tmp.set(new Uint8Array(buffer1), 0);
  931. tmp.set(new Uint8Array(buffer2), buffer1.byteLength);
  932. return tmp;
  933. },
  934. putPages = function putPages() {
  935. var n,
  936. p,
  937. arr,
  938. i,
  939. deflater,
  940. adler32,
  941. adler32cs,
  942. wPt,
  943. hPt,
  944. pageObjectNumbers = [];
  945. adler32cs = global.adler32cs || jsPDF.API.adler32cs;
  946. if (compress && typeof adler32cs === "undefined") {
  947. compress = false;
  948. } // outToPages = false as set in endDocument(). out() writes to content.
  949. for (n = 1; n <= page; n++) {
  950. pageObjectNumbers.push(newObject());
  951. wPt = (pageWidth = pagedim[n].width) * k;
  952. hPt = (pageHeight = pagedim[n].height) * k;
  953. out("<</Type /Page");
  954. out("/Parent 1 0 R");
  955. out("/Resources 2 0 R");
  956. out("/MediaBox [0 0 " + hpf(wPt) + " " + hpf(hPt) + "]"); // Added for annotation plugin
  957. events.publish("putPage", {
  958. pageNumber: n,
  959. page: pages[n]
  960. });
  961. out("/Contents " + (objectNumber + 1) + " 0 R");
  962. out(">>");
  963. out("endobj"); // Page content
  964. p = pages[n].join("\n");
  965. if (apiMode === ApiMode.ADVANCED) {
  966. // if the user forgot to switch back to COMPAT mode, we must balance the graphics stack again
  967. p += "\nQ";
  968. }
  969. newObject();
  970. if (compress) {
  971. arr = [];
  972. i = p.length;
  973. while (i--) {
  974. arr[i] = p.charCodeAt(i);
  975. }
  976. adler32 = adler32cs.from(p);
  977. deflater = new Deflater(6);
  978. p = deflater.append(new Uint8Array(arr));
  979. p = appendBuffer(p, deflater.flush());
  980. arr = new Uint8Array(p.byteLength + 6);
  981. arr.set(new Uint8Array([120, 156]));
  982. arr.set(p, 2);
  983. arr.set(new Uint8Array([adler32 & 0xff, adler32 >> 8 & 0xff, adler32 >> 16 & 0xff, adler32 >> 24 & 0xff]), p.byteLength + 2);
  984. var strings = [],
  985. chunkSize = 0xffff; // There is a maximum stack size. We cannot call String.fromCharCode with as many arguments as we want
  986. for (var j = 0; j * chunkSize < arr.length; j++) {
  987. strings.push(String.fromCharCode.apply(null, arr.subarray(j * chunkSize, (j + 1) * chunkSize)));
  988. }
  989. p = strings.join('');
  990. out("<</Length " + p.length + " /Filter [/FlateDecode]>>");
  991. } else {
  992. out("<</Length " + p.length + ">>");
  993. }
  994. putStream(p);
  995. out("endobj");
  996. }
  997. offsets[1] = content_length;
  998. out("1 0 obj");
  999. out("<</Type /Pages");
  1000. var kids = "/Kids [";
  1001. for (i = 0; i < page; i++) {
  1002. kids += pageObjectNumbers[i] + " 0 R ";
  1003. }
  1004. out(kids + "]");
  1005. out("/Count " + page);
  1006. out(">>");
  1007. out("endobj");
  1008. events.publish("postPutPages");
  1009. },
  1010. putFont = function putFont(font) {
  1011. events.publish("putFont", {
  1012. font: font,
  1013. out: out,
  1014. newObject: newObject,
  1015. putStream: putStream
  1016. });
  1017. if (font.isAlreadyPutted !== true) {
  1018. font.objectNumber = newObject();
  1019. out("<<");
  1020. out("/Type /Font");
  1021. out("/BaseFont /" + font.postScriptName);
  1022. out("/Subtype /Type1");
  1023. if (typeof font.encoding === "string") {
  1024. out("/Encoding /" + font.encoding);
  1025. }
  1026. out("/FirstChar 32");
  1027. out("/LastChar 255");
  1028. out(">>");
  1029. out("endobj");
  1030. }
  1031. },
  1032. putFonts = function putFonts() {
  1033. for (var fontKey in fonts) {
  1034. if (fonts.hasOwnProperty(fontKey)) {
  1035. putFont(fonts[fontKey]);
  1036. }
  1037. }
  1038. },
  1039. putXObject = function putXObject(xObject) {
  1040. xObject.objectNumber = newObject();
  1041. out("<<");
  1042. out("/Type /XObject");
  1043. out("/Subtype /Form");
  1044. out("/BBox [" + [hpf(xObject.x), hpf(xObject.y), hpf(xObject.x + xObject.width), hpf(xObject.y + xObject.height)].join(" ") + "]");
  1045. out("/Matrix [" + xObject.matrix.toString() + "]"); // TODO: /Resources
  1046. var p = xObject.pages[1].join("\n");
  1047. out("/Length " + p.length);
  1048. out(">>");
  1049. putStream(p);
  1050. out("endobj");
  1051. },
  1052. putXObjects = function putXObjects() {
  1053. for (var xObjectKey in renderTargets) {
  1054. if (renderTargets.hasOwnProperty(xObjectKey)) {
  1055. putXObject(renderTargets[xObjectKey]);
  1056. }
  1057. }
  1058. },
  1059. interpolateAndEncodeRGBStream = function interpolateAndEncodeRGBStream(colors, numberSamples) {
  1060. var tValues = [];
  1061. var t;
  1062. var dT = 1.0 / (numberSamples - 1);
  1063. for (t = 0.0; t < 1.0; t += dT) {
  1064. tValues.push(t);
  1065. }
  1066. tValues.push(1.0); // add first and last control point if not present
  1067. if (colors[0].offset != 0.0) {
  1068. var c0 = {
  1069. offset: 0.0,
  1070. color: colors[0].color
  1071. };
  1072. colors.unshift(c0);
  1073. }
  1074. if (colors[colors.length - 1].offset != 1.0) {
  1075. var c1 = {
  1076. offset: 1.0,
  1077. color: colors[colors.length - 1].color
  1078. };
  1079. colors.push(c1);
  1080. }
  1081. var out = "";
  1082. var index = 0;
  1083. for (var i = 0; i < tValues.length; i++) {
  1084. t = tValues[i];
  1085. while (t > colors[index + 1].offset) {
  1086. index++;
  1087. }
  1088. var a = colors[index].offset;
  1089. var b = colors[index + 1].offset;
  1090. var d = (t - a) / (b - a);
  1091. var aColor = colors[index].color;
  1092. var bColor = colors[index + 1].color;
  1093. 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));
  1094. }
  1095. return out.trim();
  1096. },
  1097. putShadingPattern = function putShadingPattern(pattern, numberSamples) {
  1098. /*
  1099. Axial patterns shade between the two points specified in coords, radial patterns between the inner
  1100. and outer circle.
  1101. The user can specify an array (colors) that maps t-Values in [0, 1] to RGB colors. These are now
  1102. interpolated to equidistant samples and written to pdf as a sample (type 0) function.
  1103. */
  1104. // The number of color samples that should be used to describe the shading.
  1105. // The higher, the more accurate the gradient will be.
  1106. numberSamples || (numberSamples = 21);
  1107. var funcObjectNumber = newObject();
  1108. var stream = interpolateAndEncodeRGBStream(pattern.colors, numberSamples);
  1109. out("<< /FunctionType 0");
  1110. out("/Domain [0.0 1.0]");
  1111. out("/Size [" + numberSamples + "]");
  1112. out("/BitsPerSample 8");
  1113. out("/Range [0.0 1.0 0.0 1.0 0.0 1.0]");
  1114. out("/Decode [0.0 1.0 0.0 1.0 0.0 1.0]");
  1115. out("/Length " + stream.length); // The stream is Hex encoded
  1116. out("/Filter /ASCIIHexDecode");
  1117. out(">>");
  1118. putStream(stream);
  1119. out("endobj");
  1120. pattern.objectNumber = newObject();
  1121. out("<< /ShadingType " + pattern.type);
  1122. out("/ColorSpace /DeviceRGB");
  1123. var coords = "/Coords [" + hpf(parseFloat(pattern.coords[0])) + " " + // x1
  1124. hpf(parseFloat(pattern.coords[1])) + " "; // y1
  1125. if (pattern.type === 2) {
  1126. // axial
  1127. coords += hpf(parseFloat(pattern.coords[2])) + " " + // x2
  1128. hpf(parseFloat(pattern.coords[3])); // y2
  1129. } else {
  1130. // radial
  1131. coords += hpf(parseFloat(pattern.coords[2])) + " " + // r1
  1132. hpf(parseFloat(pattern.coords[3])) + " " + // x2
  1133. hpf(parseFloat(pattern.coords[4])) + " " + // y2
  1134. hpf(parseFloat(pattern.coords[5])); // r2
  1135. }
  1136. coords += "]";
  1137. out(coords);
  1138. if (pattern.matrix) {
  1139. out("/Matrix [" + pattern.matrix.toString() + "]");
  1140. }
  1141. out("/Function " + funcObjectNumber + " 0 R");
  1142. out("/Extend [true true]");
  1143. out(">>");
  1144. out("endobj");
  1145. },
  1146. putTilingPattern = function putTilingPattern(pattern) {
  1147. var resourcesObjectNumber = newObject();
  1148. out("<<");
  1149. putResourceDictionary();
  1150. out(">>");
  1151. out("endobj");
  1152. pattern.objectNumber = newObject();
  1153. out("<< /Type /Pattern");
  1154. out("/PatternType 1"); // tiling pattern
  1155. out("/PaintType 1"); // colored tiling pattern
  1156. out("/TilingType 1"); // constant spacing
  1157. out("/BBox [" + pattern.boundingBox.map(hpf).join(" ") + "]");
  1158. out("/XStep " + hpf(pattern.xStep));
  1159. out("/YStep " + hpf(pattern.yStep));
  1160. out("/Length " + pattern.stream.length);
  1161. out("/Resources " + resourcesObjectNumber + " 0 R"); // TODO: resources
  1162. pattern.matrix && out("/Matrix [" + pattern.matrix.toString() + "]");
  1163. out(">>");
  1164. putStream(pattern.stream);
  1165. out("endobj");
  1166. },
  1167. putPatterns = function putPatterns() {
  1168. var patternKey;
  1169. for (patternKey in patterns) {
  1170. if (patterns.hasOwnProperty(patternKey)) {
  1171. if (patterns[patternKey] instanceof API.ShadingPattern) {
  1172. putShadingPattern(patterns[patternKey]);
  1173. } else if (patterns[patternKey] instanceof API.TilingPattern) {
  1174. putTilingPattern(patterns[patternKey]);
  1175. }
  1176. }
  1177. }
  1178. },
  1179. putGState = function putGState(gState) {
  1180. gState.objectNumber = newObject();
  1181. out("<<");
  1182. for (var p in gState) {
  1183. switch (p) {
  1184. case "opacity":
  1185. out("/ca " + f2(gState[p]));
  1186. break;
  1187. case "stroke-opacity":
  1188. out("/CA " + f2(gState[p]));
  1189. break;
  1190. }
  1191. }
  1192. out(">>");
  1193. out("endobj");
  1194. },
  1195. putGStates = function putGStates() {
  1196. var gStateKey;
  1197. for (gStateKey in gStates) {
  1198. if (gStates.hasOwnProperty(gStateKey)) {
  1199. putGState(gStates[gStateKey]);
  1200. }
  1201. }
  1202. },
  1203. putXobjectDict = function putXobjectDict() {
  1204. for (var xObjectKey in renderTargets) {
  1205. if (renderTargets.hasOwnProperty(xObjectKey) && renderTargets[xObjectKey].objectNumber >= 0) {
  1206. out("/" + xObjectKey + " " + renderTargets[xObjectKey].objectNumber + " 0 R");
  1207. }
  1208. }
  1209. events.publish("putXobjectDict");
  1210. },
  1211. putShadingPatternDict = function putShadingPatternDict() {
  1212. for (var patternKey in patterns) {
  1213. if (patterns.hasOwnProperty(patternKey) && patterns[patternKey] instanceof API.ShadingPattern && patterns[patternKey].objectNumber >= 0) {
  1214. out("/" + patternKey + " " + patterns[patternKey].objectNumber + " 0 R");
  1215. }
  1216. }
  1217. events.publish("putShadingPatternDict");
  1218. },
  1219. putTilingPatternDict = function putTilingPatternDict() {
  1220. for (var patternKey in patterns) {
  1221. if (patterns.hasOwnProperty(patternKey) && patterns[patternKey] instanceof API.TilingPattern && patterns[patternKey].objectNumber >= 0) {
  1222. out("/" + patternKey + " " + patterns[patternKey].objectNumber + " 0 R");
  1223. }
  1224. }
  1225. events.publish("putTilingPatternDict");
  1226. },
  1227. putGStatesDict = function putGStatesDict() {
  1228. var gStateKey;
  1229. for (gStateKey in gStates) {
  1230. if (gStates.hasOwnProperty(gStateKey) && gStates[gStateKey].objectNumber >= 0) {
  1231. out("/" + gStateKey + " " + gStates[gStateKey].objectNumber + " 0 R");
  1232. }
  1233. }
  1234. events.publish("putGStateDict");
  1235. },
  1236. putResourceDictionary = function putResourceDictionary() {
  1237. out("/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]");
  1238. out("/Font <<"); // Do this for each font, the '1' bit is the index of the font
  1239. for (var fontKey in fonts) {
  1240. if (fonts.hasOwnProperty(fontKey)) {
  1241. out("/" + fontKey + " " + fonts[fontKey].objectNumber + " 0 R");
  1242. }
  1243. }
  1244. out(">>");
  1245. out("/Shading <<");
  1246. putShadingPatternDict();
  1247. out(">>");
  1248. out("/Pattern <<");
  1249. putTilingPatternDict();
  1250. out(">>");
  1251. out("/ExtGState <<");
  1252. putGStatesDict();
  1253. out(">>");
  1254. out("/XObject <<");
  1255. putXobjectDict();
  1256. out(">>");
  1257. },
  1258. putResources = function putResources() {
  1259. putFonts();
  1260. putGStates();
  1261. putXObjects();
  1262. putPatterns();
  1263. events.publish("putResources"); // Resource dictionary
  1264. offsets[2] = content_length;
  1265. out("2 0 obj");
  1266. out("<<");
  1267. putResourceDictionary();
  1268. out(">>");
  1269. out("endobj");
  1270. events.publish("postPutResources");
  1271. },
  1272. putAdditionalObjects = function putAdditionalObjects() {
  1273. events.publish("putAdditionalObjects");
  1274. for (var i = 0; i < additionalObjects.length; i++) {
  1275. var obj = additionalObjects[i];
  1276. offsets[obj.objId] = content_length;
  1277. out(obj.objId + " 0 obj");
  1278. out(obj.content);
  1279. out("endobj");
  1280. }
  1281. objectNumber += additionalObjects.length;
  1282. events.publish("postPutAdditionalObjects");
  1283. },
  1284. addToFontDictionary = function addToFontDictionary(fontKey, fontName, fontStyle) {
  1285. // this is mapping structure for quick font key lookup.
  1286. // returns the KEY of the font (ex: "F1") for a given
  1287. // pair of font name and type (ex: "Arial". "Italic")
  1288. if (!fontmap.hasOwnProperty(fontName)) {
  1289. fontmap[fontName] = {};
  1290. }
  1291. fontmap[fontName][fontStyle] = fontKey;
  1292. },
  1293. addFont = function addFont(postScriptName, fontName, fontStyle, encoding, isStandardFont) {
  1294. isStandardFont = isStandardFont || false;
  1295. var fontKey = "F" + (Object.keys(fonts).length + 1).toString(10),
  1296. // This is FontObject
  1297. font = {
  1298. id: fontKey,
  1299. postScriptName: postScriptName,
  1300. fontName: fontName,
  1301. fontStyle: fontStyle,
  1302. encoding: encoding,
  1303. isStandardFont: isStandardFont,
  1304. metadata: {}
  1305. };
  1306. var instance = this;
  1307. events.publish("addFont", {
  1308. font: font,
  1309. instance: instance
  1310. });
  1311. if (fontKey !== undefined) {
  1312. fonts[fontKey] = font;
  1313. addToFontDictionary(fontKey, fontName, fontStyle);
  1314. }
  1315. return fontKey;
  1316. },
  1317. addFonts = function addFonts() {
  1318. var HELVETICA = "helvetica",
  1319. TIMES = "times",
  1320. COURIER = "courier",
  1321. NORMAL = "normal",
  1322. BOLD = "bold",
  1323. ITALIC = "italic",
  1324. BOLD_ITALIC = "bolditalic",
  1325. ZAPF = "zapfdingbats",
  1326. SYMBOL = "symbol",
  1327. 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]];
  1328. for (var i = 0, l = standardFonts.length; i < l; i++) {
  1329. var fontKey = addFont(standardFonts[i][0], standardFonts[i][1], standardFonts[i][2], standardFonts[i][3], true); // adding aliases for standard fonts, this time matching the capitalization
  1330. var parts = standardFonts[i][0].split("-");
  1331. addToFontDictionary(fontKey, parts[0], parts[1] || "");
  1332. }
  1333. events.publish("addFonts", {
  1334. fonts: fonts,
  1335. dictionary: fontmap
  1336. });
  1337. },
  1338. matrixMult = function matrixMult(m1, m2) {
  1339. 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);
  1340. },
  1341. Matrix = function Matrix(a, b, c, d, e, f) {
  1342. this.a = a;
  1343. this.b = b;
  1344. this.c = c;
  1345. this.d = d;
  1346. this.e = e;
  1347. this.f = f;
  1348. };
  1349. Matrix.prototype = {
  1350. toString: function toString() {
  1351. return [hpf(this.a), hpf(this.b), hpf(this.c), hpf(this.d), hpf(this.e), hpf(this.f)].join(" ");
  1352. },
  1353. inversed: function inversed() {
  1354. var a = this.a,
  1355. b = this.b,
  1356. c = this.c,
  1357. d = this.d,
  1358. e = this.e,
  1359. f = this.f;
  1360. var quot = 1 / (a * d - b * c);
  1361. var aInv = d * quot;
  1362. var bInv = -b * quot;
  1363. var cInv = -c * quot;
  1364. var dInv = a * quot;
  1365. var eInv = -aInv * e - cInv * f;
  1366. var fInv = -bInv * e - dInv * f;
  1367. return new Matrix(aInv, bInv, cInv, dInv, eInv, fInv);
  1368. }
  1369. };
  1370. var unitMatrix = new Matrix(1, 0, 0, 1, 0, 0),
  1371. // Used (1) to save the current stream state to the XObjects stack and (2) to save completed form
  1372. // objects in the xObjects map.
  1373. RenderTarget = function RenderTarget() {
  1374. this.page = page;
  1375. this.currentPage = currentPage;
  1376. this.pages = pages.slice(0);
  1377. this.pagedim = pagedim.slice(0);
  1378. this.pagesContext = pagesContext.slice(0);
  1379. this.x = pageX;
  1380. this.y = pageY;
  1381. this.matrix = pageMatrix;
  1382. this.width = pageWidth;
  1383. this.height = pageHeight;
  1384. this.id = ""; // set by endFormObject()
  1385. this.objectNumber = -1; // will be set by putXObject()
  1386. };
  1387. RenderTarget.prototype = {
  1388. restore: function restore() {
  1389. page = this.page;
  1390. currentPage = this.currentPage;
  1391. pagesContext = this.pagesContext;
  1392. pagedim = this.pagedim;
  1393. pages = this.pages;
  1394. pageX = this.x;
  1395. pageY = this.y;
  1396. pageMatrix = this.matrix;
  1397. pageWidth = this.width;
  1398. pageHeight = this.height;
  1399. }
  1400. };
  1401. var beginNewRenderTarget = function beginNewRenderTarget(x, y, width, height, matrix) {
  1402. // save current state
  1403. renderTargetStack.push(new RenderTarget()); // clear pages
  1404. page = currentPage = 0;
  1405. pages = [];
  1406. pageX = x;
  1407. pageY = y;
  1408. pageMatrix = matrix;
  1409. beginPage(width, height);
  1410. },
  1411. endFormObject = function endFormObject(key) {
  1412. // only add it if it is not already present (the keys provided by the user must be unique!)
  1413. if (renderTargetMap[key]) return; // save the created xObject
  1414. var newXObject = new RenderTarget();
  1415. var xObjectId = "Xo" + (Object.keys(renderTargets).length + 1).toString(10);
  1416. newXObject.id = xObjectId;
  1417. renderTargetMap[key] = xObjectId;
  1418. renderTargets[xObjectId] = newXObject;
  1419. events.publish("addFormObject", newXObject); // restore state from stack
  1420. renderTargetStack.pop().restore();
  1421. },
  1422. /**
  1423. * Adds a new pattern for later use.
  1424. * @param {String} key The key by it can be referenced later. The keys must be unique!
  1425. * @param {API.Pattern} pattern The pattern
  1426. */
  1427. addPattern = function addPattern(key, pattern) {
  1428. // only add it if it is not already present (the keys provided by the user must be unique!)
  1429. if (patternMap[key]) return;
  1430. var prefix = pattern instanceof API.ShadingPattern ? "Sh" : "P";
  1431. var patternKey = prefix + (Object.keys(patterns).length + 1).toString(10);
  1432. pattern.id = patternKey;
  1433. patternMap[key] = patternKey;
  1434. patterns[patternKey] = pattern;
  1435. events.publish("addPattern", pattern);
  1436. },
  1437. /**
  1438. * Adds a new Graphics State. Duplicates are automatically eliminated.
  1439. * @param {String} key Might also be null, if no later reference to this gState is needed
  1440. * @param {Object} gState The gState object
  1441. */
  1442. addGState = function addGState(key, gState) {
  1443. // only add it if it is not already present (the keys provided by the user must be unique!)
  1444. if (key && gStatesMap[key]) return;
  1445. var duplicate = false;
  1446. for (var s in gStates) {
  1447. if (gStates.hasOwnProperty(s)) {
  1448. if (gStates[s].equals(gState)) {
  1449. duplicate = true;
  1450. break;
  1451. }
  1452. }
  1453. }
  1454. if (duplicate) {
  1455. gState = gStates[s];
  1456. } else {
  1457. var gStateKey = "GS" + (Object.keys(gStates).length + 1).toString(10);
  1458. gStates[gStateKey] = gState;
  1459. gState.id = gStateKey;
  1460. } // several user keys may point to the same GState object
  1461. key && (gStatesMap[key] = gState.id);
  1462. events.publish("addGState", gState);
  1463. return gState;
  1464. },
  1465. SAFE = function __safeCall(fn) {
  1466. fn.foo = function __safeCallWrapper() {
  1467. try {
  1468. return fn.apply(this, arguments);
  1469. } catch (e) {
  1470. var stack = e.stack || "";
  1471. if (~stack.indexOf(" at ")) stack = stack.split(" at ")[1];
  1472. var m = "Error in function " + stack.split("\n")[0].split("<")[0] + ": " + e.message;
  1473. if (global.console) {
  1474. global.console.error(m, e);
  1475. if (global.alert) alert(m);
  1476. } else {
  1477. throw new Error(m);
  1478. }
  1479. }
  1480. };
  1481. fn.foo.bar = fn;
  1482. return fn.foo;
  1483. },
  1484. to8bitStream = function to8bitStream(text, flags) {
  1485. /**
  1486. * PDF 1.3 spec:
  1487. * "For text strings encoded in Unicode, the first two bytes must be 254 followed by
  1488. * 255, representing the Unicode byte order marker, U+FEFF. (This sequence conflicts
  1489. * with the PDFDocEncoding character sequence thorn ydieresis, which is unlikely
  1490. * to be a meaningful beginning of a word or phrase.) The remainder of the
  1491. * string consists of Unicode character codes, according to the UTF-16 encoding
  1492. * specified in the Unicode standard, version 2.0. Commonly used Unicode values
  1493. * are represented as 2 bytes per character, with the high-order byte appearing first
  1494. * in the string."
  1495. *
  1496. * In other words, if there are chars in a string with char code above 255, we
  1497. * recode the string to UCS2 BE - string doubles in length and BOM is prepended.
  1498. *
  1499. * HOWEVER!
  1500. * Actual *content* (body) text (as opposed to strings used in document properties etc)
  1501. * does NOT expect BOM. There, it is treated as a literal GID (Glyph ID)
  1502. *
  1503. * Because of Adobe's focus on "you subset your fonts!" you are not supposed to have
  1504. * a font that maps directly Unicode (UCS2 / UTF16BE) code to font GID, but you could
  1505. * fudge it with "Identity-H" encoding and custom CIDtoGID map that mimics Unicode
  1506. * code page. There, however, all characters in the stream are treated as GIDs,
  1507. * including BOM, which is the reason we need to skip BOM in content text (i.e. that
  1508. * that is tied to a font).
  1509. *
  1510. * To signal this "special" PDFEscape / to8bitStream handling mode,
  1511. * API.text() function sets (unless you overwrite it with manual values
  1512. * given to API.text(.., flags) )
  1513. * flags.autoencode = true
  1514. * flags.noBOM = true
  1515. *
  1516. * ===================================================================================
  1517. * `flags` properties relied upon:
  1518. * .sourceEncoding = string with encoding label.
  1519. * "Unicode" by default. = encoding of the incoming text.
  1520. * pass some non-existing encoding name
  1521. * (ex: 'Do not touch my strings! I know what I am doing.')
  1522. * to make encoding code skip the encoding step.
  1523. * .outputEncoding = Either valid PDF encoding name
  1524. * (must be supported by jsPDF font metrics, otherwise no encoding)
  1525. * or a JS object, where key = sourceCharCode, value = outputCharCode
  1526. * missing keys will be treated as: sourceCharCode === outputCharCode
  1527. * .noBOM
  1528. * See comment higher above for explanation for why this is important
  1529. * .autoencode
  1530. * See comment higher above for explanation for why this is important
  1531. */
  1532. var i, l, sourceEncoding, encodingBlock, outputEncoding, newtext, isUnicode, ch, bch;
  1533. flags = flags || {};
  1534. sourceEncoding = flags.sourceEncoding || "Unicode";
  1535. outputEncoding = flags.outputEncoding; // This 'encoding' section relies on font metrics format
  1536. // attached to font objects by, among others,
  1537. // "Willow Systems' standard_font_metrics plugin"
  1538. // see jspdf.plugin.standard_font_metrics.js for format
  1539. // of the font.metadata.encoding Object.
  1540. // It should be something like
  1541. // .encoding = {'codePages':['WinANSI....'], 'WinANSI...':{code:code, ...}}
  1542. // .widths = {0:width, code:width, ..., 'fof':divisor}
  1543. // .kerning = {code:{previous_char_code:shift, ..., 'fof':-divisor},...}
  1544. if ((flags.autoencode || outputEncoding) && fonts[activeFontKey].metadata && fonts[activeFontKey].metadata[sourceEncoding] && fonts[activeFontKey].metadata[sourceEncoding].encoding) {
  1545. encodingBlock = fonts[activeFontKey].metadata[sourceEncoding].encoding; // each font has default encoding. Some have it clearly defined.
  1546. if (!outputEncoding && fonts[activeFontKey].encoding) {
  1547. outputEncoding = fonts[activeFontKey].encoding;
  1548. } // Hmmm, the above did not work? Let's try again, in different place.
  1549. if (!outputEncoding && encodingBlock.codePages) {
  1550. outputEncoding = encodingBlock.codePages[0]; // let's say, first one is the default
  1551. }
  1552. if (typeof outputEncoding === "string") {
  1553. outputEncoding = encodingBlock[outputEncoding];
  1554. } // we want output encoding to be a JS Object, where
  1555. // key = sourceEncoding's character code and
  1556. // value = outputEncoding's character code.
  1557. if (outputEncoding) {
  1558. isUnicode = false;
  1559. newtext = [];
  1560. for (i = 0, l = text.length; i < l; i++) {
  1561. ch = outputEncoding[text.charCodeAt(i)];
  1562. if (ch) {
  1563. newtext.push(String.fromCharCode(ch));
  1564. } else {
  1565. newtext.push(text[i]);
  1566. } // since we are looping over chars anyway, might as well
  1567. // check for residual unicodeness
  1568. if (newtext[i].charCodeAt(0) >> 8) {
  1569. /* more than 255 */
  1570. isUnicode = true;
  1571. }
  1572. }
  1573. text = newtext.join("");
  1574. }
  1575. }
  1576. i = text.length; // isUnicode may be set to false above. Hence the triple-equal to undefined
  1577. while (isUnicode === undefined && i !== 0) {
  1578. if (text.charCodeAt(i - 1) >> 8) {
  1579. /* more than 255 */
  1580. isUnicode = true;
  1581. }
  1582. i--;
  1583. }
  1584. if (!isUnicode) {
  1585. return text;
  1586. }
  1587. newtext = flags.noBOM ? [] : [254, 255];
  1588. for (i = 0, l = text.length; i < l; i++) {
  1589. ch = text.charCodeAt(i);
  1590. bch = ch >> 8; // divide by 256
  1591. if (bch >> 8) {
  1592. /* something left after dividing by 256 second time */
  1593. throw new Error("Character at position " + i + " of string '" + text + "' exceeds 16bits. Cannot be encoded into UCS-2 BE");
  1594. }
  1595. newtext.push(bch);
  1596. newtext.push(ch - (bch << 8));
  1597. }
  1598. return String.fromCharCode.apply(undefined, newtext);
  1599. },
  1600. pdfEscape = function pdfEscape(text, flags) {
  1601. /**
  1602. * Replace '/', '(', and ')' with pdf-safe versions
  1603. *
  1604. * Doing to8bitStream does NOT make this PDF display unicode text. For that
  1605. * we also need to reference a unicode font and embed it - royal pain in the rear.
  1606. *
  1607. * There is still a benefit to to8bitStream - PDF simply cannot handle 16bit chars,
  1608. * which JavaScript Strings are happy to provide. So, while we still cannot display
  1609. * 2-byte characters property, at least CONDITIONALLY converting (entire string containing)
  1610. * 16bit chars to (USC-2-BE) 2-bytes per char + BOM streams we ensure that entire PDF
  1611. * is still parseable.
  1612. * This will allow immediate support for unicode in document properties strings.
  1613. */
  1614. return to8bitStream(text, flags).replace(/\\/g, "\\\\").replace(/\(/g, "\\(").replace(/\)/g, "\\)");
  1615. },
  1616. putInfo = function putInfo() {
  1617. out("/Producer (jsPDF " + jsPDF.version + ")");
  1618. for (var key in documentProperties) {
  1619. if (documentProperties.hasOwnProperty(key) && documentProperties[key]) {
  1620. out("/" + key.substr(0, 1).toUpperCase() + key.substr(1) + " (" + pdfEscape(documentProperties[key]) + ")");
  1621. }
  1622. }
  1623. out("/CreationDate (" + creationDate + ")");
  1624. },
  1625. putCatalog = function putCatalog() {
  1626. out("/Type /Catalog");
  1627. out("/Pages 1 0 R"); // PDF13ref Section 7.2.1
  1628. if (!zoomMode) zoomMode = "fullwidth";
  1629. switch (zoomMode) {
  1630. case "fullwidth":
  1631. out("/OpenAction [3 0 R /FitH null]");
  1632. break;
  1633. case "fullheight":
  1634. out("/OpenAction [3 0 R /FitV null]");
  1635. break;
  1636. case "fullpage":
  1637. out("/OpenAction [3 0 R /Fit]");
  1638. break;
  1639. case "original":
  1640. out("/OpenAction [3 0 R /XYZ null null 1]");
  1641. break;
  1642. default:
  1643. var pcn = "" + zoomMode;
  1644. if (pcn.substr(pcn.length - 1) === "%") zoomMode = parseInt(zoomMode) / 100;
  1645. if (typeof zoomMode === "number") {
  1646. out("/OpenAction [3 0 R /XYZ null null " + f2(zoomMode) + "]");
  1647. }
  1648. }
  1649. if (!layoutMode) layoutMode = "continuous";
  1650. switch (layoutMode) {
  1651. case "continuous":
  1652. out("/PageLayout /OneColumn");
  1653. break;
  1654. case "single":
  1655. out("/PageLayout /SinglePage");
  1656. break;
  1657. case "two":
  1658. case "twoleft":
  1659. out("/PageLayout /TwoColumnLeft");
  1660. break;
  1661. case "tworight":
  1662. out("/PageLayout /TwoColumnRight");
  1663. break;
  1664. }
  1665. if (pageMode) {
  1666. /**
  1667. * A name object specifying how the document should be displayed when opened:
  1668. * UseNone : Neither document outline nor thumbnail images visible -- DEFAULT
  1669. * UseOutlines : Document outline visible
  1670. * UseThumbs : Thumbnail images visible
  1671. * FullScreen : Full-screen mode, with no menu bar, window controls, or any other window visible
  1672. */
  1673. out("/PageMode /" + pageMode);
  1674. }
  1675. events.publish("putCatalog");
  1676. },
  1677. putTrailer = function putTrailer() {
  1678. out("/Size " + (objectNumber + 1));
  1679. out("/Root " + objectNumber + " 0 R");
  1680. out("/Info " + (objectNumber - 1) + " 0 R");
  1681. out("/ID [ <" + fileId + "> <" + fileId + "> ]");
  1682. },
  1683. beginPage = function beginPage(width, height) {
  1684. outToPages = true;
  1685. pages[++page] = [];
  1686. pagedim[page] = {
  1687. width: Number(width) || pageWidth,
  1688. height: Number(height) || pageHeight
  1689. };
  1690. pagesContext[page] = {};
  1691. _setPage(page);
  1692. },
  1693. _addPage = function _addPage(width, height) {
  1694. // Dimensions are stored as user units and converted to points on output
  1695. var orientation = typeof height === "string" && height.toLowerCase();
  1696. if (typeof width === "string") {
  1697. var format = width.toLowerCase();
  1698. if (pageFormats.hasOwnProperty(format)) {
  1699. width = pageFormats[format][0] / k;
  1700. height = pageFormats[format][1] / k;
  1701. }
  1702. }
  1703. if (Array.isArray(width)) {
  1704. height = width[1];
  1705. width = width[0];
  1706. }
  1707. if (orientation) {
  1708. switch (orientation.substr(0, 1)) {
  1709. case "l":
  1710. if (height > width) orientation = "s";
  1711. break;
  1712. case "p":
  1713. if (width > height) orientation = "s";
  1714. break;
  1715. }
  1716. if (orientation === "s") {
  1717. tmp = width;
  1718. width = height;
  1719. height = tmp;
  1720. }
  1721. }
  1722. beginPage(width, height); // Set line width
  1723. out(hpf(lineWidth * k) + " w"); // Set draw color
  1724. out(drawColor); // resurrecting non-default line caps, joins
  1725. if (lineCapID !== 0) {
  1726. out(lineCapID + " J");
  1727. }
  1728. if (lineJoinID !== 0) {
  1729. out(lineJoinID + " j");
  1730. }
  1731. events.publish("addPage", {
  1732. pageNumber: page
  1733. });
  1734. },
  1735. _deletePage = function _deletePage(n) {
  1736. if (n > 0 && n <= page) {
  1737. pages.splice(n, 1);
  1738. pagedim.splice(n, 1);
  1739. page--;
  1740. if (currentPage > page) {
  1741. currentPage = page;
  1742. }
  1743. this.setPage(currentPage);
  1744. }
  1745. },
  1746. _setPage = function _setPage(n) {
  1747. if (n > 0 && n <= page) {
  1748. currentPage = n;
  1749. pageWidth = pagedim[n].width;
  1750. pageHeight = pagedim[n].height;
  1751. }
  1752. },
  1753. /**
  1754. * Returns a document-specific font key - a label assigned to a
  1755. * font name + font type combination at the time the font was added
  1756. * to the font inventory.
  1757. *
  1758. * Font key is used as label for the desired font for a block of text
  1759. * to be added to the PDF document stream.
  1760. * @private
  1761. * @function
  1762. * @param {String} fontName can be undefined on "falthy" to indicate "use current"
  1763. * @param {String} fontStyle can be undefined on "falthy" to indicate "use current"
  1764. * @returns {String} Font key.
  1765. */
  1766. _getFont = function getFont(fontName, fontStyle, options) {
  1767. var key = undefined,
  1768. fontNameLowerCase;
  1769. options = options || {};
  1770. fontName = fontName !== undefined ? fontName : fonts[activeFontKey].fontName;
  1771. fontStyle = fontStyle !== undefined ? fontStyle : fonts[activeFontKey].fontStyle;
  1772. fontNameLowerCase = fontName.toLowerCase();
  1773. if (fontmap[fontNameLowerCase] !== undefined && fontmap[fontNameLowerCase][fontStyle] !== undefined) {
  1774. key = fontmap[fontNameLowerCase][fontStyle];
  1775. } else if (fontmap[fontName] !== undefined && fontmap[fontName][fontStyle] !== undefined) {
  1776. key = fontmap[fontName][fontStyle];
  1777. } else {
  1778. if (options.disableWarning === false) {
  1779. console.warn("Unable to look up font label for font '" + fontName + "', '" + fontStyle + "'. Refer to getFontList() for available fonts.");
  1780. }
  1781. }
  1782. if (!key && !options.noFallback) {
  1783. key = fontmap["times"][fontStyle];
  1784. if (key == null) {
  1785. key = fontmap["times"]["normal"];
  1786. }
  1787. }
  1788. return key;
  1789. },
  1790. buildDocument = function buildDocument() {
  1791. outToPages = false; // switches out() to content
  1792. objectNumber = 2;
  1793. content_length = 0;
  1794. content = [];
  1795. offsets = [];
  1796. additionalObjects = []; // Added for AcroForm
  1797. events.publish("buildDocument"); // putHeader()
  1798. out("%PDF-" + pdfVersion);
  1799. out("%\xBA\xDF\xAC\xE0");
  1800. putPages(); // Must happen after putPages
  1801. // Modifies current object Id
  1802. putAdditionalObjects();
  1803. putResources(); // Info
  1804. newObject();
  1805. out("<<");
  1806. putInfo();
  1807. out(">>");
  1808. out("endobj"); // Catalog
  1809. newObject();
  1810. out("<<");
  1811. putCatalog();
  1812. out(">>");
  1813. out("endobj"); // Cross-ref
  1814. var o = content_length,
  1815. i,
  1816. p = "0000000000";
  1817. out("xref");
  1818. out("0 " + (objectNumber + 1));
  1819. out(p + " 65535 f ");
  1820. for (i = 1; i <= objectNumber; i++) {
  1821. var offset = offsets[i];
  1822. if (typeof offset === "function") {
  1823. out((p + offsets[i]()).slice(-10) + " 00000 n ");
  1824. } else {
  1825. out((p + offsets[i]).slice(-10) + " 00000 n ");
  1826. }
  1827. } // Trailer
  1828. out("trailer");
  1829. out("<<");
  1830. putTrailer();
  1831. out(">>");
  1832. out("startxref");
  1833. out("" + o);
  1834. out("%%EOF");
  1835. outToPages = true;
  1836. return content.join("\n");
  1837. },
  1838. getStyle = function getStyle(style) {
  1839. // see path-painting operators in PDF spec
  1840. // The default in MrRio's implementation is "S" (stroke), whereas the default in the yWorks implementation
  1841. // was "n" (none). Although this has nothing to do with transforms, we should use the API switch here.
  1842. var op = apiMode === ApiMode.COMPAT ? "S" : "n";
  1843. if (style === "D") {
  1844. op = "S"; // stroke
  1845. } else if (style === "F") {
  1846. op = "f"; // fill
  1847. } else if (style === "FD" || style === "DF") {
  1848. op = "B"; // both
  1849. } else if (style === "f" || style === "f*" || style === "B" || style === "B*") {
  1850. /*
  1851. Allow direct use of these PDF path-painting operators:
  1852. - f fill using nonzero winding number rule
  1853. - f* fill using even-odd rule
  1854. - B fill then stroke with fill using non-zero winding number rule
  1855. - B* fill then stroke with fill using even-odd rule
  1856. */
  1857. op = style;
  1858. }
  1859. return op;
  1860. },
  1861. // puts the style for the previously drawn path. If a patternKey is provided, the pattern is used to fill
  1862. // the path. Use patternMatrix to transform the pattern to rhe right location.
  1863. putStyle = function putStyle(style, patternKey, patternData) {
  1864. if (style === null || apiMode === ApiMode.ADVANCED && style === undefined) {
  1865. return;
  1866. }
  1867. style = getStyle(style); // stroking / filling / both the path
  1868. if (!patternKey) {
  1869. out(style);
  1870. return;
  1871. }
  1872. if (!patternData) {
  1873. patternData = {
  1874. matrix: unitMatrix
  1875. };
  1876. }
  1877. if (patternData instanceof Matrix) {
  1878. patternData = {
  1879. matrix: patternData
  1880. };
  1881. }
  1882. patternData.key = patternKey;
  1883. patternData || (patternData = unitMatrix);
  1884. fillWithPattern(patternData, style);
  1885. },
  1886. fillWithPattern = function fillWithPattern(patternData, style) {
  1887. var patternId = patternMap[patternData.key];
  1888. var pattern = patterns[patternId];
  1889. if (pattern instanceof API.ShadingPattern) {
  1890. out("q");
  1891. out(clipRuleFromStyle(style));
  1892. if (pattern.gState) {
  1893. API.setGState(pattern.gState);
  1894. }
  1895. out(patternData.matrix.toString() + " cm");
  1896. out("/" + patternId + " sh");
  1897. out("Q");
  1898. } else if (pattern instanceof API.TilingPattern) {
  1899. // pdf draws patterns starting at the bottom left corner and they are not affected by the global transformation,
  1900. // so we must flip them
  1901. var matrix = new Matrix(1, 0, 0, -1, 0, pageHeight);
  1902. if (patternData.matrix) {
  1903. 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
  1904. // for each use
  1905. patternId = pattern.createClone(patternData.key, patternData.boundingBox, patternData.xStep, patternData.yStep, matrix).id;
  1906. }
  1907. out("q");
  1908. out("/Pattern cs");
  1909. out("/" + patternId + " scn");
  1910. if (pattern.gState) {
  1911. API.setGState(pattern.gState);
  1912. }
  1913. out(style);
  1914. out("Q");
  1915. }
  1916. },
  1917. clipRuleFromStyle = function clipRuleFromStyle(style) {
  1918. switch (style) {
  1919. case "f":
  1920. case "F":
  1921. return "W n";
  1922. case "f*":
  1923. return "W* n";
  1924. case "B":
  1925. return "W S";
  1926. case "B*":
  1927. return "W* S";
  1928. // these two are for compatibility reasons (in the past, calling any primitive method with a shading pattern
  1929. // and "n"/"S" as style would still fill/fill and stroke the path)
  1930. case "S":
  1931. return "W S";
  1932. case "n":
  1933. return "W n";
  1934. }
  1935. },
  1936. getArrayBuffer = function getArrayBuffer() {
  1937. var data = buildDocument(),
  1938. len = data.length,
  1939. ab = new ArrayBuffer(len),
  1940. u8 = new Uint8Array(ab);
  1941. while (len--) {
  1942. u8[len] = data.charCodeAt(len);
  1943. }
  1944. return ab;
  1945. },
  1946. getBlob = function getBlob() {
  1947. return new Blob([getArrayBuffer()], {
  1948. type: "application/pdf"
  1949. });
  1950. },
  1951. _output = SAFE(function (type, options) {
  1952. if (typeof options === "string") {
  1953. options = {
  1954. filename: options
  1955. };
  1956. } else {
  1957. options = options || {};
  1958. options.filename = options.filename || "generated.pdf";
  1959. }
  1960. var datauri = ("" + type).substr(0, 6) === "dataur" ? "data:application/pdf;filename=" + options.filename + ";base64," + btoa(buildDocument()) : 0;
  1961. switch (type) {
  1962. case undefined:
  1963. return buildDocument();
  1964. case "save":
  1965. if ((typeof navigator === "undefined" ? "undefined" : _typeof(navigator)) === "object" && navigator.getUserMedia) {
  1966. if (global.URL === undefined || global.URL.createObjectURL === undefined) {
  1967. return API.output("dataurlnewwindow");
  1968. }
  1969. }
  1970. saveAs(getBlob(), options.filename);
  1971. if (typeof saveAs.unload === "function") {
  1972. if (global.setTimeout) {
  1973. setTimeout(saveAs.unload, 911);
  1974. }
  1975. }
  1976. break;
  1977. case "arraybuffer":
  1978. return getArrayBuffer();
  1979. case "blob":
  1980. return getBlob();
  1981. case "bloburi":
  1982. case "bloburl":
  1983. // User is responsible of calling revokeObjectURL
  1984. return global.URL && global.URL.createObjectURL(getBlob()) || void 0;
  1985. case "datauristring":
  1986. case "dataurlstring":
  1987. return datauri;
  1988. case "dataurlnewwindow":
  1989. 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>";
  1990. var nW = global.open();
  1991. if (nW !== null) {
  1992. nW.document.write(htmlForNewWindow);
  1993. }
  1994. if (nW || typeof safari === "undefined") return nW;
  1995. /* pass through */
  1996. case "datauri":
  1997. case "dataurl":
  1998. return global.document.location.href = datauri;
  1999. default:
  2000. throw new Error('Output type "' + type + '" is not supported.');
  2001. } // @TODO: Add different output options
  2002. }),
  2003. /**
  2004. * Used to see if a supplied hotfix was requested when the pdf instance was created.
  2005. * @param {string} hotfixName - The name of the hotfix to check.
  2006. * @returns {boolean}
  2007. */
  2008. hasHotfix = function hasHotfix(hotfixName) {
  2009. return Array.isArray(hotfixes) === true && hotfixes.indexOf(hotfixName) > -1;
  2010. };
  2011. switch (unit) {
  2012. case "pt":
  2013. k = 1;
  2014. break;
  2015. case "mm":
  2016. k = 72 / 25.4000508;
  2017. break;
  2018. case "cm":
  2019. k = 72 / 2.54000508;
  2020. break;
  2021. case "in":
  2022. k = 72;
  2023. break;
  2024. case "px":
  2025. if (hasHotfix("px_scaling") == true) {
  2026. k = 72 / 96;
  2027. } else {
  2028. k = 96 / 72;
  2029. }
  2030. break;
  2031. case "pc":
  2032. k = 12;
  2033. break;
  2034. case "em":
  2035. k = 12;
  2036. break;
  2037. case "ex":
  2038. k = 6;
  2039. break;
  2040. default:
  2041. throw "Invalid unit: " + unit;
  2042. }
  2043. setCreationDate();
  2044. setFileId(); //---------------------------------------
  2045. // Public API
  2046. /**
  2047. * Object exposing internal API to plugins
  2048. * @public
  2049. * @ignore
  2050. */
  2051. API.internal = {
  2052. pdfEscape: pdfEscape,
  2053. getStyle: getStyle,
  2054. /**
  2055. * Returns {FontObject} describing a particular font.
  2056. * @public
  2057. * @function
  2058. * @param {String} fontName (Optional) Font's family name
  2059. * @param {String} fontStyle (Optional) Font's style variation name (Example:"Italic")
  2060. * @returns {FontObject}
  2061. */
  2062. getFont: function getFont() {
  2063. return fonts[_getFont.apply(API, arguments)];
  2064. },
  2065. getFontSize: function getFontSize() {
  2066. return activeFontSize;
  2067. },
  2068. getCharSpace: function getCharSpace() {
  2069. return activeCharSpace;
  2070. },
  2071. getTextColor: function getTextColor() {
  2072. var colorEncoded = textColor.split(" ");
  2073. if (colorEncoded.length === 2 && colorEncoded[1] === "g") {
  2074. // convert grayscale value to rgb so that it can be converted to hex for consistency
  2075. var floatVal = parseFloat(colorEncoded[0]);
  2076. colorEncoded = [floatVal, floatVal, floatVal, "r"];
  2077. }
  2078. var colorAsHex = "#";
  2079. for (var i = 0; i < 3; i++) {
  2080. colorAsHex += ("0" + Math.floor(parseFloat(colorEncoded[i]) * 255).toString(16)).slice(-2);
  2081. }
  2082. return colorAsHex;
  2083. },
  2084. getLineHeight: function getLineHeight() {
  2085. return activeFontSize * lineHeightProportion;
  2086. },
  2087. write: function write(string1
  2088. /*, string2, string3, etc */
  2089. ) {
  2090. out(arguments.length === 1 ? string1 : Array.prototype.join.call(arguments, " "));
  2091. },
  2092. getCoordinateString: function getCoordinateString(value) {
  2093. return hpf(scaleByK(value));
  2094. },
  2095. getVerticalCoordinateString: function getVerticalCoordinateString(value) {
  2096. return hpf(transformScaleY(value));
  2097. },
  2098. collections: {},
  2099. newObject: newObject,
  2100. newAdditionalObject: newAdditionalObject,
  2101. newObjectDeferred: newObjectDeferred,
  2102. newObjectDeferredBegin: newObjectDeferredBegin,
  2103. putStream: putStream,
  2104. events: events,
  2105. // ratio that you use in multiplication of a given "size" number to arrive to 'point'
  2106. // units of measurement.
  2107. // scaleFactor is set at initialization of the document and calculated against the stated
  2108. // default measurement units for the document.
  2109. // If default is "mm", k is the number that will turn number in 'mm' into 'points' number.
  2110. // through multiplication.
  2111. scaleFactor: k,
  2112. pageSize: {
  2113. getWidth: function getWidth() {
  2114. return pageWidth;
  2115. },
  2116. getHeight: function getHeight() {
  2117. return pageHeight;
  2118. }
  2119. },
  2120. output: function output(type, options) {
  2121. return _output(type, options);
  2122. },
  2123. getNumberOfPages: function getNumberOfPages() {
  2124. return pages.length - 1;
  2125. },
  2126. pages: pages,
  2127. out: out,
  2128. f2: f2,
  2129. getPageInfo: function getPageInfo(pageNumberOneBased) {
  2130. var objId = (pageNumberOneBased - 1) * 2 + 3;
  2131. return {
  2132. objId: objId,
  2133. pageNumber: pageNumberOneBased,
  2134. pageContext: pagesContext[pageNumberOneBased]
  2135. };
  2136. },
  2137. getCurrentPageInfo: function getCurrentPageInfo() {
  2138. var objId = (currentPage - 1) * 2 + 3;
  2139. return {
  2140. objId: objId,
  2141. pageNumber: currentPage,
  2142. pageContext: pagesContext[currentPage]
  2143. };
  2144. },
  2145. getPDFVersion: function getPDFVersion() {
  2146. return pdfVersion;
  2147. },
  2148. hasHotfix: hasHotfix //Expose the hasHotfix check so plugins can also check them.
  2149. };
  2150. function advancedAPI() {
  2151. // prepend global change of basis matrix
  2152. // (Now, instead of converting every coordinate to the pdf coordinate system, we apply a matrix
  2153. // that does this job for us (however, texts, images and similar objects must be drawn bottom up))
  2154. this.saveGraphicsState();
  2155. out(new Matrix(k, 0, 0, -k, 0, pageHeight * k).toString() + " cm");
  2156. this.setFontSize(this.getFontSize() / k);
  2157. apiMode = ApiMode.ADVANCED;
  2158. }
  2159. function compatAPI() {
  2160. this.restoreGraphicsState();
  2161. apiMode = ApiMode.COMPAT;
  2162. }
  2163. /**
  2164. * @callback ApiSwitchBody
  2165. * @param {jsPDF} pdf
  2166. */
  2167. /**
  2168. * For compatibility reasons jsPDF offers two API modes which differ in the way they convert between the the usual
  2169. * screen coordinates and the PDF coordinate system.
  2170. * - "compat": Offers full compatibility across all plugins but does not allow arbitrary transforms
  2171. * - "advanced": Allows arbitrary transforms and more advanced features like pattern fills. Some plugins might
  2172. * not support this mode, though.
  2173. * Initial mode is "compat".
  2174. *
  2175. * You can either provide a callback to the body argument, which means that jsPDF will automatically switch back to
  2176. * the original API mode afterwards; or you can omit the callback and switch back manually using {@link compatAPI}.
  2177. *
  2178. * Note, that the calls to {@link saveGraphicsState} and {@link restoreGraphicsState} need to be balanced within the
  2179. * callback or between calls of this method and its counterpart {@link compatAPI}. Calls to {@link beginFormObject}
  2180. * or {@link beginTilingPattern} need to be closed by their counterparts before switching back to "compat" API mode.
  2181. *
  2182. * @param {ApiSwitchBody=} body When provided, this callback will be called after the API mode has been switched.
  2183. * The API mode will be switched back automatically afterwards.
  2184. * @returns {jsPDF}
  2185. * @methodOf jsPDF#
  2186. * @name advancedAPI
  2187. */
  2188. API.advancedAPI = function (body) {
  2189. var doSwitch = apiMode === ApiMode.COMPAT;
  2190. if (doSwitch) {
  2191. advancedAPI.call(this);
  2192. }
  2193. if (typeof body !== "function") {
  2194. return this;
  2195. }
  2196. body(this);
  2197. if (doSwitch) {
  2198. compatAPI.call(this);
  2199. }
  2200. return this;
  2201. };
  2202. /**
  2203. * Switches to "compat" API mode. See {@link advancedAPI} for more details.
  2204. *
  2205. * @param {ApiSwitchBody=} body When provided, this callback will be called after the API mode has been switched.
  2206. * The API mode will be switched back automatically afterwards.
  2207. * @return {jsPDF}
  2208. * @methodOf jsPDF#
  2209. * @name compatApi
  2210. */
  2211. API.compatAPI = function (body) {
  2212. var doSwitch = apiMode === ApiMode.ADVANCED;
  2213. if (doSwitch) {
  2214. compatAPI.call(this);
  2215. }
  2216. if (typeof body !== "function") {
  2217. return this;
  2218. }
  2219. body(this);
  2220. if (doSwitch) {
  2221. advancedAPI.call(this);
  2222. }
  2223. return this;
  2224. };
  2225. /**
  2226. * @return {boolean} True iff the current API mode is "advanced". See {@link advancedAPI}.
  2227. * @methodOf jsPDF#
  2228. * @name isAdvancedAPI
  2229. */
  2230. API.isAdvancedAPI = function () {
  2231. return apiMode === ApiMode.ADVANCED;
  2232. };
  2233. /**
  2234. * Inserts a debug comment into the pdf.
  2235. * @param {String} text
  2236. * @returns {jsPDF}
  2237. * @methodOf jsPDF#
  2238. * @name comment
  2239. */
  2240. API.comment = function (text) {
  2241. out("#" + text);
  2242. return this;
  2243. };
  2244. /**
  2245. * An object representing a pdf graphics state.
  2246. * @param parameters A parameter object that contains all properties this graphics state wants to set.
  2247. * Supported are: opacity, stroke-opacity
  2248. * @constructor
  2249. */
  2250. API.GState = function (parameters) {
  2251. var supported = "opacity,stroke-opacity".split(",");
  2252. for (var p in parameters) {
  2253. if (parameters.hasOwnProperty(p) && supported.indexOf(p) >= 0) {
  2254. this[p] = parameters[p];
  2255. }
  2256. }
  2257. this.id = ""; // set by addGState()
  2258. this.objectNumber = -1; // will be set by putGState()
  2259. };
  2260. API.GState.prototype.equals = function equals(other) {
  2261. var ignore = "id,objectNumber,equals";
  2262. if (!other || _typeof(other) !== _typeof(this)) return false;
  2263. var count = 0;
  2264. for (var p in this) {
  2265. if (ignore.indexOf(p) >= 0) continue;
  2266. if (this.hasOwnProperty(p) && !other.hasOwnProperty(p)) return false;
  2267. if (this[p] !== other[p]) return false;
  2268. count++;
  2269. }
  2270. for (var p in other) {
  2271. if (other.hasOwnProperty(p) && ignore.indexOf(p) < 0) count--;
  2272. }
  2273. return count === 0;
  2274. };
  2275. /**
  2276. * Adds a new {@link GState} for later use. See {@link setGState}.
  2277. * @param {String} key
  2278. * @param {GState} gState
  2279. * @function
  2280. * @instance
  2281. * @returns {jsPDF}
  2282. *
  2283. * @methodOf jsPDF#
  2284. * @name addPage
  2285. */
  2286. API.addGState = function (key, gState) {
  2287. addGState(key, gState);
  2288. return this;
  2289. };
  2290. /**
  2291. * Adds (and transfers the focus to) new page to the PDF document.
  2292. * @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 />
  2293. * 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]
  2294. * @param {string} orientation Orientation of the new page. Possible values are "portrait" or "landscape" (or shortcuts "p" (Default), "l")
  2295. * @function
  2296. * @instance
  2297. * @returns {jsPDF}
  2298. *
  2299. * @memberOf jsPDF
  2300. * @name addPage
  2301. */
  2302. API.addPage = function (format, orientation) {
  2303. _addPage.apply(this, arguments);
  2304. return this;
  2305. };
  2306. /**
  2307. * Adds (and transfers the focus to) new page to the PDF document.
  2308. * @function
  2309. * @instance
  2310. * @returns {jsPDF}
  2311. *
  2312. * @memberOf jsPDF
  2313. * @name setPage
  2314. * @param {number} page Switch the active page to the page number specified
  2315. * @example
  2316. * doc = jsPDF()
  2317. * doc.addPage()
  2318. * doc.addPage()
  2319. * doc.text('I am on page 3', 10, 10)
  2320. * doc.setPage(1)
  2321. * doc.text('I am on page 1', 10, 10)
  2322. */
  2323. API.setPage = function (page) {
  2324. _setPage.apply(this, arguments);
  2325. return this;
  2326. };
  2327. /**
  2328. * @name insertPage
  2329. * @memberOf jsPDF
  2330. *
  2331. * @function
  2332. * @instance
  2333. * @param {Object} beforePage
  2334. * @returns {jsPDF}
  2335. */
  2336. API.insertPage = function (beforePage) {
  2337. this.addPage();
  2338. this.movePage(currentPage, beforePage);
  2339. return this;
  2340. };
  2341. /**
  2342. * @name movePage
  2343. * @memberOf jsPDF
  2344. * @function
  2345. * @instance
  2346. * @param {Object} targetPage
  2347. * @param {Object} beforePage
  2348. * @returns {jsPDF}
  2349. */
  2350. API.movePage = function (targetPage, beforePage) {
  2351. var tmpPagesContext, tmpPagedim, tmpPages, i;
  2352. if (targetPage > beforePage) {
  2353. tmpPages = pages[targetPage];
  2354. tmpPagedim = pagedim[targetPage];
  2355. tmpPagesContext = pagesContext[targetPage];
  2356. for (i = targetPage; i > beforePage; i--) {
  2357. pages[i] = pages[i - 1];
  2358. pagedim[i] = pagedim[i - 1];
  2359. pagesContext[i] = pagesContext[i - 1];
  2360. }
  2361. pages[beforePage] = tmpPages;
  2362. pagedim[beforePage] = tmpPagedim;
  2363. pagesContext[beforePage] = tmpPagesContext;
  2364. this.setPage(beforePage);
  2365. } else if (targetPage < beforePage) {
  2366. tmpPages = pages[targetPage];
  2367. tmpPagedim = pagedim[targetPage];
  2368. tmpPagesContext = pagesContext[targetPage];
  2369. for (i = targetPage; i < beforePage; i++) {
  2370. pages[i] = pages[i + 1];
  2371. pagedim[i] = pagedim[i + 1];
  2372. pagesContext[i] = pagesContext[i + 1];
  2373. }
  2374. pages[beforePage] = tmpPages;
  2375. pagedim[beforePage] = tmpPagedim;
  2376. pagesContext[beforePage] = tmpPagesContext;
  2377. this.setPage(beforePage);
  2378. }
  2379. return this;
  2380. };
  2381. /**
  2382. * @name deletePage
  2383. * @memberOf jsPDF
  2384. * @function
  2385. * @instance
  2386. * @returns {jsPDF}
  2387. */
  2388. API.deletePage = function () {
  2389. _deletePage.apply(this, arguments);
  2390. return this;
  2391. };
  2392. /**
  2393. * @name setCreationDate
  2394. * @memberOf jsPDF
  2395. * @function
  2396. * @instance
  2397. * @param {Object} date
  2398. * @returns {jsPDF}
  2399. */
  2400. API.setCreationDate = function (date) {
  2401. setCreationDate(date);
  2402. return this;
  2403. };
  2404. /**
  2405. * @name getCreationDate
  2406. * @memberOf jsPDF
  2407. * @function
  2408. * @instance
  2409. * @param {Object} type
  2410. * @returns {Object}
  2411. */
  2412. API.getCreationDate = function (type) {
  2413. return getCreationDate(type);
  2414. };
  2415. /**
  2416. * @name setFileId
  2417. * @memberOf jsPDF
  2418. * @function
  2419. * @instance
  2420. * @param {string} value GUID
  2421. * @returns {jsPDF}
  2422. */
  2423. API.setFileId = function (value) {
  2424. setFileId(value);
  2425. return this;
  2426. };
  2427. /**
  2428. * @name getFileId
  2429. * @memberOf jsPDF
  2430. * @function
  2431. * @instance
  2432. *
  2433. * @returns {string} GUID
  2434. */
  2435. API.getFileId = function () {
  2436. return getFileId();
  2437. };
  2438. /**
  2439. * Set the display mode options of the page like zoom and layout.
  2440. *
  2441. * @param {integer|String} zoom You can pass an integer or percentage as
  2442. * a string. 2 will scale the document up 2x, '200%' will scale up by the
  2443. * same amount. You can also set it to 'fullwidth', 'fullheight',
  2444. * 'fullpage', or 'original'.
  2445. *
  2446. * Only certain PDF readers support this, such as Adobe Acrobat
  2447. *
  2448. * @param {string} layout Layout mode can be: 'continuous' - this is the
  2449. * default continuous scroll. 'single' - the single page mode only shows one
  2450. * page at a time. 'twoleft' - two column left mode, first page starts on
  2451. * the left, and 'tworight' - pages are laid out in two columns, with the
  2452. * first page on the right. This would be used for books.
  2453. * @param {string} pmode 'UseOutlines' - it shows the
  2454. * outline of the document on the left. 'UseThumbs' - shows thumbnails along
  2455. * the left. 'FullScreen' - prompts the user to enter fullscreen mode.
  2456. *
  2457. * @returns {jsPDF}
  2458. * @function
  2459. * @instance
  2460. * @name setDisplayMode
  2461. * @methodOf jsPDF#
  2462. */
  2463. API.setDisplayMode = function (zoom, layout, pmode) {
  2464. zoomMode = zoom;
  2465. layoutMode = layout;
  2466. pageMode = pmode;
  2467. var validPageModes = [undefined, null, "UseNone", "UseOutlines", "UseThumbs", "FullScreen"];
  2468. if (validPageModes.indexOf(pmode) == -1) {
  2469. throw new Error('Page mode must be one of UseNone, UseOutlines, UseThumbs, or FullScreen. "' + pmode + '" is not recognized.');
  2470. }
  2471. return this;
  2472. };
  2473. /**
  2474. * Saves the current graphics state ("pushes it on the stack"). It can be restored by {@link restoreGraphicsState}
  2475. * later. Here, the general pdf graphics state is meant, also including the current transformation matrix,
  2476. * fill and stroke colors etc.
  2477. * @function
  2478. * @returns {jsPDF}
  2479. * @methodOf jsPDF#
  2480. * @name saveGraphicsState
  2481. */
  2482. API.saveGraphicsState = function () {
  2483. out("q"); // as we cannot set font key and size independently we must keep track of both
  2484. fontStateStack.push({
  2485. key: activeFontKey,
  2486. size: activeFontSize,
  2487. color: textColor
  2488. });
  2489. return this;
  2490. };
  2491. /**
  2492. * Restores a previously saved graphics state saved by {@link saveGraphicsState} ("pops the stack").
  2493. * @function
  2494. * @returns {jsPDF}
  2495. * @methodOf jsPDF#
  2496. * @name restoreGraphicsState
  2497. */
  2498. API.restoreGraphicsState = function () {
  2499. out("Q"); // restore previous font state
  2500. var fontState = fontStateStack.pop();
  2501. activeFontKey = fontState.key;
  2502. activeFontSize = fontState.size;
  2503. textColor = fontState.color;
  2504. activeGState = null;
  2505. return this;
  2506. };
  2507. /**
  2508. * Appends this matrix to the left of all previously applied matrices.
  2509. *
  2510. * Only available in "advanced" API mode.
  2511. *
  2512. * @param {Matrix} matrix
  2513. * @function
  2514. * @returns {jsPDF}
  2515. * @methodOf jsPDF#
  2516. * @name setCurrentTransformationMatrix
  2517. */
  2518. API.setCurrentTransformationMatrix = function (matrix) {
  2519. advancedApiModeTrap("setCurrentTransformationMatrix()");
  2520. out(matrix.toString() + " cm");
  2521. return this;
  2522. };
  2523. /**
  2524. * Starts a new pdf form object, which means that all conseequent draw calls target a new independent object
  2525. * until {@link endFormObject} is called. The created object can be referenced and drawn later using
  2526. * {@link doFormObject}. Nested form objects are possible.
  2527. * x, y, width, height set the bounding box that is used to clip the content.
  2528. *
  2529. * Only available in "advanced" API mode.
  2530. *
  2531. * @param {number} x
  2532. * @param {number} y
  2533. * @param {number} width
  2534. * @param {number} height
  2535. * @param {Matrix} matrix The matrix that will be applied to convert the form objects coordinate system to
  2536. * the parent's.
  2537. * @function
  2538. * @returns {jsPDF}
  2539. * @methodOf jsPDF#
  2540. * @name beginFormObject
  2541. */
  2542. API.beginFormObject = function (x, y, width, height, matrix) {
  2543. advancedApiModeTrap("beginFormObject()"); // The user can set the output target to a new form object. Nested form objects are possible.
  2544. // Currently, they use the resource dictionary of the surrounding stream. This should be changed, as
  2545. // the PDF-Spec states:
  2546. // "In PDF 1.2 and later versions, form XObjects may be independent of the content streams in which
  2547. // they appear, and this is strongly recommended although not requiredIn PDF 1.2 and later versions,
  2548. // form XObjects may be independent of the content streams in which they appear, and this is strongly
  2549. // recommended although not required"
  2550. beginNewRenderTarget(x, y, width, height, matrix);
  2551. return this;
  2552. };
  2553. /**
  2554. * Completes and saves the form object. Only available in "advanced" API mode.
  2555. * @param {String} key The key by which this form object can be referenced.
  2556. * @function
  2557. * @returns {jsPDF}
  2558. * @methodOf jsPDF#
  2559. * @name endFormObject
  2560. */
  2561. API.endFormObject = function (key) {
  2562. advancedApiModeTrap("endFormObject()");
  2563. endFormObject(key);
  2564. return this;
  2565. };
  2566. /**
  2567. * Draws the specified form object by referencing to the respective pdf XObject created with
  2568. * {@link API.beginFormObject} and {@link endFormObject}.
  2569. * The location is determined by matrix.
  2570. *
  2571. * Only available in "advanced" API mode.
  2572. *
  2573. * @param {String} key The key to the form object.
  2574. * @param {Matrix} matrix The matrix applied before drawing the form object.
  2575. * @function
  2576. * @returns {jsPDF}
  2577. * @methodOf jsPDF#
  2578. * @name doFormObject
  2579. */
  2580. API.doFormObject = function (key, matrix) {
  2581. advancedApiModeTrap("doFormObject()");
  2582. var xObject = renderTargets[renderTargetMap[key]];
  2583. out("q");
  2584. out(matrix.toString() + " cm");
  2585. out("/" + xObject.id + " Do");
  2586. out("Q");
  2587. return this;
  2588. };
  2589. /**
  2590. * Returns the form object specified by key.
  2591. * @param key {String}
  2592. * @returns {{x: number, y: number, width: number, height: number, matrix: Matrix}}
  2593. * @function
  2594. * @returns {jsPDF}
  2595. * @methodOf jsPDF#
  2596. * @name getFormObject
  2597. */
  2598. API.getFormObject = function (key) {
  2599. var xObject = renderTargets[renderTargetMap[key]];
  2600. return {
  2601. x: xObject.x,
  2602. y: xObject.y,
  2603. width: xObject.width,
  2604. height: xObject.height,
  2605. matrix: xObject.matrix
  2606. };
  2607. };
  2608. /**
  2609. * A matrix object for 2D homogenous transformations:
  2610. * | a b 0 |
  2611. * | c d 0 |
  2612. * | e f 1 |
  2613. * pdf multiplies matrices righthand: v' = v x m1 x m2 x ...
  2614. * @param {number} a
  2615. * @param {number} b
  2616. * @param {number} c
  2617. * @param {number} d
  2618. * @param {number} e
  2619. * @param {number} f
  2620. * @constructor
  2621. */
  2622. API.Matrix = Matrix;
  2623. /**
  2624. * Multiplies two matrices. (see {@link Matrix})
  2625. * @param {Matrix} m1
  2626. * @param {Matrix} m2
  2627. * @methodOf jsPDF#
  2628. * @name matrixMult
  2629. */
  2630. API.matrixMult = matrixMult;
  2631. /**
  2632. * The unit matrix (equivalent to new Matrix(1, 0, 0, 1, 0, 0)).
  2633. * @type {Matrix}
  2634. * @fieldOf jsPDF#
  2635. * @name unitMatrix
  2636. */
  2637. API.unitMatrix = unitMatrix;
  2638. var Pattern = function Pattern(gState, matrix) {
  2639. this.gState = gState;
  2640. this.matrix = matrix;
  2641. this.id = ""; // set by addPattern()
  2642. this.objectNumber = -1; // will be set by putPattern()
  2643. };
  2644. /**
  2645. * A pattern describing a shading pattern.
  2646. *
  2647. * Only available in "advanced" API mode.
  2648. *
  2649. * @param {String} type One of "axial" or "radial"
  2650. * @param {Array<Number>} coords Either [x1, y1, x2, y2] for "axial" type describing the two interpolation points
  2651. * or [x1, y1, r, x2, y2, r2] for "radial" describing inner and the outer circle.
  2652. * @param {Array<Object>} colors An array of objects with the fields "offset" and "color". "offset" describes
  2653. * the offset in parameter space [0, 1]. "color" is an array of length 3 describing RGB values in [0, 255].
  2654. * @param {GState=} gState An additional graphics state that gets applied to the pattern (optional).
  2655. * @param {Matrix=} matrix A matrix that describes the transformation between the pattern coordinate system
  2656. * and the use coordinate system (optional).
  2657. * @constructor
  2658. * @extends API.Pattern
  2659. */
  2660. API.ShadingPattern = function (type, coords, colors, gState, matrix) {
  2661. advancedApiModeTrap("ShadingPattern"); // see putPattern() for information how they are realized
  2662. this.type = type === "axial" ? 2 : 3;
  2663. this.coords = coords;
  2664. this.colors = colors;
  2665. Pattern.call(this, gState, matrix);
  2666. };
  2667. /**
  2668. * A PDF Tiling pattern.
  2669. *
  2670. * Only available in "advanced" API mode.
  2671. *
  2672. * @param {Array.<Number>} boundingBox The bounding box at which one pattern cell gets clipped.
  2673. * @param {Number} xStep Horizontal spacing between pattern cells.
  2674. * @param {Number} yStep Vertical spacing between pattern cells.
  2675. * @param {API.GState=} gState An additional graphics state that gets applied to the pattern (optional).
  2676. * @param {Matrix=} matrix A matrix that describes the transformation between the pattern coordinate system
  2677. * and the use coordinate system (optional).
  2678. * @constructor
  2679. * @extends API.Pattern
  2680. */
  2681. API.TilingPattern = function (boundingBox, xStep, yStep, gState, matrix) {
  2682. advancedApiModeTrap("TilingPattern");
  2683. this.boundingBox = boundingBox;
  2684. this.xStep = xStep;
  2685. this.yStep = yStep;
  2686. this.stream = ""; // set by endTilingPattern();
  2687. this.cloneIndex = 0;
  2688. Pattern.call(this, gState, matrix);
  2689. };
  2690. API.TilingPattern.prototype = {
  2691. createClone: function createClone(patternKey, boundingBox, xStep, yStep, matrix) {
  2692. var clone = new API.TilingPattern(boundingBox || this.boundingBox, xStep || this.xStep, yStep || this.yStep, this.gState, matrix || this.matrix);
  2693. clone.stream = this.stream;
  2694. var key = patternKey + "$$" + this.cloneIndex++ + "$$";
  2695. addPattern(key, clone);
  2696. return clone;
  2697. }
  2698. };
  2699. /**
  2700. * Adds a new {@link API.ShadingPattern} for later use. Only available in "advanced" API mode.
  2701. * @param {String} key
  2702. * @param {Pattern} pattern
  2703. * @function
  2704. * @returns {jsPDF}
  2705. * @methodOf jsPDF#
  2706. * @name addPattern
  2707. */
  2708. API.addShadingPattern = function (key, pattern) {
  2709. advancedApiModeTrap("addShadingPattern()");
  2710. addPattern(key, pattern);
  2711. return this;
  2712. };
  2713. /**
  2714. * Begins a new tiling pattern. All subsequent render calls are drawn to this pattern until {@link API.endTilingPattern}
  2715. * gets called. Only available in "advanced" API mode.
  2716. * @param {API.Pattern} pattern
  2717. * @methodOf jsPDF#
  2718. * @name beginTilingPattern
  2719. */
  2720. API.beginTilingPattern = function (pattern) {
  2721. advancedApiModeTrap("beginTilingPattern()");
  2722. beginNewRenderTarget(pattern.boundingBox[0], pattern.boundingBox[1], pattern.boundingBox[2] - pattern.boundingBox[0], pattern.boundingBox[3] - pattern.boundingBox[1], pattern.matrix);
  2723. };
  2724. /**
  2725. * Ends a tiling pattern and sets the render target to the one active before {@link API.beginTilingPattern} has been called.
  2726. *
  2727. * Only available in "advanced" API mode.
  2728. *
  2729. * @param {string} key A unique key that is used to reference this pattern at later use.
  2730. * @param {API.Pattern} pattern The pattern to end.
  2731. * @methodOf jsPDF#
  2732. * @name endTilingPattern
  2733. */
  2734. API.endTilingPattern = function (key, pattern) {
  2735. advancedApiModeTrap("endTilingPattern()"); // retrieve the stream
  2736. pattern.stream = pages[currentPage].join("\n");
  2737. addPattern(key, pattern);
  2738. events.publish("endTilingPattern", pattern); // restore state from stack
  2739. renderTargetStack.pop().restore();
  2740. };
  2741. /**
  2742. * Adds text to page. Supports adding multiline text when 'text' argument is an Array of Strings.
  2743. *
  2744. * @function
  2745. * @param {String|Array} text String or array of strings to be added to the page. Each line is shifted one line down
  2746. * per font, spacing settings declared before this call.
  2747. * @param {number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
  2748. * @param {number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
  2749. * @param {Object} options Collection of settings signalling how the text must be encoded. Defaults are sane. If you
  2750. * think you want to pass some flags, you likely can read the source.
  2751. * @param {number|Matrix} transform If transform is a number the text will be rotated by this value around the
  2752. * anchor set by x and y.
  2753. *
  2754. * If it is a Matrix, this matrix gets directly applied to the text, which allows shearing
  2755. * effects etc.; the x and y offsets are then applied AFTER the coordinate system has been established by this
  2756. * matrix. This means passing a rotation matrix that is equivalent to some rotation angle will in general yield a
  2757. * DIFFERENT result. A matrix is only allowed in "advanced" API mode.
  2758. *
  2759. * @param align {string}
  2760. * @returns {jsPDF}
  2761. * @methodOf jsPDF#
  2762. * @name text
  2763. */
  2764. API.text = function (text, x, y, options, transform) {
  2765. /**
  2766. * Inserts something like this into PDF
  2767. * BT
  2768. * /F1 16 Tf % Font name + size
  2769. * 16 TL % How many units down for next line in multiline text
  2770. * 0 g % color
  2771. * 28.35 813.54 Td % position
  2772. * (line one) Tj
  2773. * T* (line two) Tj
  2774. * T* (line three) Tj
  2775. * ET
  2776. */
  2777. if (transform !== undefined && transform instanceof Matrix) {
  2778. advancedApiModeTrap("The transform parameter of text() with a Matrix value");
  2779. }
  2780. var xtra = "";
  2781. var isHex = false;
  2782. var lineHeight = lineHeightProportion;
  2783. var scope = this;
  2784. function ESC(s) {
  2785. s = s.split("\t").join(Array(options.TabLen || 9).join(" "));
  2786. return pdfEscape(s, flags);
  2787. }
  2788. function transformTextToSpecialArray(text) {
  2789. //we don't want to destroy original text array, so cloning it
  2790. var sa = text.concat();
  2791. var da = [];
  2792. var len = sa.length;
  2793. var curDa; //we do array.join('text that must not be PDFescaped")
  2794. //thus, pdfEscape each component separately
  2795. while (len--) {
  2796. curDa = sa.shift();
  2797. if (typeof curDa === "string") {
  2798. da.push(curDa);
  2799. } else {
  2800. if (Object.prototype.toString.call(text) === "[object Array]" && curDa.length === 1) {
  2801. da.push(curDa[0]);
  2802. } else {
  2803. da.push([curDa[0], curDa[1], curDa[2]]);
  2804. }
  2805. }
  2806. }
  2807. return da;
  2808. }
  2809. function processTextByFunction(text, processingFunction) {
  2810. var result;
  2811. if (typeof text === "string") {
  2812. result = processingFunction(text)[0];
  2813. } else if (Object.prototype.toString.call(text) === "[object Array]") {
  2814. //we don't want to destroy original text array, so cloning it
  2815. var sa = text.concat();
  2816. var da = [];
  2817. var len = sa.length;
  2818. var curDa;
  2819. var tmpResult; //we do array.join('text that must not be PDFescaped")
  2820. //thus, pdfEscape each component separately
  2821. while (len--) {
  2822. curDa = sa.shift();
  2823. if (typeof curDa === "string") {
  2824. da.push(processingFunction(curDa)[0]);
  2825. } else if (Object.prototype.toString.call(curDa) === "[object Array]" && curDa[0] === "string") {
  2826. tmpResult = processingFunction(curDa[0], curDa[1], curDa[2]);
  2827. da.push([tmpResult[0], tmpResult[1], tmpResult[2]]);
  2828. }
  2829. }
  2830. result = da;
  2831. }
  2832. return result;
  2833. } //backwardsCompatibility
  2834. var tmp; // Pre-August-2012 the order of arguments was function(x, y, text, flags)
  2835. // in effort to make all calls have similar signature like
  2836. // function(data, coordinates... , miscellaneous)
  2837. // this method had its args flipped.
  2838. // code below allows backward compatibility with old arg order.
  2839. if (typeof text === "number") {
  2840. tmp = y;
  2841. y = x;
  2842. x = text;
  2843. text = tmp;
  2844. }
  2845. var flags = arguments[3];
  2846. var angle = arguments[4];
  2847. var align = arguments[5];
  2848. if (_typeof(flags) !== "object" || flags === null) {
  2849. if (typeof angle === "string") {
  2850. align = angle;
  2851. angle = null;
  2852. }
  2853. if (typeof flags === "string") {
  2854. align = flags;
  2855. flags = null;
  2856. }
  2857. if (typeof flags === "number") {
  2858. angle = flags;
  2859. flags = null;
  2860. }
  2861. options = {
  2862. flags: flags,
  2863. angle: angle,
  2864. align: align
  2865. };
  2866. } //Check if text is of type String
  2867. var textIsOfTypeString = false;
  2868. var tmpTextIsOfTypeString = true;
  2869. if (typeof text === "string") {
  2870. textIsOfTypeString = true;
  2871. } else if (Object.prototype.toString.call(text) === "[object Array]") {
  2872. //we don't want to destroy original text array, so cloning it
  2873. var sa = text.concat();
  2874. var da = [];
  2875. var len = sa.length;
  2876. var curDa; //we do array.join('text that must not be PDFescaped")
  2877. //thus, pdfEscape each component separately
  2878. while (len--) {
  2879. curDa = sa.shift();
  2880. if (typeof curDa !== "string" || Object.prototype.toString.call(curDa) === "[object Array]" && typeof curDa[0] !== "string") {
  2881. tmpTextIsOfTypeString = false;
  2882. }
  2883. }
  2884. textIsOfTypeString = tmpTextIsOfTypeString;
  2885. }
  2886. if (textIsOfTypeString === false) {
  2887. throw new Error('Type of text must be string or Array. "' + text + '" is not recognized.');
  2888. } //Escaping
  2889. var activeFontEncoding = fonts[activeFontKey].encoding;
  2890. if (activeFontEncoding === "WinAnsiEncoding" || activeFontEncoding === "StandardEncoding") {
  2891. text = processTextByFunction(text, function (text, posX, posY) {
  2892. return [ESC(text), posX, posY];
  2893. });
  2894. } //If there are any newlines in text, we assume
  2895. //the user wanted to print multiple lines, so break the
  2896. //text up into an array. If the text is already an array,
  2897. //we assume the user knows what they are doing.
  2898. //Convert text into an array anyway to simplify
  2899. //later code.
  2900. if (typeof text === "string") {
  2901. if (text.match(/[\r?\n]/)) {
  2902. text = text.split(/\r\n|\r|\n/g);
  2903. } else {
  2904. text = [text];
  2905. }
  2906. } //multiline
  2907. var maxWidth = options.maxWidth || 0;
  2908. if (maxWidth > 0) {
  2909. if (typeof text === "string") {
  2910. text = scope.splitTextToSize(text, maxWidth);
  2911. } else if (Object.prototype.toString.call(text) === "[object Array]") {
  2912. text = scope.splitTextToSize(text.join(" "), maxWidth);
  2913. }
  2914. } //creating Payload-Object to make text byRef
  2915. var payload = {
  2916. text: text,
  2917. x: x,
  2918. y: y,
  2919. options: options,
  2920. mutex: {
  2921. pdfEscape: pdfEscape,
  2922. activeFontKey: activeFontKey,
  2923. fonts: fonts,
  2924. activeFontSize: activeFontSize
  2925. }
  2926. };
  2927. events.publish("preProcessText", payload);
  2928. text = payload.text;
  2929. options = payload.options; //angle
  2930. var angle = options.angle;
  2931. var transformationMatrix = null;
  2932. if (angle && typeof angle === "number") {
  2933. angle *= Math.PI / 180;
  2934. if (apiMode === ApiMode.ADVANCED) {
  2935. angle = -angle;
  2936. }
  2937. var c = Math.cos(angle),
  2938. s = Math.sin(angle);
  2939. transformationMatrix = new Matrix(c, s, -s, c, 0, 0);
  2940. } else if (angle && angle instanceof Matrix) {
  2941. transformationMatrix = angle;
  2942. } //charSpace
  2943. var charSpace = options.charSpace;
  2944. if (charSpace !== undefined) {
  2945. xtra += charSpace + " Tc\n";
  2946. } //lang
  2947. var lang = options.lang;
  2948. var tmpRenderingMode = -1;
  2949. var parmRenderingMode = options.renderingMode || options.stroke;
  2950. var pageContext = scope.internal.getCurrentPageInfo().pageContext;
  2951. switch (parmRenderingMode) {
  2952. case 0:
  2953. case false:
  2954. case "fill":
  2955. tmpRenderingMode = 0;
  2956. break;
  2957. case 1:
  2958. case true:
  2959. case "stroke":
  2960. tmpRenderingMode = 1;
  2961. break;
  2962. case 2:
  2963. case "fillThenStroke":
  2964. tmpRenderingMode = 2;
  2965. break;
  2966. case 3:
  2967. case "invisible":
  2968. tmpRenderingMode = 3;
  2969. break;
  2970. case 4:
  2971. case "fillAndAddForClipping":
  2972. tmpRenderingMode = 4;
  2973. break;
  2974. case 5:
  2975. case "strokeAndAddPathForClipping":
  2976. tmpRenderingMode = 5;
  2977. break;
  2978. case 6:
  2979. case "fillThenStrokeAndAddToPathForClipping":
  2980. tmpRenderingMode = 6;
  2981. break;
  2982. case 7:
  2983. case "addToPathForClipping":
  2984. tmpRenderingMode = 7;
  2985. break;
  2986. }
  2987. var usedRenderingMode = pageContext.usedRenderingMode || -1; //if the coder wrote it explicitly to use a specific
  2988. //renderingMode, then use it
  2989. if (tmpRenderingMode !== -1) {
  2990. xtra += tmpRenderingMode + " Tr\n"; //otherwise check if we used the rendering Mode already
  2991. //if so then set the rendering Mode...
  2992. } else if (usedRenderingMode !== -1) {
  2993. xtra += "0 Tr\n";
  2994. }
  2995. if (tmpRenderingMode !== -1) {
  2996. pageContext.usedRenderingMode = tmpRenderingMode;
  2997. } //align
  2998. var align = options.align || "left";
  2999. var leading = activeFontSize * lineHeight;
  3000. var pageWidth = scope.internal.pageSize.getWidth();
  3001. var k = scope.internal.scaleFactor;
  3002. var activeFont = fonts[activeFontKey];
  3003. var charSpace = options.charSpace || activeCharSpace;
  3004. var maxWidth = options.maxWidth || 0;
  3005. var lineWidths;
  3006. var flags = {};
  3007. var wordSpacingPerLine = [];
  3008. if (Object.prototype.toString.call(text) === "[object Array]") {
  3009. var da = transformTextToSpecialArray(text);
  3010. var newY;
  3011. var maxLineLength;
  3012. var lineWidths;
  3013. if (align !== "left") {
  3014. lineWidths = da.map(function (v) {
  3015. return scope.getStringUnitWidth(v, {
  3016. font: activeFont,
  3017. charSpace: charSpace,
  3018. fontSize: activeFontSize
  3019. }) * activeFontSize / k;
  3020. });
  3021. }
  3022. var maxLineLength = Math.max.apply(Math, lineWidths); //The first line uses the "main" Td setting,
  3023. //and the subsequent lines are offset by the
  3024. //previous line's x coordinate.
  3025. var prevWidth = 0;
  3026. var delta;
  3027. var newX;
  3028. var xOffset = 0;
  3029. if (align === "right") {
  3030. xOffset = -lineWidths[0];
  3031. text = [];
  3032. for (var i = 0, len = da.length; i < len; i++) {
  3033. delta = maxLineLength - lineWidths[i];
  3034. if (i === 0) {
  3035. newX = 0;
  3036. newY = 0;
  3037. } else {
  3038. newX = prevWidth - lineWidths[i];
  3039. newY = leading;
  3040. }
  3041. text.push([da[i], newX, newY]);
  3042. prevWidth = lineWidths[i];
  3043. }
  3044. } else if (align === "center") {
  3045. xOffset = -lineWidths[0] / 2;
  3046. text = [];
  3047. for (var i = 0, len = da.length; i < len; i++) {
  3048. delta = (maxLineLength - lineWidths[i]) / 2;
  3049. if (i === 0) {
  3050. newX = 0;
  3051. newY = 0;
  3052. } else {
  3053. newX = (prevWidth - lineWidths[i]) / 2;
  3054. newY = leading;
  3055. }
  3056. text.push([da[i], newX, newY]);
  3057. prevWidth = lineWidths[i];
  3058. }
  3059. } else if (align === "left") {
  3060. text = [];
  3061. for (var i = 0, len = da.length; i < len; i++) {
  3062. text.push(da[i]);
  3063. }
  3064. } else if (align === "justify") {
  3065. text = [];
  3066. var maxWidth = maxWidth !== 0 ? maxWidth : pageWidth;
  3067. for (var i = 0, len = da.length; i < len; i++) {
  3068. newX = 0;
  3069. newY = i === 0 ? 0 : leading;
  3070. if (i < len - 1) {
  3071. wordSpacingPerLine.push((maxWidth - lineWidths[i]) / (da[i].split(" ").length - 1));
  3072. }
  3073. text.push([da[i], newX, newY]);
  3074. }
  3075. } else {
  3076. throw new Error('Unrecognized alignment option, use "left", "center", "right" or "justify".');
  3077. }
  3078. } //R2L
  3079. var doReversing = typeof options.R2L === "boolean" ? options.R2L : R2L;
  3080. if (doReversing === true) {
  3081. text = processTextByFunction(text, function (text, posX, posY) {
  3082. return [text.split("").reverse().join(""), posX, posY];
  3083. });
  3084. } //creating Payload-Object to make text byRef
  3085. var payload = {
  3086. text: text,
  3087. x: x,
  3088. y: y,
  3089. options: options,
  3090. mutex: {
  3091. pdfEscape: pdfEscape,
  3092. activeFontKey: activeFontKey,
  3093. fonts: fonts,
  3094. activeFontSize: activeFontSize
  3095. }
  3096. };
  3097. events.publish("postProcessText", payload);
  3098. text = payload.text;
  3099. isHex = payload.mutex.isHex;
  3100. var da = transformTextToSpecialArray(text);
  3101. text = [];
  3102. var variant = 0;
  3103. var len = da.length;
  3104. var posX;
  3105. var posY;
  3106. var content;
  3107. var wordSpacing = "";
  3108. for (var i = 0; i < len; i++) {
  3109. wordSpacing = "";
  3110. if (Object.prototype.toString.call(da[i]) !== "[object Array]") {
  3111. content = (isHex ? "<" : "(") + da[i] + (isHex ? ">" : ")");
  3112. variant = 0;
  3113. } else if (Object.prototype.toString.call(da[i]) === "[object Array]") {
  3114. posX = da[i][1] * k; // x offset must always be scaled!
  3115. // y offset/leading must NOT be scaled by k as it is dependent of the font size, which is always given
  3116. // in plain pt
  3117. posY = -da[i][2];
  3118. content = (isHex ? "<" : "(") + da[i][0] + (isHex ? ">" : ")");
  3119. variant = 1;
  3120. }
  3121. if (wordSpacingPerLine !== undefined && wordSpacingPerLine[i] !== undefined) {
  3122. wordSpacing = wordSpacingPerLine[i] + " Tw\n";
  3123. }
  3124. if (variant === 1 && i > 0) {
  3125. text.push(wordSpacing + hpf(posX) + " " + hpf(posY) + " " + " Td\n" + content);
  3126. } else {
  3127. text.push(wordSpacing + content);
  3128. }
  3129. }
  3130. if (variant === 0) {
  3131. text = text.join(" Tj\nT* ");
  3132. } else {
  3133. text = text.join(" Tj\n");
  3134. }
  3135. if (apiMode === ApiMode.ADVANCED && transformationMatrix === null) {
  3136. transformationMatrix = unitMatrix;
  3137. }
  3138. if (transformationMatrix !== null) {
  3139. // It is kind of more intuitive to apply a plain rotation around the text anchor set by x and y
  3140. // but when the user supplies an arbitrary transformation matrix, the x and y offsets should be applied
  3141. // in the coordinate system established by this matrix
  3142. if (typeof angle === "number") {
  3143. transformationMatrix = matrixMult(transformationMatrix, new Matrix(1, 0, 0, 1, scaleByK(x), transformScaleY(y)));
  3144. } else {
  3145. transformationMatrix = matrixMult(new Matrix(1, 0, 0, 1, scaleByK(x), transformScaleY(y)), transformationMatrix);
  3146. }
  3147. transformationMatrix = matrixMult( // xOffset must always be scaled!
  3148. new Matrix(1, 0, 0, 1, xOffset * k, 0), transformationMatrix);
  3149. if (apiMode === ApiMode.ADVANCED) {
  3150. transformationMatrix = matrixMult(new Matrix(1, 0, 0, -1, 0, 0), transformationMatrix);
  3151. }
  3152. text = transformationMatrix.toString() + " Tm\n" + text;
  3153. } else {
  3154. text = hpf(scaleByK(x + xOffset)) + " " + hpf(transformScaleY(y)) + " " + " Td\n" + text;
  3155. }
  3156. text += " Tj\n";
  3157. var result = "BT\n/" + activeFontKey + " " + activeFontSize + " Tf\n" + // font face, style, size
  3158. (activeFontSize * lineHeight).toFixed(2) + " TL\n" + // line spacing
  3159. textColor + "\n";
  3160. result += xtra;
  3161. result += text;
  3162. result += "ET";
  3163. out(result);
  3164. return scope;
  3165. };
  3166. /**
  3167. * Letter spacing method to print text with gaps
  3168. *
  3169. * @function
  3170. * @instance
  3171. * @param {String|Array} text String to be added to the page.
  3172. * @param {number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
  3173. * @param {number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
  3174. * @param {number} spacing Spacing (in units declared at inception)
  3175. * @returns {jsPDF}
  3176. * @methodOf jsPDF#
  3177. * @name lstext
  3178. * @deprecated We'll be removing this function. It doesn't take character width into account.
  3179. */
  3180. API.lstext = function (text, x, y, spacing) {
  3181. console.warn("jsPDF.lstext is deprecated");
  3182. for (var i = 0, len = text.length; i < len; i++, x += spacing) {
  3183. this.text(text[i], x, y);
  3184. }
  3185. return this;
  3186. };
  3187. /**
  3188. * Draws a line from (x1, y1) to (x2, y2). No extra call to {@link API.stroke} is needed.
  3189. * @param {number} x1
  3190. * @param {number} y1
  3191. * @param {number} x2
  3192. * @param {number} y2
  3193. * @return {jsPDF}
  3194. * @methodOf jsPDF#
  3195. * @name line
  3196. */
  3197. API.line = function (x1, y1, x2, y2) {
  3198. if (apiMode === ApiMode.COMPAT) {
  3199. return this.lines([[x2 - x1, y2 - y1]], x1, y1, [1, 1], "D");
  3200. } else {
  3201. return this.lines([[x2 - x1, y2 - y1]], x1, y1, [1, 1]).stroke();
  3202. }
  3203. };
  3204. /**
  3205. * Begin a new subpath by moving the current point to coordinates (x, y). The PDF "m" operator.
  3206. * @param {number} x
  3207. * @param {number} y
  3208. * @methodOf jsPDF#
  3209. * @name moveTo
  3210. */
  3211. API.moveTo = function (x, y) {
  3212. out(hpf(scaleByK(x)) + " " + hpf(transformScaleY(y)) + " m");
  3213. };
  3214. /**
  3215. * Append a straight line segment from the current point to the point (x, y). The PDF "l" operator.
  3216. * @param {number} x
  3217. * @param {number} y
  3218. * @methodOf jsPDF#
  3219. * @name lineTo
  3220. */
  3221. API.lineTo = function (x, y) {
  3222. out(hpf(scaleByK(x)) + " " + hpf(transformScaleY(y)) + " l");
  3223. };
  3224. /**
  3225. * Append a cubic Bézier curve to the current path. The curve shall extend from the current point to the point
  3226. * (x3, y3), using (x1, y1) and (x2, y2) as Bézier control points. The new current point shall be (x3, x3).
  3227. * @param {number} x1
  3228. * @param {number} y1
  3229. * @param {number} x2
  3230. * @param {number} y2
  3231. * @param {number} x3
  3232. * @param {number} y3
  3233. * @methodOf jsPDF#
  3234. * @name curveTo
  3235. */
  3236. API.curveTo = function (x1, y1, x2, y2, x3, y3) {
  3237. out([hpf(scaleByK(x1)), hpf(transformScaleY(y1)), hpf(scaleByK(x2)), hpf(transformScaleY(y2)), hpf(scaleByK(x3)), hpf(transformScaleY(y3)), "c"].join(" "));
  3238. }; // PDF supports these path painting and clip path operators:
  3239. //
  3240. // S - stroke
  3241. // s - close/stroke
  3242. // f (F) - fill non-zero
  3243. // f* - fill evenodd
  3244. // B - fill stroke nonzero
  3245. // B* - fill stroke evenodd
  3246. // b - close fill stroke nonzero
  3247. // b* - close fill stroke evenodd
  3248. // n - nothing (consume path)
  3249. // W - clip nonzero
  3250. // W* - clip evenodd
  3251. //
  3252. // In order to keep the API small, we omit the close-and-fill/stroke operators and provide a separate close()
  3253. // method.
  3254. /**
  3255. * Close the current path. The PDF "h" operator.
  3256. * @return jsPDF
  3257. * @methodOf jsPDF#
  3258. * @name close
  3259. */
  3260. API.close = function () {
  3261. out("h");
  3262. return this;
  3263. };
  3264. /**
  3265. * Stroke the path. The PDF "S" operator.
  3266. * @return jsPDF
  3267. * @methodOf jsPDF#
  3268. * @name stroke
  3269. */
  3270. API.stroke = function () {
  3271. out("S");
  3272. return this;
  3273. };
  3274. /**
  3275. * @typedef {Object} PatternData
  3276. * @property {string} key The key of the pattern
  3277. * @property {Matrix} matrix The matrix that gets applied to the pattern right before drawing.
  3278. * @property {number[]|undefined} boundingBox Only relevant for tiling patterns. The bounding box at which one
  3279. * pattern cell gets clipped
  3280. * @property {number|undefined} xStep Only relevant for tiling patterns. Horizontal spacing between pattern cells
  3281. * @property {number|undefined} yStep Only relevant for tiling patterns. Vertical spacing between pattern cells
  3282. */
  3283. /**
  3284. * Fill the current path using the nonzero winding number rule. If a pattern is provided, the path will be filled
  3285. * with this pattern, otherwise with the current fill color. Equivalent to the PDF "f" operator.
  3286. * @param {PatternData=} pattern If provided the path will be filled with this pattern
  3287. * @return jsPDF
  3288. * @methodOf jsPDF#
  3289. * @name fill
  3290. */
  3291. API.fill = function (pattern) {
  3292. fillWithOptionalPattern("f", pattern);
  3293. return this;
  3294. };
  3295. /**
  3296. * Fill the current path using the even-odd rule. The PDF f* operator.
  3297. * @see API.fill
  3298. * @param {PatternData=} pattern Optional pattern
  3299. * @return jsPDF
  3300. * @methodOf jsPDF#
  3301. * @name fillEvenOdd
  3302. */
  3303. API.fillEvenOdd = function (pattern) {
  3304. fillWithOptionalPattern("f*", pattern);
  3305. return this;
  3306. };
  3307. /**
  3308. * Fill using the nonzero winding number rule and then stroke the current Path. The PDF "B" operator.
  3309. * @see API.fill
  3310. * @param {PatternData=} pattern Optional pattern
  3311. * @return jsPDF
  3312. * @methodOf jsPDF#
  3313. * @name fillStroke
  3314. */
  3315. API.fillStroke = function (pattern) {
  3316. fillWithOptionalPattern("B", pattern);
  3317. return this;
  3318. };
  3319. /**
  3320. * Fill using the even-odd rule and then stroke the current Path. The PDF "B" operator.
  3321. * @see API.fill
  3322. * @param {PatternData=} pattern Optional pattern
  3323. * @return jsPDF
  3324. * @methodOf jsPDF#
  3325. * @name fillStrokeEvenOdd
  3326. */
  3327. API.fillStrokeEvenOdd = function (pattern) {
  3328. fillWithOptionalPattern("B*", pattern);
  3329. return this;
  3330. };
  3331. function fillWithOptionalPattern(style, pattern) {
  3332. if (_typeof(pattern) === "object") {
  3333. fillWithPattern(pattern, style);
  3334. } else {
  3335. out(style);
  3336. }
  3337. }
  3338. /**
  3339. * Modify the current clip path by intersecting it with the current path using the nonzero winding number rule. Note
  3340. * that this will NOT consume the current path. In order to only use this path for clipping call
  3341. * {@link API.discardPath} afterwards.
  3342. *
  3343. * When in "compat" API mode this method has a historical bug and will always stroke the path as well, use
  3344. * {@link API.clip_fixed} instead.
  3345. * @return jsPDF
  3346. * @methodOf jsPDF#
  3347. * @name clip
  3348. */
  3349. API.clip = function () {
  3350. if (apiMode === ApiMode.COMPAT) {
  3351. // By patrick-roberts, github.com/MrRio/jsPDF/issues/328
  3352. // Call .clip() after calling .rect() with a style argument of null
  3353. out("W"); // clip
  3354. out("S"); // stroke path; necessary for clip to work
  3355. } else {
  3356. out("W");
  3357. }
  3358. return this;
  3359. };
  3360. /**
  3361. * Modify the current clip path by intersecting it with the current path using the even-odd rule. Note
  3362. * that this will NOT consume the current path. In order to only use this path for clipping call
  3363. * {@link API.discardPath} afterwards.
  3364. *
  3365. * @return jsPDF
  3366. * @methodOf jsPDF#
  3367. * @name clipEvenOdd
  3368. */
  3369. API.clipEvenOdd = function () {
  3370. out("W*");
  3371. return this;
  3372. };
  3373. /**
  3374. * Consumes the current path without any effect. Mainly used in combination with {@link clip} or
  3375. * {@link clipEvenOdd}. The PDF "n" operator.
  3376. * @return {jsPDF}
  3377. * @methodOf jsPDF#
  3378. * @name discardPath
  3379. */
  3380. API.discardPath = function () {
  3381. out("n");
  3382. return this;
  3383. };
  3384. /**
  3385. * This fixes the previous function clip(). Perhaps the 'stroke path' hack was due to the missing 'n' instruction?
  3386. * We introduce the fixed version so as to not break API.
  3387. * @param fillRule
  3388. * @deprecated Don't use this method when in "advanced" API mode.
  3389. * @methodOf jsPDF#
  3390. * @name clip_fixed
  3391. */
  3392. API.clip_fixed = function (fillRule) {
  3393. // Call .clip() after calling drawing ops with a style argument of null
  3394. // W is the PDF clipping op
  3395. if ("evenodd" === fillRule) {
  3396. out("W*");
  3397. } else {
  3398. out("W");
  3399. } // End the path object without filling or stroking it.
  3400. // This operator is a path-painting no-op, used primarily for the side effect of changing the current clipping path
  3401. // (see Section 4.4.3, “Clipping Path Operators”)
  3402. out("n");
  3403. };
  3404. /**
  3405. * @typedef {Object} PatternData
  3406. * {Matrix|undefined} matrix
  3407. * {Number|undefined} xStep
  3408. * {Number|undefined} yStep
  3409. * {Array.<Number>|undefined} boundingBox
  3410. */
  3411. /**
  3412. * Adds series of curves (straight lines or cubic bezier curves) to canvas, starting at `x`, `y` coordinates.
  3413. * All data points in `lines` are relative to last line origin.
  3414. * `x`, `y` become x1,y1 for first line / curve in the set.
  3415. * For lines you only need to specify [x2, y2] - (ending point) vector against x1, y1 starting point.
  3416. * 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.
  3417. *
  3418. * @example .lines([[2,2],[-2,2],[1,1,2,2,3,3],[2,1]], 212,110, 10) // line, line, bezier curve, line
  3419. * @param {Array} lines Array of *vector* shifts as pairs (lines) or sextets (cubic bezier curves).
  3420. * @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
  3421. * @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
  3422. * @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.
  3423. * @param {String=} style A string specifying the painting style or null. Valid styles include:
  3424. * 'S' [default] - stroke,
  3425. * 'F' - fill,
  3426. * and 'DF' (or 'FD') - fill then stroke.
  3427. * In "compat" API mode, a null value postpones setting the style so that a shape may be composed using multiple
  3428. * method calls. The last drawing method call used to define the shape should not have a null style argument.
  3429. *
  3430. * In "advanced" API mode this parameter is deprecated.
  3431. * @param {Boolean=} closed If true, the path is closed with a straight line from the end of the last curve to the starting point.
  3432. * @param {String=} patternKey The pattern key for the pattern that should be used to fill the path. Deprecated!
  3433. * @param {(Matrix|PatternData)=} patternData The matrix that transforms the pattern into user space, or an object that
  3434. * will modify the pattern on use. Deprecated!
  3435. * @function
  3436. * @instance
  3437. * @returns {jsPDF}
  3438. * @methodOf jsPDF#
  3439. * @name lines
  3440. */
  3441. API.lines = function (lines, x, y, scale, style, closed, patternKey, patternData) {
  3442. 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)
  3443. // in effort to make all calls have similar signature like
  3444. // function(content, coordinateX, coordinateY , miscellaneous)
  3445. // this method had its args flipped.
  3446. // code below allows backward compatibility with old arg order.
  3447. if (typeof lines === "number") {
  3448. var tmp = y;
  3449. y = x;
  3450. x = lines;
  3451. lines = tmp;
  3452. }
  3453. scale = scale || [1, 1]; // starting point
  3454. this.moveTo(x, y);
  3455. scalex = scale[0];
  3456. scaley = scale[1];
  3457. l = lines.length; //, x2, y2 // bezier only. In page default measurement "units", *after* scaling
  3458. //, x3, y3 // bezier only. In page default measurement "units", *after* scaling
  3459. // ending point for all, lines and bezier. . In page default measurement "units", *after* scaling
  3460. x4 = x; // last / ending point = starting point for first item.
  3461. y4 = y; // last / ending point = starting point for first item.
  3462. for (i = 0; i < l; i++) {
  3463. leg = lines[i];
  3464. if (leg.length === 2) {
  3465. // simple line
  3466. x4 = leg[0] * scalex + x4; // here last x4 was prior ending point
  3467. y4 = leg[1] * scaley + y4; // here last y4 was prior ending point
  3468. this.lineTo(x4, y4);
  3469. } else {
  3470. // bezier curve
  3471. x2 = leg[0] * scalex + x4; // here last x4 is prior ending point
  3472. y2 = leg[1] * scaley + y4; // here last y4 is prior ending point
  3473. x3 = leg[2] * scalex + x4; // here last x4 is prior ending point
  3474. y3 = leg[3] * scaley + y4; // here last y4 is prior ending point
  3475. x4 = leg[4] * scalex + x4; // here last x4 was prior ending point
  3476. y4 = leg[5] * scaley + y4; // here last y4 was prior ending point
  3477. this.curveTo(x2, y2, x3, y3, x4, y4);
  3478. }
  3479. }
  3480. if (closed) {
  3481. this.close();
  3482. }
  3483. putStyle(style, patternKey, patternData);
  3484. return this;
  3485. };
  3486. /**
  3487. * Similar to {@link API.lines} but all coordinates are interpreted as absolute coordinates instead of relative.
  3488. * @param {Array<Object>} lines An array of {op: operator, c: coordinates} object, where op is one of "m" (move to), "l" (line to)
  3489. * "c" (cubic bezier curve) and "h" (close (sub)path)). c is an array of coordinates. "m" and "l" expect two, "c"
  3490. * six and "h" an empty array (or undefined).
  3491. * @param {String=} style The style. Deprecated!
  3492. * @param {String=} patternKey The pattern key for the pattern that should be used to fill the path. Deprecated!
  3493. * @param {(Matrix|PatternData)=} patternData The matrix that transforms the pattern into user space, or an object that
  3494. * will modify the pattern on use. Deprecated!
  3495. * @function
  3496. * @returns {jsPDF}
  3497. * @methodOf jsPDF#
  3498. * @name path
  3499. */
  3500. API.path = function (lines, style, patternKey, patternData) {
  3501. for (var i = 0; i < lines.length; i++) {
  3502. var leg = lines[i];
  3503. var coords = leg.c;
  3504. switch (leg.op) {
  3505. case "m":
  3506. this.moveTo(coords[0], coords[1]);
  3507. break;
  3508. case "l":
  3509. this.lineTo(coords[0], coords[1]);
  3510. break;
  3511. case "c":
  3512. this.curveTo.apply(this, coords);
  3513. break;
  3514. case "h":
  3515. this.close();
  3516. break;
  3517. }
  3518. }
  3519. putStyle(style, patternKey, patternData);
  3520. return this;
  3521. };
  3522. /**
  3523. * Adds a rectangle to PDF
  3524. *
  3525. * @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
  3526. * @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
  3527. * @param {Number} w Width (in units declared at inception of PDF document)
  3528. * @param {Number} h Height (in units declared at inception of PDF document)
  3529. * @param {String=} style A string specifying the painting style or null. Valid styles include:
  3530. * 'S' [default] - stroke,
  3531. * 'F' - fill,
  3532. * and 'DF' (or 'FD') - fill then stroke.
  3533. * In "compat" API mode, a null value postpones setting the style so that a shape may be composed using multiple
  3534. * method calls. The last drawing method call used to define the shape should not have a null style argument.
  3535. *
  3536. * In "advanced" API mode this parameter is deprecated.
  3537. * @param {String=} patternKey The pattern key for the pattern that should be used to fill the primitive. Deprecated!
  3538. * @param {(Matrix|PatternData)=} patternData The matrix that transforms the pattern into user space, or an object that
  3539. * will modify the pattern on use. Deprecated!
  3540. * @function
  3541. * @instance
  3542. * @returns {jsPDF}
  3543. * @methodOf jsPDF#
  3544. * @name rect
  3545. */
  3546. API.rect = function (x, y, w, h, style, patternKey, patternData) {
  3547. if (apiMode === ApiMode.COMPAT) {
  3548. h = -h;
  3549. }
  3550. out([hpf(scaleByK(x)), hpf(transformScaleY(y)), hpf(scaleByK(w)), hpf(scaleByK(h)), "re"].join(" "));
  3551. putStyle(style, patternKey, patternData);
  3552. return this;
  3553. };
  3554. /**
  3555. * Adds a triangle to PDF
  3556. *
  3557. * @param {Number} x1 Coordinate (in units declared at inception of PDF document) against left edge of the page
  3558. * @param {Number} y1 Coordinate (in units declared at inception of PDF document) against upper edge of the page
  3559. * @param {Number} x2 Coordinate (in units declared at inception of PDF document) against left edge of the page
  3560. * @param {Number} y2 Coordinate (in units declared at inception of PDF document) against upper edge of the page
  3561. * @param {Number} x3 Coordinate (in units declared at inception of PDF document) against left edge of the page
  3562. * @param {Number} y3 Coordinate (in units declared at inception of PDF document) against upper edge of the page
  3563. * @param {String=} style A string specifying the painting style or null. Valid styles include:
  3564. * 'S' [default] - stroke,
  3565. * 'F' - fill,
  3566. * and 'DF' (or 'FD') - fill then stroke.
  3567. * In "compat" API mode, a null value postpones setting the style so that a shape may be composed using multiple
  3568. * method calls. The last drawing method call used to define the shape should not have a null style argument.
  3569. *
  3570. * In "advanced" API mode this parameter is deprecated.
  3571. * @param {String=} patternKey The pattern key for the pattern that should be used to fill the primitive. Deprecated!
  3572. * @param {(Matrix|PatternData)=} patternData The matrix that transforms the pattern into user space, or an object that
  3573. * will modify the pattern on use. Deprecated!
  3574. * @function
  3575. * @instance
  3576. * @returns {jsPDF}
  3577. * @methodOf jsPDF#
  3578. * @name triangle
  3579. */
  3580. API.triangle = function (x1, y1, x2, y2, x3, y3, style, patternKey, patternData) {
  3581. this.lines([[x2 - x1, y2 - y1], // vector to point 2
  3582. [x3 - x2, y3 - y2], // vector to point 3
  3583. [x1 - x3, y1 - y3] // closing vector back to point 1
  3584. ], x1, y1, // start of path
  3585. [1, 1], style, true, patternKey, patternData);
  3586. return this;
  3587. };
  3588. /**
  3589. * Adds a rectangle with rounded corners to PDF
  3590. *
  3591. * @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
  3592. * @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
  3593. * @param {Number} w Width (in units declared at inception of PDF document)
  3594. * @param {Number} h Height (in units declared at inception of PDF document)
  3595. * @param {Number} rx Radius along x axis (in units declared at inception of PDF document)
  3596. * @param {Number} ry Radius along y axis (in units declared at inception of PDF document)
  3597. * @param {String=} style A string specifying the painting style or null. Valid styles include:
  3598. * 'S' [default] - stroke,
  3599. * 'F' - fill,
  3600. * and 'DF' (or 'FD') - fill then stroke.
  3601. * In "compat" API mode, a null value postpones setting the style so that a shape may be composed using multiple
  3602. * method calls. The last drawing method call used to define the shape should not have a null style argument.
  3603. *
  3604. * In "advanced" API mode this parameter is deprecated.
  3605. * @param {String=} patternKey The pattern key for the pattern that should be used to fill the primitive. Deprecated!
  3606. * @param {(Matrix|PatternData)=} patternData The matrix that transforms the pattern into user space, or an object that
  3607. * will modify the pattern on use. Deprecated!
  3608. * @function
  3609. * @instance
  3610. * @returns {jsPDF}
  3611. * @methodOf jsPDF#
  3612. * @name roundedRect
  3613. */
  3614. API.roundedRect = function (x, y, w, h, rx, ry, style, patternKey, patternData) {
  3615. var MyArc = 4 / 3 * (Math.SQRT2 - 1);
  3616. rx = Math.min(rx, w * 0.5);
  3617. ry = Math.min(ry, h * 0.5);
  3618. 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
  3619. [1, 1], style, true, patternKey, patternData);
  3620. return this;
  3621. };
  3622. /**
  3623. * Adds an ellipse to PDF
  3624. *
  3625. * @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
  3626. * @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
  3627. * @param {Number} rx Radius along x axis (in units declared at inception of PDF document)
  3628. * @param {Number} ry Radius along y axis (in units declared at inception of PDF document)
  3629. * @param {String=} style A string specifying the painting style or null. Valid styles include:
  3630. * 'S' [default] - stroke,
  3631. * 'F' - fill,
  3632. * and 'DF' (or 'FD') - fill then stroke.
  3633. * In "compat" API mode, a null value postpones setting the style so that a shape may be composed using multiple
  3634. * method calls. The last drawing method call used to define the shape should not have a null style argument.
  3635. *
  3636. * In "advanced" API mode this parameter is deprecated.
  3637. * @param {String=} patternKey The pattern key for the pattern that should be used to fill the primitive. Deprecated!
  3638. * @param {(Matrix|PatternData)=} patternData The matrix that transforms the pattern into user space, or an object that
  3639. * will modify the pattern on use. Deprecated!
  3640. * @function
  3641. * @instance
  3642. * @returns {jsPDF}
  3643. * @methodOf jsPDF#
  3644. * @name ellipse
  3645. */
  3646. API.ellipse = function (x, y, rx, ry, style, patternKey, patternData) {
  3647. var lx = 4 / 3 * (Math.SQRT2 - 1) * rx,
  3648. ly = 4 / 3 * (Math.SQRT2 - 1) * ry;
  3649. this.moveTo(x + rx, y);
  3650. this.curveTo(x + rx, y - ly, x + lx, y - ry, x, y - ry);
  3651. this.curveTo(x - lx, y - ry, x - rx, y - ly, x - rx, y);
  3652. this.curveTo(x - rx, y + ly, x - lx, y + ry, x, y + ry);
  3653. this.curveTo(x + lx, y + ry, x + rx, y + ly, x + rx, y);
  3654. putStyle(style, patternKey, patternData);
  3655. return this;
  3656. };
  3657. /**
  3658. * Adds an circle to PDF
  3659. *
  3660. * @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
  3661. * @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
  3662. * @param {Number} r Radius (in units declared at inception of PDF document)
  3663. * @param {String=} style A string specifying the painting style or null. Valid styles include:
  3664. * 'S' [default] - stroke,
  3665. * 'F' - fill,
  3666. * and 'DF' (or 'FD') - fill then stroke.
  3667. * In "compat" API mode, a null value postpones setting the style so that a shape may be composed using multiple
  3668. * method calls. The last drawing method call used to define the shape should not have a null style argument.
  3669. *
  3670. * In "advanced" API mode this parameter is deprecated.
  3671. * @param {String=} patternKey The pattern key for the pattern that should be used to fill the primitive. Deprecated!
  3672. * @param {(Matrix|PatternData)=} patternData The matrix that transforms the pattern into user space, or an object that
  3673. * will modify the pattern on use. Deprecated!
  3674. * @function
  3675. * @instance
  3676. * @returns {jsPDF}
  3677. * @methodOf jsPDF#
  3678. * @name circle
  3679. */
  3680. API.circle = function (x, y, r, style, patternKey, patternData) {
  3681. return this.ellipse(x, y, r, r, style, patternKey, patternData);
  3682. };
  3683. /**
  3684. * Adds a properties to the PDF document
  3685. *
  3686. * @param {Object} properties A property_name-to-property_value object structure.
  3687. * @function
  3688. * @instance
  3689. * @returns {jsPDF}
  3690. * @methodOf jsPDF#
  3691. * @name setProperties
  3692. */
  3693. API.setProperties = function (properties) {
  3694. // copying only those properties we can render.
  3695. for (var property in documentProperties) {
  3696. if (documentProperties.hasOwnProperty(property) && properties[property]) {
  3697. documentProperties[property] = properties[property];
  3698. }
  3699. }
  3700. return this;
  3701. };
  3702. /**
  3703. * Sets font size for upcoming text elements.
  3704. *
  3705. * @param {number} size Font size in points.
  3706. * @function
  3707. * @instance
  3708. * @returns {jsPDF}
  3709. * @methodOf jsPDF#
  3710. * @name setFontSize
  3711. */
  3712. API.setFontSize = function (size) {
  3713. // convert font size into current unit system
  3714. if (apiMode === ApiMode.ADVANCED) {
  3715. activeFontSize = size / k;
  3716. } else {
  3717. activeFontSize = size;
  3718. }
  3719. out("/" + activeFontKey + " " + activeFontSize + " Tf");
  3720. return this;
  3721. };
  3722. /**
  3723. * @return {number}
  3724. * @methodOf jsPDF#
  3725. * @name getFontSize
  3726. */
  3727. API.getFontSize = function () {
  3728. if (apiMode === ApiMode.COMPAT) {
  3729. return activeFontSize;
  3730. } else {
  3731. return activeFontSize * k;
  3732. }
  3733. };
  3734. /**
  3735. * Sets text font face, variant for upcoming text elements.
  3736. * See output of jsPDF.getFontList() for possible font names, styles.
  3737. *
  3738. * @param {string} fontName Font name or family. Example: "times"
  3739. * @param {string} fontStyle Font style or variant. Example: "italic"
  3740. * @function
  3741. * @instance
  3742. * @returns {jsPDF}
  3743. * @methodOf jsPDF#
  3744. * @name setFont
  3745. */
  3746. API.setFont = function (fontName, fontStyle) {
  3747. activeFontKey = _getFont(fontName, fontStyle); // if font is not found, the above line blows up and we never go further
  3748. out("/" + activeFontKey + " " + activeFontSize + " Tf");
  3749. return this;
  3750. };
  3751. /**
  3752. * Switches font style or variant for upcoming text elements,
  3753. * while keeping the font face or family same.
  3754. * See output of jsPDF.getFontList() for possible font names, styles.
  3755. *
  3756. * @param {string} style Font style or variant. Example: "italic"
  3757. * @function
  3758. * @instance
  3759. * @returns {jsPDF}
  3760. * @methodOf jsPDF#
  3761. * @name setFontStyle
  3762. */
  3763. API.setFontStyle = API.setFontType = function (style) {
  3764. activeFontKey = _getFont(undefined, style); // if font is not found, the above line blows up and we never go further
  3765. out("/" + activeFontKey + " " + activeFontSize + " Tf");
  3766. return this;
  3767. };
  3768. /**
  3769. * Returns an object - a tree of fontName to fontStyle relationships available to
  3770. * active PDF document.
  3771. *
  3772. * @public
  3773. * @function
  3774. * @instance
  3775. * @returns {Object} Like {'times':['normal', 'italic', ... ], 'arial':['normal', 'bold', ... ], ... }
  3776. * @methodOf jsPDF#
  3777. * @name getFontList
  3778. */
  3779. API.getFontList = function () {
  3780. // TODO: iterate over fonts array or return copy of fontmap instead in case more are ever added.
  3781. var list = {},
  3782. fontName,
  3783. fontStyle,
  3784. tmp;
  3785. for (fontName in fontmap) {
  3786. if (fontmap.hasOwnProperty(fontName)) {
  3787. list[fontName] = tmp = [];
  3788. for (fontStyle in fontmap[fontName]) {
  3789. if (fontmap[fontName].hasOwnProperty(fontStyle)) {
  3790. tmp.push(fontStyle);
  3791. }
  3792. }
  3793. }
  3794. }
  3795. return list;
  3796. };
  3797. /**
  3798. * Add a custom font to the current instance.
  3799. *
  3800. * @param {String} postScriptName name of the Font. Example: "Menlo-Regular"
  3801. * @param {String} fontName of font-family from @font-face definition. Example: "Menlo Regular"
  3802. * @param {String} fontStyle style. Example: "normal"
  3803. * @function
  3804. * @instance
  3805. * @methodOf jsPDF
  3806. * @name addFont
  3807. */
  3808. API.addFont = function (postScriptName, fontName, fontStyle, encoding) {
  3809. encoding = encoding || "Identity-H";
  3810. addFont.call(this, postScriptName, fontName, fontStyle, encoding);
  3811. };
  3812. /**
  3813. * Sets line width for upcoming lines.
  3814. *
  3815. * @param {number} width Line width (in units declared at inception of PDF document)
  3816. * @function
  3817. * @instance
  3818. * @returns {jsPDF}
  3819. * @methodOf jsPDF#
  3820. * @name setLineWidth
  3821. */
  3822. API.setLineWidth = function (width) {
  3823. out(scaleByK(width).toFixed(2) + " w");
  3824. return this;
  3825. };
  3826. /**
  3827. * Sets the stroke color for upcoming elements.
  3828. *
  3829. * Depending on the number of arguments given, Gray, RGB, or CMYK
  3830. * color space is implied.
  3831. *
  3832. * When only ch1 is given, "Gray" color space is implied and it
  3833. * must be a value in the range from 0.00 (solid black) to to 1.00 (white)
  3834. * if values are communicated as String types, or in range from 0 (black)
  3835. * to 255 (white) if communicated as Number type.
  3836. * The RGB-like 0-255 range is provided for backward compatibility.
  3837. *
  3838. * When only ch1,ch2,ch3 are given, "RGB" color space is implied and each
  3839. * value must be in the range from 0.00 (minimum intensity) to to 1.00
  3840. * (max intensity) if values are communicated as String types, or
  3841. * from 0 (min intensity) to to 255 (max intensity) if values are communicated
  3842. * as Number types.
  3843. * The RGB-like 0-255 range is provided for backward compatibility.
  3844. *
  3845. * When ch1,ch2,ch3,ch4 are given, "CMYK" color space is implied and each
  3846. * value must be a in the range from 0.00 (0% concentration) to to
  3847. * 1.00 (100% concentration)
  3848. *
  3849. * Because JavaScript treats fixed point numbers badly (rounds to
  3850. * floating point nearest to binary representation) it is highly advised to
  3851. * communicate the fractional numbers as String types, not JavaScript Number type.
  3852. *
  3853. * @param {Number|String} ch1 Color channel value or {string} ch1 color value in hexadecimal, example: '#FFFFFF'
  3854. * @param {Number|String} ch2 Color channel value
  3855. * @param {Number|String} ch3 Color channel value
  3856. * @param {Number|String} ch4 Color channel value
  3857. *
  3858. * @function
  3859. * @instance
  3860. * @returns {jsPDF}
  3861. * @methodOf jsPDF#
  3862. * @name setDrawColor
  3863. */
  3864. API.setDrawColor = function (ch1, ch2, ch3, ch4) {
  3865. var options = {
  3866. ch1: ch1,
  3867. ch2: ch2,
  3868. ch3: ch3,
  3869. ch4: ch4,
  3870. pdfColorType: "draw",
  3871. precision: 2
  3872. };
  3873. out(generateColorString(options));
  3874. return this;
  3875. };
  3876. /**
  3877. * Sets the fill color for upcoming elements.
  3878. *
  3879. * Depending on the number of arguments given, Gray, RGB, or CMYK
  3880. * color space is implied.
  3881. *
  3882. * When only ch1 is given, "Gray" color space is implied and it
  3883. * must be a value in the range from 0.00 (solid black) to to 1.00 (white)
  3884. * if values are communicated as String types, or in range from 0 (black)
  3885. * to 255 (white) if communicated as Number type.
  3886. * The RGB-like 0-255 range is provided for backward compatibility.
  3887. *
  3888. * When only ch1,ch2,ch3 are given, "RGB" color space is implied and each
  3889. * value must be in the range from 0.00 (minimum intensity) to to 1.00
  3890. * (max intensity) if values are communicated as String types, or
  3891. * from 0 (min intensity) to to 255 (max intensity) if values are communicated
  3892. * as Number types.
  3893. * The RGB-like 0-255 range is provided for backward compatibility.
  3894. *
  3895. * When ch1,ch2,ch3,ch4 are given, "CMYK" color space is implied and each
  3896. * value must be a in the range from 0.00 (0% concentration) to to
  3897. * 1.00 (100% concentration)
  3898. *
  3899. * Because JavaScript treats fixed point numbers badly (rounds to
  3900. * floating point nearest to binary representation) it is highly advised to
  3901. * communicate the fractional numbers as String types, not JavaScript Number type.
  3902. *
  3903. * @param {Number|String} ch1 Color channel value or {string} ch1 color value in hexadecimal, example: '#FFFFFF'
  3904. * @param {Number|String} ch2 Color channel value
  3905. * @param {Number|String} ch3 Color channel value
  3906. * @param {Number|String} ch4 Color channel value
  3907. *
  3908. * @function
  3909. * @instance
  3910. * @returns {jsPDF}
  3911. * @methodOf jsPDF#
  3912. * @name setFillColor
  3913. */
  3914. API.setFillColor = function (ch1, ch2, ch3, ch4) {
  3915. var options = {
  3916. ch1: ch1,
  3917. ch2: ch2,
  3918. ch3: ch3,
  3919. ch4: ch4,
  3920. pdfColorType: "fill",
  3921. precision: 2
  3922. };
  3923. out(generateColorString(options));
  3924. return this;
  3925. };
  3926. /**
  3927. * Sets the text color for upcoming elements.
  3928. *
  3929. * Depending on the number of arguments given, Gray, RGB, or CMYK
  3930. * color space is implied.
  3931. *
  3932. * When only ch1 is given, "Gray" color space is implied and it
  3933. * must be a value in the range from 0.00 (solid black) to to 1.00 (white)
  3934. * if values are communicated as String types, or in range from 0 (black)
  3935. * to 255 (white) if communicated as Number type.
  3936. * The RGB-like 0-255 range is provided for backward compatibility.
  3937. *
  3938. * When only ch1,ch2,ch3 are given, "RGB" color space is implied and each
  3939. * value must be in the range from 0.00 (minimum intensity) to to 1.00
  3940. * (max intensity) if values are communicated as String types, or
  3941. * from 0 (min intensity) to to 255 (max intensity) if values are communicated
  3942. * as Number types.
  3943. * The RGB-like 0-255 range is provided for backward compatibility.
  3944. *
  3945. * When ch1,ch2,ch3,ch4 are given, "CMYK" color space is implied and each
  3946. * value must be a in the range from 0.00 (0% concentration) to to
  3947. * 1.00 (100% concentration)
  3948. *
  3949. * Because JavaScript treats fixed point numbers badly (rounds to
  3950. * floating point nearest to binary representation) it is highly advised to
  3951. * communicate the fractional numbers as String types, not JavaScript Number type.
  3952. *
  3953. * @param {Number|String} ch1 Color channel value or {string} ch1 color value in hexadecimal, example: '#FFFFFF'
  3954. * @param {Number|String} ch2 Color channel value
  3955. * @param {Number|String} ch3 Color channel value
  3956. * @param {Number|String} ch4 Color channel value
  3957. *
  3958. * @function
  3959. * @instance
  3960. * @returns {jsPDF}
  3961. * @methodOf jsPDF#
  3962. * @name setTextColor
  3963. */
  3964. API.setTextColor = function (ch1, ch2, ch3, ch4) {
  3965. var options = {
  3966. ch1: ch1,
  3967. ch2: ch2,
  3968. ch3: ch3,
  3969. ch4: ch4,
  3970. pdfColorType: "text",
  3971. precision: 3
  3972. };
  3973. textColor = generateColorString(options);
  3974. return this;
  3975. };
  3976. /**
  3977. * Initializes the default character set that the user wants to be global..
  3978. *
  3979. * @param {number} charSpace
  3980. * @function
  3981. * @instance
  3982. * @returns {jsPDF} jsPDF-instance
  3983. * @methodOf jsPDF
  3984. * @name setCharSpace
  3985. */
  3986. API.setCharSpace = function (charSpace) {
  3987. if (apiMode === ApiMode.COMPAT) {
  3988. activeCharSpace = charSpace;
  3989. } else if (apiMode === ApiMode.ADVANCED) {
  3990. activeCharSpace = charSpace / k;
  3991. }
  3992. return this;
  3993. };
  3994. /**
  3995. * Initializes the default character set that the user wants to be global..
  3996. *
  3997. * @param {boolean} boolean
  3998. * @function
  3999. * @instance
  4000. * @returns {jsPDF} jsPDF-instance
  4001. * @methodOf jsPDF
  4002. * @name setR2L
  4003. */
  4004. API.setR2L = function (boolean) {
  4005. R2L = boolean;
  4006. return this;
  4007. };
  4008. /**
  4009. * Sets a either previously added {@link GState} (via {@link addGState}) or a new {@link GState}.
  4010. * @param {String|GState} gState If type is string, a previously added GState is used, if type is GState
  4011. * it will be added before use.
  4012. * @function
  4013. * @returns {jsPDF}
  4014. * @methodOf jsPDF#
  4015. * @name setGState
  4016. */
  4017. API.setGState = function (gState) {
  4018. if (typeof gState === "string") {
  4019. gState = gStates[gStatesMap[gState]];
  4020. } else {
  4021. gState = addGState(null, gState);
  4022. }
  4023. if (!gState.equals(activeGState)) {
  4024. out("/" + gState.id + " gs");
  4025. activeGState = gState;
  4026. }
  4027. };
  4028. /**
  4029. * Is an Object providing a mapping from human-readable to
  4030. * integer flag values designating the varieties of line cap
  4031. * and join styles.
  4032. *
  4033. * @fieldOf jsPDF#
  4034. * @name CapJoinStyles
  4035. */
  4036. API.CapJoinStyles = {
  4037. 0: 0,
  4038. butt: 0,
  4039. but: 0,
  4040. miter: 0,
  4041. 1: 1,
  4042. round: 1,
  4043. rounded: 1,
  4044. circle: 1,
  4045. 2: 2,
  4046. projecting: 2,
  4047. project: 2,
  4048. square: 2,
  4049. bevel: 2
  4050. };
  4051. /**
  4052. * Sets the line cap styles
  4053. * See {jsPDF.CapJoinStyles} for variants
  4054. *
  4055. * @param {String|Number} style A string or number identifying the type of line cap
  4056. * @function
  4057. * @instance
  4058. * @returns {jsPDF}
  4059. * @methodOf jsPDF#
  4060. * @name setLineCap
  4061. */
  4062. API.setLineCap = function (style) {
  4063. var id = this.CapJoinStyles[style];
  4064. if (id === undefined) {
  4065. throw new Error("Line cap style of '" + style + "' is not recognized. See or extend .CapJoinStyles property for valid styles");
  4066. }
  4067. lineCapID = id;
  4068. out(id + " J");
  4069. return this;
  4070. };
  4071. /**
  4072. * Sets the line join styles
  4073. * See {jsPDF.CapJoinStyles} for variants
  4074. *
  4075. * @param {String|Number} style A string or number identifying the type of line join
  4076. * @function
  4077. * @instance
  4078. * @returns {jsPDF}
  4079. * @methodOf jsPDF#
  4080. * @name setLineJoin
  4081. */
  4082. API.setLineJoin = function (style) {
  4083. var id = this.CapJoinStyles[style];
  4084. if (id === undefined) {
  4085. throw new Error("Line join style of '" + style + "' is not recognized. See or extend .CapJoinStyles property for valid styles");
  4086. }
  4087. lineJoinID = id;
  4088. out(id + " j");
  4089. return this;
  4090. };
  4091. /**
  4092. * Sets the miter limit.
  4093. * @param {number} miterLimit
  4094. * @function
  4095. * @returns {jsPDF}
  4096. * @methodOf jsPDF#
  4097. * @name setMiterLimit
  4098. */
  4099. API.setLineMiterLimit = function (miterLimit) {
  4100. out(hpf(miterLimit) + " M");
  4101. return this;
  4102. };
  4103. /**
  4104. * Sets the line dash pattern.
  4105. * @param {Array<number>} array An array containing 0-2 numbers. The first number sets the length of the
  4106. * dashes, the second number the length of the gaps. If the second number is missing, the gaps are considered
  4107. * to be as long as the dashes. An empty array means solid, unbroken lines.
  4108. * @param phase The phase lines start with.
  4109. * @function
  4110. * @returns {jsPDF}
  4111. * @methodOf jsPDF#
  4112. * @name setLineDashPattern
  4113. */
  4114. API.setLineDashPattern = function (array, phase) {
  4115. out(["[" + (array[0] !== undefined ? array[0] : ""), (array[1] !== undefined ? array[1] : "") + "]", phase, "d"].join(" "));
  4116. return this;
  4117. };
  4118. /**
  4119. * Generates the PDF document.
  4120. *
  4121. * If `type` argument is undefined, output is raw body of resulting PDF returned as a string.
  4122. *
  4123. * @param {string} type A string identifying one of the possible output types.
  4124. * @param {Object} options An object providing some additional signalling to PDF generator.
  4125. *
  4126. * @function
  4127. * @instance
  4128. * @returns {jsPDF}
  4129. * @memberOf jsPDF
  4130. * @name output
  4131. */
  4132. API.output = _output;
  4133. /**
  4134. * Saves as PDF document. An alias of jsPDF.output('save', 'filename.pdf')
  4135. *
  4136. * @memberOf jsPDF
  4137. * @name save
  4138. * @function
  4139. * @instance
  4140. * @param {string} filename The filename including extension.
  4141. * @returns {jsPDF} jsPDF-instance
  4142. */
  4143. API.save = function (filename) {
  4144. API.output("save", filename);
  4145. }; // applying plugins (more methods) ON TOP of built-in API.
  4146. // this is intentional as we allow plugins to override
  4147. // built-ins
  4148. for (var plugin in jsPDF.API) {
  4149. if (jsPDF.API.hasOwnProperty(plugin)) {
  4150. if (plugin === "events" && jsPDF.API.events.length) {
  4151. (function (events, newEvents) {
  4152. // jsPDF.API.events is a JS Array of Arrays
  4153. // where each Array is a pair of event name, handler
  4154. // Events were added by plugins to the jsPDF instantiator.
  4155. // These are always added to the new instance and some ran
  4156. // during instantiation.
  4157. var eventname, handler_and_args, i;
  4158. for (i = newEvents.length - 1; i !== -1; i--) {
  4159. // subscribe takes 3 args: 'topic', function, runonce_flag
  4160. // if undefined, runonce is false.
  4161. // users can attach callback directly,
  4162. // or they can attach an array with [callback, runonce_flag]
  4163. // that's what the "apply" magic is for below.
  4164. eventname = newEvents[i][0];
  4165. handler_and_args = newEvents[i][1];
  4166. events.subscribe.apply(events, [eventname].concat(typeof handler_and_args === "function" ? [handler_and_args] : handler_and_args));
  4167. }
  4168. })(events, jsPDF.API.events);
  4169. } else {
  4170. API[plugin] = jsPDF.API[plugin];
  4171. }
  4172. }
  4173. } //////////////////////////////////////////////////////
  4174. // continuing initialization of jsPDF Document object
  4175. //////////////////////////////////////////////////////
  4176. // Add the first page automatically
  4177. addFonts();
  4178. activeFontKey = "F1";
  4179. _addPage(format, orientation);
  4180. events.publish("initialized");
  4181. return API;
  4182. }
  4183. /**
  4184. * jsPDF.API is a STATIC property of jsPDF class.
  4185. * jsPDF.API is an object you can add methods and properties to.
  4186. * The methods / properties you add will show up in new jsPDF objects.
  4187. *
  4188. * One property is prepopulated. It is the 'events' Object. Plugin authors can add topics,
  4189. * callbacks to this object. These will be reassigned to all new instances of jsPDF.
  4190. *
  4191. * @static
  4192. * @public
  4193. * @memberOf jsPDF
  4194. * @name API
  4195. *
  4196. * @example
  4197. * jsPDF.API.mymethod = function(){
  4198. * // 'this' will be ref to internal API object. see jsPDF source
  4199. * // , so you can refer to built-in methods like so:
  4200. * // this.line(....)
  4201. * // this.text(....)
  4202. * }
  4203. * var pdfdoc = new jsPDF()
  4204. * pdfdoc.mymethod() // <- !!!!!!
  4205. */
  4206. jsPDF.API = {
  4207. events: []
  4208. };
  4209. /**
  4210. * The version of jsPDF
  4211. * @name version
  4212. * @type {string}
  4213. * @memberOf jsPDF
  4214. */
  4215. jsPDF.version = "0.0.0";
  4216. if (typeof define === "function" && define.amd) {
  4217. define(function () {
  4218. return jsPDF;
  4219. });
  4220. } else if (typeof module !== "undefined" && module.exports) {
  4221. module.exports = jsPDF;
  4222. module.exports.jsPDF = jsPDF;
  4223. } else {
  4224. global.jsPDF = jsPDF;
  4225. }
  4226. return jsPDF;
  4227. }(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
  4228. // while `this` is nsIContentFrameMessageManager
  4229. // with an attribute `content` that corresponds to the window
  4230. /**
  4231. * @license
  4232. * Copyright (c) 2016 Alexander Weidt,
  4233. * https://github.com/BiggA94
  4234. *
  4235. * Licensed under the MIT License. http://opensource.org/licenses/mit-license
  4236. */
  4237. /**
  4238. * jsPDF AcroForm Plugin
  4239. *
  4240. * @name AcroForm
  4241. * @module
  4242. */
  4243. (function (jsPDFAPI, globalObj) {
  4244. var scope;
  4245. var pageHeight;
  4246. var scaleFactor = 1;
  4247. var inherit = function inherit(child, parent) {
  4248. child.prototype = Object.create(parent.prototype);
  4249. child.prototype.constructor = child;
  4250. };
  4251. var scale = function scale(x) {
  4252. return x * (scaleFactor / 1); // 1 = (96 / 72)
  4253. };
  4254. var createFormXObject = function createFormXObject(formObject) {
  4255. var xobj = new AcroFormXObject();
  4256. var height = AcroFormAppearance.internal.getHeight(formObject) || 0;
  4257. var width = AcroFormAppearance.internal.getWidth(formObject) || 0;
  4258. xobj.BBox = [0, 0, width.toFixed(2), height.toFixed(2)];
  4259. return xobj;
  4260. };
  4261. var setBitPosition = function setBitPosition(variable, position, value) {
  4262. variable = variable || 0;
  4263. value = value || 1;
  4264. var bitMask = 1;
  4265. bitMask = bitMask << position - 1;
  4266. if (value == 1) {
  4267. // Set the Bit to 1
  4268. var variable = variable | bitMask;
  4269. } else {
  4270. // Set the Bit to 0
  4271. var variable = variable & ~bitMask;
  4272. }
  4273. return variable;
  4274. };
  4275. /**
  4276. * Calculating the Ff entry:
  4277. *
  4278. * The Ff entry contains flags, that have to be set bitwise In the Following
  4279. * the number in the Comment is the BitPosition
  4280. */
  4281. var calculateFlagsOnOptions = function calculateFlagsOnOptions(flags, opts, PDFVersion) {
  4282. var PDFVersion = PDFVersion || 1.3;
  4283. var flags = flags || 0; // 1, readOnly
  4284. if (opts.readOnly == true) {
  4285. flags = setBitPosition(flags, 1);
  4286. } // 2, required
  4287. if (opts.required == true) {
  4288. flags = setBitPosition(flags, 2);
  4289. } // 4, noExport
  4290. if (opts.noExport == true) {
  4291. flags = setBitPosition(flags, 3);
  4292. } // 13, multiline
  4293. if (opts.multiline == true) {
  4294. flags = setBitPosition(flags, 13);
  4295. } // 14, Password
  4296. if (opts.password) {
  4297. flags = setBitPosition(flags, 14);
  4298. } // 15, NoToggleToOff (Radio buttons only
  4299. if (opts.noToggleToOff) {
  4300. flags = setBitPosition(flags, 15);
  4301. } // 16, Radio
  4302. if (opts.radio) {
  4303. flags = setBitPosition(flags, 16);
  4304. } // 17, Pushbutton
  4305. if (opts.pushbutton) {
  4306. flags = setBitPosition(flags, 17);
  4307. } // 18, Combo (If not set, the choiceField is a listBox!!)
  4308. if (opts.combo) {
  4309. flags = setBitPosition(flags, 18);
  4310. } // 19, Edit
  4311. if (opts.edit) {
  4312. flags = setBitPosition(flags, 19);
  4313. } // 20, Sort
  4314. if (opts.sort) {
  4315. flags = setBitPosition(flags, 20);
  4316. } // 21, FileSelect, PDF 1.4...
  4317. if (opts.fileSelect && PDFVersion >= 1.4) {
  4318. flags = setBitPosition(flags, 21);
  4319. } // 22, MultiSelect (PDF 1.4)
  4320. if (opts.multiSelect && PDFVersion >= 1.4) {
  4321. flags = setBitPosition(flags, 22);
  4322. } // 23, DoNotSpellCheck (PDF 1.4)
  4323. if (opts.doNotSpellCheck && PDFVersion >= 1.4) {
  4324. flags = setBitPosition(flags, 23);
  4325. } // 24, DoNotScroll (PDF 1.4)
  4326. if (opts.doNotScroll == true && PDFVersion >= 1.4) {
  4327. flags = setBitPosition(flags, 24);
  4328. } // 25, RichText (PDF 1.4)
  4329. if (opts.richText && PDFVersion >= 1.4) {
  4330. flags = setBitPosition(flags, 25);
  4331. }
  4332. return flags;
  4333. };
  4334. var calculateCoordinates = function calculateCoordinates(args) {
  4335. var x = args[0];
  4336. var y = args[1];
  4337. var w = args[2];
  4338. var h = args[3];
  4339. var coordinates = {};
  4340. if (Array.isArray(x)) {
  4341. x[0] = scale(x[0]);
  4342. x[1] = scale(x[1]);
  4343. x[2] = scale(x[2]);
  4344. x[3] = scale(x[3]);
  4345. } else {
  4346. x = scale(x);
  4347. y = scale(y);
  4348. w = scale(w);
  4349. h = scale(h);
  4350. }
  4351. coordinates.lowerLeft_X = x || 0;
  4352. coordinates.lowerLeft_Y = scale(pageHeight) - y - h || 0;
  4353. coordinates.upperRight_X = x + w || 0;
  4354. coordinates.upperRight_Y = scale(pageHeight) - y || 0;
  4355. return [coordinates.lowerLeft_X.toFixed(2), coordinates.lowerLeft_Y.toFixed(2), coordinates.upperRight_X.toFixed(2), coordinates.upperRight_Y.toFixed(2)];
  4356. };
  4357. var calculateAppearanceStream = function calculateAppearanceStream(formObject) {
  4358. if (formObject.appearanceStreamContent) {
  4359. // If appearanceStream is already set, use it
  4360. return formObject.appearanceStreamContent;
  4361. }
  4362. if (!formObject.V && !formObject.DV) {
  4363. return;
  4364. } // else calculate it
  4365. var stream = [];
  4366. var text = formObject.V || formObject.DV;
  4367. var calcRes = calculateX(formObject, text);
  4368. stream.push("/Tx BMC");
  4369. stream.push("q");
  4370. stream.push("/F1 " + calcRes.fontSize.toFixed(2) + " Tf");
  4371. stream.push("1 0 0 1 0 0 Tm"); // Text Matrix
  4372. stream.push("BT"); // Begin Text
  4373. stream.push(calcRes.text);
  4374. stream.push("ET"); // End Text
  4375. stream.push("Q");
  4376. stream.push("EMC");
  4377. var appearanceStreamContent = new createFormXObject(formObject);
  4378. appearanceStreamContent.stream = stream.join("\n");
  4379. return appearanceStreamContent;
  4380. };
  4381. var calculateX = function calculateX(formObject, text, font, maxFontSize) {
  4382. var maxFontSize = maxFontSize || 12;
  4383. var font = font || "helvetica";
  4384. var returnValue = {
  4385. text: "",
  4386. fontSize: ""
  4387. }; // Remove Brackets
  4388. text = text.substr(0, 1) == "(" ? text.substr(1) : text;
  4389. text = text.substr(text.length - 1) == ")" ? text.substr(0, text.length - 1) : text; // split into array of words
  4390. var textSplit = text.split(" ");
  4391. var fontSize = maxFontSize; // The Starting fontSize (The Maximum)
  4392. var lineSpacing = 2;
  4393. var borderPadding = 2;
  4394. var height = AcroFormAppearance.internal.getHeight(formObject) || 0;
  4395. height = height < 0 ? -height : height;
  4396. var width = AcroFormAppearance.internal.getWidth(formObject) || 0;
  4397. width = width < 0 ? -width : width;
  4398. var isSmallerThanWidth = function isSmallerThanWidth(i, lastLine, fontSize) {
  4399. if (i + 1 < textSplit.length) {
  4400. var tmp = lastLine + " " + textSplit[i + 1];
  4401. var TextWidth = calculateFontSpace(tmp, fontSize + "px", font).width;
  4402. var FieldWidth = width - 2 * borderPadding;
  4403. return TextWidth <= FieldWidth;
  4404. } else {
  4405. return false;
  4406. }
  4407. };
  4408. fontSize++;
  4409. FontSize: while (true) {
  4410. var text = "";
  4411. fontSize--;
  4412. var textHeight = calculateFontSpace("3", fontSize + "px", font).height;
  4413. var startY = formObject.multiline ? height - fontSize : (height - textHeight) / 2;
  4414. startY += lineSpacing;
  4415. var startX = -borderPadding;
  4416. var lastY = startY;
  4417. var firstWordInLine = 0,
  4418. lastWordInLine = 0;
  4419. var lastLength = 0;
  4420. if (fontSize <= 0) {
  4421. // In case, the Text doesn't fit at all
  4422. fontSize = 12;
  4423. text = "(...) Tj\n";
  4424. text += "% Width of Text: " + calculateFontSpace(text, "1px").width + ", FieldWidth:" + width + "\n";
  4425. break;
  4426. }
  4427. lastLength = calculateFontSpace(textSplit[0] + " ", fontSize + "px", font).width;
  4428. var lastLine = "";
  4429. var lineCount = 0;
  4430. Line: for (var i in textSplit) {
  4431. if (textSplit.hasOwnProperty(i)) {
  4432. lastLine += textSplit[i] + " "; // Remove last blank
  4433. lastLine = lastLine.substr(lastLine.length - 1) == " " ? lastLine.substr(0, lastLine.length - 1) : lastLine;
  4434. var key = parseInt(i);
  4435. lastLength = calculateFontSpace(lastLine + " ", fontSize + "px", font).width;
  4436. var nextLineIsSmaller = isSmallerThanWidth(key, lastLine, fontSize);
  4437. var isLastWord = i >= textSplit.length - 1;
  4438. if (nextLineIsSmaller && !isLastWord) {
  4439. lastLine += " ";
  4440. continue; // Line
  4441. } else if (!nextLineIsSmaller && !isLastWord) {
  4442. if (!formObject.multiline) {
  4443. continue FontSize;
  4444. } else {
  4445. if ((textHeight + lineSpacing) * (lineCount + 2) + lineSpacing > height) {
  4446. // If the Text is higher than the
  4447. // FieldObject
  4448. continue FontSize;
  4449. }
  4450. lastWordInLine = key; // go on
  4451. }
  4452. } else if (isLastWord) {
  4453. lastWordInLine = key;
  4454. } else {
  4455. if (formObject.multiline && (textHeight + lineSpacing) * (lineCount + 2) + lineSpacing > height) {
  4456. // If the Text is higher than the FieldObject
  4457. continue FontSize;
  4458. }
  4459. }
  4460. var line = "";
  4461. for (var x = firstWordInLine; x <= lastWordInLine; x++) {
  4462. line += textSplit[x] + " ";
  4463. } // Remove last blank
  4464. line = line.substr(line.length - 1) == " " ? line.substr(0, line.length - 1) : line; // lastLength -= blankSpace.width;
  4465. lastLength = calculateFontSpace(line, fontSize + "px", font).width; // Calculate startX
  4466. switch (formObject.Q) {
  4467. case 2:
  4468. // Right justified
  4469. startX = width - lastLength - borderPadding;
  4470. break;
  4471. case 1:
  4472. // Q = 1 := Text-Alignment: Center
  4473. startX = (width - lastLength) / 2;
  4474. break;
  4475. case 0:
  4476. default:
  4477. startX = borderPadding;
  4478. break;
  4479. }
  4480. text += startX.toFixed(2) + " " + lastY.toFixed(2) + " Td\n";
  4481. text += "(" + line + ") Tj\n"; // reset X in PDF
  4482. text += -startX.toFixed(2) + " 0 Td\n"; // After a Line, adjust y position
  4483. lastY = -(fontSize + lineSpacing);
  4484. lastLength = 0;
  4485. firstWordInLine = lastWordInLine + 1;
  4486. lineCount++;
  4487. lastLine = "";
  4488. continue Line;
  4489. }
  4490. }
  4491. break;
  4492. }
  4493. returnValue.text = text;
  4494. returnValue.fontSize = fontSize;
  4495. return returnValue;
  4496. };
  4497. /**
  4498. * Small workaround for calculating the TextMetric approximately.
  4499. *
  4500. * @param text
  4501. * @param fontsize
  4502. * @returns {TextMetrics} (Has Height and Width)
  4503. */
  4504. var calculateFontSpace = function calculateFontSpace(text, fontSize, fontType) {
  4505. fontType = fontType || "helvetica";
  4506. var font = scope.internal.getFont(fontType);
  4507. var width = scope.getStringUnitWidth(text, {
  4508. font: font,
  4509. fontSize: parseFloat(fontSize),
  4510. charSpace: 0
  4511. }) * parseFloat(fontSize);
  4512. var height = scope.getStringUnitWidth("3", {
  4513. font: font,
  4514. fontSize: parseFloat(fontSize),
  4515. charSpace: 0
  4516. }) * parseFloat(fontSize) * 1.5;
  4517. var result = {
  4518. height: height,
  4519. width: width
  4520. };
  4521. return result;
  4522. };
  4523. var acroformPluginTemplate = {
  4524. fields: [],
  4525. xForms: [],
  4526. /**
  4527. * acroFormDictionaryRoot contains information about the AcroForm
  4528. * Dictionary 0: The Event-Token, the AcroFormDictionaryCallback has
  4529. * 1: The Object ID of the Root
  4530. */
  4531. acroFormDictionaryRoot: null,
  4532. /**
  4533. * After the PDF gets evaluated, the reference to the root has to be
  4534. * reset, this indicates, whether the root has already been printed
  4535. * out
  4536. */
  4537. printedOut: false,
  4538. internal: null,
  4539. isInitialized: false
  4540. };
  4541. var annotReferenceCallback = function annotReferenceCallback() {
  4542. var fields = scope.internal.acroformPlugin.acroFormDictionaryRoot.Fields;
  4543. for (var i in fields) {
  4544. if (fields.hasOwnProperty(i)) {
  4545. var formObject = fields[i]; // add Annot Reference!
  4546. if (formObject.hasAnnotation) {
  4547. // If theres an Annotation Widget in the Form Object, put the
  4548. // Reference in the /Annot array
  4549. createAnnotationReference.call(scope, formObject);
  4550. }
  4551. }
  4552. }
  4553. };
  4554. var putForm = function putForm(formObject) {
  4555. if (scope.internal.acroformPlugin.printedOut) {
  4556. scope.internal.acroformPlugin.printedOut = false;
  4557. scope.internal.acroformPlugin.acroFormDictionaryRoot = null;
  4558. }
  4559. if (!scope.internal.acroformPlugin.acroFormDictionaryRoot) {
  4560. initializeAcroForm.call(scope);
  4561. }
  4562. scope.internal.acroformPlugin.acroFormDictionaryRoot.Fields.push(formObject);
  4563. };
  4564. /**
  4565. * Create the Reference to the widgetAnnotation, so that it gets referenced
  4566. * in the Annot[] int the+ (Requires the Annotation Plugin)
  4567. */
  4568. var createAnnotationReference = function createAnnotationReference(object) {
  4569. var options = {
  4570. type: "reference",
  4571. object: object
  4572. };
  4573. scope.annotationPlugin.annotations[scope.internal.getPageInfo(object.page).pageNumber].push(options);
  4574. }; // Callbacks
  4575. var putCatalogCallback = function putCatalogCallback() {
  4576. // Put reference to AcroForm to DocumentCatalog
  4577. if (typeof scope.internal.acroformPlugin.acroFormDictionaryRoot != "undefined") {
  4578. // for safety, shouldn't normally be the case
  4579. scope.internal.write("/AcroForm " + scope.internal.acroformPlugin.acroFormDictionaryRoot.objId + " " + 0 + " R");
  4580. } else {
  4581. console.log("Root missing...");
  4582. }
  4583. };
  4584. /**
  4585. * Adds /Acroform X 0 R to Document Catalog, and creates the AcroForm
  4586. * Dictionary
  4587. */
  4588. var AcroFormDictionaryCallback = function AcroFormDictionaryCallback() {
  4589. // Remove event
  4590. scope.internal.events.unsubscribe(scope.internal.acroformPlugin.acroFormDictionaryRoot._eventID);
  4591. delete scope.internal.acroformPlugin.acroFormDictionaryRoot._eventID;
  4592. scope.internal.acroformPlugin.printedOut = true;
  4593. };
  4594. /**
  4595. * Creates the single Fields and writes them into the Document
  4596. *
  4597. * If fieldArray is set, use the fields that are inside it instead of the
  4598. * fields from the AcroRoot (for the FormXObjects...)
  4599. */
  4600. var createFieldCallback = function createFieldCallback(fieldArray) {
  4601. var standardFields = !fieldArray;
  4602. if (!fieldArray) {
  4603. // in case there is no fieldArray specified, we want to print out
  4604. // the Fields of the AcroForm
  4605. // Print out Root
  4606. scope.internal.newObjectDeferredBegin(scope.internal.acroformPlugin.acroFormDictionaryRoot.objId);
  4607. scope.internal.out(scope.internal.acroformPlugin.acroFormDictionaryRoot.getString());
  4608. }
  4609. var fieldArray = fieldArray || scope.internal.acroformPlugin.acroFormDictionaryRoot.Kids;
  4610. for (var i in fieldArray) {
  4611. if (fieldArray.hasOwnProperty(i)) {
  4612. var form = fieldArray[i];
  4613. var oldRect = form.Rect;
  4614. if (form.Rect) {
  4615. form.Rect = calculateCoordinates.call(this, form.Rect);
  4616. } // Start Writing the Object
  4617. scope.internal.newObjectDeferredBegin(form.objId);
  4618. var content = form.objId + " 0 obj\n<<\n";
  4619. if (_typeof(form) === "object" && typeof form.getContent === "function") {
  4620. content += form.getContent();
  4621. }
  4622. form.Rect = oldRect;
  4623. if (form.hasAppearanceStream && !form.appearanceStreamContent) {
  4624. // Calculate Appearance
  4625. var appearance = calculateAppearanceStream.call(this, form);
  4626. content += "/AP << /N " + appearance + " >>\n";
  4627. scope.internal.acroformPlugin.xForms.push(appearance);
  4628. } // Assume AppearanceStreamContent is a Array with N,R,D (at least
  4629. // one of them!)
  4630. if (form.appearanceStreamContent) {
  4631. content += "/AP << "; // Iterate over N,R and D
  4632. for (var k in form.appearanceStreamContent) {
  4633. if (form.appearanceStreamContent.hasOwnProperty(k)) {
  4634. var value = form.appearanceStreamContent[k];
  4635. content += "/" + k + " ";
  4636. content += "<< ";
  4637. if (Object.keys(value).length >= 1 || Array.isArray(value)) {
  4638. // appearanceStream is an Array or Object!
  4639. for (var i in value) {
  4640. if (value.hasOwnProperty(i)) {
  4641. var obj = value[i];
  4642. if (typeof obj === "function") {
  4643. // if Function is referenced, call it in order
  4644. // to get the FormXObject
  4645. obj = obj.call(this, form);
  4646. }
  4647. content += "/" + i + " " + obj + " "; // In case the XForm is already used, e.g. OffState
  4648. // of CheckBoxes, don't add it
  4649. if (!(scope.internal.acroformPlugin.xForms.indexOf(obj) >= 0)) scope.internal.acroformPlugin.xForms.push(obj);
  4650. }
  4651. }
  4652. } else {
  4653. var obj = value;
  4654. if (typeof obj === "function") {
  4655. // if Function is referenced, call it in order to
  4656. // get the FormXObject
  4657. obj = obj.call(this, form);
  4658. }
  4659. content += "/" + i + " " + obj + " \n";
  4660. if (!(scope.internal.acroformPlugin.xForms.indexOf(obj) >= 0)) scope.internal.acroformPlugin.xForms.push(obj);
  4661. }
  4662. content += " >>\n";
  4663. }
  4664. } // appearance stream is a normal Object..
  4665. content += ">>\n";
  4666. }
  4667. content += ">>\nendobj\n";
  4668. scope.internal.out(content);
  4669. }
  4670. }
  4671. if (standardFields) {
  4672. createXFormObjectCallback.call(this, scope.internal.acroformPlugin.xForms);
  4673. }
  4674. };
  4675. var createXFormObjectCallback = function createXFormObjectCallback(fieldArray) {
  4676. for (var i in fieldArray) {
  4677. if (fieldArray.hasOwnProperty(i)) {
  4678. var key = i;
  4679. var form = fieldArray[i]; // Start Writing the Object
  4680. scope.internal.newObjectDeferredBegin(form && form.objId);
  4681. var content = "";
  4682. if (_typeof(form) === "object" && typeof form.getString === "function") {
  4683. content = form.getString();
  4684. }
  4685. scope.internal.out(content);
  4686. delete fieldArray[key];
  4687. }
  4688. }
  4689. };
  4690. var initializeAcroForm = function initializeAcroForm() {
  4691. if (this.internal !== undefined && (this.internal.acroformPlugin === undefined || this.internal.acroformPlugin.isInitialized === false)) {
  4692. scope = this;
  4693. AcroFormField.FieldNum = 0;
  4694. this.internal.acroformPlugin = JSON.parse(JSON.stringify(acroformPluginTemplate));
  4695. if (this.internal.acroformPlugin.acroFormDictionaryRoot) {
  4696. // return;
  4697. throw new Error("Exception while creating AcroformDictionary");
  4698. }
  4699. scaleFactor = scope.internal.scaleFactor;
  4700. pageHeight = scope.internal.pageSize.getHeight(); // The Object Number of the AcroForm Dictionary
  4701. scope.internal.acroformPlugin.acroFormDictionaryRoot = new AcroFormDictionary(); // add Callback for creating the AcroForm Dictionary
  4702. scope.internal.acroformPlugin.acroFormDictionaryRoot._eventID = scope.internal.events.subscribe("postPutResources", AcroFormDictionaryCallback);
  4703. scope.internal.events.subscribe("buildDocument", annotReferenceCallback); // buildDocument
  4704. // Register event, that is triggered when the DocumentCatalog is
  4705. // written, in order to add /AcroForm
  4706. scope.internal.events.subscribe("putCatalog", putCatalogCallback); // Register event, that creates all Fields
  4707. scope.internal.events.subscribe("postPutPages", createFieldCallback);
  4708. scope.internal.acroformPlugin.isInitialized = true;
  4709. }
  4710. };
  4711. var arrayToPdfArray = function arrayToPdfArray(array) {
  4712. if (Array.isArray(array)) {
  4713. var content = " [";
  4714. for (var i in array) {
  4715. if (array.hasOwnProperty(i)) {
  4716. var element = array[i].toString();
  4717. content += element;
  4718. content += i < array.length - 1 ? " " : "";
  4719. }
  4720. }
  4721. content += "]";
  4722. return content;
  4723. }
  4724. };
  4725. var toPdfString = function toPdfString(string) {
  4726. string = string || ""; // put Bracket at the Beginning of the String
  4727. if (string.indexOf("(") !== 0) {
  4728. string = "(" + string;
  4729. }
  4730. if (string.substring(string.length - 1) != ")") {
  4731. string += ")";
  4732. }
  4733. return string;
  4734. }; // ##########################
  4735. // Classes
  4736. // ##########################
  4737. var AcroFormPDFObject = function AcroFormPDFObject() {
  4738. // The Object ID in the PDF Object Model
  4739. // todo
  4740. var _objId;
  4741. Object.defineProperty(this, "objId", {
  4742. get: function get() {
  4743. if (!_objId) {
  4744. _objId = scope.internal.newObjectDeferred();
  4745. }
  4746. if (!_objId) {
  4747. console.log("Couldn't create Object ID");
  4748. }
  4749. return _objId;
  4750. },
  4751. configurable: false
  4752. });
  4753. };
  4754. AcroFormPDFObject.prototype.toString = function () {
  4755. return this.objId + " 0 R";
  4756. };
  4757. AcroFormPDFObject.prototype.getString = function () {
  4758. var res = this.objId + " 0 obj\n<<";
  4759. var content = this.getContent();
  4760. res += content + ">>\n";
  4761. if (this.stream) {
  4762. res += "stream\n";
  4763. res += this.stream;
  4764. res += "\nendstream\n";
  4765. }
  4766. res += "endobj\n";
  4767. return res;
  4768. };
  4769. AcroFormPDFObject.prototype.getContent = function () {
  4770. /**
  4771. * Prints out all enumerable Variables from the Object
  4772. *
  4773. * @param fieldObject
  4774. * @returns {string}
  4775. */
  4776. var createContentFromFieldObject = function createContentFromFieldObject(fieldObject) {
  4777. var content = "";
  4778. var keys = Object.keys(fieldObject).filter(function (key) {
  4779. return key != "content" && key != "appearanceStreamContent" && key.substring(0, 1) != "_";
  4780. });
  4781. for (var i in keys) {
  4782. if (keys.hasOwnProperty(i)) {
  4783. var key = keys[i];
  4784. var value = fieldObject[key];
  4785. /*
  4786. * if (key == 'Rect' && value) { value =
  4787. * AcroForm.internal.calculateCoordinates.call(jsPDF.API.acroformPlugin.internal,
  4788. * value); }
  4789. */
  4790. if (value) {
  4791. if (Array.isArray(value)) {
  4792. content += "/" + key + " " + arrayToPdfArray(value) + "\n";
  4793. } else if (value instanceof AcroFormPDFObject) {
  4794. // In case it is a reference to another PDFObject,
  4795. // take the referennce number
  4796. content += "/" + key + " " + value.objId + " 0 R" + "\n";
  4797. } else {
  4798. content += "/" + key + " " + value + "\n";
  4799. }
  4800. }
  4801. }
  4802. }
  4803. return content;
  4804. };
  4805. var object = "";
  4806. object += createContentFromFieldObject(this);
  4807. return object;
  4808. };
  4809. var AcroFormXObject = function AcroFormXObject() {
  4810. AcroFormPDFObject.call(this);
  4811. this.Type = "/XObject";
  4812. this.Subtype = "/Form";
  4813. this.FormType = 1;
  4814. this.BBox;
  4815. this.Matrix;
  4816. this.Resources = "2 0 R";
  4817. this.PieceInfo;
  4818. var _stream;
  4819. Object.defineProperty(this, "Length", {
  4820. enumerable: true,
  4821. get: function get() {
  4822. return _stream !== undefined ? _stream.length : 0;
  4823. }
  4824. });
  4825. Object.defineProperty(this, "stream", {
  4826. enumerable: false,
  4827. set: function set(val) {
  4828. _stream = val.trim();
  4829. },
  4830. get: function get() {
  4831. if (_stream) {
  4832. return _stream;
  4833. } else {
  4834. return null;
  4835. }
  4836. }
  4837. });
  4838. };
  4839. inherit(AcroFormXObject, AcroFormPDFObject); // ##### The Objects, the User can Create:
  4840. var AcroFormDictionary = function AcroFormDictionary() {
  4841. AcroFormPDFObject.call(this);
  4842. var _Kids = [];
  4843. Object.defineProperty(this, "Kids", {
  4844. enumerable: false,
  4845. configurable: true,
  4846. get: function get() {
  4847. if (_Kids.length > 0) {
  4848. return _Kids;
  4849. } else {
  4850. return;
  4851. }
  4852. }
  4853. });
  4854. Object.defineProperty(this, "Fields", {
  4855. enumerable: true,
  4856. configurable: true,
  4857. get: function get() {
  4858. return _Kids;
  4859. }
  4860. }); // Default Appearance
  4861. this.DA;
  4862. };
  4863. inherit(AcroFormDictionary, AcroFormPDFObject); // The Field Object contains the Variables, that every Field needs
  4864. // Rectangle for Appearance: lower_left_X, lower_left_Y, width, height
  4865. var AcroFormField = function AcroFormField() {
  4866. AcroFormPDFObject.call(this);
  4867. var _Rect = null;
  4868. Object.defineProperty(this, "Rect", {
  4869. enumerable: true,
  4870. configurable: false,
  4871. get: function get() {
  4872. if (!_Rect) {
  4873. return;
  4874. }
  4875. var tmp = _Rect; // var calculatedRes =
  4876. // AcroForm.internal.calculateCoordinates(_Rect); // do
  4877. // later!
  4878. return tmp;
  4879. },
  4880. set: function set(val) {
  4881. _Rect = val;
  4882. }
  4883. });
  4884. var _FT = "";
  4885. Object.defineProperty(this, "FT", {
  4886. enumerable: true,
  4887. set: function set(val) {
  4888. _FT = val;
  4889. },
  4890. get: function get() {
  4891. return _FT;
  4892. }
  4893. });
  4894. var _F = 4;
  4895. Object.defineProperty(this, "F", {
  4896. enumerable: true,
  4897. set: function set(val) {
  4898. _F = val;
  4899. },
  4900. get: function get() {
  4901. return _F;
  4902. }
  4903. });
  4904. /**
  4905. * The Partial name of the Field Object. It has to be unique.
  4906. */
  4907. var _T = null;
  4908. Object.defineProperty(this, "T", {
  4909. enumerable: true,
  4910. configurable: false,
  4911. set: function set(val) {
  4912. _T = val;
  4913. },
  4914. get: function get() {
  4915. if (!_T || _T.length < 1) {
  4916. if (this instanceof AcroFormChildClass) {
  4917. // In case of a Child from a Radio´Group, you don't
  4918. // need a FieldName!!!
  4919. return;
  4920. }
  4921. return "(FieldObject" + AcroFormField.FieldNum++ + ")";
  4922. }
  4923. if (_T.substring(0, 1) == "(" && _T.substring(_T.length - 1)) {
  4924. return _T;
  4925. }
  4926. return "(" + _T + ")";
  4927. }
  4928. });
  4929. var _DA = null; // Defines the default appearance (Needed for variable Text)
  4930. Object.defineProperty(this, "DA", {
  4931. enumerable: true,
  4932. get: function get() {
  4933. if (!_DA) {
  4934. return;
  4935. }
  4936. return "(" + _DA + ")";
  4937. },
  4938. set: function set(val) {
  4939. _DA = val;
  4940. }
  4941. });
  4942. var _DV = null; // Defines the default value
  4943. Object.defineProperty(this, "DV", {
  4944. enumerable: true,
  4945. configurable: true,
  4946. get: function get() {
  4947. if (!_DV) {
  4948. return;
  4949. }
  4950. return _DV;
  4951. },
  4952. set: function set(val) {
  4953. _DV = val;
  4954. }
  4955. });
  4956. var _V = null; // Defines the default value
  4957. Object.defineProperty(this, "V", {
  4958. enumerable: true,
  4959. configurable: true,
  4960. get: function get() {
  4961. if (!_V) {
  4962. return;
  4963. }
  4964. return _V;
  4965. },
  4966. set: function set(val) {
  4967. _V = val;
  4968. }
  4969. }); // this.Type = "/Annot";
  4970. // this.Subtype = "/Widget";
  4971. Object.defineProperty(this, "Type", {
  4972. enumerable: true,
  4973. get: function get() {
  4974. return this.hasAnnotation ? "/Annot" : null;
  4975. }
  4976. });
  4977. Object.defineProperty(this, "Subtype", {
  4978. enumerable: true,
  4979. get: function get() {
  4980. return this.hasAnnotation ? "/Widget" : null;
  4981. }
  4982. });
  4983. /**
  4984. *
  4985. * @type {Array}
  4986. */
  4987. this.BG;
  4988. Object.defineProperty(this, "hasAnnotation", {
  4989. enumerable: false,
  4990. get: function get() {
  4991. if (this.Rect || this.BC || this.BG) {
  4992. return true;
  4993. }
  4994. return false;
  4995. }
  4996. });
  4997. Object.defineProperty(this, "hasAppearanceStream", {
  4998. enumerable: false,
  4999. configurable: true,
  5000. writable: true
  5001. });
  5002. Object.defineProperty(this, "page", {
  5003. enumerable: false,
  5004. configurable: true,
  5005. writable: true
  5006. });
  5007. };
  5008. inherit(AcroFormField, AcroFormPDFObject);
  5009. var AcroFormChoiceField = function AcroFormChoiceField() {
  5010. AcroFormField.call(this); // Field Type = Choice Field
  5011. this.FT = "/Ch"; // options
  5012. this.Opt = [];
  5013. this.V = "()"; // Top Index
  5014. this.TI = 0;
  5015. /**
  5016. * Defines, whether the
  5017. *
  5018. * @type {boolean}
  5019. */
  5020. var _combo = false;
  5021. Object.defineProperty(this, "combo", {
  5022. enumerable: false,
  5023. get: function get() {
  5024. return _combo;
  5025. },
  5026. set: function set(val) {
  5027. _combo = val;
  5028. }
  5029. });
  5030. /**
  5031. * Defines, whether the Choice Field is an Edit Field. An Edit Field
  5032. * is automatically an Combo Field.
  5033. */
  5034. Object.defineProperty(this, "edit", {
  5035. enumerable: true,
  5036. set: function set(val) {
  5037. if (val == true) {
  5038. this._edit = true; // ComboBox has to be true
  5039. this.combo = true;
  5040. } else {
  5041. this._edit = false;
  5042. }
  5043. },
  5044. get: function get() {
  5045. if (!this._edit) {
  5046. return false;
  5047. }
  5048. return this._edit;
  5049. },
  5050. configurable: false
  5051. });
  5052. this.hasAppearanceStream = true;
  5053. };
  5054. inherit(AcroFormChoiceField, AcroFormField);
  5055. var AcroFormListBox = function AcroFormListBox() {
  5056. AcroFormChoiceField.call(this);
  5057. this.combo = false;
  5058. };
  5059. inherit(AcroFormListBox, AcroFormChoiceField);
  5060. var AcroFormComboBox = function AcroFormComboBox() {
  5061. AcroFormListBox.call(this);
  5062. this.combo = true;
  5063. };
  5064. inherit(AcroFormComboBox, AcroFormListBox);
  5065. var AcroFormEditBox = function AcroFormEditBox() {
  5066. AcroFormComboBox.call(this);
  5067. this.edit = true;
  5068. };
  5069. inherit(AcroFormEditBox, AcroFormComboBox);
  5070. var AcroFormButton = function AcroFormButton() {
  5071. AcroFormField.call(this);
  5072. this.FT = "/Btn"; // this.hasAnnotation = true;
  5073. };
  5074. inherit(AcroFormButton, AcroFormField);
  5075. var AcroFormPushButton = function AcroFormPushButton() {
  5076. AcroFormButton.call(this);
  5077. var _pushbutton = true;
  5078. Object.defineProperty(this, "pushbutton", {
  5079. enumerable: false,
  5080. get: function get() {
  5081. return _pushbutton;
  5082. },
  5083. set: function set(val) {
  5084. _pushbutton = val;
  5085. }
  5086. });
  5087. };
  5088. inherit(AcroFormPushButton, AcroFormButton);
  5089. var AcroFormRadioButton = function AcroFormRadioButton() {
  5090. AcroFormButton.call(this);
  5091. var _radio = true;
  5092. Object.defineProperty(this, "radio", {
  5093. enumerable: false,
  5094. get: function get() {
  5095. return _radio;
  5096. },
  5097. set: function set(val) {
  5098. _radio = val;
  5099. }
  5100. });
  5101. var _Kids = [];
  5102. Object.defineProperty(this, "Kids", {
  5103. enumerable: true,
  5104. get: function get() {
  5105. if (_Kids.length > 0) {
  5106. return _Kids;
  5107. }
  5108. }
  5109. });
  5110. Object.defineProperty(this, "__Kids", {
  5111. get: function get() {
  5112. return _Kids;
  5113. }
  5114. });
  5115. var _noToggleToOff;
  5116. Object.defineProperty(this, "noToggleToOff", {
  5117. enumerable: false,
  5118. get: function get() {
  5119. return _noToggleToOff;
  5120. },
  5121. set: function set(val) {
  5122. _noToggleToOff = val;
  5123. }
  5124. }); // this.hasAnnotation = false;
  5125. };
  5126. inherit(AcroFormRadioButton, AcroFormButton);
  5127. /*
  5128. * The Child classs of a RadioButton (the radioGroup) -> The single
  5129. * Buttons
  5130. */
  5131. var AcroFormChildClass = function AcroFormChildClass(parent, name) {
  5132. AcroFormField.call(this);
  5133. this.Parent = parent; // todo: set AppearanceType as variable that can be set from the
  5134. // outside...
  5135. this._AppearanceType = AcroFormAppearance.RadioButton.Circle; // The Default appearanceType is the Circle
  5136. this.appearanceStreamContent = this._AppearanceType.createAppearanceStream(name); // Set Print in the Annot Flag
  5137. this.F = setBitPosition(this.F, 3, 1); // Set AppearanceCharacteristicsDictionary with default appearance
  5138. // if field is not interacting with user
  5139. this.MK = this._AppearanceType.createMK(); // (8) -> Cross, (1)-> Circle, ()-> nothing
  5140. // Default Appearance is Off
  5141. this.AS = "/Off"; // + name;
  5142. this._Name = name;
  5143. };
  5144. inherit(AcroFormChildClass, AcroFormField);
  5145. AcroFormRadioButton.prototype.setAppearance = function (appearance) {
  5146. if (!("createAppearanceStream" in appearance && "createMK" in appearance)) {
  5147. console.log("Couldn't assign Appearance to RadioButton. Appearance was Invalid!");
  5148. return;
  5149. }
  5150. for (var i in this.__Kids) {
  5151. if (this.__Kids.hasOwnProperty(i)) {
  5152. var child = this.__Kids[i];
  5153. child.appearanceStreamContent = appearance.createAppearanceStream(child._Name);
  5154. child.MK = appearance.createMK();
  5155. }
  5156. }
  5157. };
  5158. AcroFormRadioButton.prototype.createOption = function (name) {
  5159. var parent = this;
  5160. var kidCount = this.__Kids.length; // Create new Child for RadioGroup
  5161. var child = new AcroFormChildClass(parent, name); // Add to Parent
  5162. this.__Kids.push(child);
  5163. jsPDFAPI.addField(child);
  5164. return child;
  5165. };
  5166. /**
  5167. * @name AcroFormCheckBox
  5168. *
  5169. * @memberOf AcroForm
  5170. * @function
  5171. */
  5172. var AcroFormCheckBox = function AcroFormCheckBox() {
  5173. AcroFormButton.call(this);
  5174. this.appearanceStreamContent = AcroFormAppearance.CheckBox.createAppearanceStream();
  5175. this.MK = AcroFormAppearance.CheckBox.createMK();
  5176. this.AS = "/On";
  5177. this.V = "/On";
  5178. };
  5179. inherit(AcroFormCheckBox, AcroFormButton);
  5180. var AcroFormTextField = function AcroFormTextField() {
  5181. AcroFormField.call(this);
  5182. this.DA = AcroFormAppearance.createDefaultAppearanceStream();
  5183. this.F = 4;
  5184. var _V;
  5185. Object.defineProperty(this, "V", {
  5186. get: function get() {
  5187. if (_V) {
  5188. return toPdfString(_V);
  5189. } else {
  5190. return _V;
  5191. }
  5192. },
  5193. enumerable: true,
  5194. set: function set(val) {
  5195. _V = val;
  5196. }
  5197. });
  5198. var _DV;
  5199. Object.defineProperty(this, "DV", {
  5200. get: function get() {
  5201. if (_DV) {
  5202. return toPdfString(_DV);
  5203. } else {
  5204. return _DV;
  5205. }
  5206. },
  5207. enumerable: true,
  5208. set: function set(val) {
  5209. _DV = val;
  5210. }
  5211. });
  5212. var _multiline = false;
  5213. Object.defineProperty(this, "multiline", {
  5214. enumerable: false,
  5215. get: function get() {
  5216. return _multiline;
  5217. },
  5218. set: function set(val) {
  5219. _multiline = val;
  5220. }
  5221. });
  5222. /**
  5223. * For PDF 1.4
  5224. *
  5225. * @type {boolean}
  5226. */
  5227. var _fileSelect = false;
  5228. Object.defineProperty(this, "fileSelect", {
  5229. enumerable: false,
  5230. get: function get() {
  5231. return _fileSelect;
  5232. },
  5233. set: function set(val) {
  5234. _fileSelect = val;
  5235. }
  5236. });
  5237. /**
  5238. * For PDF 1.4
  5239. *
  5240. * @type {boolean}
  5241. */
  5242. var _doNotSpellCheck = false;
  5243. Object.defineProperty(this, "doNotSpellCheck", {
  5244. enumerable: false,
  5245. get: function get() {
  5246. return _doNotSpellCheck;
  5247. },
  5248. set: function set(val) {
  5249. _doNotSpellCheck = val;
  5250. }
  5251. });
  5252. /**
  5253. * For PDF 1.4
  5254. *
  5255. * @type {boolean}
  5256. */
  5257. var _doNotScroll = false;
  5258. Object.defineProperty(this, "doNotScroll", {
  5259. enumerable: false,
  5260. get: function get() {
  5261. return _doNotScroll;
  5262. },
  5263. set: function set(val) {
  5264. _doNotScroll = val;
  5265. }
  5266. });
  5267. var _MaxLen = false;
  5268. Object.defineProperty(this, "MaxLen", {
  5269. enumerable: true,
  5270. get: function get() {
  5271. return _MaxLen;
  5272. },
  5273. set: function set(val) {
  5274. _MaxLen = val;
  5275. }
  5276. });
  5277. Object.defineProperty(this, "hasAppearanceStream", {
  5278. enumerable: false,
  5279. get: function get() {
  5280. return this.V || this.DV;
  5281. }
  5282. });
  5283. };
  5284. inherit(AcroFormTextField, AcroFormField);
  5285. var AcroFormPasswordField = function AcroFormPasswordField() {
  5286. AcroFormTextField.call(this);
  5287. var _password = true;
  5288. Object.defineProperty(this, "password", {
  5289. enumerable: false,
  5290. get: function get() {
  5291. return _password;
  5292. },
  5293. set: function set(val) {
  5294. _password = val;
  5295. }
  5296. });
  5297. };
  5298. inherit(AcroFormPasswordField, AcroFormTextField); // Contains Methods for creating standard appearances
  5299. var AcroFormAppearance = {
  5300. CheckBox: {
  5301. createAppearanceStream: function createAppearanceStream() {
  5302. var appearance = {
  5303. N: {
  5304. On: AcroFormAppearance.CheckBox.YesNormal
  5305. },
  5306. D: {
  5307. On: AcroFormAppearance.CheckBox.YesPushDown,
  5308. Off: AcroFormAppearance.CheckBox.OffPushDown
  5309. }
  5310. };
  5311. return appearance;
  5312. },
  5313. /**
  5314. * If any other icons are needed, the number between the
  5315. * brackets can be changed
  5316. *
  5317. * @returns {string}
  5318. */
  5319. createMK: function createMK() {
  5320. return "<< /CA (3)>>";
  5321. },
  5322. /**
  5323. * Returns the standard On Appearance for a CheckBox
  5324. *
  5325. * @returns {AcroFormXObject}
  5326. */
  5327. YesPushDown: function YesPushDown(formObject) {
  5328. var xobj = createFormXObject(formObject);
  5329. var stream = [];
  5330. var zapfDingbatsId = scope.internal.getFont("zapfdingbats", "normal").id;
  5331. formObject.Q = 1; // set text-alignment as centered
  5332. var calcRes = calculateX(formObject, "3", "ZapfDingbats", 50);
  5333. stream.push("0.749023 g");
  5334. stream.push("0 0 " + AcroFormAppearance.internal.getWidth(formObject).toFixed(2) + " " + AcroFormAppearance.internal.getHeight(formObject).toFixed(2) + " re");
  5335. stream.push("f");
  5336. stream.push("BMC");
  5337. stream.push("q");
  5338. stream.push("0 0 1 rg");
  5339. stream.push("/" + zapfDingbatsId + " " + calcRes.fontSize.toFixed(2) + " Tf 0 g");
  5340. stream.push("BT");
  5341. stream.push(calcRes.text);
  5342. stream.push("ET");
  5343. stream.push("Q");
  5344. stream.push("EMC");
  5345. xobj.stream = stream.join("\n");
  5346. return xobj;
  5347. },
  5348. YesNormal: function YesNormal(formObject) {
  5349. var xobj = createFormXObject(formObject);
  5350. var zapfDingbatsId = scope.internal.getFont("zapfdingbats", "normal").id;
  5351. var stream = [];
  5352. formObject.Q = 1; // set text-alignment as centered
  5353. var height = AcroFormAppearance.internal.getHeight(formObject);
  5354. var width = AcroFormAppearance.internal.getWidth(formObject);
  5355. var calcRes = calculateX(formObject, "3", "ZapfDingbats", height * 0.9);
  5356. stream.push("1 g");
  5357. stream.push("0 0 " + width.toFixed(2) + " " + height.toFixed(2) + " re");
  5358. stream.push("f");
  5359. stream.push("q");
  5360. stream.push("0 0 1 rg");
  5361. stream.push("0 0 " + (width - 1).toFixed(2) + " " + (height - 1).toFixed(2) + " re");
  5362. stream.push("W");
  5363. stream.push("n");
  5364. stream.push("0 g");
  5365. stream.push("BT");
  5366. stream.push("/" + zapfDingbatsId + " " + calcRes.fontSize.toFixed(2) + " Tf 0 g");
  5367. stream.push(calcRes.text);
  5368. stream.push("ET");
  5369. stream.push("Q");
  5370. xobj.stream = stream.join("\n");
  5371. return xobj;
  5372. },
  5373. /**
  5374. * Returns the standard Off Appearance for a CheckBox
  5375. *
  5376. * @returns {AcroFormXObject}
  5377. */
  5378. OffPushDown: function OffPushDown(formObject) {
  5379. var xobj = createFormXObject(formObject);
  5380. var stream = [];
  5381. stream.push("0.749023 g");
  5382. stream.push("0 0 " + AcroFormAppearance.internal.getWidth(formObject).toFixed(2) + " " + AcroFormAppearance.internal.getHeight(formObject).toFixed(2) + " re");
  5383. stream.push("f");
  5384. xobj.stream = stream.join("\n");
  5385. return xobj;
  5386. }
  5387. },
  5388. RadioButton: {
  5389. Circle: {
  5390. createAppearanceStream: function createAppearanceStream(name) {
  5391. var appearanceStreamContent = {
  5392. D: {
  5393. Off: AcroFormAppearance.RadioButton.Circle.OffPushDown
  5394. },
  5395. N: {}
  5396. };
  5397. appearanceStreamContent.N[name] = AcroFormAppearance.RadioButton.Circle.YesNormal;
  5398. appearanceStreamContent.D[name] = AcroFormAppearance.RadioButton.Circle.YesPushDown;
  5399. return appearanceStreamContent;
  5400. },
  5401. createMK: function createMK() {
  5402. return "<< /CA (l)>>";
  5403. },
  5404. YesNormal: function YesNormal(formObject) {
  5405. var xobj = createFormXObject(formObject);
  5406. var stream = []; // Make the Radius of the Circle relative to min(height,
  5407. // width) of formObject
  5408. var DotRadius = AcroFormAppearance.internal.getWidth(formObject) <= AcroFormAppearance.internal.getHeight(formObject) ? AcroFormAppearance.internal.getWidth(formObject) / 4 : AcroFormAppearance.internal.getHeight(formObject) / 4; // The Borderpadding...
  5409. DotRadius *= 0.9;
  5410. var c = AcroFormAppearance.internal.Bezier_C;
  5411. /*
  5412. * The Following is a Circle created with Bezier-Curves.
  5413. */
  5414. stream.push("q");
  5415. stream.push("1 0 0 1 " + AcroFormAppearance.internal.getWidth(formObject) / 2 + " " + AcroFormAppearance.internal.getHeight(formObject) / 2 + " cm");
  5416. stream.push(DotRadius + " 0 m");
  5417. stream.push(DotRadius + " " + DotRadius * c + " " + DotRadius * c + " " + DotRadius + " 0 " + DotRadius + " c");
  5418. stream.push("-" + DotRadius * c + " " + DotRadius + " -" + DotRadius + " " + DotRadius * c + " -" + DotRadius + " 0 c");
  5419. stream.push("-" + DotRadius + " -" + DotRadius * c + " -" + DotRadius * c + " -" + DotRadius + " 0 -" + DotRadius + " c");
  5420. stream.push(DotRadius * c + " -" + DotRadius + " " + DotRadius + " -" + DotRadius * c + " " + DotRadius + " 0 c");
  5421. stream.push("f");
  5422. stream.push("Q");
  5423. xobj.stream = stream.join("\n");
  5424. return xobj;
  5425. },
  5426. YesPushDown: function YesPushDown(formObject) {
  5427. var xobj = createFormXObject(formObject);
  5428. var stream = [];
  5429. var DotRadius = AcroFormAppearance.internal.getWidth(formObject) <= AcroFormAppearance.internal.getHeight(formObject) ? AcroFormAppearance.internal.getWidth(formObject) / 4 : AcroFormAppearance.internal.getHeight(formObject) / 4; // The Borderpadding...
  5430. DotRadius *= 0.9; // Save results for later use; no need to waste
  5431. // processor ticks on doing math
  5432. var k = DotRadius * 2; // var c = AcroFormAppearance.internal.Bezier_C;
  5433. var kc = k * AcroFormAppearance.internal.Bezier_C;
  5434. var dc = DotRadius * AcroFormAppearance.internal.Bezier_C;
  5435. stream.push("0.749023 g");
  5436. stream.push("q");
  5437. stream.push("1 0 0 1 " + (AcroFormAppearance.internal.getWidth(formObject) / 2).toFixed(2) + " " + (AcroFormAppearance.internal.getHeight(formObject) / 2).toFixed(2) + " cm");
  5438. stream.push(k + " 0 m");
  5439. stream.push(k + " " + kc + " " + kc + " " + k + " 0 " + k + " c");
  5440. stream.push("-" + kc + " " + k + " -" + k + " " + kc + " -" + k + " 0 c");
  5441. stream.push("-" + k + " -" + kc + " -" + kc + " -" + k + " 0 -" + k + " c");
  5442. stream.push(kc + " -" + k + " " + k + " -" + kc + " " + k + " 0 c");
  5443. stream.push("f");
  5444. stream.push("Q");
  5445. stream.push("0 g");
  5446. stream.push("q");
  5447. stream.push("1 0 0 1 " + (AcroFormAppearance.internal.getWidth(formObject) / 2).toFixed(2) + " " + (AcroFormAppearance.internal.getHeight(formObject) / 2).toFixed(2) + " cm");
  5448. stream.push(DotRadius + " 0 m");
  5449. stream.push("" + DotRadius + " " + dc + " " + dc + " " + DotRadius + " 0 " + DotRadius + " c");
  5450. stream.push("-" + dc + " " + DotRadius + " -" + DotRadius + " " + dc + " -" + DotRadius + " 0 c");
  5451. stream.push("-" + DotRadius + " -" + dc + " -" + dc + " -" + DotRadius + " 0 -" + DotRadius + " c");
  5452. stream.push(dc + " -" + DotRadius + " " + DotRadius + " -" + dc + " " + DotRadius + " 0 c");
  5453. stream.push("f");
  5454. stream.push("Q");
  5455. xobj.stream = stream.join("\n");
  5456. return xobj;
  5457. },
  5458. OffPushDown: function OffPushDown(formObject) {
  5459. var xobj = createFormXObject(formObject);
  5460. var stream = [];
  5461. var DotRadius = AcroFormAppearance.internal.getWidth(formObject) <= AcroFormAppearance.internal.getHeight(formObject) ? AcroFormAppearance.internal.getWidth(formObject) / 4 : AcroFormAppearance.internal.getHeight(formObject) / 4; // The Borderpadding...
  5462. DotRadius *= 0.9; // Save results for later use; no need to waste
  5463. // processor ticks on doing math
  5464. var k = DotRadius * 2; // var c = AcroFormAppearance.internal.Bezier_C;
  5465. var kc = k * AcroFormAppearance.internal.Bezier_C;
  5466. stream.push("0.749023 g");
  5467. stream.push("q");
  5468. stream.push("1 0 0 1 " + (AcroFormAppearance.internal.getWidth(formObject) / 2).toFixed(2) + " " + (AcroFormAppearance.internal.getHeight(formObject) / 2).toFixed(2) + " cm");
  5469. stream.push(k + " 0 m");
  5470. stream.push(k + " " + kc + " " + kc + " " + k + " 0 " + k + " c");
  5471. stream.push("-" + kc + " " + k + " -" + k + " " + kc + " -" + k + " 0 c");
  5472. stream.push("-" + k + " -" + kc + " -" + kc + " -" + k + " 0 -" + k + " c");
  5473. stream.push(kc + " -" + k + " " + k + " -" + kc + " " + k + " 0 c");
  5474. stream.push("f");
  5475. stream.push("Q");
  5476. xobj.stream = stream.join("\n");
  5477. return xobj;
  5478. }
  5479. },
  5480. Cross: {
  5481. /**
  5482. * Creates the Actual AppearanceDictionary-References
  5483. *
  5484. * @param {string} name
  5485. * @returns {Object}
  5486. * @ignore
  5487. */
  5488. createAppearanceStream: function createAppearanceStream(name) {
  5489. var appearanceStreamContent = {
  5490. D: {
  5491. Off: AcroFormAppearance.RadioButton.Cross.OffPushDown
  5492. },
  5493. N: {}
  5494. };
  5495. appearanceStreamContent.N[name] = AcroFormAppearance.RadioButton.Cross.YesNormal;
  5496. appearanceStreamContent.D[name] = AcroFormAppearance.RadioButton.Cross.YesPushDown;
  5497. return appearanceStreamContent;
  5498. },
  5499. createMK: function createMK() {
  5500. return "<< /CA (8)>>";
  5501. },
  5502. YesNormal: function YesNormal(formObject) {
  5503. var xobj = createFormXObject(formObject);
  5504. var stream = [];
  5505. var cross = AcroFormAppearance.internal.calculateCross(formObject);
  5506. stream.push("q");
  5507. stream.push("1 1 " + (AcroFormAppearance.internal.getWidth(formObject) - 2).toFixed(2) + " " + (AcroFormAppearance.internal.getHeight(formObject) - 2).toFixed(2) + " re");
  5508. stream.push("W");
  5509. stream.push("n");
  5510. stream.push(cross.x1.x.toFixed(2) + " " + cross.x1.y.toFixed(2) + " m");
  5511. stream.push(cross.x2.x.toFixed(2) + " " + cross.x2.y.toFixed(2) + " l");
  5512. stream.push(cross.x4.x.toFixed(2) + " " + cross.x4.y.toFixed(2) + " m");
  5513. stream.push(cross.x3.x.toFixed(2) + " " + cross.x3.y.toFixed(2) + " l");
  5514. stream.push("s");
  5515. stream.push("Q");
  5516. xobj.stream = stream.join("\n");
  5517. return xobj;
  5518. },
  5519. YesPushDown: function YesPushDown(formObject) {
  5520. var xobj = createFormXObject(formObject);
  5521. var cross = AcroFormAppearance.internal.calculateCross(formObject);
  5522. var stream = [];
  5523. stream.push("0.749023 g");
  5524. stream.push("0 0 " + AcroFormAppearance.internal.getWidth(formObject).toFixed(2) + " " + AcroFormAppearance.internal.getHeight(formObject).toFixed(2) + " re");
  5525. stream.push("f");
  5526. stream.push("q");
  5527. stream.push("1 1 " + (AcroFormAppearance.internal.getWidth(formObject) - 2).toFixed(2) + " " + (AcroFormAppearance.internal.getHeight(formObject) - 2).toFixed(2) + " re");
  5528. stream.push("W");
  5529. stream.push("n");
  5530. stream.push(cross.x1.x.toFixed(2) + " " + cross.x1.y.toFixed(2) + " m");
  5531. stream.push(cross.x2.x.toFixed(2) + " " + cross.x2.y.toFixed(2) + " l");
  5532. stream.push(cross.x4.x.toFixed(2) + " " + cross.x4.y.toFixed(2) + " m");
  5533. stream.push(cross.x3.x.toFixed(2) + " " + cross.x3.y.toFixed(2) + " l");
  5534. stream.push("s");
  5535. stream.push("Q");
  5536. xobj.stream = stream.join("\n");
  5537. return xobj;
  5538. },
  5539. OffPushDown: function OffPushDown(formObject) {
  5540. var xobj = createFormXObject(formObject);
  5541. var stream = [];
  5542. stream.push("0.749023 g");
  5543. stream.push("0 0 " + AcroFormAppearance.internal.getWidth(formObject).toFixed(2) + " " + AcroFormAppearance.internal.getHeight(formObject).toFixed(2) + " re");
  5544. stream.push("f");
  5545. xobj.stream = stream.join("\n");
  5546. return xobj;
  5547. }
  5548. }
  5549. },
  5550. /**
  5551. * Returns the standard Appearance
  5552. *
  5553. * @returns {AcroFormXObject}
  5554. */
  5555. createDefaultAppearanceStream: function createDefaultAppearanceStream(formObject) {
  5556. // Set Helvetica to Standard Font (size: auto)
  5557. // Color: Black
  5558. return "/F1 0 Tf 0 g";
  5559. }
  5560. };
  5561. AcroFormAppearance.internal = {
  5562. Bezier_C: 0.551915024494,
  5563. calculateCross: function calculateCross(formObject) {
  5564. var min = function min(x, y) {
  5565. return x > y ? y : x;
  5566. };
  5567. var width = AcroFormAppearance.internal.getWidth(formObject);
  5568. var height = AcroFormAppearance.internal.getHeight(formObject);
  5569. var a = min(width, height);
  5570. var cross = {
  5571. x1: {
  5572. // upperLeft
  5573. x: (width - a) / 2,
  5574. y: (height - a) / 2 + a // height - borderPadding
  5575. },
  5576. x2: {
  5577. // lowerRight
  5578. x: (width - a) / 2 + a,
  5579. y: (height - a) / 2 // borderPadding
  5580. },
  5581. x3: {
  5582. // lowerLeft
  5583. x: (width - a) / 2,
  5584. y: (height - a) / 2 // borderPadding
  5585. },
  5586. x4: {
  5587. // upperRight
  5588. x: (width - a) / 2 + a,
  5589. y: (height - a) / 2 + a // height - borderPadding
  5590. }
  5591. };
  5592. return cross;
  5593. }
  5594. };
  5595. AcroFormAppearance.internal.getWidth = function (formObject) {
  5596. var result = 0;
  5597. if (_typeof(formObject) === "object") {
  5598. result = scale(formObject.Rect[2]); // (formObject.Rect[2] -
  5599. // formObject.Rect[0]) || 0;
  5600. }
  5601. return result;
  5602. };
  5603. AcroFormAppearance.internal.getHeight = function (formObject) {
  5604. var result = 0;
  5605. if (_typeof(formObject) === "object") {
  5606. result = scale(formObject.Rect[3]); // (formObject.Rect[1] -
  5607. // formObject.Rect[3]) || 0;
  5608. }
  5609. return result;
  5610. }; // Public:
  5611. /**
  5612. * Add an AcroForm-Field to the {jsPDF}-instance
  5613. *
  5614. * @memberOf AcroForm
  5615. * @name addField
  5616. * @param {Object} fieldObject
  5617. * @returns {jsPDF}
  5618. */
  5619. jsPDFAPI.addField = function (fieldObject) {
  5620. initializeAcroForm.call(this); // var opt = parseOptions(fieldObject);
  5621. if (fieldObject instanceof AcroFormTextField) {
  5622. this.addTextField.call(this, fieldObject);
  5623. } else if (fieldObject instanceof AcroFormChoiceField) {
  5624. this.addChoiceField.call(this, fieldObject);
  5625. } else if (fieldObject instanceof AcroFormButton) {
  5626. this.addButton.call(this, fieldObject);
  5627. } else if (fieldObject instanceof AcroFormChildClass) {
  5628. putForm.call(this, fieldObject);
  5629. } else if (fieldObject) {
  5630. // try to put..
  5631. putForm.call(this, fieldObject);
  5632. }
  5633. fieldObject.page = scope.internal.getCurrentPageInfo().pageNumber;
  5634. return this;
  5635. };
  5636. /**
  5637. * @name addButton
  5638. * @param {AcroFormButton}
  5639. * @memberOf AcroForm
  5640. */
  5641. jsPDFAPI.addButton = function (opts) {
  5642. initializeAcroForm.call(this);
  5643. var options = opts || new AcroFormField();
  5644. options.FT = "/Btn";
  5645. options.Ff = calculateFlagsOnOptions(options.Ff, opts, scope.internal.getPDFVersion());
  5646. putForm.call(this, options);
  5647. };
  5648. jsPDFAPI.addTextField = function (opts) {
  5649. initializeAcroForm.call(this);
  5650. var options = opts || new AcroFormField();
  5651. options.FT = "/Tx";
  5652. options.Ff = calculateFlagsOnOptions(options.Ff, opts, scope.internal.getPDFVersion()); // Add field
  5653. putForm.call(this, options);
  5654. };
  5655. jsPDFAPI.addChoiceField = function (opts) {
  5656. initializeAcroForm.call(this);
  5657. var options = opts || new AcroFormField();
  5658. options.FT = "/Ch";
  5659. options.Ff = calculateFlagsOnOptions(options.Ff, opts, scope.internal.getPDFVersion()); // options.hasAnnotation = true;
  5660. // Add field
  5661. putForm.call(this, options);
  5662. };
  5663. if (_typeof(globalObj) == "object") {
  5664. globalObj["ChoiceField"] = AcroFormChoiceField;
  5665. globalObj["ListBox"] = AcroFormListBox;
  5666. globalObj["ComboBox"] = AcroFormComboBox;
  5667. globalObj["EditBox"] = AcroFormEditBox;
  5668. globalObj["Button"] = AcroFormButton;
  5669. globalObj["PushButton"] = AcroFormPushButton;
  5670. globalObj["RadioButton"] = AcroFormRadioButton;
  5671. globalObj["CheckBox"] = AcroFormCheckBox;
  5672. globalObj["TextField"] = AcroFormTextField;
  5673. globalObj["PasswordField"] = AcroFormPasswordField; // backwardsCompatibility
  5674. globalObj["AcroForm"] = {
  5675. Appearance: AcroFormAppearance
  5676. };
  5677. }
  5678. jsPDFAPI.AcroFormChoiceField = AcroFormChoiceField;
  5679. jsPDFAPI.AcroFormListBox = AcroFormListBox;
  5680. jsPDFAPI.AcroFormComboBox = AcroFormComboBox;
  5681. jsPDFAPI.AcroFormEditBox = AcroFormEditBox;
  5682. jsPDFAPI.AcroFormButton = AcroFormButton;
  5683. jsPDFAPI.AcroFormPushButton = AcroFormPushButton;
  5684. jsPDFAPI.AcroFormRadioButton = AcroFormRadioButton;
  5685. jsPDFAPI.AcroFormCheckBox = AcroFormCheckBox;
  5686. jsPDFAPI.AcroFormTextField = AcroFormTextField;
  5687. jsPDFAPI.AcroFormPasswordField = AcroFormPasswordField;
  5688. jsPDFAPI.AcroFormAppearance = AcroFormAppearance;
  5689. jsPDFAPI.AcroForm = {
  5690. ChoiceField: AcroFormChoiceField,
  5691. ListBox: AcroFormListBox,
  5692. ComboBox: AcroFormComboBox,
  5693. EditBox: AcroFormEditBox,
  5694. Button: AcroFormButton,
  5695. PushButton: AcroFormPushButton,
  5696. RadioButton: AcroFormRadioButton,
  5697. CheckBox: AcroFormCheckBox,
  5698. TextField: AcroFormTextField,
  5699. PasswordField: AcroFormPasswordField,
  5700. Appearance: AcroFormAppearance
  5701. };
  5702. })(jsPDF.API, typeof window !== "undefined" && window || typeof global !== "undefined" && global);
  5703. /** @license
  5704. * jsPDF addImage plugin
  5705. * Copyright (c) 2012 Jason Siefken, https://github.com/siefkenj/
  5706. * 2013 Chris Dowling, https://github.com/gingerchris
  5707. * 2013 Trinh Ho, https://github.com/ineedfat
  5708. * 2013 Edwin Alejandro Perez, https://github.com/eaparango
  5709. * 2013 Norah Smith, https://github.com/burnburnrocket
  5710. * 2014 Diego Casorran, https://github.com/diegocr
  5711. * 2014 James Robb, https://github.com/jamesbrobb
  5712. *
  5713. *
  5714. */
  5715. /**
  5716. * @name addImage
  5717. * @module
  5718. */
  5719. (function (jsPDFAPI) {
  5720. var namespace = "addImage_";
  5721. var imageFileTypeHeaders = {
  5722. PNG: [[0x89, 0x50, 0x4e, 0x47]],
  5723. TIFF: [[0x4d, 0x4d, 0x00, 0x2a], //Motorola
  5724. [0x49, 0x49, 0x2a, 0x00] //Intel
  5725. ],
  5726. JPEG: [[0xff, 0xd8, 0xff, 0xe0, undefined, undefined, 0x4a, 0x46, 0x49, 0x46, 0x00], //JFIF
  5727. [0xff, 0xd8, 0xff, 0xe1, undefined, undefined, 0x45, 0x78, 0x69, 0x66, 0x00, 0x00] //Exif
  5728. ],
  5729. JPEG2000: [[0x00, 0x00, 0x00, 0x0c, 0x6a, 0x50, 0x20, 0x20]],
  5730. GIF87a: [[0x47, 0x49, 0x46, 0x38, 0x37, 0x61]],
  5731. GIF89a: [[0x47, 0x49, 0x46, 0x38, 0x39, 0x61]],
  5732. BMP: [[0x42, 0x4d], //BM - Windows 3.1x, 95, NT, ... etc.
  5733. [0x42, 0x41], //BA - OS/2 struct bitmap array
  5734. [0x43, 0x49], //CI - OS/2 struct color icon
  5735. [0x43, 0x50], //CP - OS/2 const color pointer
  5736. [0x49, 0x43], //IC - OS/2 struct icon
  5737. [0x50, 0x54] //PT - OS/2 pointer
  5738. ]
  5739. };
  5740. /**
  5741. * Recognize filetype of Image by magic-bytes
  5742. *
  5743. * https://en.wikipedia.org/wiki/List_of_file_signatures
  5744. *
  5745. * @name getImageFileTypeByImageData
  5746. * @public
  5747. * @function
  5748. * @param {string|arraybuffer} imageData imageData as base64 encoded DataUrl or arraybuffer
  5749. * @param {string} format format of file if filetype-recognition fails, e.g. 'JPEG'
  5750. *
  5751. * @returns {string} filetype of Image
  5752. */
  5753. jsPDFAPI.getImageFileTypeByImageData = function (imageData, fallbackFormat) {
  5754. fallbackFormat = fallbackFormat || "UNKNOWN";
  5755. var i;
  5756. var j;
  5757. var result = "UNKNOWN";
  5758. var headerSchemata;
  5759. var compareResult;
  5760. var fileType;
  5761. if (jsPDFAPI.isArrayBufferView(imageData)) {
  5762. imageData = jsPDFAPI.arrayBufferToBinaryString(imageData);
  5763. }
  5764. for (fileType in imageFileTypeHeaders) {
  5765. headerSchemata = imageFileTypeHeaders[fileType];
  5766. for (i = 0; i < headerSchemata.length; i += 1) {
  5767. compareResult = true;
  5768. for (j = 0; j < headerSchemata[i].length; j += 1) {
  5769. if (headerSchemata[i][j] === undefined) {
  5770. continue;
  5771. }
  5772. if (headerSchemata[i][j] !== imageData.charCodeAt(j)) {
  5773. compareResult = false;
  5774. break;
  5775. }
  5776. }
  5777. if (compareResult === true) {
  5778. result = fileType;
  5779. break;
  5780. }
  5781. }
  5782. }
  5783. if (result === "UNKNOWN" && fallbackFormat !== "UNKNOWN") {
  5784. console.warn('FileType of Image not recognized. Processing image as "' + fallbackFormat + '".');
  5785. result = fallbackFormat;
  5786. }
  5787. return result;
  5788. }; // Image functionality ported from pdf.js
  5789. var putImage = function putImage(img) {
  5790. var objectNumber = this.internal.newObject(),
  5791. out = this.internal.write,
  5792. putStream = this.internal.putStream;
  5793. img["n"] = objectNumber;
  5794. out("<</Type /XObject");
  5795. out("/Subtype /Image");
  5796. out("/Width " + img["w"]);
  5797. out("/Height " + img["h"]);
  5798. if (img["cs"] === this.color_spaces.INDEXED) {
  5799. out("/ColorSpace [/Indexed /DeviceRGB " + ( // if an indexed png defines more than one colour with transparency, we've created a smask
  5800. img["pal"].length / 3 - 1) + " " + ("smask" in img ? objectNumber + 2 : objectNumber + 1) + " 0 R]");
  5801. } else {
  5802. out("/ColorSpace /" + img["cs"]);
  5803. if (img["cs"] === this.color_spaces.DEVICE_CMYK) {
  5804. out("/Decode [1 0 1 0 1 0 1 0]");
  5805. }
  5806. }
  5807. out("/BitsPerComponent " + img["bpc"]);
  5808. if ("f" in img) {
  5809. out("/Filter /" + img["f"]);
  5810. }
  5811. if ("dp" in img) {
  5812. out("/DecodeParms <<" + img["dp"] + ">>");
  5813. }
  5814. if ("trns" in img && img["trns"].constructor == Array) {
  5815. var trns = "",
  5816. i = 0,
  5817. len = img["trns"].length;
  5818. for (; i < len; i++) {
  5819. trns += img["trns"][i] + " " + img["trns"][i] + " ";
  5820. }
  5821. out("/Mask [" + trns + "]");
  5822. }
  5823. if ("smask" in img) {
  5824. out("/SMask " + (objectNumber + 1) + " 0 R");
  5825. }
  5826. out("/Length " + img["data"].length + ">>");
  5827. putStream(img["data"]);
  5828. out("endobj"); // Soft mask
  5829. if ("smask" in img) {
  5830. var dp = "/Predictor " + img["p"] + " /Colors 1 /BitsPerComponent " + img["bpc"] + " /Columns " + img["w"];
  5831. var smask = {
  5832. w: img["w"],
  5833. h: img["h"],
  5834. cs: "DeviceGray",
  5835. bpc: img["bpc"],
  5836. dp: dp,
  5837. data: img["smask"]
  5838. };
  5839. if ("f" in img) smask.f = img["f"];
  5840. putImage.call(this, smask);
  5841. } //Palette
  5842. if (img["cs"] === this.color_spaces.INDEXED) {
  5843. this.internal.newObject(); //out('<< /Filter / ' + img['f'] +' /Length ' + img['pal'].length + '>>');
  5844. //putStream(zlib.compress(img['pal']));
  5845. out("<< /Length " + img["pal"].length + ">>");
  5846. putStream(this.arrayBufferToBinaryString(new Uint8Array(img["pal"])));
  5847. out("endobj");
  5848. }
  5849. },
  5850. putResourcesCallback = function putResourcesCallback() {
  5851. var images = this.internal.collections[namespace + "images"];
  5852. for (var i in images) {
  5853. putImage.call(this, images[i]);
  5854. }
  5855. },
  5856. putXObjectsDictCallback = function putXObjectsDictCallback() {
  5857. var images = this.internal.collections[namespace + "images"],
  5858. out = this.internal.write,
  5859. image;
  5860. for (var i in images) {
  5861. image = images[i];
  5862. out("/I" + image["i"], image["n"], "0", "R");
  5863. }
  5864. },
  5865. checkCompressValue = function checkCompressValue(value) {
  5866. if (value && typeof value === "string") value = value.toUpperCase();
  5867. return value in jsPDFAPI.image_compression ? value : jsPDFAPI.image_compression.NONE;
  5868. },
  5869. getImages = function getImages() {
  5870. var images = this.internal.collections[namespace + "images"]; //first run, so initialise stuff
  5871. if (!images) {
  5872. this.internal.collections[namespace + "images"] = images = {};
  5873. this.internal.events.subscribe("putResources", putResourcesCallback);
  5874. this.internal.events.subscribe("putXobjectDict", putXObjectsDictCallback);
  5875. }
  5876. return images;
  5877. },
  5878. getImageIndex = function getImageIndex(images) {
  5879. var imageIndex = 0;
  5880. if (images) {
  5881. // this is NOT the first time this method is ran on this instance of jsPDF object.
  5882. imageIndex = Object.keys ? Object.keys(images).length : function (o) {
  5883. var i = 0;
  5884. for (var e in o) {
  5885. if (o.hasOwnProperty(e)) {
  5886. i++;
  5887. }
  5888. }
  5889. return i;
  5890. }(images);
  5891. }
  5892. return imageIndex;
  5893. },
  5894. notDefined = function notDefined(value) {
  5895. return typeof value === "undefined" || value === null || value.length === 0;
  5896. },
  5897. generateAliasFromData = function generateAliasFromData(data) {
  5898. return typeof data === "string" && jsPDFAPI.sHashCode(data);
  5899. },
  5900. isImageTypeSupported = function isImageTypeSupported(type) {
  5901. return typeof jsPDFAPI["process" + type.toUpperCase()] === "function";
  5902. },
  5903. isDOMElement = function isDOMElement(object) {
  5904. return _typeof(object) === "object" && object.nodeType === 1;
  5905. },
  5906. createDataURIFromElement = function createDataURIFromElement(element, format) {
  5907. //if element is an image which uses data url definition, just return the dataurl
  5908. if (element.nodeName === "IMG" && element.hasAttribute("src")) {
  5909. var src = "" + element.getAttribute("src");
  5910. if (src.indexOf("data:image/") === 0) return unescape(src); // only if the user doesn't care about a format
  5911. if (!format && /\.png(?:[?#].*)?$/i.test(src)) format = "png";
  5912. }
  5913. if (element.nodeName === "CANVAS") {
  5914. var canvas = element;
  5915. } else {
  5916. var canvas = document.createElement("canvas");
  5917. canvas.width = element.clientWidth || element.width;
  5918. canvas.height = element.clientHeight || element.height;
  5919. var ctx = canvas.getContext("2d");
  5920. if (!ctx) {
  5921. throw "addImage requires canvas to be supported by browser.";
  5922. }
  5923. ctx.drawImage(element, 0, 0, canvas.width, canvas.height);
  5924. }
  5925. return canvas.toDataURL(("" + format).toLowerCase() == "png" ? "image/png" : "image/jpeg");
  5926. },
  5927. checkImagesForAlias = function checkImagesForAlias(alias, images) {
  5928. var cached_info;
  5929. if (images) {
  5930. for (var e in images) {
  5931. if (alias === images[e].alias) {
  5932. cached_info = images[e];
  5933. break;
  5934. }
  5935. }
  5936. }
  5937. return cached_info;
  5938. },
  5939. determineWidthAndHeight = function determineWidthAndHeight(w, h, info) {
  5940. if (!w && !h) {
  5941. w = -96;
  5942. h = -96;
  5943. }
  5944. if (w < 0) {
  5945. w = -1 * info["w"] * 72 / w / this.internal.scaleFactor;
  5946. }
  5947. if (h < 0) {
  5948. h = -1 * info["h"] * 72 / h / this.internal.scaleFactor;
  5949. }
  5950. if (w === 0) {
  5951. w = h * info["w"] / info["h"];
  5952. }
  5953. if (h === 0) {
  5954. h = w * info["h"] / info["w"];
  5955. }
  5956. return [w, h];
  5957. },
  5958. writeImageToPDF = function writeImageToPDF(x, y, w, h, info, index, images, rotation) {
  5959. var dims = determineWidthAndHeight.call(this, w, h, info),
  5960. coord = this.internal.getCoordinateString,
  5961. vcoord = this.internal.getVerticalCoordinateString;
  5962. w = dims[0];
  5963. h = dims[1];
  5964. images[index] = info;
  5965. if (rotation) {
  5966. rotation *= Math.PI / 180;
  5967. var c = Math.cos(rotation);
  5968. var s = Math.sin(rotation); //like in pdf Reference do it 4 digits instead of 2
  5969. var f4 = function f4(number) {
  5970. return number.toFixed(4);
  5971. };
  5972. var rotationTransformationMatrix = [f4(c), f4(s), f4(s * -1), f4(c), 0, 0, "cm"];
  5973. }
  5974. this.internal.write("q"); //Save graphics state
  5975. if (rotation) {
  5976. this.internal.write([1, "0", "0", 1, coord(x), vcoord(y + h), "cm"].join(" ")); //Translate
  5977. this.internal.write(rotationTransformationMatrix.join(" ")); //Rotate
  5978. this.internal.write([coord(w), "0", "0", coord(h), "0", "0", "cm"].join(" ")); //Scale
  5979. } else {
  5980. this.internal.write([coord(w), "0", "0", coord(h), coord(x), vcoord(y + h), "cm"].join(" ")); //Translate and Scale
  5981. }
  5982. if (this.isAdvancedAPI()) {
  5983. // draw image bottom up when in "advanced" API mode
  5984. this.internal.write([1, 0, 0, -1, 0, 0, "cm"].join(" "));
  5985. }
  5986. this.internal.write("/I" + info["i"] + " Do"); //Paint Image
  5987. this.internal.write("Q"); //Restore graphics state
  5988. };
  5989. /**
  5990. * COLOR SPACES
  5991. */
  5992. jsPDFAPI.color_spaces = {
  5993. DEVICE_RGB: "DeviceRGB",
  5994. DEVICE_GRAY: "DeviceGray",
  5995. DEVICE_CMYK: "DeviceCMYK",
  5996. CAL_GREY: "CalGray",
  5997. CAL_RGB: "CalRGB",
  5998. LAB: "Lab",
  5999. ICC_BASED: "ICCBased",
  6000. INDEXED: "Indexed",
  6001. PATTERN: "Pattern",
  6002. SEPARATION: "Separation",
  6003. DEVICE_N: "DeviceN"
  6004. };
  6005. /**
  6006. * DECODE METHODS
  6007. */
  6008. jsPDFAPI.decode = {
  6009. DCT_DECODE: "DCTDecode",
  6010. FLATE_DECODE: "FlateDecode",
  6011. LZW_DECODE: "LZWDecode",
  6012. JPX_DECODE: "JPXDecode",
  6013. JBIG2_DECODE: "JBIG2Decode",
  6014. ASCII85_DECODE: "ASCII85Decode",
  6015. ASCII_HEX_DECODE: "ASCIIHexDecode",
  6016. RUN_LENGTH_DECODE: "RunLengthDecode",
  6017. CCITT_FAX_DECODE: "CCITTFaxDecode"
  6018. };
  6019. /**
  6020. * IMAGE COMPRESSION TYPES
  6021. */
  6022. jsPDFAPI.image_compression = {
  6023. NONE: "NONE",
  6024. FAST: "FAST",
  6025. MEDIUM: "MEDIUM",
  6026. SLOW: "SLOW"
  6027. };
  6028. /**
  6029. * @name sHashCode
  6030. * @function
  6031. * @param {string} str
  6032. * @returns {string}
  6033. */
  6034. jsPDFAPI.sHashCode = function (str) {
  6035. str = str || "";
  6036. return Array.prototype.reduce && str.split("").reduce(function (a, b) {
  6037. a = (a << 5) - a + b.charCodeAt(0);
  6038. return a & a;
  6039. }, 0);
  6040. };
  6041. /**
  6042. * @name isString
  6043. * @function
  6044. * @param {any} object
  6045. * @returns {boolean}
  6046. */
  6047. jsPDFAPI.isString = function (object) {
  6048. return typeof object === "string";
  6049. };
  6050. /**
  6051. * Validates if given String is a valid Base64-String
  6052. *
  6053. * @name validateStringAsBase64
  6054. * @public
  6055. * @function
  6056. * @param {String} possible Base64-String
  6057. *
  6058. * @returns {boolean}
  6059. */
  6060. jsPDFAPI.validateStringAsBase64 = function (possibleBase64String) {
  6061. possibleBase64String = possibleBase64String || "";
  6062. var result = true;
  6063. if (possibleBase64String.length % 4 !== 0) {
  6064. result = false;
  6065. }
  6066. if (/[A-Za-z0-9\/]+/.test(possibleBase64String.substr(0, possibleBase64String.length - 2)) === false) {
  6067. result = false;
  6068. }
  6069. if (/[A-Za-z0-9\/][A-Za-z0-9+\/]|[A-Za-z0-9+\/]=|==/.test(possibleBase64String.substr(-2)) === false) {
  6070. result = false;
  6071. }
  6072. return result;
  6073. };
  6074. /**
  6075. * Strips out and returns info from a valid base64 data URI
  6076. *
  6077. * @name extractInfoFromBase64DataURI
  6078. * @function
  6079. * @param {string} dataUrl a valid data URI of format 'data:[<MIME-type>][;base64],<data>'
  6080. * @returns {Array}an Array containing the following
  6081. * [0] the complete data URI
  6082. * [1] <MIME-type>
  6083. * [2] format - the second part of the mime-type i.e 'png' in 'image/png'
  6084. * [4] <data>
  6085. */
  6086. jsPDFAPI.extractInfoFromBase64DataURI = function (dataURI) {
  6087. return /^data:([\w]+?\/([\w]+?));\S*;*base64,(.+)$/g.exec(dataURI);
  6088. };
  6089. /**
  6090. * Check to see if ArrayBuffer is supported
  6091. *
  6092. * @name supportsArrayBuffer
  6093. * @function
  6094. * @returns {boolean}
  6095. */
  6096. jsPDFAPI.supportsArrayBuffer = function () {
  6097. return typeof ArrayBuffer !== "undefined" && typeof Uint8Array !== "undefined";
  6098. };
  6099. /**
  6100. * Tests supplied object to determine if ArrayBuffer
  6101. *
  6102. * @name isArrayBuffer
  6103. * @function
  6104. * @param {Object} object an Object
  6105. *
  6106. * @returns {boolean}
  6107. */
  6108. jsPDFAPI.isArrayBuffer = function (object) {
  6109. if (!this.supportsArrayBuffer()) return false;
  6110. return object instanceof ArrayBuffer;
  6111. };
  6112. /**
  6113. * Tests supplied object to determine if it implements the ArrayBufferView (TypedArray) interface
  6114. *
  6115. * @name isArrayBufferView
  6116. * @function
  6117. * @param {Object} object an Object
  6118. * @returns {boolean}
  6119. */
  6120. jsPDFAPI.isArrayBufferView = function (object) {
  6121. if (!this.supportsArrayBuffer()) return false;
  6122. if (typeof Uint32Array === "undefined") return false;
  6123. 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;
  6124. };
  6125. /**
  6126. * Convert the Buffer to a Binary String
  6127. *
  6128. * @name binaryStringToUint8Array
  6129. * @public
  6130. * @function
  6131. * @param {ArrayBuffer} BinaryString with ImageData
  6132. *
  6133. * @returns {Uint8Array}
  6134. */
  6135. jsPDFAPI.binaryStringToUint8Array = function (binary_string) {
  6136. /*
  6137. * not sure how efficient this will be will bigger files. Is there a native method?
  6138. */
  6139. var len = binary_string.length;
  6140. var bytes = new Uint8Array(len);
  6141. for (var i = 0; i < len; i++) {
  6142. bytes[i] = binary_string.charCodeAt(i);
  6143. }
  6144. return bytes;
  6145. };
  6146. /**
  6147. * Convert the Buffer to a Binary String
  6148. *
  6149. * @name arrayBufferToBinaryString
  6150. * @public
  6151. * @function
  6152. * @param {ArrayBuffer} ArrayBuffer with ImageData
  6153. *
  6154. * @returns {String}
  6155. */
  6156. jsPDFAPI.arrayBufferToBinaryString = function (buffer) {
  6157. if (typeof atob === "function") {
  6158. return atob(this.arrayBufferToBase64(buffer));
  6159. }
  6160. if (typeof TextDecoder === "function") {
  6161. var decoder = new TextDecoder("ascii"); // test if the encoding is supported
  6162. if (decoder.encoding === "ascii") {
  6163. return decoder.decode(buffer);
  6164. }
  6165. } //Fallback-solution
  6166. var data = this.isArrayBuffer(buffer) ? buffer : new Uint8Array(buffer);
  6167. var chunkSizeForSlice = 0x5000;
  6168. var binary_string = "";
  6169. var slicesCount = Math.ceil(data.byteLength / chunkSizeForSlice);
  6170. for (var i = 0; i < slicesCount; i++) {
  6171. binary_string += String.fromCharCode.apply(null, data.slice(i * chunkSizeForSlice, i * chunkSizeForSlice + chunkSizeForSlice));
  6172. }
  6173. return binary_string;
  6174. };
  6175. /**
  6176. * Converts an ArrayBuffer directly to base64
  6177. *
  6178. * Taken from http://jsperf.com/encoding-xhr-image-data/31
  6179. *
  6180. * Need to test if this is a better solution for larger files
  6181. *
  6182. * @name arrayBufferToBase64
  6183. * @param {arraybuffer} arrayBuffer
  6184. * @public
  6185. * @function
  6186. *
  6187. * @returns {string}
  6188. */
  6189. jsPDFAPI.arrayBufferToBase64 = function (arrayBuffer) {
  6190. var base64 = "";
  6191. var encodings = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  6192. var bytes = new Uint8Array(arrayBuffer);
  6193. var byteLength = bytes.byteLength;
  6194. var byteRemainder = byteLength % 3;
  6195. var mainLength = byteLength - byteRemainder;
  6196. var a, b, c, d;
  6197. var chunk; // Main loop deals with bytes in chunks of 3
  6198. for (var i = 0; i < mainLength; i = i + 3) {
  6199. // Combine the three bytes into a single integer
  6200. chunk = bytes[i] << 16 | bytes[i + 1] << 8 | bytes[i + 2]; // Use bitmasks to extract 6-bit segments from the triplet
  6201. a = (chunk & 16515072) >> 18; // 16515072 = (2^6 - 1) << 18
  6202. b = (chunk & 258048) >> 12; // 258048 = (2^6 - 1) << 12
  6203. c = (chunk & 4032) >> 6; // 4032 = (2^6 - 1) << 6
  6204. d = chunk & 63; // 63 = 2^6 - 1
  6205. // Convert the raw binary segments to the appropriate ASCII encoding
  6206. base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d];
  6207. } // Deal with the remaining bytes and padding
  6208. if (byteRemainder == 1) {
  6209. chunk = bytes[mainLength];
  6210. a = (chunk & 252) >> 2; // 252 = (2^6 - 1) << 2
  6211. // Set the 4 least significant bits to zero
  6212. b = (chunk & 3) << 4; // 3 = 2^2 - 1
  6213. base64 += encodings[a] + encodings[b] + "==";
  6214. } else if (byteRemainder == 2) {
  6215. chunk = bytes[mainLength] << 8 | bytes[mainLength + 1];
  6216. a = (chunk & 64512) >> 10; // 64512 = (2^6 - 1) << 10
  6217. b = (chunk & 1008) >> 4; // 1008 = (2^6 - 1) << 4
  6218. // Set the 2 least significant bits to zero
  6219. c = (chunk & 15) << 2; // 15 = 2^4 - 1
  6220. base64 += encodings[a] + encodings[b] + encodings[c] + "=";
  6221. }
  6222. return base64;
  6223. };
  6224. /**
  6225. *
  6226. * @name createImageInfo
  6227. * @param {Object} data
  6228. * @param {number} wd width
  6229. * @param {number} ht height
  6230. * @param {Object} cs colorSpace
  6231. * @param {number} bpc bits per channel
  6232. * @param {any} f
  6233. * @param {number} imageIndex
  6234. * @param {string} alias
  6235. * @param {any} dp
  6236. * @param {any} trns
  6237. * @param {any} pal
  6238. * @param {any} smask
  6239. * @param {any} p
  6240. * @public
  6241. * @function
  6242. *
  6243. * @returns {Object}
  6244. */
  6245. jsPDFAPI.createImageInfo = function (data, wd, ht, cs, bpc, f, imageIndex, alias, dp, trns, pal, smask, p) {
  6246. var info = {
  6247. alias: alias,
  6248. w: wd,
  6249. h: ht,
  6250. cs: cs,
  6251. bpc: bpc,
  6252. i: imageIndex,
  6253. data: data // n: objectNumber will be added by putImage code
  6254. };
  6255. if (f) info.f = f;
  6256. if (dp) info.dp = dp;
  6257. if (trns) info.trns = trns;
  6258. if (pal) info.pal = pal;
  6259. if (smask) info.smask = smask;
  6260. if (p) info.p = p; // predictor parameter for PNG compression
  6261. return info;
  6262. };
  6263. /**
  6264. * Adds an Image to the PDF.
  6265. *
  6266. * @name addImage
  6267. * @public
  6268. * @function
  6269. * @param {string/Image-Element/Canvas-Element/Uint8Array} imageData imageData as base64 encoded DataUrl or Image-HTMLElement or Canvas-HTMLElement
  6270. * @param {string} format format of file if filetype-recognition fails, e.g. 'JPEG'
  6271. * @param {number} x x Coordinate (in units declared at inception of PDF document) against left edge of the page
  6272. * @param {number} y y Coordinate (in units declared at inception of PDF document) against upper edge of the page
  6273. * @param {number} width width of the image (in units declared at inception of PDF document)
  6274. * @param {number} height height of the Image (in units declared at inception of PDF document)
  6275. * @param {string} alias alias of the image (if used multiple times)
  6276. * @param {string} compression compression of the generated JPEG, can have the values 'NONE', 'FAST', 'MEDIUM' and 'SLOW'
  6277. * @param {number} rotation rotation of the image in degrees (0-359)
  6278. *
  6279. * @returns jsPDF
  6280. */
  6281. jsPDFAPI.addImage = function (imageData, format, x, y, w, h, alias, compression, rotation) {
  6282. var tmpImageData = "";
  6283. if (typeof format !== "string") {
  6284. var tmp = h;
  6285. h = w;
  6286. w = y;
  6287. y = x;
  6288. x = format;
  6289. format = tmp;
  6290. }
  6291. if (_typeof(imageData) === "object" && !isDOMElement(imageData) && "imageData" in imageData) {
  6292. var options = imageData;
  6293. imageData = options.imageData;
  6294. format = options.format || format;
  6295. x = options.x || x || 0;
  6296. y = options.y || y || 0;
  6297. w = options.w || w;
  6298. h = options.h || h;
  6299. alias = options.alias || alias;
  6300. compression = options.compression || compression;
  6301. rotation = options.rotation || options.angle || rotation;
  6302. }
  6303. if (typeof imageData === "string") {
  6304. imageData = unescape(imageData);
  6305. }
  6306. if (isNaN(x) || isNaN(y)) {
  6307. console.error("jsPDF.addImage: Invalid coordinates", arguments);
  6308. throw new Error("Invalid coordinates passed to jsPDF.addImage");
  6309. }
  6310. var images = getImages.call(this),
  6311. info;
  6312. if (!(info = checkImagesForAlias(imageData, images))) {
  6313. var dataAsBinaryString;
  6314. if (isDOMElement(imageData)) imageData = createDataURIFromElement(imageData, format);
  6315. if (notDefined(alias)) alias = generateAliasFromData(imageData);
  6316. if (!(info = checkImagesForAlias(alias, images))) {
  6317. if (this.isString(imageData)) {
  6318. tmpImageData = this.convertStringToImageData(imageData);
  6319. if (tmpImageData !== "") {
  6320. imageData = tmpImageData;
  6321. } else {
  6322. tmpImageData = this.loadImageFile(imageData);
  6323. if (tmpImageData !== undefined) {
  6324. imageData = tmpImageData;
  6325. }
  6326. }
  6327. }
  6328. format = this.getImageFileTypeByImageData(imageData, format);
  6329. if (!isImageTypeSupported(format)) throw new Error("addImage does not support files of type '" + format + "', please ensure that a plugin for '" + format + "' support is added.");
  6330. /**
  6331. * need to test if it's more efficient to convert all binary strings
  6332. * to TypedArray - or should we just leave and process as string?
  6333. */
  6334. if (this.supportsArrayBuffer()) {
  6335. // no need to convert if imageData is already uint8array
  6336. if (!(imageData instanceof Uint8Array)) {
  6337. dataAsBinaryString = imageData;
  6338. imageData = this.binaryStringToUint8Array(imageData);
  6339. }
  6340. }
  6341. info = this["process" + format.toUpperCase()](imageData, getImageIndex(images), alias, checkCompressValue(compression), dataAsBinaryString);
  6342. if (!info) throw new Error("An unkwown error occurred whilst processing the image");
  6343. }
  6344. }
  6345. writeImageToPDF.call(this, x, y, w, h, info, info.i, images, rotation);
  6346. return this;
  6347. };
  6348. /**
  6349. * @name convertStringToImageData
  6350. * @function
  6351. * @param {string} stringData
  6352. * @returns {string} binary data
  6353. */
  6354. jsPDFAPI.convertStringToImageData = function (stringData) {
  6355. var base64Info;
  6356. var imageData = "";
  6357. if (this.isString(stringData)) {
  6358. var base64Info = this.extractInfoFromBase64DataURI(stringData);
  6359. if (base64Info !== null) {
  6360. if (jsPDFAPI.validateStringAsBase64(base64Info[3])) {
  6361. imageData = atob(base64Info[3]); //convert to binary string
  6362. }
  6363. } else if (jsPDFAPI.validateStringAsBase64(stringData)) {
  6364. imageData = atob(stringData);
  6365. }
  6366. }
  6367. return imageData;
  6368. };
  6369. /**
  6370. * JPEG SUPPORT
  6371. **/
  6372. //takes a string imgData containing the raw bytes of
  6373. //a jpeg image and returns [width, height]
  6374. //Algorithm from: http://www.64lines.com/jpeg-width-height
  6375. var getJpegSize = function getJpegSize(imgData) {
  6376. var width, height, numcomponents; // Verify we have a valid jpeg header 0xff,0xd8,0xff,0xe0,?,?,'J','F','I','F',0x00
  6377. 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) {
  6378. throw new Error("getJpegSize requires a binary string jpeg file");
  6379. }
  6380. var blockLength = imgData.charCodeAt(4) * 256 + imgData.charCodeAt(5);
  6381. var i = 4,
  6382. len = imgData.length;
  6383. while (i < len) {
  6384. i += blockLength;
  6385. if (imgData.charCodeAt(i) !== 0xff) {
  6386. throw new Error("getJpegSize could not find the size of the image");
  6387. }
  6388. if (imgData.charCodeAt(i + 1) === 0xc0 || //(SOF) Huffman - Baseline DCT
  6389. imgData.charCodeAt(i + 1) === 0xc1 || //(SOF) Huffman - Extended sequential DCT
  6390. imgData.charCodeAt(i + 1) === 0xc2 || // Progressive DCT (SOF2)
  6391. imgData.charCodeAt(i + 1) === 0xc3 || // Spatial (sequential) lossless (SOF3)
  6392. imgData.charCodeAt(i + 1) === 0xc4 || // Differential sequential DCT (SOF5)
  6393. imgData.charCodeAt(i + 1) === 0xc5 || // Differential progressive DCT (SOF6)
  6394. imgData.charCodeAt(i + 1) === 0xc6 || // Differential spatial (SOF7)
  6395. imgData.charCodeAt(i + 1) === 0xc7) {
  6396. height = imgData.charCodeAt(i + 5) * 256 + imgData.charCodeAt(i + 6);
  6397. width = imgData.charCodeAt(i + 7) * 256 + imgData.charCodeAt(i + 8);
  6398. numcomponents = imgData.charCodeAt(i + 9);
  6399. return [width, height, numcomponents];
  6400. } else {
  6401. i += 2;
  6402. blockLength = imgData.charCodeAt(i) * 256 + imgData.charCodeAt(i + 1);
  6403. }
  6404. }
  6405. },
  6406. getJpegSizeFromBytes = function getJpegSizeFromBytes(data) {
  6407. var hdr = data[0] << 8 | data[1];
  6408. if (hdr !== 0xffd8) throw new Error("Supplied data is not a JPEG");
  6409. var len = data.length,
  6410. block = (data[4] << 8) + data[5],
  6411. pos = 4,
  6412. bytes,
  6413. width,
  6414. height,
  6415. numcomponents;
  6416. while (pos < len) {
  6417. pos += block;
  6418. bytes = readBytes(data, pos);
  6419. block = (bytes[2] << 8) + bytes[3];
  6420. if ((bytes[1] === 0xc0 || bytes[1] === 0xc2) && bytes[0] === 0xff && block > 7) {
  6421. bytes = readBytes(data, pos + 5);
  6422. width = (bytes[2] << 8) + bytes[3];
  6423. height = (bytes[0] << 8) + bytes[1];
  6424. numcomponents = bytes[4];
  6425. return {
  6426. width: width,
  6427. height: height,
  6428. numcomponents: numcomponents
  6429. };
  6430. }
  6431. pos += 2;
  6432. }
  6433. throw new Error("getJpegSizeFromBytes could not find the size of the image");
  6434. },
  6435. readBytes = function readBytes(data, offset) {
  6436. return data.subarray(offset, offset + 5);
  6437. };
  6438. /**
  6439. * @ignore
  6440. */
  6441. jsPDFAPI.processJPEG = function (data, index, alias, compression, dataAsBinaryString, colorSpace) {
  6442. var filter = this.decode.DCT_DECODE,
  6443. bpc = 8,
  6444. dims;
  6445. if (!this.isString(data) && !this.isArrayBuffer(data) && !this.isArrayBufferView(data)) {
  6446. return null;
  6447. }
  6448. if (this.isString(data)) {
  6449. dims = getJpegSize(data);
  6450. }
  6451. if (this.isArrayBuffer(data)) {
  6452. data = new Uint8Array(data);
  6453. }
  6454. if (this.isArrayBufferView(data)) {
  6455. dims = getJpegSizeFromBytes(data); // if we already have a stored binary string rep use that
  6456. data = dataAsBinaryString || this.arrayBufferToBinaryString(data);
  6457. }
  6458. if (colorSpace === undefined) {
  6459. switch (dims.numcomponents) {
  6460. case 1:
  6461. colorSpace = this.color_spaces.DEVICE_GRAY;
  6462. break;
  6463. case 4:
  6464. colorSpace = this.color_spaces.DEVICE_CMYK;
  6465. break;
  6466. default:
  6467. case 3:
  6468. colorSpace = this.color_spaces.DEVICE_RGB;
  6469. break;
  6470. }
  6471. }
  6472. return this.createImageInfo(data, dims.width, dims.height, colorSpace, bpc, filter, index, alias);
  6473. };
  6474. /**
  6475. * @ignore
  6476. */
  6477. jsPDFAPI.processJPG = function ()
  6478. /*data, index, alias, compression, dataAsBinaryString*/
  6479. {
  6480. return this.processJPEG.apply(this, arguments);
  6481. };
  6482. /**
  6483. * @name loadImageFile
  6484. * @function
  6485. * @param {string} path
  6486. * @param {boolean} sync
  6487. * @param {function} callback
  6488. */
  6489. jsPDFAPI.loadImageFile = function (path, sync, callback) {
  6490. sync = sync || true;
  6491. callback = callback || function () {};
  6492. var isNode = Object.prototype.toString.call(typeof process !== "undefined" ? process : 0) === "[object process]";
  6493. var xhrMethod = function xhrMethod(url, sync, callback) {
  6494. var req = new XMLHttpRequest();
  6495. var byteArray = [];
  6496. var i = 0;
  6497. var sanitizeUnicode = function sanitizeUnicode(data) {
  6498. var dataLength = data.length;
  6499. var StringFromCharCode = String.fromCharCode; //Transform Unicode to ASCII
  6500. for (i = 0; i < dataLength; i += 1) {
  6501. byteArray.push(StringFromCharCode(data.charCodeAt(i) & 0xff));
  6502. }
  6503. return byteArray.join("");
  6504. };
  6505. req.open("GET", url, !sync); // XHR binary charset opt by Marcus Granado 2006 [http://mgran.blogspot.com]
  6506. req.overrideMimeType("text/plain; charset=x-user-defined");
  6507. if (sync === false) {
  6508. req.onload = function () {
  6509. return sanitizeUnicode(this.responseText);
  6510. };
  6511. }
  6512. req.send(null);
  6513. if (req.status !== 200) {
  6514. console.warn('Unable to load file "' + url + '"');
  6515. return;
  6516. }
  6517. if (sync) {
  6518. return sanitizeUnicode(req.responseText);
  6519. }
  6520. }; //we have a browser and probably no CORS-Problem
  6521. if ((typeof window === "undefined" ? "undefined" : _typeof(window)) !== undefined && (typeof location === "undefined" ? "undefined" : _typeof(location)) === "object" && location.protocol.substr(0, 4) === "http") {
  6522. return xhrMethod(path, sync, callback);
  6523. }
  6524. };
  6525. /**
  6526. * @name getImageProperties
  6527. * @function
  6528. * @param {Object} imageData
  6529. * @returns {Object}
  6530. */
  6531. jsPDFAPI.getImageProperties = function (imageData) {
  6532. var info;
  6533. var tmpImageData = "";
  6534. var format;
  6535. if (isDOMElement(imageData)) {
  6536. imageData = createDataURIFromElement(imageData);
  6537. }
  6538. if (this.isString(imageData)) {
  6539. tmpImageData = this.convertStringToImageData(imageData);
  6540. if (tmpImageData !== "") {
  6541. imageData = tmpImageData;
  6542. } else {
  6543. tmpImageData = this.loadImageFile(imageData);
  6544. if (tmpImageData !== undefined) {
  6545. imageData = tmpImageData;
  6546. }
  6547. }
  6548. }
  6549. format = this.getImageFileTypeByImageData(imageData);
  6550. if (!isImageTypeSupported(format)) throw new Error("addImage does not support files of type '" + format + "', please ensure that a plugin for '" + format + "' support is added.");
  6551. /**
  6552. * need to test if it's more efficient to convert all binary strings
  6553. * to TypedArray - or should we just leave and process as string?
  6554. */
  6555. if (this.supportsArrayBuffer()) {
  6556. // no need to convert if imageData is already uint8array
  6557. if (!(imageData instanceof Uint8Array)) {
  6558. imageData = this.binaryStringToUint8Array(imageData);
  6559. }
  6560. }
  6561. info = this["process" + format.toUpperCase()](imageData);
  6562. if (!info) {
  6563. throw new Error("An unkwown error occurred whilst processing the image");
  6564. }
  6565. return {
  6566. fileType: format,
  6567. width: info.w,
  6568. height: info.h,
  6569. colorSpace: info.cs,
  6570. compressionMode: info.f,
  6571. bitsPerComponent: info.bpc
  6572. };
  6573. };
  6574. })(jsPDF.API);
  6575. /**
  6576. * @license
  6577. * Copyright (c) 2014 Steven Spungin (TwelveTone LLC) steven@twelvetone.tv
  6578. *
  6579. * Licensed under the MIT License.
  6580. * http://opensource.org/licenses/mit-license
  6581. */
  6582. /**
  6583. * jsPDF Annotations PlugIn
  6584. *
  6585. * There are many types of annotations in a PDF document. Annotations are placed
  6586. * on a page at a particular location. They are not 'attached' to an object.
  6587. * <br />
  6588. * This plugin current supports <br />
  6589. * <li> Goto Page (set pageNumber and top in options)
  6590. * <li> Goto Name (set name and top in options)
  6591. * <li> Goto URL (set url in options)
  6592. * <p>
  6593. * The destination magnification factor can also be specified when goto is a page number or a named destination. (see documentation below)
  6594. * (set magFactor in options). XYZ is the default.
  6595. * </p>
  6596. * <p>
  6597. * Links, Text, Popup, and FreeText are supported.
  6598. * </p>
  6599. * <p>
  6600. * Options In PDF spec Not Implemented Yet
  6601. * <li> link border
  6602. * <li> named target
  6603. * <li> page coordinates
  6604. * <li> destination page scaling and layout
  6605. * <li> actions other than URL and GotoPage
  6606. * <li> background / hover actions
  6607. * </p>
  6608. * @name annotations
  6609. * @module
  6610. */
  6611. /*
  6612. Destination Magnification Factors
  6613. See PDF 1.3 Page 386 for meanings and options
  6614. [supported]
  6615. XYZ (options; left top zoom)
  6616. Fit (no options)
  6617. FitH (options: top)
  6618. FitV (options: left)
  6619. [not supported]
  6620. FitR
  6621. FitB
  6622. FitBH
  6623. FitBV
  6624. */
  6625. (function (jsPDFAPI) {
  6626. var annotationPlugin = {
  6627. /**
  6628. * An array of arrays, indexed by <em>pageNumber</em>.
  6629. */
  6630. annotations: [],
  6631. f2: function f2(number) {
  6632. return number.toFixed(2);
  6633. },
  6634. notEmpty: function notEmpty(obj) {
  6635. if (typeof obj != "undefined") {
  6636. if (obj != "") {
  6637. return true;
  6638. }
  6639. }
  6640. }
  6641. };
  6642. jsPDF.API.annotationPlugin = annotationPlugin;
  6643. jsPDF.API.events.push(["addPage", function (info) {
  6644. this.annotationPlugin.annotations[info.pageNumber] = [];
  6645. }]);
  6646. jsPDFAPI.events.push(["putPage", function (info) {
  6647. //TODO store annotations in pageContext so reorder/remove will not affect them.
  6648. var pageAnnos = this.annotationPlugin.annotations[info.pageNumber];
  6649. var found = false;
  6650. for (var a = 0; a < pageAnnos.length && !found; a++) {
  6651. var anno = pageAnnos[a];
  6652. switch (anno.type) {
  6653. case "link":
  6654. if (annotationPlugin.notEmpty(anno.options.url) || annotationPlugin.notEmpty(anno.options.pageNumber)) {
  6655. found = true;
  6656. break;
  6657. }
  6658. case "reference":
  6659. case "text":
  6660. case "freetext":
  6661. found = true;
  6662. break;
  6663. }
  6664. }
  6665. if (found == false) {
  6666. return;
  6667. }
  6668. this.internal.write("/Annots [");
  6669. var f2 = this.annotationPlugin.f2;
  6670. var k = this.internal.scaleFactor;
  6671. var pageHeight = this.internal.pageSize.getHeight();
  6672. var pageInfo = this.internal.getPageInfo(info.pageNumber);
  6673. for (var a = 0; a < pageAnnos.length; a++) {
  6674. var anno = pageAnnos[a];
  6675. switch (anno.type) {
  6676. case "reference":
  6677. // References to Widget Anotations (for AcroForm Fields)
  6678. this.internal.write(" " + anno.object.objId + " 0 R ");
  6679. break;
  6680. case "text":
  6681. // Create a an object for both the text and the popup
  6682. var objText = this.internal.newAdditionalObject();
  6683. var objPopup = this.internal.newAdditionalObject();
  6684. var title = anno.title || "Note";
  6685. 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) + "] ";
  6686. line = "<</Type /Annot /Subtype /" + "Text" + " " + rect + "/Contents (" + anno.contents + ")";
  6687. line += " /Popup " + objPopup.objId + " 0 R";
  6688. line += " /P " + pageInfo.objId + " 0 R";
  6689. line += " /T (" + title + ") >>";
  6690. objText.content = line;
  6691. var parent = objText.objId + " 0 R";
  6692. var popoff = 30;
  6693. 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) + "] ";
  6694. line = "<</Type /Annot /Subtype /" + "Popup" + " " + rect + " /Parent " + parent;
  6695. if (anno.open) {
  6696. line += " /Open true";
  6697. }
  6698. line += " >>";
  6699. objPopup.content = line;
  6700. this.internal.write(objText.objId, "0 R", objPopup.objId, "0 R");
  6701. break;
  6702. case "freetext":
  6703. 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) + "] ";
  6704. var color = anno.color || "#000000";
  6705. line = "<</Type /Annot /Subtype /" + "FreeText" + " " + rect + "/Contents (" + anno.contents + ")";
  6706. line += " /DS(font: Helvetica,sans-serif 12.0pt; text-align:left; color:#" + color + ")";
  6707. line += " /Border [0 0 0]";
  6708. line += " >>";
  6709. this.internal.write(line);
  6710. break;
  6711. case "link":
  6712. if (anno.options.name) {
  6713. var loc = this.annotations._nameMap[anno.options.name];
  6714. anno.options.pageNumber = loc.page;
  6715. anno.options.top = loc.y;
  6716. } else {
  6717. if (!anno.options.top) {
  6718. anno.options.top = 0;
  6719. }
  6720. }
  6721. 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) + "] ";
  6722. var line = "";
  6723. if (anno.options.url) {
  6724. line = "<</Type /Annot /Subtype /Link " + rect + "/Border [0 0 0] /A <</S /URI /URI (" + anno.options.url + ") >>";
  6725. } else if (anno.options.pageNumber) {
  6726. // first page is 0
  6727. var info = this.internal.getPageInfo(anno.options.pageNumber);
  6728. line = "<</Type /Annot /Subtype /Link " + rect + "/Border [0 0 0] /Dest [" + info.objId + " 0 R";
  6729. anno.options.magFactor = anno.options.magFactor || "XYZ";
  6730. switch (anno.options.magFactor) {
  6731. case "Fit":
  6732. line += " /Fit]";
  6733. break;
  6734. case "FitH":
  6735. //anno.options.top = anno.options.top || f2(pageHeight * k);
  6736. line += " /FitH " + anno.options.top + "]";
  6737. break;
  6738. case "FitV":
  6739. anno.options.left = anno.options.left || 0;
  6740. line += " /FitV " + anno.options.left + "]";
  6741. break;
  6742. case "XYZ":
  6743. default:
  6744. var top = f2((pageHeight - anno.options.top) * k); // || f2(pageHeight * k);
  6745. anno.options.left = anno.options.left || 0; // 0 or null zoom will not change zoom factor
  6746. if (typeof anno.options.zoom === "undefined") {
  6747. anno.options.zoom = 0;
  6748. }
  6749. line += " /XYZ " + anno.options.left + " " + top + " " + anno.options.zoom + "]";
  6750. break;
  6751. }
  6752. }
  6753. if (line != "") {
  6754. line += " >>";
  6755. this.internal.write(line);
  6756. }
  6757. break;
  6758. }
  6759. }
  6760. this.internal.write("]");
  6761. }]);
  6762. /**
  6763. * @name createAnnotation
  6764. * @function
  6765. * @param {Object} options
  6766. */
  6767. jsPDFAPI.createAnnotation = function (options) {
  6768. switch (options.type) {
  6769. case "link":
  6770. this.link(options.bounds.x, options.bounds.y, options.bounds.w, options.bounds.h, options);
  6771. break;
  6772. case "text":
  6773. case "freetext":
  6774. this.annotationPlugin.annotations[this.internal.getCurrentPageInfo().pageNumber].push(options);
  6775. break;
  6776. }
  6777. };
  6778. /**
  6779. * Create a link
  6780. *
  6781. * valid options
  6782. * <li> pageNumber or url [required]
  6783. * <p>If pageNumber is specified, top and zoom may also be specified</p>
  6784. * @name link
  6785. * @function
  6786. * @param {number} x
  6787. * @param {number} y
  6788. * @param {number} w
  6789. * @param {number} h
  6790. * @param {Object} options
  6791. */
  6792. jsPDFAPI.link = function (x, y, w, h, options) {
  6793. this.annotationPlugin.annotations[this.internal.getCurrentPageInfo().pageNumber].push({
  6794. x: x,
  6795. y: y,
  6796. w: w,
  6797. h: h,
  6798. options: options,
  6799. type: "link"
  6800. });
  6801. };
  6802. /**
  6803. * Currently only supports single line text.
  6804. * Returns the width of the text/link
  6805. *
  6806. * @name textWithLink
  6807. * @function
  6808. * @param {string} text
  6809. * @param {number} x
  6810. * @param {number} y
  6811. * @param {Object} options
  6812. * @returns {number} width the width of the text/link
  6813. */
  6814. jsPDFAPI.textWithLink = function (text, x, y, options) {
  6815. var width = this.getTextWidth(text);
  6816. var height = this.internal.getLineHeight() / this.internal.scaleFactor;
  6817. this.text(text, x, y); //TODO We really need the text baseline height to do this correctly.
  6818. // Or ability to draw text on top, bottom, center, or baseline.
  6819. y += height * 0.2;
  6820. this.link(x, y - height, width, height, options);
  6821. return width;
  6822. }; //TODO move into external library
  6823. /**
  6824. * @name getTextWidth
  6825. * @function
  6826. * @param {string} text
  6827. * @returns {number} txtWidth
  6828. */
  6829. jsPDFAPI.getTextWidth = function (text) {
  6830. var fontSize = this.internal.getFontSize();
  6831. var txtWidth = this.getStringUnitWidth(text) * fontSize / this.internal.scaleFactor;
  6832. return txtWidth;
  6833. }; //TODO move into external library
  6834. /**
  6835. * @name getLineHeight
  6836. * @function
  6837. * @returns {number} lineHeight
  6838. */
  6839. jsPDFAPI.getLineHeight = function () {
  6840. return this.internal.getLineHeight();
  6841. };
  6842. return this;
  6843. })(jsPDF.API);
  6844. /**
  6845. * @license
  6846. * Copyright (c) 2017 Aras Abbasi
  6847. *
  6848. * Licensed under the MIT License.
  6849. * http://opensource.org/licenses/mit-license
  6850. */
  6851. /**
  6852. * jsPDF arabic parser PlugIn
  6853. *
  6854. * @name arabic
  6855. * @module
  6856. */
  6857. (function (jsPDFAPI) {
  6858. var arLangCodes = {
  6859. ar: "Arabic (Standard)",
  6860. "ar-DZ": "Arabic (Algeria)",
  6861. "ar-BH": "Arabic (Bahrain)",
  6862. "ar-EG": "Arabic (Egypt)",
  6863. "ar-IQ": "Arabic (Iraq)",
  6864. "ar-JO": "Arabic (Jordan)",
  6865. "ar-KW": "Arabic (Kuwait)",
  6866. "ar-LB": "Arabic (Lebanon)",
  6867. "ar-LY": "Arabic (Libya)",
  6868. "ar-MA": "Arabic (Morocco)",
  6869. "ar-OM": "Arabic (Oman)",
  6870. "ar-QA": "Arabic (Qatar)",
  6871. "ar-SA": "Arabic (Saudi Arabia)",
  6872. "ar-SY": "Arabic (Syria)",
  6873. "ar-TN": "Arabic (Tunisia)",
  6874. "ar-AE": "Arabic (U.A.E.)",
  6875. "ar-YE": "Arabic (Yemen)",
  6876. fa: "Persian",
  6877. "fa-IR": "Persian/Iran",
  6878. ur: "Urdu"
  6879. };
  6880. var arLangCodesKeys = Object.keys(arLangCodes);
  6881. /**
  6882. * Arabic shape substitutions: char code => (isolated, final, initial, medial).
  6883. */
  6884. var arabicSubst = {
  6885. 1569: [65152],
  6886. 1570: [65153, 65154, 65153, 65154],
  6887. 1571: [65155, 65156, 65155, 65156],
  6888. 1572: [65157, 65158],
  6889. 1573: [65159, 65160, 65159, 65160],
  6890. 1574: [65161, 65162, 65163, 65164],
  6891. 1575: [65165, 65166, 65165, 65166],
  6892. 1576: [65167, 65168, 65169, 65170],
  6893. 1577: [65171, 65172],
  6894. 1578: [65173, 65174, 65175, 65176],
  6895. 1579: [65177, 65178, 65179, 65180],
  6896. 1580: [65181, 65182, 65183, 65184],
  6897. 1581: [65185, 65186, 65187, 65188],
  6898. 1582: [65189, 65190, 65191, 65192],
  6899. 1583: [65193, 65194, 65193],
  6900. 1584: [65195, 65196, 65195],
  6901. 1585: [65197, 65198, 65197],
  6902. 1586: [65199, 65200, 65199],
  6903. 1587: [65201, 65202, 65203, 65204],
  6904. 1588: [65205, 65206, 65207, 65208],
  6905. 1589: [65209, 65210, 65211, 65212],
  6906. 1590: [65213, 65214, 65215, 65216],
  6907. 1591: [65217, 65218, 65219, 65220],
  6908. 1592: [65221, 65222, 65223, 65224],
  6909. 1593: [65225, 65226, 65227, 65228],
  6910. 1594: [65229, 65230, 65231, 65232],
  6911. 1601: [65233, 65234, 65235, 65236],
  6912. 1602: [65237, 65238, 65239, 65240],
  6913. 1603: [65241, 65242, 65243, 65244],
  6914. 1604: [65245, 65246, 65247, 65248],
  6915. 1605: [65249, 65250, 65251, 65252],
  6916. 1606: [65253, 65254, 65255, 65256],
  6917. 1607: [65257, 65258, 65259, 65260],
  6918. 1608: [65261, 65262, 65261],
  6919. 1609: [65263, 65264, 64488, 64489],
  6920. 1610: [65265, 65266, 65267, 65268],
  6921. 1649: [64336, 64337],
  6922. 1655: [64477],
  6923. 1657: [64358, 64359, 64360, 64361],
  6924. 1658: [64350, 64351, 64352, 64353],
  6925. 1659: [64338, 64339, 64340, 64341],
  6926. 1662: [64342, 64343, 64344, 64345],
  6927. 1663: [64354, 64355, 64356, 64357],
  6928. 1664: [64346, 64347, 64348, 64349],
  6929. 1667: [64374, 64375, 64376, 64377],
  6930. 1668: [64370, 64371, 64372, 64373],
  6931. 1670: [64378, 64379, 64380, 64381],
  6932. 1671: [64382, 64383, 64384, 64385],
  6933. 1672: [64392, 64393],
  6934. 1676: [64388, 64389],
  6935. 1677: [64386, 64387],
  6936. 1678: [64390, 64391],
  6937. 1681: [64396, 64397],
  6938. 1688: [64394, 64395, 64394],
  6939. 1700: [64362, 64363, 64364, 64365],
  6940. 1702: [64366, 64367, 64368, 64369],
  6941. 1705: [64398, 64399, 64400, 64401],
  6942. 1709: [64467, 64468, 64469, 64470],
  6943. 1711: [64402, 64403, 64404, 64405],
  6944. 1713: [64410, 64411, 64412, 64413],
  6945. 1715: [64406, 64407, 64408, 64409],
  6946. 1722: [64414, 64415],
  6947. 1723: [64416, 64417, 64418, 64419],
  6948. 1726: [64426, 64427, 64428, 64429],
  6949. 1728: [64420, 64421],
  6950. 1729: [64422, 64423, 64424, 64425],
  6951. 1733: [64480, 64481],
  6952. 1734: [64473, 64474],
  6953. 1735: [64471, 64472],
  6954. 1736: [64475, 64476],
  6955. 1737: [64482, 64483],
  6956. 1739: [64478, 64479],
  6957. 1740: [64508, 64509, 64510, 64511],
  6958. 1744: [64484, 64485, 64486, 64487],
  6959. 1746: [64430, 64431],
  6960. 1747: [64432, 64433]
  6961. };
  6962. var arabiclaasubst = {
  6963. 1570: [65269, 65270, 65269, 65270],
  6964. 1571: [65271, 65272, 65271, 65272],
  6965. 1573: [65273, 65274, 65273, 65274],
  6966. 1575: [65275, 65276, 65275, 65276]
  6967. };
  6968. var arabicorigsubst = {
  6969. 1570: [65153, 65154, 65153, 65154],
  6970. 1571: [65155, 65156, 65155, 65156],
  6971. 1573: [65159, 65160, 65159, 65160],
  6972. 1575: [65165, 65166, 65165, 65166]
  6973. };
  6974. var arabic_diacritics = {
  6975. 1612: 64606,
  6976. // Shadda + Dammatan
  6977. 1613: 64607,
  6978. // Shadda + Kasratan
  6979. 1614: 64608,
  6980. // Shadda + Fatha
  6981. 1615: 64609,
  6982. // Shadda + Damma
  6983. 1616: 64610 // Shadda + Kasra
  6984. };
  6985. var alfletter = [1570, 1571, 1573, 1575];
  6986. var endedletter = [1569, 1570, 1571, 1572, 1573, 1575, 1577, 1583, 1584, 1585, 1586, 1608, 1688];
  6987. var isolatedForm = 0;
  6988. var finalForm = 1;
  6989. var initialForm = 2;
  6990. var medialForm = 3; //private
  6991. function isArabicLetter(letter) {
  6992. return letter !== undefined && arabicSubst[letter.charCodeAt(0)] !== undefined;
  6993. }
  6994. function isArabicEndLetter(letter) {
  6995. return letter !== undefined && endedletter.indexOf(letter.charCodeAt(0)) >= 0;
  6996. }
  6997. function isArabicAlfLetter(letter) {
  6998. return letter !== undefined && alfletter.indexOf(letter.charCodeAt(0)) >= 0;
  6999. }
  7000. function arabicLetterHasFinalForm(letter) {
  7001. return isArabicLetter(letter) && arabicSubst[letter.charCodeAt(0)].length >= 2;
  7002. }
  7003. function arabicLetterHasMedialForm(letter) {
  7004. return isArabicLetter(letter) && arabicSubst[letter.charCodeAt(0)].length == 4;
  7005. }
  7006. function isArabicDiacritic(letter) {
  7007. return letter !== undefined && arabic_diacritics[letter.charCodeAt(0)] !== undefined;
  7008. }
  7009. function getCorrectForm(currentChar, beforeChar, nextChar, arabicSubstition) {
  7010. if (!isArabicLetter(currentChar)) {
  7011. return -1;
  7012. }
  7013. arabicSubstition = arabicSubstition || {};
  7014. arabicSubst = Object.assign(arabicSubst, arabicSubstition);
  7015. if (!arabicLetterHasFinalForm(currentChar) || !isArabicLetter(beforeChar) && !isArabicLetter(nextChar) || !isArabicLetter(nextChar) && isArabicEndLetter(beforeChar) || isArabicEndLetter(currentChar) && !isArabicLetter(beforeChar) || isArabicEndLetter(currentChar) && isArabicAlfLetter(beforeChar) || isArabicEndLetter(currentChar) && isArabicEndLetter(beforeChar)) {
  7016. arabicSubst = Object.assign(arabicSubst, arabicorigsubst);
  7017. return isolatedForm;
  7018. }
  7019. if (arabicLetterHasMedialForm(currentChar) && isArabicLetter(beforeChar) && !isArabicEndLetter(beforeChar) && isArabicLetter(nextChar) && arabicLetterHasFinalForm(nextChar)) {
  7020. arabicSubst = Object.assign(arabicSubst, arabicorigsubst);
  7021. return medialForm;
  7022. }
  7023. if (isArabicEndLetter(currentChar) || !isArabicLetter(nextChar)) {
  7024. arabicSubst = Object.assign(arabicSubst, arabicorigsubst);
  7025. return finalForm;
  7026. }
  7027. arabicSubst = Object.assign(arabicSubst, arabicorigsubst);
  7028. return initialForm;
  7029. }
  7030. var commonSubstition = function commonSubstition(character) {
  7031. var replacementTable = {
  7032. "(": ")",
  7033. ")": "("
  7034. };
  7035. return replacementTable[character] || character;
  7036. };
  7037. /**
  7038. * @name processArabic
  7039. * @function
  7040. * @param {string} text
  7041. * @param {boolean} reverse
  7042. * @returns {string}
  7043. */
  7044. var processArabic = jsPDFAPI.processArabic = function (text, reverse) {
  7045. text = text || "";
  7046. reverse = reverse || false;
  7047. var result = "";
  7048. var i = 0;
  7049. var position = 0;
  7050. var currentLetter = "";
  7051. var prevLetter = "";
  7052. var nextLetter = "";
  7053. var resultingLetter;
  7054. var localPrevLetter;
  7055. var localCurrentLetter;
  7056. var localNextLetter;
  7057. for (i = 0; i < text.length; i += 1) {
  7058. currentLetter = text[i];
  7059. prevLetter = text[i - 1];
  7060. nextLetter = text[i + 1];
  7061. if (!isArabicLetter(currentLetter)) {
  7062. result += reverse ? commonSubstition(currentLetter) : currentLetter;
  7063. } else {
  7064. if (prevLetter !== undefined && prevLetter.charCodeAt(0) === 1604 && isArabicAlfLetter(currentLetter)) {
  7065. localPrevLetter = text[i - 2];
  7066. localCurrentLetter = currentLetter;
  7067. localNextLetter = text[i + 1];
  7068. position = getCorrectForm(localCurrentLetter, localPrevLetter, localNextLetter, arabiclaasubst);
  7069. resultingLetter = String.fromCharCode(arabiclaasubst[currentLetter.charCodeAt(0)][position]);
  7070. result = result.substr(0, result.length - 1) + resultingLetter;
  7071. } else if (prevLetter !== undefined && prevLetter.charCodeAt(0) === 1617 && isArabicDiacritic(currentLetter)) {
  7072. localPrevLetter = text[i - 2];
  7073. localCurrentLetter = currentLetter;
  7074. localNextLetter = text[i + 1];
  7075. position = getCorrectForm(localCurrentLetter, localPrevLetter, localNextLetter, arabicorigsubst);
  7076. resultingLetter = String.fromCharCode(arabic_diacritics[currentLetter.charCodeAt(0)][position]);
  7077. result = result.substr(0, result.length - 1) + resultingLetter;
  7078. } else {
  7079. position = getCorrectForm(currentLetter, prevLetter, nextLetter, arabicorigsubst);
  7080. result += String.fromCharCode(arabicSubst[currentLetter.charCodeAt(0)][position]);
  7081. }
  7082. }
  7083. }
  7084. return reverse ? result.split("").reverse().join("") : result;
  7085. };
  7086. var arabicParserFunction = function arabicParserFunction(args) {
  7087. var text = args.text;
  7088. var x = args.x;
  7089. var y = args.y;
  7090. var options = args.options || {};
  7091. var mutex = args.mutex || {};
  7092. var lang = options.lang;
  7093. var tmpText = [];
  7094. if (arLangCodesKeys.indexOf(lang) >= 0) {
  7095. if (Object.prototype.toString.call(text) === "[object Array]") {
  7096. var i = 0;
  7097. tmpText = [];
  7098. for (i = 0; i < text.length; i += 1) {
  7099. if (Object.prototype.toString.call(text[i]) === "[object Array]") {
  7100. tmpText.push([processArabic(text[i][0], true), text[i][1], text[i][2]]);
  7101. } else {
  7102. tmpText.push([processArabic(text[i], true)]);
  7103. }
  7104. }
  7105. args.text = tmpText;
  7106. } else {
  7107. args.text = processArabic(text, true);
  7108. } //force charSpace if not given.
  7109. if (options.charSpace === undefined) {
  7110. args.options.charSpace = 0;
  7111. } //if R2L is true, set it false.
  7112. if (options.R2L === true) {
  7113. args.options.R2L = false;
  7114. }
  7115. }
  7116. };
  7117. jsPDFAPI.events.push(["preProcessText", arabicParserFunction]);
  7118. })(jsPDF.API);
  7119. /** @license
  7120. * jsPDF Autoprint Plugin
  7121. *
  7122. * Licensed under the MIT License.
  7123. * http://opensource.org/licenses/mit-license
  7124. */
  7125. /**
  7126. * @name autoprint
  7127. * @module
  7128. */
  7129. (function (jsPDFAPI) {
  7130. /**
  7131. * Makes the PDF automatically print. This works in Chrome, Firefox, Acrobat
  7132. * Reader.
  7133. *
  7134. * @name autoPrint
  7135. * @function
  7136. * @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 .
  7137. * @returns {jsPDF}
  7138. * @example
  7139. * var doc = new jsPDF();
  7140. * doc.text(10, 10, 'This is a test');
  7141. * doc.autoPrint({variant: 'non-conform'});
  7142. * doc.save('autoprint.pdf');
  7143. */
  7144. jsPDFAPI.autoPrint = function (options) {
  7145. var refAutoPrintTag;
  7146. options = options || {};
  7147. options.variant = options.variant || "non-conform";
  7148. switch (options.variant) {
  7149. case "javascript":
  7150. //https://github.com/Rob--W/pdf.js/commit/c676ecb5a0f54677b9f3340c3ef2cf42225453bb
  7151. this.addJS("print({});");
  7152. break;
  7153. case "non-conform":
  7154. default:
  7155. this.internal.events.subscribe("postPutResources", function () {
  7156. refAutoPrintTag = this.internal.newObject();
  7157. this.internal.out("<<");
  7158. this.internal.out("/S /Named");
  7159. this.internal.out("/Type /Action");
  7160. this.internal.out("/N /Print");
  7161. this.internal.out(">>");
  7162. this.internal.out("endobj");
  7163. });
  7164. this.internal.events.subscribe("putCatalog", function () {
  7165. this.internal.out("/OpenAction " + refAutoPrintTag + " 0 R");
  7166. });
  7167. break;
  7168. }
  7169. return this;
  7170. };
  7171. })(jsPDF.API);
  7172. /**
  7173. * @license
  7174. * Copyright (c) 2014 Steven Spungin (TwelveTone LLC) steven@twelvetone.tv
  7175. *
  7176. * Licensed under the MIT License.
  7177. * http://opensource.org/licenses/mit-license
  7178. */
  7179. /**
  7180. * jsPDF Canvas PlugIn
  7181. * This plugin mimics the HTML5 Canvas
  7182. *
  7183. * The goal is to provide a way for current canvas users to print directly to a PDF.
  7184. * @name canvas
  7185. * @module
  7186. */
  7187. (function (jsPDFAPI) {
  7188. jsPDFAPI.events.push(["initialized", function () {
  7189. this.canvas.pdf = this;
  7190. }]);
  7191. /**
  7192. * @name canvas
  7193. * @static
  7194. * @type {Object}
  7195. */
  7196. jsPDFAPI.canvas = {
  7197. /**
  7198. * @name getContext
  7199. * @function
  7200. * @param {string} the context type
  7201. */
  7202. getContext: function getContext(name) {
  7203. this.pdf.context2d._canvas = this;
  7204. return this.pdf.context2d;
  7205. },
  7206. childNodes: [],
  7207. style: {},
  7208. autoContext2dResizeX: true,
  7209. autoContext2dResizeY: true
  7210. };
  7211. /**
  7212. * Width of the canvas
  7213. *
  7214. * @name width
  7215. * @property {number} width
  7216. */
  7217. Object.defineProperty(jsPDFAPI.canvas, "width", {
  7218. get: function get() {
  7219. return this._width;
  7220. },
  7221. set: function set(value) {
  7222. this._width = value;
  7223. if (this.autoContext2dResizeX) {
  7224. this.getContext("2d").pageWrapX = value + 1;
  7225. }
  7226. }
  7227. });
  7228. /**
  7229. * Height of the canvas
  7230. *
  7231. * @name height
  7232. * @property {number} height
  7233. */
  7234. Object.defineProperty(jsPDFAPI.canvas, "height", {
  7235. get: function get() {
  7236. return this._height;
  7237. },
  7238. set: function set(value) {
  7239. this._height = value;
  7240. if (this.autoContext2dResizeY) {
  7241. this.getContext("2d").pageWrapY = value + 1;
  7242. }
  7243. }
  7244. });
  7245. return this;
  7246. })(jsPDF.API);
  7247. /**
  7248. * @license
  7249. * ====================================================================
  7250. * Copyright (c) 2013 Youssef Beddad, youssef.beddad@gmail.com
  7251. * 2013 Eduardo Menezes de Morais, eduardo.morais@usp.br
  7252. * 2013 Lee Driscoll, https://github.com/lsdriscoll
  7253. * 2014 Juan Pablo Gaviria, https://github.com/juanpgaviria
  7254. * 2014 James Hall, james@parall.ax
  7255. * 2014 Diego Casorran, https://github.com/diegocr
  7256. *
  7257. *
  7258. * ====================================================================
  7259. */
  7260. /**
  7261. * @name cell
  7262. * @module
  7263. */
  7264. (function (jsPDFAPI) {
  7265. /*jslint browser:true */
  7266. /*global document: false, jsPDF */
  7267. var padding = 3,
  7268. margin = 13,
  7269. headerFunction,
  7270. lastCellPos = {
  7271. x: undefined,
  7272. y: undefined,
  7273. w: undefined,
  7274. h: undefined,
  7275. ln: undefined
  7276. },
  7277. pages = 1,
  7278. setLastCellPosition = function setLastCellPosition(x, y, w, h, ln) {
  7279. lastCellPos = {
  7280. x: x,
  7281. y: y,
  7282. w: w,
  7283. h: h,
  7284. ln: ln
  7285. };
  7286. },
  7287. getLastCellPosition = function getLastCellPosition() {
  7288. return lastCellPos;
  7289. },
  7290. NO_MARGINS = {
  7291. left: 0,
  7292. top: 0,
  7293. bottom: 0
  7294. };
  7295. /**
  7296. * @name setHeaderFunction
  7297. * @function
  7298. * @param {function} func
  7299. */
  7300. jsPDFAPI.setHeaderFunction = function (func) {
  7301. headerFunction = func;
  7302. };
  7303. /**
  7304. * @name getTextDimensions
  7305. * @function
  7306. * @param {string} txt
  7307. * @returns {Object} dimensions
  7308. */
  7309. jsPDFAPI.getTextDimensions = function (text, options) {
  7310. var fontSize = this.table_font_size || this.internal.getFontSize();
  7311. var fontStyle = this.internal.getFont().fontStyle;
  7312. options = options || {};
  7313. var scaleFactor = options.scaleFactor || this.internal.scaleFactor;
  7314. var width = 0;
  7315. var amountOfLines = 0;
  7316. var height = 0;
  7317. var tempWidth = 0;
  7318. if (typeof text === "string") {
  7319. width = this.getStringUnitWidth(text) * fontSize;
  7320. if (width !== 0) {
  7321. amountOfLines = 1;
  7322. }
  7323. } else if (Object.prototype.toString.call(text) === "[object Array]") {
  7324. for (var i = 0; i < text.length; i++) {
  7325. tempWidth = this.getStringUnitWidth(text[i]) * fontSize;
  7326. if (width < tempWidth) {
  7327. width = tempWidth;
  7328. }
  7329. }
  7330. if (width !== 0) {
  7331. amountOfLines = text.length;
  7332. }
  7333. } else {
  7334. console.error("getTextDimensions expects text-parameter to be of type String or an Array of Strings.");
  7335. }
  7336. width = width / scaleFactor;
  7337. height = amountOfLines * fontSize * 1.15 / scaleFactor;
  7338. return {
  7339. w: width,
  7340. h: height
  7341. };
  7342. };
  7343. /**
  7344. * @name cellAddPage
  7345. * @function
  7346. */
  7347. jsPDFAPI.cellAddPage = function () {
  7348. var margins = this.margins || NO_MARGINS;
  7349. this.addPage();
  7350. setLastCellPosition(margins.left, margins.top, undefined, undefined); //setLastCellPosition(undefined, undefined, undefined, undefined, undefined);
  7351. pages += 1;
  7352. };
  7353. /**
  7354. * @name cellInitialize
  7355. * @function
  7356. */
  7357. jsPDFAPI.cellInitialize = function () {
  7358. lastCellPos = {
  7359. x: undefined,
  7360. y: undefined,
  7361. w: undefined,
  7362. h: undefined,
  7363. ln: undefined
  7364. };
  7365. pages = 1;
  7366. };
  7367. /**
  7368. * @name cell
  7369. * @function
  7370. * @param {number} x
  7371. * @param {number} y
  7372. * @param {number} w
  7373. * @param {number} h
  7374. * @param {string} txt
  7375. * @param {number} ln lineNumber
  7376. * @param {string} align
  7377. * @return {jsPDF} jsPDF-instance
  7378. */
  7379. jsPDFAPI.cell = function (x, y, w, h, txt, ln, align) {
  7380. var curCell = getLastCellPosition();
  7381. var pgAdded = false; // If this is not the first cell, we must change its position
  7382. if (curCell.ln !== undefined) {
  7383. if (curCell.ln === ln) {
  7384. //Same line
  7385. x = curCell.x + curCell.w;
  7386. y = curCell.y;
  7387. } else {
  7388. //New line
  7389. var margins = this.margins || NO_MARGINS;
  7390. if (curCell.y + curCell.h + h + margin >= this.internal.pageSize.getHeight() - margins.bottom) {
  7391. this.cellAddPage();
  7392. pgAdded = true;
  7393. if (this.printHeaders && this.tableHeaderRow) {
  7394. this.printHeaderRow(ln, true);
  7395. }
  7396. } //We ignore the passed y: the lines may have different heights
  7397. y = getLastCellPosition().y + getLastCellPosition().h;
  7398. if (pgAdded) y = margin + 10;
  7399. }
  7400. }
  7401. if (txt[0] !== undefined) {
  7402. if (this.printingHeaderRow) {
  7403. this.rect(x, y, w, h, "FD");
  7404. } else {
  7405. this.rect(x, y, w, h);
  7406. }
  7407. if (align === "right") {
  7408. if (!(txt instanceof Array)) {
  7409. txt = [txt];
  7410. }
  7411. for (var i = 0; i < txt.length; i++) {
  7412. var currentLine = txt[i];
  7413. var textSize = this.getStringUnitWidth(currentLine) * this.internal.getFontSize();
  7414. this.text(currentLine, x + w - textSize - padding, y + this.internal.getLineHeight() * (i + 1));
  7415. }
  7416. } else {
  7417. this.text(txt, x + padding, y + this.internal.getLineHeight());
  7418. }
  7419. }
  7420. setLastCellPosition(x, y, w, h, ln);
  7421. return this;
  7422. };
  7423. /**
  7424. * Return the maximum value from an array
  7425. *
  7426. * @name arrayMax
  7427. * @function
  7428. * @param {Array} array
  7429. * @param comparisonFn
  7430. * @returns {number}
  7431. */
  7432. jsPDFAPI.arrayMax = function (array, comparisonFn) {
  7433. var max = array[0],
  7434. i,
  7435. ln,
  7436. item;
  7437. for (i = 0, ln = array.length; i < ln; i += 1) {
  7438. item = array[i];
  7439. if (comparisonFn) {
  7440. if (comparisonFn(max, item) === -1) {
  7441. max = item;
  7442. }
  7443. } else {
  7444. if (item > max) {
  7445. max = item;
  7446. }
  7447. }
  7448. }
  7449. return max;
  7450. };
  7451. /**
  7452. * Create a table from a set of data.
  7453. * @name table
  7454. * @function
  7455. * @param {Integer} [x] : left-position for top-left corner of table
  7456. * @param {Integer} [y] top-position for top-left corner of table
  7457. * @param {Object[]} [data] As array of objects containing key-value pairs corresponding to a row of data.
  7458. * @param {String[]} [headers] Omit or null to auto-generate headers at a performance cost
  7459. * @param {Object} [config.printHeaders] True to print column headers at the top of every page
  7460. * @param {Object} [config.autoSize] True to dynamically set the column widths to match the widest cell value
  7461. * @param {Object} [config.margins] margin values for left, top, bottom, and width
  7462. * @param {Object} [config.fontSize] Integer fontSize to use (optional)
  7463. * @returns {jsPDF} jsPDF-instance
  7464. */
  7465. jsPDFAPI.table = function (x, y, data, headers, config) {
  7466. if (!data) {
  7467. throw "No data for PDF table";
  7468. }
  7469. var headerNames = [],
  7470. headerPrompts = [],
  7471. header,
  7472. i,
  7473. ln,
  7474. cln,
  7475. columnMatrix = {},
  7476. columnWidths = {},
  7477. columnData,
  7478. column,
  7479. columnMinWidths = [],
  7480. j,
  7481. tableHeaderConfigs = [],
  7482. model,
  7483. jln,
  7484. func,
  7485. //set up defaults. If a value is provided in config, defaults will be overwritten:
  7486. autoSize = false,
  7487. printHeaders = true,
  7488. fontSize = 12,
  7489. margins = NO_MARGINS;
  7490. margins.width = this.internal.pageSize.getWidth();
  7491. if (config) {
  7492. //override config defaults if the user has specified non-default behavior:
  7493. if (config.autoSize === true) {
  7494. autoSize = true;
  7495. }
  7496. if (config.printHeaders === false) {
  7497. printHeaders = false;
  7498. }
  7499. if (config.fontSize) {
  7500. fontSize = config.fontSize;
  7501. }
  7502. if (config.css && typeof config.css["font-size"] !== "undefined") {
  7503. fontSize = config.css["font-size"] * 16;
  7504. }
  7505. if (config.margins) {
  7506. margins = config.margins;
  7507. }
  7508. }
  7509. /**
  7510. * @property {Number} lnMod
  7511. * Keep track of the current line number modifier used when creating cells
  7512. */
  7513. this.lnMod = 0;
  7514. lastCellPos = {
  7515. x: undefined,
  7516. y: undefined,
  7517. w: undefined,
  7518. h: undefined,
  7519. ln: undefined
  7520. }, pages = 1;
  7521. this.printHeaders = printHeaders;
  7522. this.margins = margins;
  7523. this.setFontSize(fontSize);
  7524. this.table_font_size = fontSize; // Set header values
  7525. if (headers === undefined || headers === null) {
  7526. // No headers defined so we derive from data
  7527. headerNames = Object.keys(data[0]);
  7528. } else if (headers[0] && typeof headers[0] !== "string") {
  7529. var px2pt = 0.264583 * 72 / 25.4; // Split header configs into names and prompts
  7530. for (i = 0, ln = headers.length; i < ln; i += 1) {
  7531. header = headers[i];
  7532. headerNames.push(header.name);
  7533. headerPrompts.push(header.prompt);
  7534. columnWidths[header.name] = header.width * px2pt;
  7535. }
  7536. } else {
  7537. headerNames = headers;
  7538. }
  7539. if (autoSize) {
  7540. // Create a matrix of columns e.g., {column_title: [row1_Record, row2_Record]}
  7541. func = function func(rec) {
  7542. return rec[header];
  7543. };
  7544. for (i = 0, ln = headerNames.length; i < ln; i += 1) {
  7545. header = headerNames[i];
  7546. columnMatrix[header] = data.map(func); // get header width
  7547. columnMinWidths.push(this.getTextDimensions(headerPrompts[i] || header, {
  7548. scaleFactor: 1
  7549. }).w);
  7550. column = columnMatrix[header]; // get cell widths
  7551. for (j = 0, cln = column.length; j < cln; j += 1) {
  7552. columnData = column[j];
  7553. columnMinWidths.push(this.getTextDimensions(columnData, {
  7554. scaleFactor: 1
  7555. }).w);
  7556. } // get final column width
  7557. columnWidths[header] = jsPDFAPI.arrayMax(columnMinWidths); //have to reset
  7558. columnMinWidths = [];
  7559. }
  7560. } // -- Construct the table
  7561. if (printHeaders) {
  7562. var lineHeight = this.calculateLineHeight(headerNames, columnWidths, headerPrompts.length ? headerPrompts : headerNames); // Construct the header row
  7563. for (i = 0, ln = headerNames.length; i < ln; i += 1) {
  7564. header = headerNames[i];
  7565. tableHeaderConfigs.push([x, y, columnWidths[header], lineHeight, String(headerPrompts.length ? headerPrompts[i] : header)]);
  7566. } // Store the table header config
  7567. this.setTableHeaderRow(tableHeaderConfigs); // Print the header for the start of the table
  7568. this.printHeaderRow(1, false);
  7569. } // Construct the data rows
  7570. for (i = 0, ln = data.length; i < ln; i += 1) {
  7571. var lineHeight;
  7572. model = data[i];
  7573. lineHeight = this.calculateLineHeight(headerNames, columnWidths, model);
  7574. for (j = 0, jln = headerNames.length; j < jln; j += 1) {
  7575. header = headerNames[j];
  7576. this.cell(x, y, columnWidths[header], lineHeight, model[header], i + 2, header.align);
  7577. }
  7578. }
  7579. this.lastCellPos = lastCellPos;
  7580. this.table_x = x;
  7581. this.table_y = y;
  7582. return this;
  7583. };
  7584. /**
  7585. * Calculate the height for containing the highest column
  7586. *
  7587. * @name calculateLineHeight
  7588. * @function
  7589. * @param {String[]} headerNames is the header, used as keys to the data
  7590. * @param {Integer[]} columnWidths is size of each column
  7591. * @param {Object[]} model is the line of data we want to calculate the height of
  7592. * @returns {number} lineHeight
  7593. */
  7594. jsPDFAPI.calculateLineHeight = function (headerNames, columnWidths, model) {
  7595. var header,
  7596. lineHeight = 0;
  7597. for (var j = 0; j < headerNames.length; j++) {
  7598. header = headerNames[j];
  7599. model[header] = this.splitTextToSize(String(model[header]), columnWidths[header] - padding);
  7600. var h = this.internal.getLineHeight() * model[header].length + padding;
  7601. if (h > lineHeight) lineHeight = h;
  7602. }
  7603. return lineHeight;
  7604. };
  7605. /**
  7606. * Store the config for outputting a table header
  7607. *
  7608. * @name setTableHeaderRow
  7609. * @function
  7610. * @param {Object[]} config
  7611. * An array of cell configs that would define a header row: Each config matches the config used by jsPDFAPI.cell
  7612. * except the ln parameter is excluded
  7613. */
  7614. jsPDFAPI.setTableHeaderRow = function (config) {
  7615. this.tableHeaderRow = config;
  7616. };
  7617. /**
  7618. * Output the store header row
  7619. *
  7620. * @name printHeaderRow
  7621. * @function
  7622. * @param {number} lineNumber The line number to output the header at
  7623. * @param {boolean} new_page
  7624. */
  7625. jsPDFAPI.printHeaderRow = function (lineNumber, new_page) {
  7626. if (!this.tableHeaderRow) {
  7627. throw "Property tableHeaderRow does not exist.";
  7628. }
  7629. var tableHeaderCell, tmpArray, i, ln;
  7630. this.printingHeaderRow = true;
  7631. if (headerFunction !== undefined) {
  7632. var position = headerFunction(this, pages);
  7633. setLastCellPosition(position[0], position[1], position[2], position[3], -1);
  7634. }
  7635. this.setFontStyle("bold");
  7636. var tempHeaderConf = [];
  7637. for (i = 0, ln = this.tableHeaderRow.length; i < ln; i += 1) {
  7638. this.setFillColor(200, 200, 200);
  7639. tableHeaderCell = this.tableHeaderRow[i];
  7640. if (new_page) {
  7641. this.margins.top = margin;
  7642. tableHeaderCell[1] = this.margins && this.margins.top || 0;
  7643. tempHeaderConf.push(tableHeaderCell);
  7644. }
  7645. tmpArray = [].concat(tableHeaderCell);
  7646. this.cell.apply(this, tmpArray.concat(lineNumber));
  7647. }
  7648. if (tempHeaderConf.length > 0) {
  7649. this.setTableHeaderRow(tempHeaderConf);
  7650. }
  7651. this.setFontStyle("normal");
  7652. this.printingHeaderRow = false;
  7653. };
  7654. })(jsPDF.API);
  7655. /**
  7656. * jsPDF Context2D PlugIn Copyright (c) 2014 Steven Spungin (TwelveTone LLC) steven@twelvetone.tv
  7657. *
  7658. * Licensed under the MIT License. http://opensource.org/licenses/mit-license
  7659. */
  7660. /**
  7661. * TODO implement stroke opacity (refactor from fill() method )
  7662. * TODO transform angle and radii parameters
  7663. */
  7664. /**
  7665. * This plugin mimics the HTML5 Canvas's context2d.
  7666. *
  7667. * The goal is to provide a way for current canvas implementations to print directly to a PDF.
  7668. *
  7669. * @name context2d
  7670. * @module
  7671. */
  7672. (function (jsPDFAPI, globalObj) {
  7673. jsPDFAPI.events.push(["initialized", function () {
  7674. this.context2d.pdf = this;
  7675. this.context2d.internal.pdf = this;
  7676. this.context2d.ctx = new context();
  7677. this.context2d.ctxStack = [];
  7678. this.context2d.path = [];
  7679. }]);
  7680. jsPDFAPI.context2d = {
  7681. /**
  7682. * @name pageWrapXEnabled
  7683. * @type {boolean}
  7684. * @default false
  7685. */
  7686. pageWrapXEnabled: false,
  7687. /**
  7688. * @name pageWrapYEnabled
  7689. * @type {boolean}
  7690. * @default false
  7691. */
  7692. pageWrapYEnabled: false,
  7693. /**
  7694. * @name pageWrapX
  7695. * @type {number}
  7696. * @default 9999999
  7697. */
  7698. pageWrapX: 9999999,
  7699. /**
  7700. * @name pageWrapY
  7701. * @type {number}
  7702. * @default 9999999
  7703. */
  7704. pageWrapY: 9999999,
  7705. /**
  7706. * @name ctx
  7707. * @type {Object}
  7708. */
  7709. ctx: new context(),
  7710. /**
  7711. * @name f2
  7712. * @type {function}
  7713. * @ignore
  7714. */
  7715. f2: function f2(number) {
  7716. return number.toFixed(2);
  7717. },
  7718. /**
  7719. * Fills the current drawing (path)
  7720. *
  7721. * @name fill
  7722. * @function
  7723. * @description The fill() method fills the current drawing (path). The default color is black.
  7724. */
  7725. fill: function fill() {
  7726. //evenodd or nonzero (default)
  7727. var rule = "fill";
  7728. this._drawPaths(rule, false);
  7729. },
  7730. /**
  7731. * Actually draws the path you have defined
  7732. *
  7733. * @name stroke
  7734. * @function
  7735. * @description The stroke() method actually draws the path you have defined with all those moveTo() and lineTo() methods. The default color is black.
  7736. */
  7737. stroke: function stroke() {
  7738. var rule = "stroke";
  7739. this._drawPaths(rule, false);
  7740. },
  7741. /**
  7742. * Begins a path, or resets the current
  7743. *
  7744. * @name beginPath
  7745. * @function
  7746. * @description The beginPath() method begins a path, or resets the current path.
  7747. */
  7748. beginPath: function beginPath() {
  7749. this._resetPath();
  7750. this._beginPath();
  7751. },
  7752. /**
  7753. * Moves the path to the specified point in the canvas, without creating a line
  7754. *
  7755. * @name moveTo
  7756. * @function
  7757. * @param x {Number} The x-coordinate of where to move the path to
  7758. * @param y {Number} The y-coordinate of where to move the path to
  7759. */
  7760. moveTo: function moveTo(x, y) {
  7761. x = this._wrapX(x);
  7762. y = this._wrapY(y);
  7763. var xpt = this._matrix_map_point(this.ctx._transform, [x, y]);
  7764. x = xpt[0];
  7765. y = xpt[1];
  7766. var obj = {
  7767. type: "mt",
  7768. x: x,
  7769. y: y
  7770. };
  7771. this.path.push(obj);
  7772. },
  7773. /**
  7774. * Creates a path from the current point back to the starting point
  7775. *
  7776. * @name closePath
  7777. * @function
  7778. * @description The closePath() method creates a path from the current point back to the starting point.
  7779. */
  7780. closePath: function closePath() {
  7781. this._closePath();
  7782. var obj = {
  7783. type: "close"
  7784. };
  7785. this.path.push(obj);
  7786. },
  7787. /**
  7788. * Adds a new point and creates a line to that point from the last specified point in the canvas
  7789. *
  7790. * @name lineTo
  7791. * @function
  7792. * @param x The x-coordinate of where to create the line to
  7793. * @param y The y-coordinate of where to create the line to
  7794. * @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).
  7795. */
  7796. lineTo: function lineTo(x, y) {
  7797. x = this._wrapX(x);
  7798. y = this._wrapY(y);
  7799. var xpt = this._matrix_map_point(this.ctx._transform, [x, y]);
  7800. x = xpt[0];
  7801. y = xpt[1];
  7802. var obj = {
  7803. type: "lt",
  7804. x: x,
  7805. y: y
  7806. };
  7807. this.path.push(obj);
  7808. },
  7809. /**
  7810. * Clips a region of any shape and size from the original canvas
  7811. *
  7812. * @name clip
  7813. * @function
  7814. * @description The clip() method clips a region of any shape and size from the original canvas.
  7815. */
  7816. clip: function clip() {
  7817. this._drawPaths(null, true);
  7818. },
  7819. /**
  7820. * Creates a cubic Bézier curve
  7821. *
  7822. * @name quadraticCurveTo
  7823. * @function
  7824. * @param cpx {Number} The x-coordinate of the Bézier control point
  7825. * @param cpy {Number} The y-coordinate of the Bézier control point
  7826. * @param x {Number} The x-coordinate of the ending point
  7827. * @param y {Number} The y-coordinate of the ending point
  7828. * @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.
  7829. */
  7830. quadraticCurveTo: function quadraticCurveTo(cpx, cpy, x, y) {
  7831. var x1 = this._wrapX(cpx);
  7832. var y1 = this._wrapY(cpy);
  7833. x = this._wrapX(x);
  7834. y = this._wrapY(y);
  7835. var xpt;
  7836. xpt = this._matrix_map_point(this.ctx._transform, [x, y]);
  7837. x = xpt[0];
  7838. y = xpt[1];
  7839. xpt = this._matrix_map_point(this.ctx._transform, [x1, y1]);
  7840. x1 = xpt[0];
  7841. y1 = xpt[1];
  7842. var obj = {
  7843. type: "qct",
  7844. x1: x1,
  7845. y1: y1,
  7846. x: x,
  7847. y: y
  7848. };
  7849. this.path.push(obj);
  7850. },
  7851. /**
  7852. * Creates a cubic Bézier curve
  7853. *
  7854. * @name bezierCurveTo
  7855. * @function
  7856. * @param cp1x {Number} The x-coordinate of the first Bézier control point
  7857. * @param cp1y {Number} The y-coordinate of the first Bézier control point
  7858. * @param cp2x {Number} The x-coordinate of the second Bézier control point
  7859. * @param cp2y {Number} The y-coordinate of the second Bézier control point
  7860. * @param x {Number} The x-coordinate of the ending point
  7861. * @param y {Number} The y-coordinate of the ending point
  7862. * @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.
  7863. */
  7864. bezierCurveTo: function bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) {
  7865. var x1 = this._wrapX(cp1x);
  7866. var y1 = this._wrapY(cp1y);
  7867. var x2 = this._wrapX(cp2x);
  7868. var y2 = this._wrapY(cp2y);
  7869. x = this._wrapX(x);
  7870. y = this._wrapY(y);
  7871. var xpt;
  7872. xpt = this._matrix_map_point(this.ctx._transform, [x, y]);
  7873. x = xpt[0];
  7874. y = xpt[1];
  7875. xpt = this._matrix_map_point(this.ctx._transform, [x1, y1]);
  7876. x1 = xpt[0];
  7877. y1 = xpt[1];
  7878. xpt = this._matrix_map_point(this.ctx._transform, [x2, y2]);
  7879. x2 = xpt[0];
  7880. y2 = xpt[1];
  7881. var obj = {
  7882. type: "bct",
  7883. x1: x1,
  7884. y1: y1,
  7885. x2: x2,
  7886. y2: y2,
  7887. x: x,
  7888. y: y
  7889. };
  7890. this.path.push(obj);
  7891. },
  7892. /**
  7893. * Creates an arc/curve (used to create circles, or parts of circles)
  7894. *
  7895. * @name arc
  7896. * @function
  7897. * @param x {Number} The x-coordinate of the center of the circle
  7898. * @param y {Number} The y-coordinate of the center of the circle
  7899. * @param radius {Number} The radius of the circle
  7900. * @param startAngle {Number} The starting angle, in radians (0 is at the 3 o'clock position of the arc's circle)
  7901. * @param endAngle {Number} The ending angle, in radians
  7902. * @param counterclockwise {Boolean} Optional. Specifies whether the drawing should be counterclockwise or clockwise. False is default, and indicates clockwise, while true indicates counter-clockwise.
  7903. * @description The arc() method creates an arc/curve (used to create circles, or parts of circles).
  7904. */
  7905. arc: function arc(x, y, radius, startAngle, endAngle, counterclockwise) {
  7906. x = this._wrapX(x);
  7907. y = this._wrapY(y);
  7908. counterclockwise = counterclockwise || false;
  7909. if (!this._matrix_is_identity(this.ctx._transform)) {
  7910. var xpt = this._matrix_map_point(this.ctx._transform, [x, y]);
  7911. x = xpt[0];
  7912. y = xpt[1];
  7913. var x_radPt0 = this._matrix_map_point(this.ctx._transform, [0, 0]);
  7914. var x_radPt = this._matrix_map_point(this.ctx._transform, [0, radius]);
  7915. radius = Math.sqrt(Math.pow(x_radPt[0] - x_radPt0[0], 2) + Math.pow(x_radPt[1] - x_radPt0[1], 2));
  7916. }
  7917. var obj = {
  7918. type: "arc",
  7919. x: x,
  7920. y: y,
  7921. radius: radius,
  7922. startAngle: startAngle,
  7923. endAngle: endAngle,
  7924. counterclockwise: counterclockwise
  7925. };
  7926. this.path.push(obj);
  7927. },
  7928. /**
  7929. * Creates an arc/curve between two tangents
  7930. *
  7931. * @name arcTo
  7932. * @function
  7933. * @param x1 {Number} The x-coordinate of the first tangent
  7934. * @param y1 {Number} The y-coordinate of the first tangent
  7935. * @param x2 {Number} The x-coordinate of the second tangent
  7936. * @param y2 {Number} The y-coordinate of the second tangent
  7937. * @param radius The radius of the
  7938. * @description The arcTo() method creates an arc/curve between two tangents on the canvas.
  7939. */
  7940. arcTo: function arcTo(x1, y1, x2, y2, radius) {//TODO needs to be implemented
  7941. },
  7942. //Rectangles
  7943. /**
  7944. * Creates a rectangle
  7945. *
  7946. * @name rect
  7947. * @function
  7948. * @param x {Number} The x-coordinate of the upper-left corner of the rectangle
  7949. * @param y {Number} The y-coordinate of the upper-left corner of the rectangle
  7950. * @param w {Number} The width of the rectangle, in pixels
  7951. * @param h {Number} The height of the rectangle, in pixels
  7952. * @description The rect() method creates a rectangle.
  7953. */
  7954. rect: function rect(x, y, w, h) {
  7955. this.moveTo(x, y);
  7956. this.lineTo(x + w, y);
  7957. this.lineTo(x + w, y + h);
  7958. this.lineTo(x, y + h);
  7959. this.lineTo(x, y);
  7960. this.lineTo(x + w, y);
  7961. this.lineTo(x, y);
  7962. },
  7963. /**
  7964. * Draws a "filled" rectangle
  7965. *
  7966. * @name fillRect
  7967. * @function
  7968. * @param x {Number} The x-coordinate of the upper-left corner of the rectangle
  7969. * @param y {Number} The y-coordinate of the upper-left corner of the rectangle
  7970. * @param w {Number} The width of the rectangle, in pixels
  7971. * @param h {Number} The height of the rectangle, in pixels
  7972. * @description The fillRect() method draws a "filled" rectangle. The default color of the fill is black.
  7973. */
  7974. fillRect: function fillRect(x, y, w, h) {
  7975. if (this._isFillTransparent()) {
  7976. return;
  7977. }
  7978. x = this._wrapX(x);
  7979. y = this._wrapY(y);
  7980. var xpt1 = this._matrix_map_point(this.ctx._transform, [x, y]);
  7981. var xpt2 = this._matrix_map_point(this.ctx._transform, [x + w, y]);
  7982. var xpt3 = this._matrix_map_point(this.ctx._transform, [x + w, y + h]);
  7983. var xpt4 = this._matrix_map_point(this.ctx._transform, [x, y + h]);
  7984. this.pdf.internal.out("q");
  7985. this.pdf.setLineCap("butt");
  7986. this.pdf.setLineJoin("miter");
  7987. var lines = [];
  7988. lines.push([xpt2[0] - xpt1[0], xpt2[1] - xpt1[1]]);
  7989. lines.push([xpt3[0] - xpt2[0], xpt3[1] - xpt2[1]]);
  7990. lines.push([xpt4[0] - xpt3[0], xpt4[1] - xpt3[1]]);
  7991. lines.push([xpt1[0] - xpt4[0], xpt1[1] - xpt4[1]]);
  7992. lines.push([xpt2[0] - xpt1[0], xpt2[1] - xpt1[1]]);
  7993. lines.push([xpt1[0] - xpt2[0], xpt1[1] - xpt2[1]]);
  7994. this.pdf.lines(lines, xpt1[0], xpt1[1], null, "F");
  7995. this.pdf.internal.out("Q");
  7996. },
  7997. /**
  7998. * Draws a rectangle (no fill)
  7999. *
  8000. * @name strokeRect
  8001. * @function
  8002. * @param x {Number} The x-coordinate of the upper-left corner of the rectangle
  8003. * @param y {Number} The y-coordinate of the upper-left corner of the rectangle
  8004. * @param w {Number} The width of the rectangle, in pixels
  8005. * @param h {Number} The height of the rectangle, in pixels
  8006. * @description The strokeRect() method draws a rectangle (no fill). The default color of the stroke is black.
  8007. */
  8008. strokeRect: function strokeRect(x, y, w, h) {
  8009. if (this._isStrokeTransparent()) {
  8010. return;
  8011. }
  8012. x = this._wrapX(x);
  8013. y = this._wrapY(y);
  8014. var xpt1 = this._matrix_map_point(this.ctx._transform, [x, y]);
  8015. var xpt2 = this._matrix_map_point(this.ctx._transform, [x + w, y]);
  8016. var xpt3 = this._matrix_map_point(this.ctx._transform, [x + w, y + h]);
  8017. var xpt4 = this._matrix_map_point(this.ctx._transform, [x, y + h]);
  8018. var lines = [];
  8019. lines.push([xpt2[0] - xpt1[0], xpt2[1] - xpt1[1]]);
  8020. lines.push([xpt3[0] - xpt2[0], xpt3[1] - xpt2[1]]);
  8021. lines.push([xpt4[0] - xpt3[0], xpt4[1] - xpt3[1]]);
  8022. lines.push([xpt1[0] - xpt4[0], xpt1[1] - xpt4[1]]);
  8023. lines.push([xpt2[0] - xpt1[0], xpt2[1] - xpt1[1]]);
  8024. lines.push([xpt1[0] - xpt2[0], xpt1[1] - xpt2[1]]);
  8025. this.pdf.lines(lines, xpt1[0], xpt1[1], null, "S");
  8026. },
  8027. /**
  8028. * Clears the specified pixels within a given rectangle
  8029. *
  8030. * @name clearRect
  8031. * @function
  8032. * @param x {Number} The x-coordinate of the upper-left corner of the rectangle
  8033. * @param y {Number} The y-coordinate of the upper-left corner of the rectangle
  8034. * @param w {Number} The width of the rectangle to clear, in pixels
  8035. * @param h {Number} The height of the rectangle to clear, in pixels
  8036. * @description We cannot clear PDF commands that were already written to PDF, so we use white instead. <br />
  8037. * As a special case, read a special flag (ignoreClearRect) and do nothing if it is set.
  8038. * This results in all calls to clearRect() to do nothing, and keep the canvas transparent.
  8039. * This flag is stored in the save/restore context and is managed the same way as other drawing states.
  8040. *
  8041. */
  8042. clearRect: function clearRect(x, y, w, h) {
  8043. if (this.ctx.ignoreClearRect) {
  8044. return;
  8045. }
  8046. this.save();
  8047. this._setFillStyle("#ffffff");
  8048. this.fillRect(x, y, w, h);
  8049. this.restore();
  8050. },
  8051. //Other
  8052. /**
  8053. * Saves the state of the current context
  8054. *
  8055. * @name save
  8056. * @function
  8057. */
  8058. save: function save() {
  8059. this.pdf.internal.out("q");
  8060. this.ctx._fontSize = this.pdf.internal.getFontSize();
  8061. var ctx = new context();
  8062. ctx.copy(this.ctx);
  8063. this.ctxStack.push(this.ctx);
  8064. this.ctx = ctx;
  8065. },
  8066. /**
  8067. * Returns previously saved path state and attributes
  8068. *
  8069. * @name restore
  8070. * @function
  8071. */
  8072. restore: function restore() {
  8073. this.pdf.internal.out("Q");
  8074. if (this.ctxStack.length !== 0) {
  8075. this.ctx = this.ctxStack.pop();
  8076. this._setFillStyle(this.ctx.fillStyle);
  8077. this._setStrokeStyle(this.ctx.strokeStyle);
  8078. this._setFont(this.ctx.font);
  8079. this.pdf.setFontSize(this.ctx._fontSize);
  8080. this._setLineCap(this.ctx.lineCap);
  8081. this._setLineWidth(this.ctx.lineWidth);
  8082. this._setLineJoin(this.ctx.lineJoin);
  8083. }
  8084. },
  8085. // some stubs
  8086. /**
  8087. * @name createEvent
  8088. * @function
  8089. */
  8090. createEvent: function createEvent() {
  8091. console.log("createEvent not implemented (yet)");
  8092. },
  8093. /**
  8094. * @name toDataURL
  8095. * @function
  8096. */
  8097. toDataURL: function toDataURL() {
  8098. console.log("toDataUrl not implemented (yet)");
  8099. },
  8100. //helper functions
  8101. _beginPath: function _beginPath() {
  8102. this.path.push({
  8103. type: "begin"
  8104. });
  8105. },
  8106. _closePath: function _closePath() {
  8107. var pathBegin = {
  8108. x: 0,
  8109. y: 0
  8110. };
  8111. var i = 0;
  8112. var len = this.path.length;
  8113. for (i = this.path.length - 1; i !== -1; i--) {
  8114. if (this.path[i].type === "begin") {
  8115. if (_typeof(this.path[i + 1]) === "object" && typeof this.path[i + 1].x === "number") {
  8116. pathBegin = {
  8117. x: this.path[i + 1].x,
  8118. y: this.path[i + 1].y
  8119. };
  8120. var obj = {
  8121. type: "lt",
  8122. x: pathBegin.x,
  8123. y: pathBegin.y
  8124. };
  8125. this.path.push(obj);
  8126. break;
  8127. }
  8128. }
  8129. } //TODO Repeat second move to get lineJoins correct, maybe only when lineJoin active in _drawPaths
  8130. if (_typeof(this.path[i + 2]) === "object" && typeof this.path[i + 2].x === "number") {
  8131. this.path.push(JSON.parse(JSON.stringify(this.path[i + 2])));
  8132. }
  8133. },
  8134. _resetPath: function _resetPath() {
  8135. this.path = [];
  8136. },
  8137. /**
  8138. * Get the decimal values of r, g, b and a
  8139. *
  8140. * @name _getRGBA
  8141. * @function
  8142. * @private
  8143. * @ignore
  8144. */
  8145. _getRGBA: function _getRGBA(style) {
  8146. var r, g, b, a;
  8147. if (style.isCanvasGradient === true) {
  8148. style = style.getColor();
  8149. }
  8150. var rgbColor = new RGBColor(style);
  8151. if (!style) {
  8152. return {
  8153. r: 0,
  8154. g: 0,
  8155. b: 0,
  8156. a: 0,
  8157. style: style
  8158. };
  8159. }
  8160. if (this.internal.rxTransparent.test(style)) {
  8161. r = 0;
  8162. g = 0;
  8163. b = 0;
  8164. a = 0;
  8165. } else {
  8166. var m = this.internal.rxRgb.exec(style);
  8167. if (m != null) {
  8168. r = parseInt(m[1]);
  8169. g = parseInt(m[2]);
  8170. b = parseInt(m[3]);
  8171. a = 1;
  8172. } else {
  8173. m = this.internal.rxRgba.exec(style);
  8174. if (m != null) {
  8175. r = parseInt(m[1]);
  8176. g = parseInt(m[2]);
  8177. b = parseInt(m[3]);
  8178. a = parseFloat(m[4]);
  8179. } else {
  8180. a = 1;
  8181. if (style.charAt(0) != "#") {
  8182. if (rgbColor.ok) {
  8183. style = rgbColor.toHex();
  8184. } else {
  8185. style = "#000000";
  8186. }
  8187. }
  8188. if (style.length === 4) {
  8189. r = style.substring(1, 2);
  8190. r += r;
  8191. g = style.substring(2, 3);
  8192. g += g;
  8193. b = style.substring(3, 4);
  8194. b += b;
  8195. } else {
  8196. r = style.substring(1, 3);
  8197. g = style.substring(3, 5);
  8198. b = style.substring(5, 7);
  8199. }
  8200. r = parseInt(r, 16);
  8201. g = parseInt(g, 16);
  8202. b = parseInt(b, 16);
  8203. }
  8204. }
  8205. }
  8206. return {
  8207. r: r,
  8208. g: g,
  8209. b: b,
  8210. a: a,
  8211. style: style
  8212. };
  8213. },
  8214. /**
  8215. * @name _isFilllTransparent
  8216. * @function
  8217. * @private
  8218. * @ignore
  8219. * @returns {Boolean}
  8220. */
  8221. _isFillTransparent: function _isFillTransparent() {
  8222. return this.ctx._isFillTransparent || this.globalAlpha == 0;
  8223. },
  8224. /**
  8225. * @name _isStrokeTransparent
  8226. * @function
  8227. * @private
  8228. * @ignore
  8229. * @returns {Boolean}
  8230. */
  8231. _isStrokeTransparent: function _isStrokeTransparent() {
  8232. return this.ctx._isStrokeTransparent || this.globalAlpha == 0;
  8233. },
  8234. /**
  8235. * Sets the color, gradient, or pattern used to fill the drawing
  8236. *
  8237. * @name _setFillStyle
  8238. * @function
  8239. * @private
  8240. * @ignore
  8241. */
  8242. _setFillStyle: function _setFillStyle(style) {
  8243. var rgba;
  8244. rgba = this._getRGBA(style);
  8245. this.ctx.fillStyle = style;
  8246. this.ctx._isFillTransparent = rgba.a === 0;
  8247. this.ctx._fillOpacity = rgba.a;
  8248. this.pdf.setFillColor(rgba.r, rgba.g, rgba.b, {
  8249. a: rgba.a
  8250. });
  8251. this.pdf.setTextColor(rgba.r, rgba.g, rgba.b, {
  8252. a: rgba.a
  8253. });
  8254. },
  8255. /**
  8256. * Sets the color, gradient, or pattern used for strokes
  8257. *
  8258. * @name _setStrokeStyle
  8259. * @function
  8260. * @private
  8261. * @ignore
  8262. */
  8263. _setStrokeStyle: function _setStrokeStyle(style) {
  8264. var rgba = this._getRGBA(style);
  8265. this.ctx.strokeStyle = rgba.style;
  8266. this.ctx._isStrokeTransparent = rgba.a === 0;
  8267. this.ctx._strokeOpacity = rgba.a; //TODO jsPDF to handle rgba
  8268. if (rgba.a === 0) {
  8269. this.pdf.setDrawColor(255, 255, 255);
  8270. } else if (rgba.a === 1) {
  8271. this.pdf.setDrawColor(rgba.r, rgba.g, rgba.b);
  8272. } else {
  8273. //this.pdf.setDrawColor(rgba.r, rgba.g, rgba.b, {a: rgba.a});
  8274. this.pdf.setDrawColor(rgba.r, rgba.g, rgba.b);
  8275. }
  8276. },
  8277. /**
  8278. * Sets font properties for text content
  8279. *
  8280. * @name _setFont
  8281. * @function
  8282. * @param {String} The font property uses the same syntax as the CSS font property.
  8283. * @private
  8284. * @ignore
  8285. */
  8286. _setFont: function _setFont(font) {
  8287. this.ctx.font = font;
  8288. var rx, m; //source: https://stackoverflow.com/a/10136041
  8289. 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;
  8290. m = rx.exec(font);
  8291. if (m != null) {
  8292. var fontStyle = m[1];
  8293. var fontVariant = m[2];
  8294. var fontWeight = m[3];
  8295. var fontSize = m[4];
  8296. var fontSizeUnit = m[5];
  8297. var fontFamily = m[6];
  8298. } else {
  8299. return;
  8300. }
  8301. if ("px" === fontSizeUnit) {
  8302. fontSize = Math.floor(parseFloat(fontSize)); // fontSize = fontSize * 1.25;
  8303. } else if ("em" === fontSizeUnit) {
  8304. fontSize = Math.floor(parseFloat(fontSize) * this.pdf.getFontSize());
  8305. } else {
  8306. fontSize = Math.floor(parseFloat(fontSize));
  8307. }
  8308. this.pdf.setFontSize(fontSize);
  8309. var style = "";
  8310. if (fontWeight === "bold" || parseInt(fontWeight, 10) >= 700 || fontStyle === "bold") {
  8311. style = "bold";
  8312. }
  8313. if (fontStyle === "italic") {
  8314. style += "italic";
  8315. }
  8316. if (style.length === 0) {
  8317. style = "normal";
  8318. }
  8319. var jsPdfFontName = "";
  8320. var parts = fontFamily.toLowerCase().replace(/"|'/g, "").split(/\s*,\s*/);
  8321. var fallbackFonts = {
  8322. arial: "Helvetica",
  8323. verdana: "Helvetica",
  8324. helvetica: "Helvetica",
  8325. "sans-serif": "Helvetica",
  8326. fixed: "Courier",
  8327. monospace: "Courier",
  8328. terminal: "Courier",
  8329. courier: "Courier",
  8330. times: "Times",
  8331. cursive: "Times",
  8332. fantasy: "Times",
  8333. serif: "Times"
  8334. };
  8335. for (var i = 0; i < parts.length; i++) {
  8336. if (this.pdf.internal.getFont(parts[i], style, {
  8337. noFallback: true,
  8338. disableWarning: true
  8339. }) !== undefined) {
  8340. jsPdfFontName = parts[i];
  8341. break;
  8342. } else if (style === "bolditalic" && this.pdf.internal.getFont(parts[i], "bold", {
  8343. noFallback: true,
  8344. disableWarning: true
  8345. }) !== undefined) {
  8346. jsPdfFontName = parts[i];
  8347. style = "bold";
  8348. } else if (this.pdf.internal.getFont(parts[i], "normal", {
  8349. noFallback: true,
  8350. disableWarning: true
  8351. }) !== undefined) {
  8352. jsPdfFontName = parts[i];
  8353. style = "normal";
  8354. break;
  8355. }
  8356. }
  8357. if (jsPdfFontName === "") {
  8358. for (var i = 0; i < parts.length; i++) {
  8359. if (fallbackFonts[parts[i]]) {
  8360. jsPdfFontName = fallbackFonts[parts[i]];
  8361. break;
  8362. }
  8363. }
  8364. }
  8365. jsPdfFontName = jsPdfFontName === "" ? "Times" : jsPdfFontName;
  8366. this.pdf.setFont(jsPdfFontName, style);
  8367. },
  8368. /**
  8369. * @name _setTextBaseline
  8370. * @function
  8371. * @private
  8372. * @ignore
  8373. */
  8374. _setTextBaseline: function _setTextBaseline(baseline) {
  8375. this.ctx.textBaseline = baseline;
  8376. },
  8377. /**
  8378. * @name _getTextBaseline
  8379. * @function
  8380. * @private
  8381. * @ignore
  8382. * @returns {Number}
  8383. */
  8384. _getTextBaseline: function _getTextBaseline() {
  8385. return this.ctx.textBaseline;
  8386. },
  8387. /**
  8388. * @name _setTextAlign
  8389. * @function
  8390. * @private
  8391. * @ignore
  8392. */
  8393. _setTextAlign: function _setTextAlign(canvasAlign) {
  8394. switch (canvasAlign) {
  8395. case "right":
  8396. case "end":
  8397. this.ctx.textAlign = "right";
  8398. break;
  8399. case "center":
  8400. this.ctx.textAlign = "center";
  8401. break;
  8402. case "left":
  8403. case "start":
  8404. default:
  8405. this.ctx.textAlign = "left";
  8406. break;
  8407. }
  8408. },
  8409. /**
  8410. * @name _getTextAlign
  8411. * @function
  8412. * @private
  8413. * @ignore
  8414. * @returns {String}
  8415. */
  8416. _getTextAlign: function _getTextAlign() {
  8417. return this.ctx.textAlign;
  8418. },
  8419. /**
  8420. * Draws "filled" text on the canvas
  8421. *
  8422. * @name fillText
  8423. * @function
  8424. * @param text {String} Specifies the text that will be written on the canvas
  8425. * @param x {Number} The x coordinate where to start painting the text (relative to the canvas)
  8426. * @param y {Number} The y coordinate where to start painting the text (relative to the canvas)
  8427. * @param maxWidth {Number} Optional. The maximum allowed width of the text, in pixels
  8428. * @description The fillText() method draws filled text on the canvas. The default color of the text is black.
  8429. */
  8430. fillText: function fillText(text, x, y, maxWidth) {
  8431. if (this._isFillTransparent()) {
  8432. return;
  8433. }
  8434. x = this._wrapX(x);
  8435. y = this._wrapY(y);
  8436. var xpt = this._matrix_map_point(this.ctx._transform, [x, y]);
  8437. x = xpt[0];
  8438. y = xpt[1];
  8439. var rads = this._matrix_rotation(this.ctx._transform);
  8440. var degs = rads * 57.2958; // We only use X axis as scale hint
  8441. var scale = 1;
  8442. try {
  8443. scale = this._matrix_decompose(this._getTransform()).scale[0];
  8444. } catch (e) {
  8445. console.warn(e);
  8446. } // In some cases the transform was very small (5.715760606202283e-17). Most likely a canvg rounding error.
  8447. if (scale < 0.01) {
  8448. this.pdf.text(text, x, this._getBaseline(y), {
  8449. angle: degs,
  8450. align: this.textAlign
  8451. });
  8452. } else {
  8453. var oldSize = this.pdf.internal.getFontSize();
  8454. this.pdf.setFontSize(oldSize * scale);
  8455. this.pdf.text(text, x, this._getBaseline(y), {
  8456. angle: degs,
  8457. align: this.textAlign
  8458. });
  8459. this.pdf.setFontSize(oldSize);
  8460. }
  8461. },
  8462. /**
  8463. * Draws text on the canvas (no fill)
  8464. *
  8465. * @name strokeText
  8466. * @function
  8467. * @param text {String} Specifies the text that will be written on the canvas
  8468. * @param x {Number} The x coordinate where to start painting the text (relative to the canvas)
  8469. * @param y {Number} The y coordinate where to start painting the text (relative to the canvas)
  8470. * @param maxWidth {Number} Optional. The maximum allowed width of the text, in pixels
  8471. * @description The strokeText() method draws text (with no fill) on the canvas. The default color of the text is black.
  8472. */
  8473. strokeText: function strokeText(text, x, y, maxWidth) {
  8474. if (this._isStrokeTransparent()) {
  8475. return;
  8476. }
  8477. x = this._wrapX(x);
  8478. y = this._wrapY(y);
  8479. var xpt = this._matrix_map_point(this.ctx._transform, [x, y]);
  8480. x = xpt[0];
  8481. y = xpt[1];
  8482. var rads = this._matrix_rotation(this.ctx._transform);
  8483. var degs = rads * 57.2958;
  8484. var scale = 1; // We only use the X axis as scale hint
  8485. try {
  8486. scale = this._matrix_decompose(this._getTransform()).scale[0];
  8487. } catch (e) {
  8488. console.warn(e);
  8489. }
  8490. if (scale < 0.01) {
  8491. this.pdf.text(text, x, this._getBaseline(y), {
  8492. angle: degs,
  8493. align: this.textAlign,
  8494. renderingMode: "stroke"
  8495. });
  8496. } else {
  8497. var oldSize = this.pdf.internal.getFontSize();
  8498. this.pdf.setFontSize(oldSize * scale);
  8499. this.pdf.text(text, x, this._getBaseline(y), {
  8500. angle: degs,
  8501. align: this.textAlign,
  8502. renderingMode: "stroke"
  8503. });
  8504. this.pdf.setFontSize(oldSize);
  8505. }
  8506. },
  8507. /**
  8508. * Returns an object that contains the width of the specified text
  8509. *
  8510. * @name measureText
  8511. * @function
  8512. * @param text {String} The text to be measured
  8513. * @description The measureText() method returns an object that contains the width of the specified text, in pixels.
  8514. * @returns {Number}
  8515. */
  8516. measureText: function measureText(text) {
  8517. var pdf = this.pdf;
  8518. return {
  8519. getWidth: function getWidth() {
  8520. var fontSize = pdf.internal.getFontSize();
  8521. var txtWidth = pdf.getStringUnitWidth(text) * fontSize / pdf.internal.scaleFactor; // Convert points to pixels
  8522. //TODO Use scaleFactor?
  8523. txtWidth *= 1.3333;
  8524. return txtWidth;
  8525. },
  8526. get width() {
  8527. return this.getWidth(text);
  8528. }
  8529. };
  8530. },
  8531. //Line Styles
  8532. /**
  8533. *
  8534. * @name _setLineWidth
  8535. * @function
  8536. * @private
  8537. * @ignore
  8538. */
  8539. _setLineWidth: function _setLineWidth(width) {
  8540. this.ctx.lineWidth = width;
  8541. this.pdf.setLineWidth(width);
  8542. },
  8543. /**
  8544. * @name _setLineCap
  8545. * @function
  8546. * @private
  8547. * @ignore
  8548. */
  8549. _setLineCap: function _setLineCap(style) {
  8550. this.ctx.lineCap = style;
  8551. this.pdf.setLineCap(style);
  8552. },
  8553. /**
  8554. *
  8555. * @name _setLineJoin
  8556. * @function
  8557. * @private
  8558. * @ignore
  8559. */
  8560. _setLineJoin: function _setLineJoin(style) {
  8561. this.ctx.lineJoin = style;
  8562. this.pdf.setLineJoin(style);
  8563. },
  8564. /**
  8565. *
  8566. * @name _getLineJoin
  8567. * @function
  8568. * @private
  8569. * @ignore
  8570. */
  8571. _getLineJoin: function _getLineJoin() {
  8572. return this.ctx.lineJoin;
  8573. },
  8574. /**
  8575. *
  8576. * @name _wrapX
  8577. * @function
  8578. * @private
  8579. * @ignore
  8580. */
  8581. _wrapX: function _wrapX(x) {
  8582. if (this.pageWrapXEnabled) {
  8583. return x % this.pageWrapX;
  8584. } else {
  8585. return x;
  8586. }
  8587. },
  8588. /**
  8589. * @name _wrapY
  8590. * @function
  8591. * @private
  8592. * @ignore
  8593. */
  8594. _wrapY: function _wrapY(y) {
  8595. if (this.pageWrapYEnabled) {
  8596. this._gotoPage(this._page(y));
  8597. return (y - this.lastBreak) % this.pageWrapY;
  8598. } else {
  8599. return y;
  8600. }
  8601. },
  8602. //Transformations
  8603. /**
  8604. * Scales the current drawing bigger or smaller
  8605. *
  8606. * @name scale
  8607. * @function
  8608. * @param scalewidth {Number} Scales the width of the current drawing (1=100%, 0.5=50%, 2=200%, etc.)
  8609. * @param scaleheight {Number} Scales the height of the current drawing (1=100%, 0.5=50%, 2=200%, etc.)
  8610. * @description The scale() method scales the current drawing, bigger or smaller.
  8611. */
  8612. scale: function scale(scalewidth, scaleheight) {
  8613. var matrix = [scalewidth, 0.0, 0.0, scaleheight, 0.0, 0.0];
  8614. this.ctx._transform = this._matrix_multiply(this.ctx._transform, matrix);
  8615. },
  8616. /**
  8617. * Rotates the current drawing
  8618. *
  8619. * @name rotate
  8620. * @function
  8621. * @param angle {Number} The rotation angle, in radians.
  8622. * @description To calculate from degrees to radians: degrees*Math.PI/180. <br />
  8623. * Example: to rotate 5 degrees, specify the following: 5*Math.PI/180
  8624. */
  8625. rotate: function rotate(angle) {
  8626. var matrix = [Math.cos(angle), Math.sin(angle), -Math.sin(angle), Math.cos(angle), 0.0, 0.0];
  8627. this.ctx._transform = this._matrix_multiply(this.ctx._transform, matrix);
  8628. },
  8629. /**
  8630. * Remaps the (0,0) position on the canvas
  8631. *
  8632. * @name translate
  8633. * @function
  8634. * @param x {Number} The value to add to horizontal (x) coordinates
  8635. * @param y {Number} The value to add to vertical (y) coordinates
  8636. * @description The translate() method remaps the (0,0) position on the canvas.
  8637. */
  8638. translate: function translate(x, y) {
  8639. var matrix = [1.0, 0.0, 0.0, 1.0, x, y];
  8640. this.ctx._transform = this._matrix_multiply(this.ctx._transform, matrix);
  8641. },
  8642. /**
  8643. * Replaces the current transformation matrix for the drawing
  8644. *
  8645. * @name transform
  8646. * @function
  8647. * @param a {Number} Horizontal scaling
  8648. * @param b {Number} Horizontal skewing
  8649. * @param c {Number} Vertical skewing
  8650. * @param d {Number} Vertical scaling
  8651. * @param e {Number} Horizontal moving
  8652. * @param f {Number} Vertical moving
  8653. * @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.
  8654. */
  8655. transform: function transform(a, b, c, d, e, f) {
  8656. this.ctx._transform = this._matrix_multiply(this.ctx._transform, [a, b, c, d, e, f]);
  8657. },
  8658. /**
  8659. * Resets the current transform to the identity matrix. Then runs transform()
  8660. *
  8661. * @name setTransform
  8662. * @function
  8663. * @param a {Number} Horizontal scaling
  8664. * @param b {Number} Horizontal skewing
  8665. * @param c {Number} Vertical skewing
  8666. * @param d {Number} Vertical scaling
  8667. * @param e {Number} Horizontal moving
  8668. * @param f {Number} Vertical moving
  8669. * @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.
  8670. */
  8671. setTransform: function setTransform(a, b, c, d, e, f) {
  8672. this.ctx._transform = [a, b, c, d, e, f];
  8673. },
  8674. /**
  8675. * @name _getTransform
  8676. * @function
  8677. * @private
  8678. * @ignore
  8679. */
  8680. _getTransform: function _getTransform() {
  8681. return this.ctx._transform;
  8682. },
  8683. lastBreak: 0,
  8684. // Y Position of page breaks.
  8685. pageBreaks: [],
  8686. /**
  8687. * Should only be used if pageWrapYEnabled is true
  8688. *
  8689. * @name _page
  8690. * @function
  8691. * @private
  8692. * @ignore
  8693. * @returns One-based Page Number
  8694. */
  8695. _page: function _page(y) {
  8696. if (this.pageWrapYEnabled) {
  8697. this.lastBreak = 0;
  8698. var manualBreaks = 0;
  8699. var autoBreaks = 0;
  8700. for (var i = 0; i < this.pageBreaks.length; i++) {
  8701. if (y >= this.pageBreaks[i]) {
  8702. manualBreaks++;
  8703. if (this.lastBreak === 0) {
  8704. autoBreaks++;
  8705. }
  8706. var spaceBetweenLastBreak = this.pageBreaks[i] - this.lastBreak;
  8707. this.lastBreak = this.pageBreaks[i];
  8708. var pagesSinceLastBreak = Math.floor(spaceBetweenLastBreak / this.pageWrapY);
  8709. autoBreaks += pagesSinceLastBreak;
  8710. }
  8711. }
  8712. if (this.lastBreak === 0) {
  8713. var pagesSinceLastBreak = Math.floor(y / this.pageWrapY) + 1;
  8714. autoBreaks += pagesSinceLastBreak;
  8715. }
  8716. return autoBreaks + manualBreaks;
  8717. } else {
  8718. return this.pdf.internal.getCurrentPageInfo().pageNumber;
  8719. }
  8720. },
  8721. _gotoPage: function _gotoPage(pageOneBased) {// This is a stub to be overriden if needed
  8722. },
  8723. /**
  8724. * Draws an image, canvas, or video onto the canvas
  8725. *
  8726. * @function
  8727. * @param img {} Specifies the image, canvas, or video element to use
  8728. * @param sx {Number} Optional. The x coordinate where to start clipping
  8729. * @param sy {Number} Optional. The y coordinate where to start clipping
  8730. * @param swidth {Number} Optional. The width of the clipped image
  8731. * @param sheight {Number} Optional. The height of the clipped image
  8732. * @param x {Number} The x coordinate where to place the image on the canvas
  8733. * @param y {Number} The y coordinate where to place the image on the canvas
  8734. * @param width {Number} Optional. The width of the image to use (stretch or reduce the image)
  8735. * @param height {Number} Optional. The height of the image to use (stretch or reduce the image)
  8736. *
  8737. */
  8738. drawImage: function drawImage(img, x, y, w, h, x2, y2, w2, h2) {
  8739. if (x2 !== undefined) {
  8740. x = x2;
  8741. y = y2;
  8742. w = w2;
  8743. h = h2;
  8744. }
  8745. x = this._wrapX(x);
  8746. y = this._wrapY(y);
  8747. var xRect = this._matrix_map_rect(this.ctx._transform, {
  8748. x: x,
  8749. y: y,
  8750. w: w,
  8751. h: h
  8752. });
  8753. var xRect2 = this._matrix_map_rect(this.ctx._transform, {
  8754. x: x2,
  8755. y: y2,
  8756. w: w2,
  8757. h: h2
  8758. }); // TODO implement source clipping and image scaling
  8759. var format;
  8760. var rx = /data:image\/(\w+).*/i;
  8761. var m = rx.exec(img);
  8762. if (m != null) {
  8763. format = m[1];
  8764. } else {
  8765. // format = "jpeg";
  8766. format = "png";
  8767. }
  8768. this.pdf.addImage(img, format, xRect.x, xRect.y, xRect.w, xRect.h);
  8769. },
  8770. /**
  8771. * Multiply the first matrix by the second
  8772. *
  8773. * @name matrix_multiply
  8774. * @function
  8775. * @param m1
  8776. * @param m2
  8777. * @returns {Array}
  8778. * @private
  8779. * @ignore
  8780. */
  8781. _matrix_multiply: function _matrix_multiply(m2, m1) {
  8782. var sx = m1[0];
  8783. var shy = m1[1];
  8784. var shx = m1[2];
  8785. var sy = m1[3];
  8786. var tx = m1[4];
  8787. var ty = m1[5];
  8788. var t0 = sx * m2[0] + shy * m2[2];
  8789. var t2 = shx * m2[0] + sy * m2[2];
  8790. var t4 = tx * m2[0] + ty * m2[2] + m2[4];
  8791. shy = sx * m2[1] + shy * m2[3];
  8792. sy = shx * m2[1] + sy * m2[3];
  8793. ty = tx * m2[1] + ty * m2[3] + m2[5];
  8794. sx = t0;
  8795. shx = t2;
  8796. tx = t4;
  8797. return [sx, shy, shx, sy, tx, ty];
  8798. },
  8799. /**
  8800. * @name _matrix_rotation
  8801. * @function
  8802. * @private
  8803. * @ignore
  8804. */
  8805. _matrix_rotation: function _matrix_rotation(m) {
  8806. return Math.atan2(m[2], m[0]);
  8807. },
  8808. /**
  8809. * @name _matrix_decompose
  8810. * @function
  8811. * @private
  8812. * @ignore
  8813. */
  8814. _matrix_decompose: function _matrix_decompose(matrix) {
  8815. var a = matrix[0];
  8816. var b = matrix[1];
  8817. var c = matrix[2];
  8818. var d = matrix[3];
  8819. var scaleX = Math.sqrt(a * a + b * b);
  8820. a /= scaleX;
  8821. b /= scaleX;
  8822. var shear = a * c + b * d;
  8823. c -= a * shear;
  8824. d -= b * shear;
  8825. var scaleY = Math.sqrt(c * c + d * d);
  8826. c /= scaleY;
  8827. d /= scaleY;
  8828. shear /= scaleY;
  8829. if (a * d < b * c) {
  8830. a = -a;
  8831. b = -b;
  8832. shear = -shear;
  8833. scaleX = -scaleX;
  8834. }
  8835. return {
  8836. scale: [scaleX, 0, 0, scaleY, 0, 0],
  8837. translate: [1, 0, 0, 1, matrix[4], matrix[5]],
  8838. rotate: [a, b, -b, a, 0, 0],
  8839. skew: [1, 0, shear, 1, 0, 0]
  8840. };
  8841. },
  8842. /**
  8843. * @name _matrix_map_point
  8844. * @function
  8845. * @private
  8846. * @ignore
  8847. */
  8848. _matrix_map_point: function _matrix_map_point(m1, pt) {
  8849. var sx = m1[0];
  8850. var shy = m1[1];
  8851. var shx = m1[2];
  8852. var sy = m1[3];
  8853. var tx = m1[4];
  8854. var ty = m1[5];
  8855. var px = pt[0];
  8856. var py = pt[1];
  8857. var x = px * sx + py * shx + tx;
  8858. var y = px * shy + py * sy + ty;
  8859. return [x, y];
  8860. },
  8861. /**
  8862. * @name _matrix_map_point_obj
  8863. * @function
  8864. * @private
  8865. * @ignore
  8866. */
  8867. _matrix_map_point_obj: function _matrix_map_point_obj(m1, pt) {
  8868. var xpt = this._matrix_map_point(m1, [pt.x, pt.y]);
  8869. return {
  8870. x: xpt[0],
  8871. y: xpt[1]
  8872. };
  8873. },
  8874. /**
  8875. * @name _matrix_map_rect
  8876. * @function
  8877. * @private
  8878. * @ignore
  8879. */
  8880. _matrix_map_rect: function _matrix_map_rect(m1, rect) {
  8881. var p1 = this._matrix_map_point(m1, [rect.x, rect.y]);
  8882. var p2 = this._matrix_map_point(m1, [rect.x + rect.w, rect.y + rect.h]);
  8883. return {
  8884. x: p1[0],
  8885. y: p1[1],
  8886. w: p2[0] - p1[0],
  8887. h: p2[1] - p1[1]
  8888. };
  8889. },
  8890. /**
  8891. * @name _matrix_is_identity
  8892. * @function
  8893. * @private
  8894. * @ignore
  8895. */
  8896. _matrix_is_identity: function _matrix_is_identity(m1) {
  8897. if (m1[0] != 1) {
  8898. return false;
  8899. }
  8900. if (m1[1] != 0) {
  8901. return false;
  8902. }
  8903. if (m1[2] != 0) {
  8904. return false;
  8905. }
  8906. if (m1[3] != 1) {
  8907. return false;
  8908. }
  8909. if (m1[4] != 0) {
  8910. return false;
  8911. }
  8912. if (m1[5] != 0) {
  8913. return false;
  8914. }
  8915. return true;
  8916. },
  8917. /**
  8918. * Processes the paths
  8919. *
  8920. * @function
  8921. * @param rule {String}
  8922. * @param isClip {Boolean}
  8923. * @private
  8924. * @ignore
  8925. */
  8926. _drawPaths: function _drawPaths(rule, isClip) {
  8927. var isStroke = rule === "stroke";
  8928. var isFill = !isStroke;
  8929. if (isStroke && !isClip && this._isStrokeTransparent()) {
  8930. return;
  8931. }
  8932. if (isFill && !isClip && this._isFillTransparent()) {
  8933. return;
  8934. }
  8935. var v2Support = typeof this.pdf.internal.newObject2 === "function";
  8936. var lines;
  8937. if (globalObj.outIntercept) {
  8938. lines = globalObj.outIntercept.type === "group" ? globalObj.outIntercept.stream : globalObj.outIntercept;
  8939. } else {
  8940. lines = this.internal.getCurrentPage();
  8941. }
  8942. var moves = [];
  8943. var outInterceptOld = globalObj.outIntercept;
  8944. /*
  8945. if (v2Support) {
  8946. // Blend and Mask
  8947. switch (this.ctx.globalCompositeOperation) {
  8948. case 'normal':
  8949. case 'source-over':
  8950. break;
  8951. case 'destination-in':
  8952. case 'destination-out':
  8953. //TODO this need to be added to the current group or page
  8954. // define a mask stream
  8955. var obj = this.pdf.internal.newStreamObject(); // define a mask state
  8956. var obj2 = this.pdf.internal.newObject2();
  8957. obj2.push('<</Type /ExtGState');
  8958. obj2.push('/SMask <</S /Alpha /G ' + obj.objId + ' 0 R>>'); // /S /Luminosity will need to define color space
  8959. obj2.push('>>'); // add mask to page resources
  8960. var gsName = 'MASK' + obj2.objId;
  8961. this.pdf.internal.addGraphicsState(gsName, obj2.objId);
  8962. var instruction = '/' + gsName + ' gs'; // add mask to page, group, or stream
  8963. lines.splice(0, 0, 'q');
  8964. lines.splice(1, 0, instruction);
  8965. lines.push('Q');
  8966. globalObj.outIntercept = obj;
  8967. break;
  8968. default:
  8969. var dictionaryEntry = '/' + this.pdf.internal.blendModeMap[this.ctx.globalCompositeOperation.toUpperCase()];
  8970. if (dictionaryEntry) {
  8971. this.pdf.internal.out(dictionaryEntry + ' gs');
  8972. }
  8973. break;
  8974. }
  8975. }
  8976. */
  8977. var alpha = this.ctx.globalAlpha;
  8978. if (this.ctx._fillOpacity < 1) {
  8979. // TODO combine this with global opacity
  8980. alpha = this.ctx._fillOpacity;
  8981. } //TODO check for an opacity graphics state that was already created
  8982. //TODO do not set opacity if current value is already active
  8983. /*
  8984. if (v2Support) {
  8985. var objOpac = this.pdf.internal.newObject2();
  8986. objOpac.push('<</Type /ExtGState'); //objOpac.push(this.ctx.globalAlpha + " CA"); // Stroke
  8987. //objOpac.push(this.ctx.globalAlpha + " ca"); // Not Stroke
  8988. objOpac.push('/CA ' + alpha); // Stroke
  8989. objOpac.push('/ca ' + alpha); // Not Stroke
  8990. objOpac.push('>>');
  8991. var gsName = 'GS_O_' + objOpac.objId;
  8992. this.pdf.internal.addGraphicsState(gsName, objOpac.objId);
  8993. this.pdf.internal.out('/' + gsName + ' gs');
  8994. }
  8995. */
  8996. var xPath = this.path;
  8997. for (var i = 0; i < xPath.length; i++) {
  8998. var pt = xPath[i];
  8999. switch (pt.type) {
  9000. case "begin":
  9001. moves.push({
  9002. begin: true
  9003. });
  9004. break;
  9005. case "close":
  9006. moves.push({
  9007. close: true
  9008. });
  9009. break;
  9010. case "mt":
  9011. moves.push({
  9012. start: pt,
  9013. deltas: [],
  9014. abs: []
  9015. });
  9016. break;
  9017. case "lt":
  9018. var delta = [pt.x - xPath[i - 1].x, pt.y - xPath[i - 1].y];
  9019. var iii = moves.length;
  9020. if (iii > 0) {
  9021. for (iii; iii > 0; iii--) {
  9022. if (moves[iii - 1].close !== true && moves[iii - 1].begin !== true) {
  9023. moves[iii - 1].deltas.push(delta);
  9024. moves[iii - 1].abs.push(pt);
  9025. break;
  9026. }
  9027. }
  9028. }
  9029. break;
  9030. case "bct":
  9031. 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];
  9032. moves[moves.length - 1].deltas.push(delta);
  9033. break;
  9034. case "qct":
  9035. // convert to bezier
  9036. var x1 = xPath[i - 1].x + 2.0 / 3.0 * (pt.x1 - xPath[i - 1].x);
  9037. var y1 = xPath[i - 1].y + 2.0 / 3.0 * (pt.y1 - xPath[i - 1].y);
  9038. var x2 = pt.x + 2.0 / 3.0 * (pt.x1 - pt.x);
  9039. var y2 = pt.y + 2.0 / 3.0 * (pt.y1 - pt.y);
  9040. var x3 = pt.x;
  9041. var y3 = pt.y;
  9042. 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];
  9043. moves[moves.length - 1].deltas.push(delta);
  9044. break;
  9045. case "arc":
  9046. moves.push({
  9047. deltas: [],
  9048. abs: []
  9049. });
  9050. moves[moves.length - 1].arc = true;
  9051. if (Array.isArray(moves[moves.length - 1].abs)) {
  9052. moves[moves.length - 1].abs.push(pt);
  9053. }
  9054. break;
  9055. }
  9056. }
  9057. var style;
  9058. if (!isClip) {
  9059. if (isStroke) {
  9060. style = "S";
  9061. } else {
  9062. style = "f";
  9063. }
  9064. } else {
  9065. style = null;
  9066. }
  9067. for (var i = 0; i < moves.length; i++) {
  9068. if (moves[i].begin) ;
  9069. if (moves[i].arc) {
  9070. if (moves[i].start) {
  9071. this.internal.move2(this, moves[i].start.x, moves[i].start.y);
  9072. }
  9073. var arcs = moves[i].abs;
  9074. for (var ii = 0; ii < arcs.length; ii++) {
  9075. var arc = arcs[ii]; //TODO lines deltas were getting in here
  9076. if (typeof arc.startAngle !== "undefined") {
  9077. var start = arc.startAngle * 360 / (2 * Math.PI);
  9078. var end = arc.endAngle * 360 / (2 * Math.PI);
  9079. var x = arc.x;
  9080. var y = arc.y;
  9081. this.internal.arc2(this, x, y, arc.radius, start, end, arc.counterclockwise, style, isClip);
  9082. } else {
  9083. this.internal.line2(c2d, arc.x, arc.y);
  9084. }
  9085. }
  9086. }
  9087. if (!moves[i].arc) {
  9088. if (moves[i].close !== true && moves[i].begin !== true) {
  9089. var x = moves[i].start.x;
  9090. var y = moves[i].start.y;
  9091. this.pdf.lines(moves[i].deltas, x, y, null, null);
  9092. }
  9093. }
  9094. if (moves[i].close) ;
  9095. }
  9096. if (style) {
  9097. this.pdf.internal.out(style);
  9098. }
  9099. if (isClip) {
  9100. this.pdf.clip();
  9101. }
  9102. globalObj.outIntercept = outInterceptOld; // if (this.ctx._clip_path.length > 0) {
  9103. // lines.push('Q');
  9104. // }
  9105. },
  9106. /*
  9107. _pushMask: function () {
  9108. var v2Support = typeof this.pdf.internal.newObject2 === 'function';
  9109. if (!v2Support) {
  9110. console.log('jsPDF v2 not enabled')
  9111. return;
  9112. }
  9113. // define a mask stream
  9114. var obj = this.pdf.internal.newStreamObject();
  9115. // define a mask state
  9116. var obj2 = this.pdf.internal.newObject2();
  9117. obj2.push('<</Type /ExtGState');
  9118. obj2.push('/SMask <</S /Alpha /G ' + obj.objId + ' 0 R>>'); // /S /Luminosity will need to define color space
  9119. obj2.push('>>');
  9120. // add mask to page resources
  9121. var gsName = 'MASK' + obj2.objId;
  9122. this.pdf.internal.addGraphicsState(gsName, obj2.objId);
  9123. var instruction = '/' + gsName + ' gs';
  9124. this.pdf.internal.out(instruction);
  9125. },
  9126. */
  9127. _getBaseline: function _getBaseline(y) {
  9128. var height = parseInt(this.pdf.internal.getFontSize() / this.pdf.internal.scaleFactor); // TODO Get descent from font descriptor
  9129. var descent = height * 0.25;
  9130. switch (this.ctx.textBaseline) {
  9131. case "bottom":
  9132. return y - descent;
  9133. case "top":
  9134. return y + height;
  9135. case "hanging":
  9136. return y + height - descent;
  9137. case "middle":
  9138. return y + height / 2 - descent;
  9139. case "ideographic":
  9140. // TODO not implemented
  9141. return y;
  9142. case "alphabetic":
  9143. default:
  9144. return y;
  9145. }
  9146. },
  9147. createLinearGradient: function createLinearGradient() {
  9148. var canvasGradient = function canvasGradient() {};
  9149. canvasGradient.colorStops = [];
  9150. canvasGradient.addColorStop = function (offset, color) {
  9151. this.colorStops.push([offset, color]);
  9152. };
  9153. canvasGradient.getColor = function () {
  9154. if (this.colorStops.length === 0) {
  9155. return "#000000";
  9156. }
  9157. return this.colorStops[0][1];
  9158. };
  9159. canvasGradient.isCanvasGradient = true;
  9160. return canvasGradient;
  9161. },
  9162. createPattern: function createPattern() {
  9163. return this.createLinearGradient();
  9164. },
  9165. createRadialGradient: function createRadialGradient() {
  9166. return this.createLinearGradient();
  9167. }
  9168. };
  9169. var c2d = jsPDFAPI.context2d;
  9170. /**
  9171. * Sets or returns the color, gradient, or pattern used to fill the drawing
  9172. *
  9173. * @name fillStyle
  9174. * @default #000000
  9175. * @property {(color|gradient|pattern)} value The color of the drawing. Default value is #000000<br />
  9176. * A gradient object (linear or radial) used to fill the drawing (not supported by context2d)<br />
  9177. * A pattern object to use to fill the drawing (not supported by context2d)
  9178. */
  9179. Object.defineProperty(c2d, "fillStyle", {
  9180. set: function set(value) {
  9181. this._setFillStyle(value);
  9182. },
  9183. get: function get() {
  9184. return this.ctx.fillStyle;
  9185. }
  9186. });
  9187. /**
  9188. * Sets or returns the color, gradient, or pattern used for strokes
  9189. *
  9190. * @name strokeStyle
  9191. * @default #000000
  9192. * @property {color} color A CSS color value that indicates the stroke color of the drawing. Default value is #000000 (not supported by context2d)
  9193. * @property {gradient} gradient A gradient object (linear or radial) used to create a gradient stroke (not supported by context2d)
  9194. * @property {pattern} pattern A pattern object used to create a pattern stroke (not supported by context2d)
  9195. */
  9196. Object.defineProperty(c2d, "strokeStyle", {
  9197. set: function set(value) {
  9198. this._setStrokeStyle(value);
  9199. },
  9200. get: function get() {
  9201. return this.ctx.strokeStyle;
  9202. }
  9203. }); //Line Styles
  9204. /**
  9205. * Sets or returns the style of the end caps for a line
  9206. *
  9207. * @name lineCap
  9208. * @default butt
  9209. * @property {(butt|round|square)} lineCap butt A flat edge is added to each end of the line <br/>
  9210. * round A rounded end cap is added to each end of the line<br/>
  9211. * square A square end cap is added to each end of the line<br/>
  9212. */
  9213. Object.defineProperty(c2d, "lineCap", {
  9214. set: function set(val) {
  9215. this._setLineCap(val);
  9216. },
  9217. get: function get() {
  9218. return this.ctx.lineCap;
  9219. }
  9220. });
  9221. /**
  9222. * Sets or returns the current line width
  9223. *
  9224. * @name lineWidth
  9225. * @default 1
  9226. * @property {number} lineWidth The current line width, in pixels
  9227. */
  9228. Object.defineProperty(c2d, "lineWidth", {
  9229. set: function set(value) {
  9230. this._setLineWidth(value);
  9231. },
  9232. get: function get() {
  9233. return this.ctx.lineWidth;
  9234. }
  9235. });
  9236. /**
  9237. * Sets or returns the type of corner created, when two lines meet
  9238. */
  9239. Object.defineProperty(c2d, "lineJoin", {
  9240. set: function set(val) {
  9241. this._setLineJoin(val);
  9242. },
  9243. get: function get() {
  9244. return this.ctx.lineJoin;
  9245. }
  9246. });
  9247. /**
  9248. * Sets or returns the maximum miter length
  9249. */
  9250. Object.defineProperty(c2d, "miterLimit", {
  9251. set: function set(val) {
  9252. this.ctx.miterLimit = val;
  9253. },
  9254. get: function get() {
  9255. return this.ctx.miterLimit;
  9256. }
  9257. });
  9258. Object.defineProperty(c2d, "textBaseline", {
  9259. set: function set(value) {
  9260. this._setTextBaseline(value);
  9261. },
  9262. get: function get() {
  9263. return this._getTextBaseline();
  9264. }
  9265. });
  9266. Object.defineProperty(c2d, "textAlign", {
  9267. set: function set(value) {
  9268. this._setTextAlign(value);
  9269. },
  9270. get: function get() {
  9271. return this._getTextAlign();
  9272. }
  9273. });
  9274. Object.defineProperty(c2d, "font", {
  9275. set: function set(value) {
  9276. this._setFont(value);
  9277. },
  9278. get: function get() {
  9279. return this.ctx.font;
  9280. }
  9281. });
  9282. Object.defineProperty(c2d, "globalCompositeOperation", {
  9283. set: function set(value) {
  9284. this.ctx.globalCompositeOperation = value;
  9285. },
  9286. get: function get() {
  9287. return this.ctx.globalCompositeOperation;
  9288. }
  9289. });
  9290. Object.defineProperty(c2d, "globalAlpha", {
  9291. set: function set(value) {
  9292. this.ctx.globalAlpha = value;
  9293. },
  9294. get: function get() {
  9295. return this.ctx.globalAlpha;
  9296. }
  9297. });
  9298. Object.defineProperty(c2d, "canvas", {
  9299. get: function get() {
  9300. return {
  9301. parentNode: false,
  9302. style: false
  9303. };
  9304. }
  9305. }); // Not HTML API
  9306. Object.defineProperty(c2d, "ignoreClearRect", {
  9307. set: function set(value) {
  9308. this.ctx.ignoreClearRect = value;
  9309. },
  9310. get: function get() {
  9311. return this.ctx.ignoreClearRect;
  9312. }
  9313. }); // End Not HTML API
  9314. c2d.internal = {};
  9315. c2d.internal.rxRgb = /rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/;
  9316. c2d.internal.rxRgba = /rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*([\d\.]+)\s*\)/;
  9317. 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
  9318. c2d.internal.arc = function (c2d, xc, yc, r, a1, a2, counterclockwise, style) {
  9319. var k = this.pdf.internal.scaleFactor;
  9320. var pageHeight = this.pdf.internal.pageSize.getHeight();
  9321. var f2 = this.pdf.internal.f2;
  9322. var a1r = a1 * (Math.PI / 180);
  9323. var a2r = a2 * (Math.PI / 180);
  9324. var curves = this.createArc(r, a1r, a2r, counterclockwise);
  9325. for (var i = 0; i < curves.length; i++) {
  9326. var curve = curves[i];
  9327. if (i === 0) {
  9328. 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(" "));
  9329. } else {
  9330. 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(" "));
  9331. } //c2d._lastPoint = {x: curve.x1 + xc, y: curve.y1 + yc};
  9332. c2d._lastPoint = {
  9333. x: xc,
  9334. y: yc
  9335. }; // 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'
  9336. }
  9337. if (style !== null) {
  9338. this.pdf.internal.out(this.pdf.internal.getStyle(style));
  9339. }
  9340. };
  9341. /**
  9342. *
  9343. * @param x Edge point X
  9344. * @param y Edge point Y
  9345. * @param r Radius
  9346. * @param a1 start angle
  9347. * @param a2 end angle
  9348. * @param counterclockwise
  9349. * @param style
  9350. * @param isClip
  9351. */
  9352. c2d.internal.arc2 = function (c2d, x, y, r, a1, a2, counterclockwise, style, isClip) {
  9353. // we need to convert from cartesian to polar here methinks.
  9354. var centerX = x; // + r;
  9355. var centerY = y;
  9356. if (!isClip) {
  9357. this.arc(c2d, centerX, centerY, r, a1, a2, counterclockwise, style);
  9358. } else {
  9359. this.arc(c2d, centerX, centerY, r, a1, a2, counterclockwise, null);
  9360. this.pdf.clip();
  9361. }
  9362. };
  9363. c2d.internal.move2 = function (c2d, x, y) {
  9364. var k = this.pdf.internal.scaleFactor;
  9365. var pageHeight = this.pdf.internal.pageSize.getHeight();
  9366. var f2 = this.pdf.internal.f2;
  9367. this.pdf.internal.out([f2(x * k), f2((pageHeight - y) * k), "m"].join(" "));
  9368. c2d._lastPoint = {
  9369. x: x,
  9370. y: y
  9371. };
  9372. };
  9373. c2d.internal.line2 = function (c2d, dx, dy) {
  9374. var k = this.pdf.internal.scaleFactor;
  9375. var pageHeight = this.pdf.internal.pageSize.getHeight();
  9376. var f2 = this.pdf.internal.f2; //var pt = {x: c2d._lastPoint.x + dx, y: c2d._lastPoint.y + dy};
  9377. var pt = {
  9378. x: dx,
  9379. y: dy
  9380. };
  9381. this.pdf.internal.out([f2(pt.x * k), f2((pageHeight - pt.y) * k), "l"].join(" ")); //this.pdf.internal.out('f');
  9382. c2d._lastPoint = pt;
  9383. };
  9384. /**
  9385. * 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.
  9386. *
  9387. * 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.
  9388. */
  9389. c2d.internal.createArc = function (radius, startAngle, endAngle, anticlockwise) {
  9390. var EPSILON = 0.00001; // Roughly 1/1000th of a degree, see below
  9391. // normalize startAngle, endAngle to [-2PI, 2PI]
  9392. var twoPI = Math.PI * 2;
  9393. var startAngleN = startAngle;
  9394. if (startAngleN < twoPI || startAngleN > twoPI) {
  9395. startAngleN = startAngleN % twoPI;
  9396. }
  9397. var endAngleN = endAngle;
  9398. if (endAngleN < twoPI || endAngleN > twoPI) {
  9399. endAngleN = endAngleN % twoPI;
  9400. } // Compute the sequence of arc curves, up to PI/2 at a time.
  9401. // Total arc angle is less than 2PI.
  9402. var curves = [];
  9403. var piOverTwo = Math.PI / 2.0; //var sgn = (startAngle < endAngle) ? +1 : -1; // clockwise or counterclockwise
  9404. var sgn = anticlockwise ? -1 : +1;
  9405. var a1 = startAngle;
  9406. for (var totalAngle = Math.min(twoPI, Math.abs(endAngleN - startAngleN)); totalAngle > EPSILON;) {
  9407. var a2 = a1 + sgn * Math.min(totalAngle, piOverTwo);
  9408. curves.push(this.createSmallArc(radius, a1, a2));
  9409. totalAngle -= Math.abs(a2 - a1);
  9410. a1 = a2;
  9411. }
  9412. return curves;
  9413. };
  9414. c2d.internal.getCurrentPage = function () {
  9415. return this.pdf.internal.pages[this.pdf.internal.getCurrentPageInfo().pageNumber];
  9416. };
  9417. /**
  9418. * 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.
  9419. *
  9420. * 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.
  9421. *
  9422. * 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.
  9423. */
  9424. c2d.internal.createSmallArc = function (r, a1, a2) {
  9425. // Compute all four points for an arc that subtends the same total angle
  9426. // but is centered on the X-axis
  9427. var a = (a2 - a1) / 2.0;
  9428. var x4 = r * Math.cos(a);
  9429. var y4 = r * Math.sin(a);
  9430. var x1 = x4;
  9431. var y1 = -y4;
  9432. var q1 = x1 * x1 + y1 * y1;
  9433. var q2 = q1 + x1 * x4 + y1 * y4;
  9434. var k2 = 4 / 3 * (Math.sqrt(2 * q1 * q2) - q2) / (x1 * y4 - y1 * x4);
  9435. var x2 = x1 - k2 * y1;
  9436. var y2 = y1 + k2 * x1;
  9437. var x3 = x2;
  9438. var y3 = -y2; // Find the arc points' actual locations by computing x1,y1 and x4,y4
  9439. // and rotating the control points by a + a1
  9440. var ar = a + a1;
  9441. var cos_ar = Math.cos(ar);
  9442. var sin_ar = Math.sin(ar);
  9443. return {
  9444. x1: r * Math.cos(a1),
  9445. y1: r * Math.sin(a1),
  9446. x2: x2 * cos_ar - y2 * sin_ar,
  9447. y2: x2 * sin_ar + y2 * cos_ar,
  9448. x3: x3 * cos_ar - y3 * sin_ar,
  9449. y3: x3 * sin_ar + y3 * cos_ar,
  9450. x4: r * Math.cos(a2),
  9451. y4: r * Math.sin(a2)
  9452. };
  9453. };
  9454. /**
  9455. *
  9456. * @function
  9457. * @constructor
  9458. */
  9459. function context() {
  9460. this._isStrokeTransparent = false;
  9461. this._strokeOpacity = 1;
  9462. this.strokeStyle = "#000000";
  9463. this.fillStyle = "#000000";
  9464. this._isFillTransparent = false;
  9465. this._fillOpacity = 1;
  9466. this.font = "12pt times";
  9467. this.textBaseline = "alphabetic"; // top,bottom,middle,ideographic,alphabetic,hanging
  9468. this.textAlign = "left";
  9469. this.lineWidth = 1;
  9470. this.lineJoin = "miter"; // round, bevel, miter
  9471. this.lineCap = "butt"; // butt, round, square
  9472. this._transform = [1, 0, 0, 1, 0, 0]; // sx, shy, shx, sy, tx, ty
  9473. this.globalCompositeOperation = "normal";
  9474. this.globalAlpha = 1.0;
  9475. this._clip_path = [];
  9476. this.currentPoint = {
  9477. x: 0,
  9478. y: 0
  9479. }; // TODO miter limit //default 10
  9480. // Not HTML API
  9481. this.ignoreClearRect = false;
  9482. this.copy = function (ctx) {
  9483. this._isStrokeTransparent = ctx._isStrokeTransparent;
  9484. this._strokeOpacity = ctx._strokeOpacity;
  9485. this.strokeStyle = ctx.strokeStyle;
  9486. this._isFillTransparent = ctx._isFillTransparent;
  9487. this._fillOpacity = ctx._fillOpacity;
  9488. this.fillStyle = ctx.fillStyle;
  9489. this.font = ctx.font;
  9490. this.lineWidth = ctx.lineWidth;
  9491. this.lineJoin = ctx.lineJoin;
  9492. this.lineCap = ctx.lineCap;
  9493. this.textBaseline = ctx.textBaseline;
  9494. this.textAlign = ctx.textAlign;
  9495. this._fontSize = ctx._fontSize;
  9496. this._transform = ctx._transform.slice(0);
  9497. this.globalCompositeOperation = ctx.globalCompositeOperation;
  9498. this.globalAlpha = ctx.globalAlpha;
  9499. this._clip_path = ctx._clip_path.slice(0); //TODO deep copy?
  9500. this.currentPoint = ctx.currentPoint; // Not HTML API
  9501. this.ignoreClearRect = ctx.ignoreClearRect;
  9502. };
  9503. }
  9504. return this;
  9505. })(jsPDF.API, typeof self !== "undefined" && self || typeof window !== "undefined" && window || typeof global !== "undefined" && global || Function('return typeof this === "object" && this.content')() || Function("return this")());
  9506. /**
  9507. * Copyright (c) 2018 Erik Koopmans
  9508. * Released under the MIT License.
  9509. *
  9510. * Licensed under the MIT License.
  9511. * http://opensource.org/licenses/mit-license
  9512. */
  9513. /**
  9514. * jsPDF html PlugIn
  9515. *
  9516. * @name html
  9517. * @module
  9518. */
  9519. (function (jsPDFAPI, global) {
  9520. /**
  9521. * Determine the type of a variable/object.
  9522. *
  9523. * @private
  9524. * @ignore
  9525. */
  9526. var objType = function objType(obj) {
  9527. var type = _typeof(obj);
  9528. 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";
  9529. };
  9530. /**
  9531. * Create an HTML element with optional className, innerHTML, and style.
  9532. *
  9533. * @private
  9534. * @ignore
  9535. */
  9536. var createElement = function createElement(tagName, opt) {
  9537. var el = document.createElement(tagName);
  9538. if (opt.className) el.className = opt.className;
  9539. if (opt.innerHTML) {
  9540. el.innerHTML = opt.innerHTML;
  9541. var scripts = el.getElementsByTagName("script");
  9542. for (var i = scripts.length; i-- > 0; null) {
  9543. scripts[i].parentNode.removeChild(scripts[i]);
  9544. }
  9545. }
  9546. for (var key in opt.style) {
  9547. el.style[key] = opt.style[key];
  9548. }
  9549. return el;
  9550. };
  9551. /**
  9552. * Deep-clone a node and preserve contents/properties.
  9553. *
  9554. * @private
  9555. * @ignore
  9556. */
  9557. var cloneNode = function cloneNode(node, javascriptEnabled) {
  9558. // Recursively clone the node.
  9559. var clone = node.nodeType === 3 ? document.createTextNode(node.nodeValue) : node.cloneNode(false);
  9560. for (var child = node.firstChild; child; child = child.nextSibling) {
  9561. if (javascriptEnabled === true || child.nodeType !== 1 || child.nodeName !== "SCRIPT") {
  9562. clone.appendChild(cloneNode(child, javascriptEnabled));
  9563. }
  9564. }
  9565. if (node.nodeType === 1) {
  9566. // Preserve contents/properties of special nodes.
  9567. if (node.nodeName === "CANVAS") {
  9568. clone.width = node.width;
  9569. clone.height = node.height;
  9570. clone.getContext("2d").drawImage(node, 0, 0);
  9571. } else if (node.nodeName === "TEXTAREA" || node.nodeName === "SELECT") {
  9572. clone.value = node.value;
  9573. } // Preserve the node's scroll position when it loads.
  9574. clone.addEventListener("load", function () {
  9575. clone.scrollTop = node.scrollTop;
  9576. clone.scrollLeft = node.scrollLeft;
  9577. }, true);
  9578. } // Return the cloned node.
  9579. return clone;
  9580. };
  9581. /* ----- CONSTRUCTOR ----- */
  9582. var Worker = function Worker(opt) {
  9583. // Create the root parent for the proto chain, and the starting Worker.
  9584. var root = Object.assign(Worker.convert(Promise.resolve()), JSON.parse(JSON.stringify(Worker.template)));
  9585. var self = Worker.convert(Promise.resolve(), root); // Set progress, optional settings, and return.
  9586. self = self.setProgress(1, Worker, 1, [Worker]);
  9587. self = self.set(opt);
  9588. return self;
  9589. }; // Boilerplate for subclassing Promise.
  9590. Worker.prototype = Object.create(Promise.prototype);
  9591. Worker.prototype.constructor = Worker; // Converts/casts promises into Workers.
  9592. Worker.convert = function convert(promise, inherit) {
  9593. // Uses prototypal inheritance to receive changes made to ancestors' properties.
  9594. promise.__proto__ = inherit || Worker.prototype;
  9595. return promise;
  9596. };
  9597. Worker.template = {
  9598. prop: {
  9599. src: null,
  9600. container: null,
  9601. overlay: null,
  9602. canvas: null,
  9603. img: null,
  9604. pdf: null,
  9605. pageSize: null,
  9606. callback: function callback() {}
  9607. },
  9608. progress: {
  9609. val: 0,
  9610. state: null,
  9611. n: 0,
  9612. stack: []
  9613. },
  9614. opt: {
  9615. filename: "file.pdf",
  9616. margin: [0, 0, 0, 0],
  9617. enableLinks: true,
  9618. html2canvas: {},
  9619. jsPDF: {}
  9620. }
  9621. };
  9622. /* ----- FROM / TO ----- */
  9623. Worker.prototype.from = function from(src, type) {
  9624. function getType(src) {
  9625. switch (objType(src)) {
  9626. case "string":
  9627. return "string";
  9628. case "element":
  9629. return src.nodeName.toLowerCase === "canvas" ? "canvas" : "element";
  9630. default:
  9631. return "unknown";
  9632. }
  9633. }
  9634. return this.then(function from_main() {
  9635. type = type || getType(src);
  9636. switch (type) {
  9637. case "string":
  9638. return this.set({
  9639. src: createElement("div", {
  9640. innerHTML: src
  9641. })
  9642. });
  9643. case "element":
  9644. return this.set({
  9645. src: src
  9646. });
  9647. case "canvas":
  9648. return this.set({
  9649. canvas: src
  9650. });
  9651. case "img":
  9652. return this.set({
  9653. img: src
  9654. });
  9655. default:
  9656. return this.error("Unknown source type.");
  9657. }
  9658. });
  9659. };
  9660. Worker.prototype.to = function to(target) {
  9661. // Route the 'to' request to the appropriate method.
  9662. switch (target) {
  9663. case "container":
  9664. return this.toContainer();
  9665. case "canvas":
  9666. return this.toCanvas();
  9667. case "img":
  9668. return this.toImg();
  9669. case "pdf":
  9670. return this.toPdf();
  9671. default:
  9672. return this.error("Invalid target.");
  9673. }
  9674. };
  9675. Worker.prototype.toContainer = function toContainer() {
  9676. // Set up function prerequisites.
  9677. var prereqs = [function checkSrc() {
  9678. return this.prop.src || this.error("Cannot duplicate - no source HTML.");
  9679. }, function checkPageSize() {
  9680. return this.prop.pageSize || this.setPageSize();
  9681. }];
  9682. return this.thenList(prereqs).then(function toContainer_main() {
  9683. // Define the CSS styles for the container and its overlay parent.
  9684. var overlayCSS = {
  9685. position: "fixed",
  9686. overflow: "hidden",
  9687. zIndex: 1000,
  9688. left: "-100000px",
  9689. right: 0,
  9690. bottom: 0,
  9691. top: 0
  9692. };
  9693. var containerCSS = {
  9694. position: "relative",
  9695. display: "inline-block",
  9696. width: Math.max(this.prop.src.clientWidth, this.prop.src.scrollWidth, this.prop.src.offsetWidth) + "px",
  9697. left: 0,
  9698. right: 0,
  9699. top: 0,
  9700. margin: "auto",
  9701. backgroundColor: "white"
  9702. }; // Set the overlay to hidden (could be changed in the future to provide a print preview).
  9703. var source = cloneNode(this.prop.src, this.opt.html2canvas.javascriptEnabled);
  9704. if (source.tagName === "BODY") {
  9705. containerCSS.height = Math.max(document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight) + "px";
  9706. }
  9707. this.prop.overlay = createElement("div", {
  9708. className: "html2pdf__overlay",
  9709. style: overlayCSS
  9710. });
  9711. this.prop.container = createElement("div", {
  9712. className: "html2pdf__container",
  9713. style: containerCSS
  9714. });
  9715. this.prop.container.appendChild(source);
  9716. this.prop.container.firstChild.appendChild(createElement("div", {
  9717. style: {
  9718. clear: "both",
  9719. border: "0 none transparent",
  9720. margin: 0,
  9721. padding: 0,
  9722. height: 0
  9723. }
  9724. }));
  9725. this.prop.container.style.float = "none";
  9726. this.prop.overlay.appendChild(this.prop.container);
  9727. document.body.appendChild(this.prop.overlay);
  9728. this.prop.container.firstChild.style.position = "relative";
  9729. this.prop.container.height = Math.max(this.prop.container.firstChild.clientHeight, this.prop.container.firstChild.scrollHeight, this.prop.container.firstChild.offsetHeight) + "px";
  9730. });
  9731. };
  9732. Worker.prototype.toCanvas = function toCanvas() {
  9733. // Set up function prerequisites.
  9734. var prereqs = [function checkContainer() {
  9735. return document.body.contains(this.prop.container) || this.toContainer();
  9736. }]; // Fulfill prereqs then create the canvas.
  9737. return this.thenList(prereqs).then(function toCanvas_main() {
  9738. // Handle old-fashioned 'onrendered' argument.
  9739. var options = Object.assign({}, this.opt.html2canvas);
  9740. delete options.onrendered;
  9741. if (!this.isHtml2CanvasLoaded()) {
  9742. return;
  9743. }
  9744. return html2canvas(this.prop.container, options);
  9745. }).then(function toCanvas_post(canvas) {
  9746. // Handle old-fashioned 'onrendered' argument.
  9747. var onRendered = this.opt.html2canvas.onrendered || function () {};
  9748. onRendered(canvas);
  9749. this.prop.canvas = canvas;
  9750. document.body.removeChild(this.prop.overlay);
  9751. });
  9752. };
  9753. Worker.prototype.toContext2d = function toContext2d() {
  9754. // Set up function prerequisites.
  9755. var prereqs = [function checkContainer() {
  9756. return document.body.contains(this.prop.container) || this.toContainer();
  9757. }]; // Fulfill prereqs then create the canvas.
  9758. return this.thenList(prereqs).then(function toContext2d_main() {
  9759. // Handle old-fashioned 'onrendered' argument.
  9760. var pdf = this.opt.jsPDF;
  9761. var options = Object.assign({
  9762. async: true,
  9763. allowTaint: true,
  9764. backgroundColor: "#ffffff",
  9765. imageTimeout: 15000,
  9766. logging: true,
  9767. proxy: null,
  9768. removeContainer: true,
  9769. foreignObjectRendering: false,
  9770. useCORS: false
  9771. }, this.opt.html2canvas);
  9772. delete options.onrendered;
  9773. options.windowHeight = options.windowHeight || 0;
  9774. options.windowHeight = options.windowHeight == 0 ? Math.max(this.prop.container.clientHeight, this.prop.container.scrollHeight, this.prop.container.offsetHeight) : options.windowHeight;
  9775. if (!this.isHtml2CanvasLoaded()) {
  9776. return;
  9777. }
  9778. return html2canvas(this.prop.container, options);
  9779. }).then(function toContext2d_post(canvas) {
  9780. // Handle old-fashioned 'onrendered' argument.
  9781. var onRendered = this.opt.html2canvas.onrendered || function () {};
  9782. onRendered(canvas);
  9783. this.prop.canvas = canvas;
  9784. document.body.removeChild(this.prop.overlay);
  9785. });
  9786. };
  9787. Worker.prototype.toImg = function toImg() {
  9788. // Set up function prerequisites.
  9789. var prereqs = [function checkCanvas() {
  9790. return this.prop.canvas || this.toCanvas();
  9791. }]; // Fulfill prereqs then create the image.
  9792. return this.thenList(prereqs).then(function toImg_main() {
  9793. var imgData = this.prop.canvas.toDataURL("image/" + this.opt.image.type, this.opt.image.quality);
  9794. this.prop.img = document.createElement("img");
  9795. this.prop.img.src = imgData;
  9796. });
  9797. };
  9798. Worker.prototype.toPdf = function toPdf() {
  9799. // Set up function prerequisites.
  9800. var prereqs = [function checkContext2d() {
  9801. return this.toContext2d();
  9802. } //function checkCanvas() { return this.prop.canvas || this.toCanvas(); }
  9803. ]; // Fulfill prereqs then create the image.
  9804. return this.thenList(prereqs).then(function toPdf_main() {
  9805. // Create local copies of frequently used properties.
  9806. this.prop.pdf = this.prop.pdf || this.opt.jsPDF;
  9807. });
  9808. };
  9809. /* ----- OUTPUT / SAVE ----- */
  9810. Worker.prototype.output = function output(type, options, src) {
  9811. // Redirect requests to the correct function (outputPdf / outputImg).
  9812. src = src || "pdf";
  9813. if (src.toLowerCase() === "img" || src.toLowerCase() === "image") {
  9814. return this.outputImg(type, options);
  9815. } else {
  9816. return this.outputPdf(type, options);
  9817. }
  9818. };
  9819. Worker.prototype.outputPdf = function outputPdf(type, options) {
  9820. // Set up function prerequisites.
  9821. var prereqs = [function checkPdf() {
  9822. return this.prop.pdf || this.toPdf();
  9823. }]; // Fulfill prereqs then perform the appropriate output.
  9824. return this.thenList(prereqs).then(function outputPdf_main() {
  9825. /* Currently implemented output types:
  9826. * https://rawgit.com/MrRio/jsPDF/master/docs/jspdf.js.html#line992
  9827. * save(options), arraybuffer, blob, bloburi/bloburl,
  9828. * datauristring/dataurlstring, dataurlnewwindow, datauri/dataurl
  9829. */
  9830. return this.prop.pdf.output(type, options);
  9831. });
  9832. };
  9833. Worker.prototype.outputImg = function outputImg(type, options) {
  9834. // Set up function prerequisites.
  9835. var prereqs = [function checkImg() {
  9836. return this.prop.img || this.toImg();
  9837. }]; // Fulfill prereqs then perform the appropriate output.
  9838. return this.thenList(prereqs).then(function outputImg_main() {
  9839. switch (type) {
  9840. case undefined:
  9841. case "img":
  9842. return this.prop.img;
  9843. case "datauristring":
  9844. case "dataurlstring":
  9845. return this.prop.img.src;
  9846. case "datauri":
  9847. case "dataurl":
  9848. return document.location.href = this.prop.img.src;
  9849. default:
  9850. throw 'Image output type "' + type + '" is not supported.';
  9851. }
  9852. });
  9853. };
  9854. Worker.prototype.isHtml2CanvasLoaded = function () {
  9855. var result = typeof global.html2canvas !== "undefined";
  9856. if (!result) {
  9857. console.error("html2canvas not loaded.");
  9858. }
  9859. return result;
  9860. };
  9861. Worker.prototype.save = function save(filename) {
  9862. // Set up function prerequisites.
  9863. var prereqs = [function checkPdf() {
  9864. return this.prop.pdf || this.toPdf();
  9865. }];
  9866. if (!this.isHtml2CanvasLoaded()) {
  9867. return;
  9868. } // Fulfill prereqs, update the filename (if provided), and save the PDF.
  9869. return this.thenList(prereqs).set(filename ? {
  9870. filename: filename
  9871. } : null).then(function save_main() {
  9872. this.prop.pdf.save(this.opt.filename);
  9873. });
  9874. };
  9875. Worker.prototype.doCallback = function doCallback(filename) {
  9876. // Set up function prerequisites.
  9877. var prereqs = [function checkPdf() {
  9878. return this.prop.pdf || this.toPdf();
  9879. }];
  9880. if (!this.isHtml2CanvasLoaded()) {
  9881. return;
  9882. } // Fulfill prereqs, update the filename (if provided), and save the PDF.
  9883. return this.thenList(prereqs).then(function doCallback_main() {
  9884. this.prop.callback(this.prop.pdf);
  9885. });
  9886. };
  9887. /* ----- SET / GET ----- */
  9888. Worker.prototype.set = function set(opt) {
  9889. // TODO: Implement ordered pairs?
  9890. // Silently ignore invalid or empty input.
  9891. if (objType(opt) !== "object") {
  9892. return this;
  9893. } // Build an array of setter functions to queue.
  9894. var fns = Object.keys(opt || {}).map(function (key) {
  9895. if (key in Worker.template.prop) {
  9896. // Set pre-defined properties.
  9897. return function set_prop() {
  9898. this.prop[key] = opt[key];
  9899. };
  9900. } else {
  9901. switch (key) {
  9902. case "margin":
  9903. return this.setMargin.bind(this, opt.margin);
  9904. case "jsPDF":
  9905. return function set_jsPDF() {
  9906. this.opt.jsPDF = opt.jsPDF;
  9907. return this.setPageSize();
  9908. };
  9909. case "pageSize":
  9910. return this.setPageSize.bind(this, opt.pageSize);
  9911. default:
  9912. // Set any other properties in opt.
  9913. return function set_opt() {
  9914. this.opt[key] = opt[key];
  9915. };
  9916. }
  9917. }
  9918. }, this); // Set properties within the promise chain.
  9919. return this.then(function set_main() {
  9920. return this.thenList(fns);
  9921. });
  9922. };
  9923. Worker.prototype.get = function get(key, cbk) {
  9924. return this.then(function get_main() {
  9925. // Fetch the requested property, either as a predefined prop or in opt.
  9926. var val = key in Worker.template.prop ? this.prop[key] : this.opt[key];
  9927. return cbk ? cbk(val) : val;
  9928. });
  9929. };
  9930. Worker.prototype.setMargin = function setMargin(margin) {
  9931. return this.then(function setMargin_main() {
  9932. // Parse the margin property.
  9933. switch (objType(margin)) {
  9934. case "number":
  9935. margin = [margin, margin, margin, margin];
  9936. case "array":
  9937. if (margin.length === 2) {
  9938. margin = [margin[0], margin[1], margin[0], margin[1]];
  9939. }
  9940. if (margin.length === 4) {
  9941. break;
  9942. }
  9943. default:
  9944. return this.error("Invalid margin array.");
  9945. } // Set the margin property, then update pageSize.
  9946. this.opt.margin = margin;
  9947. }).then(this.setPageSize);
  9948. };
  9949. Worker.prototype.setPageSize = function setPageSize(pageSize) {
  9950. function toPx(val, k) {
  9951. return Math.floor(val * k / 72 * 96);
  9952. }
  9953. return this.then(function setPageSize_main() {
  9954. // Retrieve page-size based on jsPDF settings, if not explicitly provided.
  9955. pageSize = pageSize || jsPDF.getPageSize(this.opt.jsPDF); // Add 'inner' field if not present.
  9956. if (!pageSize.hasOwnProperty("inner")) {
  9957. pageSize.inner = {
  9958. width: pageSize.width - this.opt.margin[1] - this.opt.margin[3],
  9959. height: pageSize.height - this.opt.margin[0] - this.opt.margin[2]
  9960. };
  9961. pageSize.inner.px = {
  9962. width: toPx(pageSize.inner.width, pageSize.k),
  9963. height: toPx(pageSize.inner.height, pageSize.k)
  9964. };
  9965. pageSize.inner.ratio = pageSize.inner.height / pageSize.inner.width;
  9966. } // Attach pageSize to this.
  9967. this.prop.pageSize = pageSize;
  9968. });
  9969. };
  9970. Worker.prototype.setProgress = function setProgress(val, state, n, stack) {
  9971. // Immediately update all progress values.
  9972. if (val != null) this.progress.val = val;
  9973. if (state != null) this.progress.state = state;
  9974. if (n != null) this.progress.n = n;
  9975. if (stack != null) this.progress.stack = stack;
  9976. this.progress.ratio = this.progress.val / this.progress.state; // Return this for command chaining.
  9977. return this;
  9978. };
  9979. Worker.prototype.updateProgress = function updateProgress(val, state, n, stack) {
  9980. // Immediately update all progress values, using setProgress.
  9981. 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);
  9982. };
  9983. /* ----- PROMISE MAPPING ----- */
  9984. Worker.prototype.then = function then(onFulfilled, onRejected) {
  9985. // Wrap `this` for encapsulation.
  9986. var self = this;
  9987. return this.thenCore(onFulfilled, onRejected, function then_main(onFulfilled, onRejected) {
  9988. // Update progress while queuing, calling, and resolving `then`.
  9989. self.updateProgress(null, null, 1, [onFulfilled]);
  9990. return Promise.prototype.then.call(this, function then_pre(val) {
  9991. self.updateProgress(null, onFulfilled);
  9992. return val;
  9993. }).then(onFulfilled, onRejected).then(function then_post(val) {
  9994. self.updateProgress(1);
  9995. return val;
  9996. });
  9997. });
  9998. };
  9999. Worker.prototype.thenCore = function thenCore(onFulfilled, onRejected, thenBase) {
  10000. // Handle optional thenBase parameter.
  10001. thenBase = thenBase || Promise.prototype.then; // Wrap `this` for encapsulation and bind it to the promise handlers.
  10002. var self = this;
  10003. if (onFulfilled) {
  10004. onFulfilled = onFulfilled.bind(self);
  10005. }
  10006. if (onRejected) {
  10007. onRejected = onRejected.bind(self);
  10008. } // Cast self into a Promise to avoid polyfills recursively defining `then`.
  10009. var isNative = Promise.toString().indexOf("[native code]") !== -1 && Promise.name === "Promise";
  10010. var selfPromise = isNative ? self : Worker.convert(Object.assign({}, self), Promise.prototype); // Return the promise, after casting it into a Worker and preserving props.
  10011. var returnVal = thenBase.call(selfPromise, onFulfilled, onRejected);
  10012. return Worker.convert(returnVal, self.__proto__);
  10013. };
  10014. Worker.prototype.thenExternal = function thenExternal(onFulfilled, onRejected) {
  10015. // Call `then` and return a standard promise (exits the Worker chain).
  10016. return Promise.prototype.then.call(this, onFulfilled, onRejected);
  10017. };
  10018. Worker.prototype.thenList = function thenList(fns) {
  10019. // Queue a series of promise 'factories' into the promise chain.
  10020. var self = this;
  10021. fns.forEach(function thenList_forEach(fn) {
  10022. self = self.thenCore(fn);
  10023. });
  10024. return self;
  10025. };
  10026. Worker.prototype["catch"] = function (onRejected) {
  10027. // Bind `this` to the promise handler, call `catch`, and return a Worker.
  10028. if (onRejected) {
  10029. onRejected = onRejected.bind(this);
  10030. }
  10031. var returnVal = Promise.prototype["catch"].call(this, onRejected);
  10032. return Worker.convert(returnVal, this);
  10033. };
  10034. Worker.prototype.catchExternal = function catchExternal(onRejected) {
  10035. // Call `catch` and return a standard promise (exits the Worker chain).
  10036. return Promise.prototype["catch"].call(this, onRejected);
  10037. };
  10038. Worker.prototype.error = function error(msg) {
  10039. // Throw the error in the Promise chain.
  10040. return this.then(function error_main() {
  10041. throw new Error(msg);
  10042. });
  10043. };
  10044. /* ----- ALIASES ----- */
  10045. Worker.prototype.using = Worker.prototype.set;
  10046. Worker.prototype.saveAs = Worker.prototype.save;
  10047. Worker.prototype.export = Worker.prototype.output;
  10048. Worker.prototype.run = Worker.prototype.then; // Get dimensions of a PDF page, as determined by jsPDF.
  10049. jsPDF.getPageSize = function (orientation, unit, format) {
  10050. // Decode options object
  10051. if (_typeof(orientation) === "object") {
  10052. var options = orientation;
  10053. orientation = options.orientation;
  10054. unit = options.unit || unit;
  10055. format = options.format || format;
  10056. } // Default options
  10057. unit = unit || "mm";
  10058. format = format || "a4";
  10059. orientation = ("" + (orientation || "P")).toLowerCase();
  10060. var format_as_string = ("" + format).toLowerCase(); // Size in pt of various paper formats
  10061. var pageFormats = {
  10062. a0: [2383.94, 3370.39],
  10063. a1: [1683.78, 2383.94],
  10064. a2: [1190.55, 1683.78],
  10065. a3: [841.89, 1190.55],
  10066. a4: [595.28, 841.89],
  10067. a5: [419.53, 595.28],
  10068. a6: [297.64, 419.53],
  10069. a7: [209.76, 297.64],
  10070. a8: [147.4, 209.76],
  10071. a9: [104.88, 147.4],
  10072. a10: [73.7, 104.88],
  10073. b0: [2834.65, 4008.19],
  10074. b1: [2004.09, 2834.65],
  10075. b2: [1417.32, 2004.09],
  10076. b3: [1000.63, 1417.32],
  10077. b4: [708.66, 1000.63],
  10078. b5: [498.9, 708.66],
  10079. b6: [354.33, 498.9],
  10080. b7: [249.45, 354.33],
  10081. b8: [175.75, 249.45],
  10082. b9: [124.72, 175.75],
  10083. b10: [87.87, 124.72],
  10084. c0: [2599.37, 3676.54],
  10085. c1: [1836.85, 2599.37],
  10086. c2: [1298.27, 1836.85],
  10087. c3: [918.43, 1298.27],
  10088. c4: [649.13, 918.43],
  10089. c5: [459.21, 649.13],
  10090. c6: [323.15, 459.21],
  10091. c7: [229.61, 323.15],
  10092. c8: [161.57, 229.61],
  10093. c9: [113.39, 161.57],
  10094. c10: [79.37, 113.39],
  10095. dl: [311.81, 623.62],
  10096. letter: [612, 792],
  10097. "government-letter": [576, 756],
  10098. legal: [612, 1008],
  10099. "junior-legal": [576, 360],
  10100. ledger: [1224, 792],
  10101. tabloid: [792, 1224],
  10102. "credit-card": [153, 243]
  10103. }; // Unit conversion
  10104. switch (unit) {
  10105. case "pt":
  10106. var k = 1;
  10107. break;
  10108. case "mm":
  10109. var k = 72 / 25.4;
  10110. break;
  10111. case "cm":
  10112. var k = 72 / 2.54;
  10113. break;
  10114. case "in":
  10115. var k = 72;
  10116. break;
  10117. case "px":
  10118. var k = 72 / 96;
  10119. break;
  10120. case "pc":
  10121. var k = 12;
  10122. break;
  10123. case "em":
  10124. var k = 12;
  10125. break;
  10126. case "ex":
  10127. var k = 6;
  10128. break;
  10129. default:
  10130. throw "Invalid unit: " + unit;
  10131. } // Dimensions are stored as user units and converted to points on output
  10132. if (pageFormats.hasOwnProperty(format_as_string)) {
  10133. var pageHeight = pageFormats[format_as_string][1] / k;
  10134. var pageWidth = pageFormats[format_as_string][0] / k;
  10135. } else {
  10136. try {
  10137. var pageHeight = format[1];
  10138. var pageWidth = format[0];
  10139. } catch (err) {
  10140. throw new Error("Invalid format: " + format);
  10141. }
  10142. } // Handle page orientation
  10143. if (orientation === "p" || orientation === "portrait") {
  10144. orientation = "p";
  10145. if (pageWidth > pageHeight) {
  10146. var tmp = pageWidth;
  10147. pageWidth = pageHeight;
  10148. pageHeight = tmp;
  10149. }
  10150. } else if (orientation === "l" || orientation === "landscape") {
  10151. orientation = "l";
  10152. if (pageHeight > pageWidth) {
  10153. var tmp = pageWidth;
  10154. pageWidth = pageHeight;
  10155. pageHeight = tmp;
  10156. }
  10157. } else {
  10158. throw "Invalid orientation: " + orientation;
  10159. } // Return information (k is the unit conversion ratio from pts)
  10160. var info = {
  10161. width: pageWidth,
  10162. height: pageHeight,
  10163. unit: unit,
  10164. k: k
  10165. };
  10166. return info;
  10167. };
  10168. /**
  10169. * Generate a PDF from an HTML element or string using.
  10170. *
  10171. * @name html
  10172. * @function
  10173. * @param {Element|string} source The source element or HTML string.
  10174. * @param {Object=} options An object of optional settings.
  10175. * @description The Plugin needs html2canvas from niklasvh
  10176. */
  10177. jsPDFAPI.html = function (src, options) {
  10178. options = options || {};
  10179. options.callback = options.callback || function () {};
  10180. options.html2canvas = options.html2canvas || {};
  10181. options.html2canvas.canvas = options.html2canvas.canvas || this.canvas;
  10182. options.jsPDF = options.jsPDF || this; // Create a new worker with the given options.
  10183. var pdf = options.jsPDF;
  10184. pdf.annotations = {
  10185. _nameMap: [],
  10186. createAnnotation: function createAnnotation(href, bounds) {
  10187. var x = pdf.context2d._wrapX(bounds.left);
  10188. var y = pdf.context2d._wrapY(bounds.top);
  10189. var page = pdf.context2d._page(bounds.top);
  10190. var options;
  10191. var index = href.indexOf("#");
  10192. if (index >= 0) {
  10193. options = {
  10194. name: href.substring(index + 1)
  10195. };
  10196. } else {
  10197. options = {
  10198. url: href
  10199. };
  10200. }
  10201. pdf.link(x, y, bounds.right - bounds.left, bounds.bottom - bounds.top, options);
  10202. },
  10203. setName: function setName(name, bounds) {
  10204. var x = pdf.context2d._wrapX(bounds.left);
  10205. var y = pdf.context2d._wrapY(bounds.top);
  10206. var page = pdf.context2d._page(bounds.top);
  10207. this._nameMap[name] = {
  10208. page: page,
  10209. x: x,
  10210. y: y
  10211. };
  10212. }
  10213. };
  10214. pdf.context2d._pageBreakAt = function (y) {
  10215. this.pageBreaks.push(y);
  10216. };
  10217. pdf.context2d._gotoPage = function (pageOneBased) {
  10218. while (pdf.internal.getNumberOfPages() < pageOneBased) {
  10219. pdf.addPage();
  10220. }
  10221. pdf.setPage(pageOneBased);
  10222. };
  10223. pdf.context2d.pageWrapYEnabled = true;
  10224. pdf.context2d.pageWrapY = pdf.internal.pageSize.getHeight() / pdf.internal.scaleFactor + 1;
  10225. pdf.canvas.autoContext2dResizeY = false;
  10226. var worker = new Worker(options);
  10227. if (!options.worker) {
  10228. // If worker is not set to true, perform the traditional 'simple' operation.
  10229. return worker.from(src).doCallback();
  10230. } else {
  10231. // Otherwise, return the worker for new Promise-based operation.
  10232. return worker;
  10233. }
  10234. return this;
  10235. };
  10236. })(jsPDF.API, typeof window !== "undefined" && window || typeof global !== "undefined" && global);
  10237. /**
  10238. * @license
  10239. * ====================================================================
  10240. * Copyright (c) 2013 Youssef Beddad, youssef.beddad@gmail.com
  10241. *
  10242. *
  10243. * ====================================================================
  10244. */
  10245. /*global jsPDF */
  10246. /**
  10247. * jsPDF JavaScript plugin
  10248. *
  10249. * @name javascript
  10250. * @module
  10251. */
  10252. (function (jsPDFAPI) {
  10253. var jsNamesObj, jsJsObj, text;
  10254. /**
  10255. * @name addJS
  10256. * @function
  10257. * @param {string} javascript The javascript to be embedded into the PDF-file.
  10258. * @returns {jsPDF}
  10259. */
  10260. jsPDFAPI.addJS = function (javascript) {
  10261. text = javascript;
  10262. this.internal.events.subscribe("postPutResources", function (javascript) {
  10263. jsNamesObj = this.internal.newObject();
  10264. this.internal.out("<<");
  10265. this.internal.out("/Names [(EmbeddedJS) " + (jsNamesObj + 1) + " 0 R]");
  10266. this.internal.out(">>");
  10267. this.internal.out("endobj");
  10268. jsJsObj = this.internal.newObject();
  10269. this.internal.out("<<");
  10270. this.internal.out("/S /JavaScript");
  10271. this.internal.out("/JS (" + text + ")");
  10272. this.internal.out(">>");
  10273. this.internal.out("endobj");
  10274. });
  10275. this.internal.events.subscribe("putCatalog", function () {
  10276. if (jsNamesObj !== undefined && jsJsObj !== undefined) {
  10277. this.internal.out("/Names <</JavaScript " + jsNamesObj + " 0 R>>");
  10278. }
  10279. });
  10280. return this;
  10281. };
  10282. })(jsPDF.API);
  10283. /**
  10284. * @license
  10285. * Copyright (c) 2014 Steven Spungin (TwelveTone LLC) steven@twelvetone.tv
  10286. *
  10287. * Licensed under the MIT License.
  10288. * http://opensource.org/licenses/mit-license
  10289. */
  10290. /**
  10291. * jsPDF Outline PlugIn
  10292. *
  10293. * Generates a PDF Outline
  10294. * @name outline
  10295. * @module
  10296. */
  10297. (function (jsPDFAPI) {
  10298. jsPDFAPI.events.push(["postPutResources", function () {
  10299. var pdf = this;
  10300. var rx = /^(\d+) 0 obj$/; // Write action goto objects for each page
  10301. // this.outline.destsGoto = [];
  10302. // for (var i = 0; i < totalPages; i++) {
  10303. // var id = pdf.internal.newObject();
  10304. // this.outline.destsGoto.push(id);
  10305. // pdf.internal.write("<</D[" + (i * 2 + 3) + " 0 R /XYZ null
  10306. // null null]/S/GoTo>> endobj");
  10307. // }
  10308. //
  10309. // for (var i = 0; i < dests.length; i++) {
  10310. // pdf.internal.write("(page_" + (i + 1) + ")" + dests[i] + " 0
  10311. // R");
  10312. // }
  10313. //
  10314. if (this.outline.root.children.length > 0) {
  10315. var lines = pdf.outline.render().split(/\r\n/);
  10316. for (var i = 0; i < lines.length; i++) {
  10317. var line = lines[i];
  10318. var m = rx.exec(line);
  10319. if (m != null) {
  10320. var oid = m[1];
  10321. pdf.internal.newObjectDeferredBegin(oid);
  10322. }
  10323. pdf.internal.write(line);
  10324. }
  10325. } // This code will write named destination for each page reference
  10326. // (page_1, etc)
  10327. if (this.outline.createNamedDestinations) {
  10328. var totalPages = this.internal.pages.length; // WARNING: this assumes jsPDF starts on page 3 and pageIDs
  10329. // follow 5, 7, 9, etc
  10330. // Write destination objects for each page
  10331. var dests = [];
  10332. for (var i = 0; i < totalPages; i++) {
  10333. var id = pdf.internal.newObject();
  10334. dests.push(id);
  10335. var info = pdf.internal.getPageInfo(i + 1);
  10336. pdf.internal.write("<< /D[" + info.objId + " 0 R /XYZ null null null]>> endobj");
  10337. } // assign a name for each destination
  10338. var names2Oid = pdf.internal.newObject();
  10339. pdf.internal.write("<< /Names [ ");
  10340. for (var i = 0; i < dests.length; i++) {
  10341. pdf.internal.write("(page_" + (i + 1) + ")" + dests[i] + " 0 R");
  10342. }
  10343. pdf.internal.write(" ] >>", "endobj"); // var kids = pdf.internal.newObject();
  10344. // pdf.internal.write('<< /Kids [ ' + names2Oid + ' 0 R');
  10345. // pdf.internal.write(' ] >>', 'endobj');
  10346. var namesOid = pdf.internal.newObject();
  10347. pdf.internal.write("<< /Dests " + names2Oid + " 0 R");
  10348. pdf.internal.write(">>", "endobj");
  10349. }
  10350. }]);
  10351. jsPDFAPI.events.push(["putCatalog", function () {
  10352. var pdf = this;
  10353. if (pdf.outline.root.children.length > 0) {
  10354. pdf.internal.write("/Outlines", this.outline.makeRef(this.outline.root));
  10355. if (this.outline.createNamedDestinations) {
  10356. pdf.internal.write("/Names " + namesOid + " 0 R");
  10357. } // Open with Bookmarks showing
  10358. // pdf.internal.write("/PageMode /UseOutlines");
  10359. }
  10360. }]);
  10361. jsPDFAPI.events.push(["initialized", function () {
  10362. var pdf = this;
  10363. pdf.outline = {
  10364. createNamedDestinations: false,
  10365. root: {
  10366. children: []
  10367. }
  10368. };
  10369. /**
  10370. * Options: pageNumber
  10371. */
  10372. pdf.outline.add = function (parent, title, options) {
  10373. var item = {
  10374. title: title,
  10375. options: options,
  10376. children: []
  10377. };
  10378. if (parent == null) {
  10379. parent = this.root;
  10380. }
  10381. parent.children.push(item);
  10382. return item;
  10383. };
  10384. pdf.outline.render = function () {
  10385. this.ctx = {};
  10386. this.ctx.val = "";
  10387. this.ctx.pdf = pdf;
  10388. this.genIds_r(this.root);
  10389. this.renderRoot(this.root);
  10390. this.renderItems(this.root);
  10391. return this.ctx.val;
  10392. };
  10393. pdf.outline.genIds_r = function (node) {
  10394. node.id = pdf.internal.newObjectDeferred();
  10395. for (var i = 0; i < node.children.length; i++) {
  10396. this.genIds_r(node.children[i]);
  10397. }
  10398. };
  10399. pdf.outline.renderRoot = function (node) {
  10400. this.objStart(node);
  10401. this.line("/Type /Outlines");
  10402. if (node.children.length > 0) {
  10403. this.line("/First " + this.makeRef(node.children[0]));
  10404. this.line("/Last " + this.makeRef(node.children[node.children.length - 1]));
  10405. }
  10406. this.line("/Count " + this.count_r({
  10407. count: 0
  10408. }, node));
  10409. this.objEnd();
  10410. };
  10411. pdf.outline.renderItems = function (node) {
  10412. for (var i = 0; i < node.children.length; i++) {
  10413. var item = node.children[i];
  10414. this.objStart(item);
  10415. this.line("/Title " + this.makeString(item.title));
  10416. this.line("/Parent " + this.makeRef(node));
  10417. if (i > 0) {
  10418. this.line("/Prev " + this.makeRef(node.children[i - 1]));
  10419. }
  10420. if (i < node.children.length - 1) {
  10421. this.line("/Next " + this.makeRef(node.children[i + 1]));
  10422. }
  10423. if (item.children.length > 0) {
  10424. this.line("/First " + this.makeRef(item.children[0]));
  10425. this.line("/Last " + this.makeRef(item.children[item.children.length - 1]));
  10426. }
  10427. var count = this.count = this.count_r({
  10428. count: 0
  10429. }, item);
  10430. if (count > 0) {
  10431. this.line("/Count " + count);
  10432. }
  10433. if (item.options) {
  10434. if (item.options.pageNumber) {
  10435. // Explicit Destination
  10436. //WARNING this assumes page ids are 3,5,7, etc.
  10437. var info = pdf.internal.getPageInfo(item.options.pageNumber);
  10438. 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)
  10439. //this.line('/Dest ' + '[' + (item.options.pageNumber - 1) + ' /XYZ 0 ' + this.ctx.pdf.internal.pageSize.getHeight() + ' 0]');
  10440. // Named Destination
  10441. // this.line('/Dest (page_' + (item.options.pageNumber) + ')');
  10442. // Action Destination
  10443. // var id = pdf.internal.newObject();
  10444. // pdf.internal.write('<</D[' + (item.options.pageNumber - 1) + ' /XYZ null null null]/S/GoTo>> endobj');
  10445. // this.line('/A ' + id + ' 0 R' );
  10446. }
  10447. }
  10448. this.objEnd();
  10449. }
  10450. for (var i = 0; i < node.children.length; i++) {
  10451. var item = node.children[i];
  10452. this.renderItems(item);
  10453. }
  10454. };
  10455. pdf.outline.line = function (text) {
  10456. this.ctx.val += text + "\r\n";
  10457. };
  10458. pdf.outline.makeRef = function (node) {
  10459. return node.id + " 0 R";
  10460. };
  10461. pdf.outline.makeString = function (val) {
  10462. return "(" + pdf.internal.pdfEscape(val) + ")";
  10463. };
  10464. pdf.outline.objStart = function (node) {
  10465. this.ctx.val += "\r\n" + node.id + " 0 obj" + "\r\n<<\r\n";
  10466. };
  10467. pdf.outline.objEnd = function (node) {
  10468. this.ctx.val += ">> \r\n" + "endobj" + "\r\n";
  10469. };
  10470. pdf.outline.count_r = function (ctx, node) {
  10471. for (var i = 0; i < node.children.length; i++) {
  10472. ctx.count++;
  10473. this.count_r(ctx, node.children[i]);
  10474. }
  10475. return ctx.count;
  10476. };
  10477. }]);
  10478. return this;
  10479. })(jsPDF.API);
  10480. /**
  10481. * @license
  10482. *
  10483. * Copyright (c) 2014 James Robb, https://github.com/jamesbrobb
  10484. *
  10485. *
  10486. * ====================================================================
  10487. */
  10488. /**
  10489. * jsPDF PNG PlugIn
  10490. * @name png_support
  10491. * @module
  10492. */
  10493. (function (jsPDFAPI) {
  10494. /*
  10495. * @see http://www.w3.org/TR/PNG-Chunks.html
  10496. *
  10497. Color Allowed Interpretation
  10498. Type Bit Depths
  10499. 0 1,2,4,8,16 Each pixel is a grayscale sample.
  10500. 2 8,16 Each pixel is an R,G,B triple.
  10501. 3 1,2,4,8 Each pixel is a palette index;
  10502. a PLTE chunk must appear.
  10503. 4 8,16 Each pixel is a grayscale sample,
  10504. followed by an alpha sample.
  10505. 6 8,16 Each pixel is an R,G,B triple,
  10506. followed by an alpha sample.
  10507. */
  10508. /*
  10509. * PNG filter method types
  10510. *
  10511. * @see http://www.w3.org/TR/PNG-Filters.html
  10512. * @see http://www.libpng.org/pub/png/book/chapter09.html
  10513. *
  10514. * This is what the value 'Predictor' in decode params relates to
  10515. *
  10516. * 15 is "optimal prediction", which means the prediction algorithm can change from line to line.
  10517. * 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.
  10518. *
  10519. 0 None
  10520. 1 Sub
  10521. 2 Up
  10522. 3 Average
  10523. 4 Paeth
  10524. */
  10525. var doesNotHavePngJS = function doesNotHavePngJS() {
  10526. return typeof PNG !== "function" || typeof FlateStream !== "function";
  10527. },
  10528. canCompress = function canCompress(value) {
  10529. return value !== jsPDFAPI.image_compression.NONE && hasCompressionJS();
  10530. },
  10531. hasCompressionJS = function hasCompressionJS() {
  10532. var inst = typeof Deflater === "function";
  10533. if (!inst) throw new Error("requires deflate.js for compression");
  10534. return inst;
  10535. },
  10536. compressBytes = function compressBytes(bytes, lineLength, colorsPerPixel, compression) {
  10537. var level = 5,
  10538. filter_method = filterUp;
  10539. switch (compression) {
  10540. case jsPDFAPI.image_compression.FAST:
  10541. level = 3;
  10542. filter_method = filterSub;
  10543. break;
  10544. case jsPDFAPI.image_compression.MEDIUM:
  10545. level = 6;
  10546. filter_method = filterAverage;
  10547. break;
  10548. case jsPDFAPI.image_compression.SLOW:
  10549. level = 9;
  10550. filter_method = filterPaeth; //uses to sum to choose best filter for each line
  10551. break;
  10552. }
  10553. bytes = applyPngFilterMethod(bytes, lineLength, colorsPerPixel, filter_method);
  10554. var header = new Uint8Array(createZlibHeader(level));
  10555. var checksum = adler32(bytes);
  10556. var deflate = new Deflater(level);
  10557. var a = deflate.append(bytes);
  10558. var cBytes = deflate.flush();
  10559. var len = header.length + a.length + cBytes.length;
  10560. var cmpd = new Uint8Array(len + 4);
  10561. cmpd.set(header);
  10562. cmpd.set(a, header.length);
  10563. cmpd.set(cBytes, header.length + a.length);
  10564. cmpd[len++] = checksum >>> 24 & 0xff;
  10565. cmpd[len++] = checksum >>> 16 & 0xff;
  10566. cmpd[len++] = checksum >>> 8 & 0xff;
  10567. cmpd[len++] = checksum & 0xff;
  10568. return jsPDFAPI.arrayBufferToBinaryString(cmpd);
  10569. },
  10570. createZlibHeader = function createZlibHeader(bytes, level) {
  10571. /*
  10572. * @see http://www.ietf.org/rfc/rfc1950.txt for zlib header
  10573. */
  10574. var cm = 8;
  10575. var cinfo = Math.LOG2E * Math.log(0x8000) - 8;
  10576. var cmf = cinfo << 4 | cm;
  10577. var hdr = cmf << 8;
  10578. var flevel = Math.min(3, (level - 1 & 0xff) >> 1);
  10579. hdr |= flevel << 6;
  10580. hdr |= 0; //FDICT
  10581. hdr += 31 - hdr % 31;
  10582. return [cmf, hdr & 0xff & 0xff];
  10583. },
  10584. adler32 = function adler32(array, param) {
  10585. var adler = 1;
  10586. var s1 = adler & 0xffff,
  10587. s2 = adler >>> 16 & 0xffff;
  10588. var len = array.length;
  10589. var tlen;
  10590. var i = 0;
  10591. while (len > 0) {
  10592. tlen = len > param ? param : len;
  10593. len -= tlen;
  10594. do {
  10595. s1 += array[i++];
  10596. s2 += s1;
  10597. } while (--tlen);
  10598. s1 %= 65521;
  10599. s2 %= 65521;
  10600. }
  10601. return (s2 << 16 | s1) >>> 0;
  10602. },
  10603. applyPngFilterMethod = function applyPngFilterMethod(bytes, lineLength, colorsPerPixel, filter_method) {
  10604. var lines = bytes.length / lineLength,
  10605. result = new Uint8Array(bytes.length + lines),
  10606. filter_methods = getFilterMethods(),
  10607. i = 0,
  10608. line,
  10609. prevLine,
  10610. offset;
  10611. for (; i < lines; i++) {
  10612. offset = i * lineLength;
  10613. line = bytes.subarray(offset, offset + lineLength);
  10614. if (filter_method) {
  10615. result.set(filter_method(line, colorsPerPixel, prevLine), offset + i);
  10616. } else {
  10617. var j = 0,
  10618. len = filter_methods.length,
  10619. results = [];
  10620. for (; j < len; j++) {
  10621. results[j] = filter_methods[j](line, colorsPerPixel, prevLine);
  10622. }
  10623. var ind = getIndexOfSmallestSum(results.concat());
  10624. result.set(results[ind], offset + i);
  10625. }
  10626. prevLine = line;
  10627. }
  10628. return result;
  10629. },
  10630. filterNone = function filterNone(line, colorsPerPixel, prevLine) {
  10631. /*var result = new Uint8Array(line.length + 1);
  10632. result[0] = 0;
  10633. result.set(line, 1);*/
  10634. var result = Array.apply([], line);
  10635. result.unshift(0);
  10636. return result;
  10637. },
  10638. filterSub = function filterSub(line, colorsPerPixel, prevLine) {
  10639. var result = [],
  10640. i = 0,
  10641. len = line.length,
  10642. left;
  10643. result[0] = 1;
  10644. for (; i < len; i++) {
  10645. left = line[i - colorsPerPixel] || 0;
  10646. result[i + 1] = line[i] - left + 0x0100 & 0xff;
  10647. }
  10648. return result;
  10649. },
  10650. filterUp = function filterUp(line, colorsPerPixel, prevLine) {
  10651. var result = [],
  10652. i = 0,
  10653. len = line.length,
  10654. up;
  10655. result[0] = 2;
  10656. for (; i < len; i++) {
  10657. up = prevLine && prevLine[i] || 0;
  10658. result[i + 1] = line[i] - up + 0x0100 & 0xff;
  10659. }
  10660. return result;
  10661. },
  10662. filterAverage = function filterAverage(line, colorsPerPixel, prevLine) {
  10663. var result = [],
  10664. i = 0,
  10665. len = line.length,
  10666. left,
  10667. up;
  10668. result[0] = 3;
  10669. for (; i < len; i++) {
  10670. left = line[i - colorsPerPixel] || 0;
  10671. up = prevLine && prevLine[i] || 0;
  10672. result[i + 1] = line[i] + 0x0100 - (left + up >>> 1) & 0xff;
  10673. }
  10674. return result;
  10675. },
  10676. filterPaeth = function filterPaeth(line, colorsPerPixel, prevLine) {
  10677. var result = [],
  10678. i = 0,
  10679. len = line.length,
  10680. left,
  10681. up,
  10682. upLeft,
  10683. paeth;
  10684. result[0] = 4;
  10685. for (; i < len; i++) {
  10686. left = line[i - colorsPerPixel] || 0;
  10687. up = prevLine && prevLine[i] || 0;
  10688. upLeft = prevLine && prevLine[i - colorsPerPixel] || 0;
  10689. paeth = paethPredictor(left, up, upLeft);
  10690. result[i + 1] = line[i] - paeth + 0x0100 & 0xff;
  10691. }
  10692. return result;
  10693. },
  10694. paethPredictor = function paethPredictor(left, up, upLeft) {
  10695. var p = left + up - upLeft,
  10696. pLeft = Math.abs(p - left),
  10697. pUp = Math.abs(p - up),
  10698. pUpLeft = Math.abs(p - upLeft);
  10699. return pLeft <= pUp && pLeft <= pUpLeft ? left : pUp <= pUpLeft ? up : upLeft;
  10700. },
  10701. getFilterMethods = function getFilterMethods() {
  10702. return [filterNone, filterSub, filterUp, filterAverage, filterPaeth];
  10703. },
  10704. getIndexOfSmallestSum = function getIndexOfSmallestSum(arrays) {
  10705. var i = 0,
  10706. len = arrays.length,
  10707. sum,
  10708. min,
  10709. ind;
  10710. while (i < len) {
  10711. sum = absSum(arrays[i].slice(1));
  10712. if (sum < min || !min) {
  10713. min = sum;
  10714. ind = i;
  10715. }
  10716. i++;
  10717. }
  10718. return ind;
  10719. },
  10720. absSum = function absSum(array) {
  10721. var i = 0,
  10722. len = array.length,
  10723. sum = 0;
  10724. while (i < len) {
  10725. sum += Math.abs(array[i++]);
  10726. }
  10727. return sum;
  10728. },
  10729. getPredictorFromCompression = function getPredictorFromCompression(compression) {
  10730. var predictor;
  10731. switch (compression) {
  10732. case jsPDFAPI.image_compression.FAST:
  10733. predictor = 11;
  10734. break;
  10735. case jsPDFAPI.image_compression.MEDIUM:
  10736. predictor = 13;
  10737. break;
  10738. case jsPDFAPI.image_compression.SLOW:
  10739. predictor = 14;
  10740. break;
  10741. default:
  10742. predictor = 12;
  10743. break;
  10744. }
  10745. return predictor;
  10746. };
  10747. /**
  10748. *
  10749. * @name processPNG
  10750. * @function
  10751. * @ignore
  10752. */
  10753. jsPDFAPI.processPNG = function (imageData, imageIndex, alias, compression, dataAsBinaryString) {
  10754. var colorSpace = this.color_spaces.DEVICE_RGB,
  10755. decode = this.decode.FLATE_DECODE,
  10756. bpc = 8,
  10757. img,
  10758. dp,
  10759. trns,
  10760. colors,
  10761. pal,
  10762. smask;
  10763. /* if(this.isString(imageData)) {
  10764. }*/
  10765. if (this.isArrayBuffer(imageData)) imageData = new Uint8Array(imageData);
  10766. if (this.isArrayBufferView(imageData)) {
  10767. if (doesNotHavePngJS()) throw new Error("PNG support requires png.js and zlib.js");
  10768. img = new PNG(imageData);
  10769. imageData = img.imgData;
  10770. bpc = img.bits;
  10771. colorSpace = img.colorSpace;
  10772. colors = img.colors; //logImg(img);
  10773. /*
  10774. * colorType 6 - Each pixel is an R,G,B triple, followed by an alpha sample.
  10775. *
  10776. * colorType 4 - Each pixel is a grayscale sample, followed by an alpha sample.
  10777. *
  10778. * Extract alpha to create two separate images, using the alpha as a sMask
  10779. */
  10780. if ([4, 6].indexOf(img.colorType) !== -1) {
  10781. /*
  10782. * processes 8 bit RGBA and grayscale + alpha images
  10783. */
  10784. if (img.bits === 8) {
  10785. var pixels = img.pixelBitlength == 32 ? new Uint32Array(img.decodePixels().buffer) : img.pixelBitlength == 16 ? new Uint16Array(img.decodePixels().buffer) : new Uint8Array(img.decodePixels().buffer),
  10786. len = pixels.length,
  10787. imgData = new Uint8Array(len * img.colors),
  10788. alphaData = new Uint8Array(len),
  10789. pDiff = img.pixelBitlength - img.bits,
  10790. i = 0,
  10791. n = 0,
  10792. pixel,
  10793. pbl;
  10794. for (; i < len; i++) {
  10795. pixel = pixels[i];
  10796. pbl = 0;
  10797. while (pbl < pDiff) {
  10798. imgData[n++] = pixel >>> pbl & 0xff;
  10799. pbl = pbl + img.bits;
  10800. }
  10801. alphaData[i] = pixel >>> pbl & 0xff;
  10802. }
  10803. }
  10804. /*
  10805. * processes 16 bit RGBA and grayscale + alpha images
  10806. */
  10807. if (img.bits === 16) {
  10808. var pixels = new Uint32Array(img.decodePixels().buffer),
  10809. len = pixels.length,
  10810. imgData = new Uint8Array(len * (32 / img.pixelBitlength) * img.colors),
  10811. alphaData = new Uint8Array(len * (32 / img.pixelBitlength)),
  10812. hasColors = img.colors > 1,
  10813. i = 0,
  10814. n = 0,
  10815. a = 0,
  10816. pixel;
  10817. while (i < len) {
  10818. pixel = pixels[i++];
  10819. imgData[n++] = pixel >>> 0 & 0xff;
  10820. if (hasColors) {
  10821. imgData[n++] = pixel >>> 16 & 0xff;
  10822. pixel = pixels[i++];
  10823. imgData[n++] = pixel >>> 0 & 0xff;
  10824. }
  10825. alphaData[a++] = pixel >>> 16 & 0xff;
  10826. }
  10827. bpc = 8;
  10828. }
  10829. if (canCompress(compression)) {
  10830. imageData = compressBytes(imgData, img.width * img.colors, img.colors, compression);
  10831. smask = compressBytes(alphaData, img.width, 1, compression);
  10832. } else {
  10833. imageData = imgData;
  10834. smask = alphaData;
  10835. decode = null;
  10836. }
  10837. }
  10838. /*
  10839. * Indexed png. Each pixel is a palette index.
  10840. */
  10841. if (img.colorType === 3) {
  10842. colorSpace = this.color_spaces.INDEXED;
  10843. pal = img.palette;
  10844. if (img.transparency.indexed) {
  10845. var trans = img.transparency.indexed;
  10846. var total = 0,
  10847. i = 0,
  10848. len = trans.length;
  10849. for (; i < len; ++i) {
  10850. total += trans[i];
  10851. }
  10852. total = total / 255;
  10853. /*
  10854. * a single color is specified as 100% transparent (0),
  10855. * so we set trns to use a /Mask with that index
  10856. */
  10857. if (total === len - 1 && trans.indexOf(0) !== -1) {
  10858. trns = [trans.indexOf(0)];
  10859. /*
  10860. * there's more than one colour within the palette that specifies
  10861. * a transparency value less than 255, so we unroll the pixels to create an image sMask
  10862. */
  10863. } else if (total !== len) {
  10864. var pixels = img.decodePixels(),
  10865. alphaData = new Uint8Array(pixels.length),
  10866. i = 0,
  10867. len = pixels.length;
  10868. for (; i < len; i++) {
  10869. alphaData[i] = trans[pixels[i]];
  10870. }
  10871. smask = compressBytes(alphaData, img.width, 1);
  10872. }
  10873. }
  10874. }
  10875. var predictor = getPredictorFromCompression(compression);
  10876. 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
  10877. else dp = "/Colors " + colors + " /BitsPerComponent " + bpc + " /Columns " + img.width;
  10878. if (this.isArrayBuffer(imageData) || this.isArrayBufferView(imageData)) imageData = this.arrayBufferToBinaryString(imageData);
  10879. if (smask && this.isArrayBuffer(smask) || this.isArrayBufferView(smask)) smask = this.arrayBufferToBinaryString(smask);
  10880. return this.createImageInfo(imageData, img.width, img.height, colorSpace, bpc, decode, imageIndex, alias, dp, trns, pal, smask, predictor);
  10881. }
  10882. throw new Error("Unsupported PNG image data, try using JPEG instead.");
  10883. };
  10884. })(jsPDF.API);
  10885. /**
  10886. * @license
  10887. * Copyright (c) 2017 Aras Abbasi
  10888. *
  10889. * Licensed under the MIT License.
  10890. * http://opensource.org/licenses/mit-license
  10891. */
  10892. /**
  10893. * jsPDF gif Support PlugIn
  10894. *
  10895. * @name gif_support
  10896. * @module
  10897. */
  10898. (function (jsPDFAPI) {
  10899. jsPDFAPI.processGIF89A = function (imageData, imageIndex, alias, compression, dataAsBinaryString) {
  10900. var reader = new GifReader(imageData);
  10901. var width = reader.width,
  10902. height = reader.height;
  10903. var qu = 100;
  10904. var pixels = [];
  10905. reader.decodeAndBlitFrameRGBA(0, pixels);
  10906. var rawImageData = {
  10907. data: pixels,
  10908. width: width,
  10909. height: height
  10910. };
  10911. var encoder = new JPEGEncoder(qu);
  10912. var data = encoder.encode(rawImageData, qu);
  10913. return jsPDFAPI.processJPEG.call(this, data, imageIndex, alias, compression);
  10914. };
  10915. jsPDFAPI.processGIF87A = jsPDFAPI.processGIF89A;
  10916. })(jsPDF.API);
  10917. /**
  10918. * Copyright (c) 2018 Aras Abbasi
  10919. *
  10920. * Licensed under the MIT License.
  10921. * http://opensource.org/licenses/mit-license
  10922. */
  10923. /**
  10924. * jsPDF bmp Support PlugIn
  10925. * @name bmp_support
  10926. * @module
  10927. */
  10928. (function (jsPDFAPI) {
  10929. jsPDFAPI.processBMP = function (imageData, imageIndex, alias, compression, dataAsBinaryString) {
  10930. var reader = new BmpDecoder(imageData, false);
  10931. var width = reader.width,
  10932. height = reader.height;
  10933. var qu = 100;
  10934. var pixels = reader.getData();
  10935. var rawImageData = {
  10936. data: pixels,
  10937. width: width,
  10938. height: height
  10939. };
  10940. var encoder = new JPEGEncoder(qu);
  10941. var data = encoder.encode(rawImageData, qu);
  10942. return jsPDFAPI.processJPEG.call(this, data, imageIndex, alias, compression);
  10943. };
  10944. })(jsPDF.API);
  10945. /**
  10946. * @license
  10947. * Licensed under the MIT License.
  10948. * http://opensource.org/licenses/mit-license
  10949. */
  10950. /**
  10951. * jsPDF setLanguage Plugin
  10952. *
  10953. * @name setLanguage
  10954. * @module
  10955. */
  10956. (function (jsPDFAPI) {
  10957. /**
  10958. * Add Language Tag to the generated PDF
  10959. *
  10960. * @name setLanguage
  10961. * @function
  10962. * @param {string} langCode The Language code as ISO-639-1 (e.g. 'en') or as country language code (e.g. 'en-GB').
  10963. * @returns {jsPDF}
  10964. * @example
  10965. * var doc = new jsPDF()
  10966. * doc.text(10, 10, 'This is a test')
  10967. * doc.setLanguage("en-US")
  10968. * doc.save('english.pdf')
  10969. */
  10970. jsPDFAPI.setLanguage = function (langCode) {
  10971. var langCodes = {
  10972. af: "Afrikaans",
  10973. sq: "Albanian",
  10974. ar: "Arabic (Standard)",
  10975. "ar-DZ": "Arabic (Algeria)",
  10976. "ar-BH": "Arabic (Bahrain)",
  10977. "ar-EG": "Arabic (Egypt)",
  10978. "ar-IQ": "Arabic (Iraq)",
  10979. "ar-JO": "Arabic (Jordan)",
  10980. "ar-KW": "Arabic (Kuwait)",
  10981. "ar-LB": "Arabic (Lebanon)",
  10982. "ar-LY": "Arabic (Libya)",
  10983. "ar-MA": "Arabic (Morocco)",
  10984. "ar-OM": "Arabic (Oman)",
  10985. "ar-QA": "Arabic (Qatar)",
  10986. "ar-SA": "Arabic (Saudi Arabia)",
  10987. "ar-SY": "Arabic (Syria)",
  10988. "ar-TN": "Arabic (Tunisia)",
  10989. "ar-AE": "Arabic (U.A.E.)",
  10990. "ar-YE": "Arabic (Yemen)",
  10991. an: "Aragonese",
  10992. hy: "Armenian",
  10993. as: "Assamese",
  10994. ast: "Asturian",
  10995. az: "Azerbaijani",
  10996. eu: "Basque",
  10997. be: "Belarusian",
  10998. bn: "Bengali",
  10999. bs: "Bosnian",
  11000. br: "Breton",
  11001. bg: "Bulgarian",
  11002. my: "Burmese",
  11003. ca: "Catalan",
  11004. ch: "Chamorro",
  11005. ce: "Chechen",
  11006. zh: "Chinese",
  11007. "zh-HK": "Chinese (Hong Kong)",
  11008. "zh-CN": "Chinese (PRC)",
  11009. "zh-SG": "Chinese (Singapore)",
  11010. "zh-TW": "Chinese (Taiwan)",
  11011. cv: "Chuvash",
  11012. co: "Corsican",
  11013. cr: "Cree",
  11014. hr: "Croatian",
  11015. cs: "Czech",
  11016. da: "Danish",
  11017. nl: "Dutch (Standard)",
  11018. "nl-BE": "Dutch (Belgian)",
  11019. en: "English",
  11020. "en-AU": "English (Australia)",
  11021. "en-BZ": "English (Belize)",
  11022. "en-CA": "English (Canada)",
  11023. "en-IE": "English (Ireland)",
  11024. "en-JM": "English (Jamaica)",
  11025. "en-NZ": "English (New Zealand)",
  11026. "en-PH": "English (Philippines)",
  11027. "en-ZA": "English (South Africa)",
  11028. "en-TT": "English (Trinidad & Tobago)",
  11029. "en-GB": "English (United Kingdom)",
  11030. "en-US": "English (United States)",
  11031. "en-ZW": "English (Zimbabwe)",
  11032. eo: "Esperanto",
  11033. et: "Estonian",
  11034. fo: "Faeroese",
  11035. fj: "Fijian",
  11036. fi: "Finnish",
  11037. fr: "French (Standard)",
  11038. "fr-BE": "French (Belgium)",
  11039. "fr-CA": "French (Canada)",
  11040. "fr-FR": "French (France)",
  11041. "fr-LU": "French (Luxembourg)",
  11042. "fr-MC": "French (Monaco)",
  11043. "fr-CH": "French (Switzerland)",
  11044. fy: "Frisian",
  11045. fur: "Friulian",
  11046. gd: "Gaelic (Scots)",
  11047. "gd-IE": "Gaelic (Irish)",
  11048. gl: "Galacian",
  11049. ka: "Georgian",
  11050. de: "German (Standard)",
  11051. "de-AT": "German (Austria)",
  11052. "de-DE": "German (Germany)",
  11053. "de-LI": "German (Liechtenstein)",
  11054. "de-LU": "German (Luxembourg)",
  11055. "de-CH": "German (Switzerland)",
  11056. el: "Greek",
  11057. gu: "Gujurati",
  11058. ht: "Haitian",
  11059. he: "Hebrew",
  11060. hi: "Hindi",
  11061. hu: "Hungarian",
  11062. is: "Icelandic",
  11063. id: "Indonesian",
  11064. iu: "Inuktitut",
  11065. ga: "Irish",
  11066. it: "Italian (Standard)",
  11067. "it-CH": "Italian (Switzerland)",
  11068. ja: "Japanese",
  11069. kn: "Kannada",
  11070. ks: "Kashmiri",
  11071. kk: "Kazakh",
  11072. km: "Khmer",
  11073. ky: "Kirghiz",
  11074. tlh: "Klingon",
  11075. ko: "Korean",
  11076. "ko-KP": "Korean (North Korea)",
  11077. "ko-KR": "Korean (South Korea)",
  11078. la: "Latin",
  11079. lv: "Latvian",
  11080. lt: "Lithuanian",
  11081. lb: "Luxembourgish",
  11082. mk: "FYRO Macedonian",
  11083. ms: "Malay",
  11084. ml: "Malayalam",
  11085. mt: "Maltese",
  11086. mi: "Maori",
  11087. mr: "Marathi",
  11088. mo: "Moldavian",
  11089. nv: "Navajo",
  11090. ng: "Ndonga",
  11091. ne: "Nepali",
  11092. no: "Norwegian",
  11093. nb: "Norwegian (Bokmal)",
  11094. nn: "Norwegian (Nynorsk)",
  11095. oc: "Occitan",
  11096. or: "Oriya",
  11097. om: "Oromo",
  11098. fa: "Persian",
  11099. "fa-IR": "Persian/Iran",
  11100. pl: "Polish",
  11101. pt: "Portuguese",
  11102. "pt-BR": "Portuguese (Brazil)",
  11103. pa: "Punjabi",
  11104. "pa-IN": "Punjabi (India)",
  11105. "pa-PK": "Punjabi (Pakistan)",
  11106. qu: "Quechua",
  11107. rm: "Rhaeto-Romanic",
  11108. ro: "Romanian",
  11109. "ro-MO": "Romanian (Moldavia)",
  11110. ru: "Russian",
  11111. "ru-MO": "Russian (Moldavia)",
  11112. sz: "Sami (Lappish)",
  11113. sg: "Sango",
  11114. sa: "Sanskrit",
  11115. sc: "Sardinian",
  11116. sd: "Sindhi",
  11117. si: "Singhalese",
  11118. sr: "Serbian",
  11119. sk: "Slovak",
  11120. sl: "Slovenian",
  11121. so: "Somani",
  11122. sb: "Sorbian",
  11123. es: "Spanish",
  11124. "es-AR": "Spanish (Argentina)",
  11125. "es-BO": "Spanish (Bolivia)",
  11126. "es-CL": "Spanish (Chile)",
  11127. "es-CO": "Spanish (Colombia)",
  11128. "es-CR": "Spanish (Costa Rica)",
  11129. "es-DO": "Spanish (Dominican Republic)",
  11130. "es-EC": "Spanish (Ecuador)",
  11131. "es-SV": "Spanish (El Salvador)",
  11132. "es-GT": "Spanish (Guatemala)",
  11133. "es-HN": "Spanish (Honduras)",
  11134. "es-MX": "Spanish (Mexico)",
  11135. "es-NI": "Spanish (Nicaragua)",
  11136. "es-PA": "Spanish (Panama)",
  11137. "es-PY": "Spanish (Paraguay)",
  11138. "es-PE": "Spanish (Peru)",
  11139. "es-PR": "Spanish (Puerto Rico)",
  11140. "es-ES": "Spanish (Spain)",
  11141. "es-UY": "Spanish (Uruguay)",
  11142. "es-VE": "Spanish (Venezuela)",
  11143. sx: "Sutu",
  11144. sw: "Swahili",
  11145. sv: "Swedish",
  11146. "sv-FI": "Swedish (Finland)",
  11147. "sv-SV": "Swedish (Sweden)",
  11148. ta: "Tamil",
  11149. tt: "Tatar",
  11150. te: "Teluga",
  11151. th: "Thai",
  11152. tig: "Tigre",
  11153. ts: "Tsonga",
  11154. tn: "Tswana",
  11155. tr: "Turkish",
  11156. tk: "Turkmen",
  11157. uk: "Ukrainian",
  11158. hsb: "Upper Sorbian",
  11159. ur: "Urdu",
  11160. ve: "Venda",
  11161. vi: "Vietnamese",
  11162. vo: "Volapuk",
  11163. wa: "Walloon",
  11164. cy: "Welsh",
  11165. xh: "Xhosa",
  11166. ji: "Yiddish",
  11167. zu: "Zulu"
  11168. };
  11169. if (this.internal.languageSettings === undefined) {
  11170. this.internal.languageSettings = {};
  11171. this.internal.languageSettings.isSubscribed = false;
  11172. }
  11173. if (langCodes[langCode] !== undefined) {
  11174. this.internal.languageSettings.languageCode = langCode;
  11175. if (this.internal.languageSettings.isSubscribed === false) {
  11176. this.internal.events.subscribe("putCatalog", function () {
  11177. this.internal.write("/Lang (" + this.internal.languageSettings.languageCode + ")");
  11178. });
  11179. this.internal.languageSettings.isSubscribed = true;
  11180. }
  11181. }
  11182. return this;
  11183. };
  11184. })(jsPDF.API);
  11185. /** @license
  11186. * MIT license.
  11187. * Copyright (c) 2012 Willow Systems Corporation, willow-systems.com
  11188. * 2014 Diego Casorran, https://github.com/diegocr
  11189. *
  11190. *
  11191. * ====================================================================
  11192. */
  11193. /**
  11194. * jsPDF split_text_to_size plugin
  11195. *
  11196. * @name split_text_to_size
  11197. * @module
  11198. */
  11199. (function (API) {
  11200. /**
  11201. * Returns an array of length matching length of the 'word' string, with each
  11202. * cell occupied by the width of the char in that position.
  11203. *
  11204. * @name getCharWidthsArray
  11205. * @function
  11206. * @param {string} text
  11207. * @param {Object} options
  11208. * @returns {Array}
  11209. */
  11210. var getCharWidthsArray = API.getCharWidthsArray = function (text, options) {
  11211. options = options || {};
  11212. var activeFont = options.font || this.internal.getFont();
  11213. var fontSize = options.fontSize || this.internal.getFontSize();
  11214. var charSpace = options.charSpace || this.internal.getCharSpace();
  11215. var widths = options.widths ? options.widths : activeFont.metadata.Unicode.widths;
  11216. var widthsFractionOf = widths.fof ? widths.fof : 1;
  11217. var kerning = options.kerning ? options.kerning : activeFont.metadata.Unicode.kerning;
  11218. var kerningFractionOf = kerning.fof ? kerning.fof : 1;
  11219. var i;
  11220. var l;
  11221. var char_code;
  11222. var prior_char_code = 0; //for kerning
  11223. var default_char_width = widths[0] || widthsFractionOf;
  11224. var output = [];
  11225. for (i = 0, l = text.length; i < l; i++) {
  11226. char_code = text.charCodeAt(i);
  11227. if (typeof activeFont.metadata.widthOfString === "function") {
  11228. output.push((activeFont.metadata.widthOfGlyph(activeFont.metadata.characterToGlyph(char_code)) + charSpace * (1000 / fontSize) || 0) / 1000);
  11229. } else {
  11230. output.push((widths[char_code] || default_char_width) / widthsFractionOf + (kerning[char_code] && kerning[char_code][prior_char_code] || 0) / kerningFractionOf);
  11231. }
  11232. prior_char_code = char_code;
  11233. }
  11234. return output;
  11235. };
  11236. /**
  11237. * Calculate the sum of a number-array
  11238. *
  11239. * @name getArraySum
  11240. * @public
  11241. * @function
  11242. * @param {Array} array Array of numbers
  11243. * @returns {number}
  11244. */
  11245. var getArraySum = API.getArraySum = function (array) {
  11246. var i = array.length,
  11247. output = 0;
  11248. while (i) {
  11249. i--;
  11250. output += array[i];
  11251. }
  11252. return output;
  11253. };
  11254. /**
  11255. * Returns a widths of string in a given font, if the font size is set as 1 point.
  11256. *
  11257. * In other words, this is "proportional" value. For 1 unit of font size, the length
  11258. * of the string will be that much.
  11259. *
  11260. * Multiply by font size to get actual width in *points*
  11261. * Then divide by 72 to get inches or divide by (72/25.6) to get 'mm' etc.
  11262. *
  11263. * @name getStringUnitWidth
  11264. * @public
  11265. * @function
  11266. * @param {string} text
  11267. * @param {string} options
  11268. * @returns {number} result
  11269. */
  11270. var getStringUnitWidth = API.getStringUnitWidth = function (text, options) {
  11271. options = options || {};
  11272. var fontSize = options.fontSize || this.internal.getFontSize();
  11273. var font = options.font || this.internal.getFont();
  11274. var charSpace = options.charSpace || this.internal.getCharSpace();
  11275. var result = 0;
  11276. if (typeof font.metadata.widthOfString === "function") {
  11277. result = font.metadata.widthOfString(text, fontSize, charSpace) / fontSize;
  11278. } else {
  11279. result = getArraySum(getCharWidthsArray.apply(this, arguments));
  11280. }
  11281. return result;
  11282. };
  11283. /**
  11284. returns array of lines
  11285. */
  11286. var splitLongWord = function splitLongWord(word, widths_array, firstLineMaxLen, maxLen) {
  11287. var answer = []; // 1st, chop off the piece that can fit on the hanging line.
  11288. var i = 0,
  11289. l = word.length,
  11290. workingLen = 0;
  11291. while (i !== l && workingLen + widths_array[i] < firstLineMaxLen) {
  11292. workingLen += widths_array[i];
  11293. i++;
  11294. } // this is first line.
  11295. answer.push(word.slice(0, i)); // 2nd. Split the rest into maxLen pieces.
  11296. var startOfLine = i;
  11297. workingLen = 0;
  11298. while (i !== l) {
  11299. if (workingLen + widths_array[i] > maxLen) {
  11300. answer.push(word.slice(startOfLine, i));
  11301. workingLen = 0;
  11302. startOfLine = i;
  11303. }
  11304. workingLen += widths_array[i];
  11305. i++;
  11306. }
  11307. if (startOfLine !== i) {
  11308. answer.push(word.slice(startOfLine, i));
  11309. }
  11310. return answer;
  11311. }; // Note, all sizing inputs for this function must be in "font measurement units"
  11312. // By default, for PDF, it's "point".
  11313. var splitParagraphIntoLines = function splitParagraphIntoLines(text, maxlen, options) {
  11314. // at this time works only on Western scripts, ones with space char
  11315. // separating the words. Feel free to expand.
  11316. if (!options) {
  11317. options = {};
  11318. }
  11319. var line = [],
  11320. lines = [line],
  11321. line_length = options.textIndent || 0,
  11322. separator_length = 0,
  11323. current_word_length = 0,
  11324. word,
  11325. widths_array,
  11326. words = text.split(" "),
  11327. spaceCharWidth = getCharWidthsArray.apply(this, [" ", options])[0],
  11328. i,
  11329. l,
  11330. tmp,
  11331. lineIndent;
  11332. if (options.lineIndent === -1) {
  11333. lineIndent = words[0].length + 2;
  11334. } else {
  11335. lineIndent = options.lineIndent || 0;
  11336. }
  11337. if (lineIndent) {
  11338. var pad = Array(lineIndent).join(" "),
  11339. wrds = [];
  11340. words.map(function (wrd) {
  11341. wrd = wrd.split(/\s*\n/);
  11342. if (wrd.length > 1) {
  11343. wrds = wrds.concat(wrd.map(function (wrd, idx) {
  11344. return (idx && wrd.length ? "\n" : "") + wrd;
  11345. }));
  11346. } else {
  11347. wrds.push(wrd[0]);
  11348. }
  11349. });
  11350. words = wrds;
  11351. lineIndent = getStringUnitWidth.apply(this, [pad, options]);
  11352. }
  11353. for (i = 0, l = words.length; i < l; i++) {
  11354. var force = 0;
  11355. word = words[i];
  11356. if (lineIndent && word[0] == "\n") {
  11357. word = word.substr(1);
  11358. force = 1;
  11359. }
  11360. widths_array = getCharWidthsArray.apply(this, [word, options]);
  11361. current_word_length = getArraySum(widths_array);
  11362. if (line_length + separator_length + current_word_length > maxlen || force) {
  11363. if (current_word_length > maxlen) {
  11364. // this happens when you have space-less long URLs for example.
  11365. // we just chop these to size. We do NOT insert hiphens
  11366. tmp = splitLongWord.apply(this, [word, widths_array, maxlen - (line_length + separator_length), maxlen]); // first line we add to existing line object
  11367. line.push(tmp.shift()); // it's ok to have extra space indicator there
  11368. // last line we make into new line object
  11369. line = [tmp.pop()]; // lines in the middle we apped to lines object as whole lines
  11370. while (tmp.length) {
  11371. lines.push([tmp.shift()]); // single fragment occupies whole line
  11372. }
  11373. current_word_length = getArraySum(widths_array.slice(word.length - (line[0] ? line[0].length : 0)));
  11374. } else {
  11375. // just put it on a new line
  11376. line = [word];
  11377. } // now we attach new line to lines
  11378. lines.push(line);
  11379. line_length = current_word_length + lineIndent;
  11380. separator_length = spaceCharWidth;
  11381. } else {
  11382. line.push(word);
  11383. line_length += separator_length + current_word_length;
  11384. separator_length = spaceCharWidth;
  11385. }
  11386. }
  11387. if (lineIndent) {
  11388. var postProcess = function postProcess(ln, idx) {
  11389. return (idx ? pad : "") + ln.join(" ");
  11390. };
  11391. } else {
  11392. var postProcess = function postProcess(ln) {
  11393. return ln.join(" ");
  11394. };
  11395. }
  11396. return lines.map(postProcess);
  11397. };
  11398. /**
  11399. * Splits a given string into an array of strings. Uses 'size' value
  11400. * (in measurement units declared as default for the jsPDF instance)
  11401. * and the font's "widths" and "Kerning" tables, where available, to
  11402. * determine display length of a given string for a given font.
  11403. *
  11404. * We use character's 100% of unit size (height) as width when Width
  11405. * table or other default width is not available.
  11406. *
  11407. * @name splitTextToSize
  11408. * @public
  11409. * @function
  11410. * @param {string} text Unencoded, regular JavaScript (Unicode, UTF-16 / UCS-2) string.
  11411. * @param {number} size Nominal number, measured in units default to this instance of jsPDF.
  11412. * @param {Object} options Optional flags needed for chopper to do the right thing.
  11413. * @returns {Array} array Array with strings chopped to size.
  11414. */
  11415. API.splitTextToSize = function (text, maxlen, options) {
  11416. options = options || {};
  11417. var fsize = options.fontSize || this.internal.getFontSize(),
  11418. newOptions = function (options) {
  11419. var widths = {
  11420. 0: 1
  11421. },
  11422. kerning = {};
  11423. if (!options.widths || !options.kerning) {
  11424. var f = this.internal.getFont(options.fontName, options.fontStyle),
  11425. encoding = "Unicode"; // NOT UTF8, NOT UTF16BE/LE, NOT UCS2BE/LE
  11426. // Actual JavaScript-native String's 16bit char codes used.
  11427. // no multi-byte logic here
  11428. if (f.metadata[encoding]) {
  11429. return {
  11430. widths: f.metadata[encoding].widths || widths,
  11431. kerning: f.metadata[encoding].kerning || kerning
  11432. };
  11433. } else {
  11434. return {
  11435. font: f.metadata,
  11436. fontSize: this.internal.getFontSize(),
  11437. charSpace: this.internal.getCharSpace()
  11438. };
  11439. }
  11440. } else {
  11441. return {
  11442. widths: options.widths,
  11443. kerning: options.kerning
  11444. };
  11445. } // then use default values
  11446. return {
  11447. widths: widths,
  11448. kerning: kerning
  11449. };
  11450. }.call(this, options); // first we split on end-of-line chars
  11451. var paragraphs;
  11452. if (Array.isArray(text)) {
  11453. paragraphs = text;
  11454. } else {
  11455. paragraphs = text.split(/\r?\n/);
  11456. } // now we convert size (max length of line) into "font size units"
  11457. // at present time, the "font size unit" is always 'point'
  11458. // 'proportional' means, "in proportion to font size"
  11459. 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.
  11460. // this may change in the future?
  11461. // until then, proportional_maxlen is likely to be in 'points'
  11462. // If first line is to be indented (shorter or longer) than maxLen
  11463. // we indicate that by using CSS-style "text-indent" option.
  11464. // here it's in font units too (which is likely 'points')
  11465. // it can be negative (which makes the first line longer than maxLen)
  11466. newOptions.textIndent = options.textIndent ? options.textIndent * 1.0 * this.internal.scaleFactor / fsize : 0;
  11467. newOptions.lineIndent = options.lineIndent;
  11468. var i,
  11469. l,
  11470. output = [];
  11471. for (i = 0, l = paragraphs.length; i < l; i++) {
  11472. output = output.concat(splitParagraphIntoLines.apply(this, [paragraphs[i], fontUnit_maxLen, newOptions]));
  11473. }
  11474. return output;
  11475. };
  11476. })(jsPDF.API);
  11477. /** @license
  11478. jsPDF standard_fonts_metrics plugin
  11479. * Copyright (c) 2012 Willow Systems Corporation, willow-systems.com
  11480. * MIT license.
  11481. *
  11482. * ====================================================================
  11483. */
  11484. /**
  11485. * This file adds the standard font metrics to jsPDF.
  11486. *
  11487. * Font metrics data is reprocessed derivative of contents of
  11488. * "Font Metrics for PDF Core 14 Fonts" package, which exhibits the following copyright and license:
  11489. *
  11490. * Copyright (c) 1989, 1990, 1991, 1992, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.
  11491. *
  11492. * This file and the 14 PostScript(R) AFM files it accompanies may be used,
  11493. * copied, and distributed for any purpose and without charge, with or without
  11494. * modification, provided that all copyright notices are retained; that the AFM
  11495. * files are not distributed without this file; that all modifications to this
  11496. * file or any of the AFM files are prominently noted in the modified file(s);
  11497. * and that this paragraph is not modified. Adobe Systems has no responsibility
  11498. * or obligation to support the use of the AFM files.
  11499. *
  11500. * @name standard_fonts_metrics
  11501. * @module
  11502. */
  11503. (function (API) {
  11504. /*
  11505. # reference (Python) versions of 'compress' and 'uncompress'
  11506. # only 'uncompress' function is featured lower as JavaScript
  11507. # if you want to unit test "roundtrip", just transcribe the reference
  11508. # 'compress' function from Python into JavaScript
  11509. def compress(data):
  11510. keys = '0123456789abcdef'
  11511. values = 'klmnopqrstuvwxyz'
  11512. mapping = dict(zip(keys, values))
  11513. vals = []
  11514. for key in data.keys():
  11515. value = data[key]
  11516. try:
  11517. keystring = hex(key)[2:]
  11518. keystring = keystring[:-1] + mapping[keystring[-1:]]
  11519. except:
  11520. keystring = key.join(["'","'"])
  11521. #print('Keystring is %s' % keystring)
  11522. try:
  11523. if value < 0:
  11524. valuestring = hex(value)[3:]
  11525. numberprefix = '-'
  11526. else:
  11527. valuestring = hex(value)[2:]
  11528. numberprefix = ''
  11529. valuestring = numberprefix + valuestring[:-1] + mapping[valuestring[-1:]]
  11530. except:
  11531. if type(value) == dict:
  11532. valuestring = compress(value)
  11533. else:
  11534. raise Exception("Don't know what to do with value type %s" % type(value))
  11535. vals.append(keystring+valuestring)
  11536. return '{' + ''.join(vals) + '}'
  11537. def uncompress(data):
  11538. decoded = '0123456789abcdef'
  11539. encoded = 'klmnopqrstuvwxyz'
  11540. mapping = dict(zip(encoded, decoded))
  11541. sign = +1
  11542. stringmode = False
  11543. stringparts = []
  11544. output = {}
  11545. activeobject = output
  11546. parentchain = []
  11547. keyparts = ''
  11548. valueparts = ''
  11549. key = None
  11550. ending = set(encoded)
  11551. i = 1
  11552. l = len(data) - 1 # stripping starting, ending {}
  11553. while i != l: # stripping {}
  11554. # -, {, }, ' are special.
  11555. ch = data[i]
  11556. i += 1
  11557. if ch == "'":
  11558. if stringmode:
  11559. # end of string mode
  11560. stringmode = False
  11561. key = ''.join(stringparts)
  11562. else:
  11563. # start of string mode
  11564. stringmode = True
  11565. stringparts = []
  11566. elif stringmode == True:
  11567. #print("Adding %s to stringpart" % ch)
  11568. stringparts.append(ch)
  11569. elif ch == '{':
  11570. # start of object
  11571. parentchain.append( [activeobject, key] )
  11572. activeobject = {}
  11573. key = None
  11574. #DEBUG = True
  11575. elif ch == '}':
  11576. # end of object
  11577. parent, key = parentchain.pop()
  11578. parent[key] = activeobject
  11579. key = None
  11580. activeobject = parent
  11581. #DEBUG = False
  11582. elif ch == '-':
  11583. sign = -1
  11584. else:
  11585. # must be number
  11586. if key == None:
  11587. #debug("In Key. It is '%s', ch is '%s'" % (keyparts, ch))
  11588. if ch in ending:
  11589. #debug("End of key")
  11590. keyparts += mapping[ch]
  11591. key = int(keyparts, 16) * sign
  11592. sign = +1
  11593. keyparts = ''
  11594. else:
  11595. keyparts += ch
  11596. else:
  11597. #debug("In value. It is '%s', ch is '%s'" % (valueparts, ch))
  11598. if ch in ending:
  11599. #debug("End of value")
  11600. valueparts += mapping[ch]
  11601. activeobject[key] = int(valueparts, 16) * sign
  11602. sign = +1
  11603. key = None
  11604. valueparts = ''
  11605. else:
  11606. valueparts += ch
  11607. #debug(activeobject)
  11608. return output
  11609. */
  11610. /**
  11611. Uncompresses data compressed into custom, base16-like format.
  11612. @public
  11613. @function
  11614. @param
  11615. @returns {Type}
  11616. */
  11617. var uncompress = function uncompress(data) {
  11618. var decoded = "0123456789abcdef",
  11619. encoded = "klmnopqrstuvwxyz",
  11620. mapping = {};
  11621. for (var i = 0; i < encoded.length; i++) {
  11622. mapping[encoded[i]] = decoded[i];
  11623. }
  11624. var undef,
  11625. output = {},
  11626. sign = 1,
  11627. stringparts,
  11628. // undef. will be [] in string mode
  11629. activeobject = output,
  11630. parentchain = [],
  11631. parent_key_pair,
  11632. keyparts = "",
  11633. valueparts = "",
  11634. key,
  11635. // undef. will be Truthy when Key is resolved.
  11636. datalen = data.length - 1,
  11637. // stripping ending }
  11638. ch;
  11639. i = 1; // stripping starting {
  11640. while (i != datalen) {
  11641. // - { } ' are special.
  11642. ch = data[i];
  11643. i += 1;
  11644. if (ch == "'") {
  11645. if (stringparts) {
  11646. // end of string mode
  11647. key = stringparts.join("");
  11648. stringparts = undef;
  11649. } else {
  11650. // start of string mode
  11651. stringparts = [];
  11652. }
  11653. } else if (stringparts) {
  11654. stringparts.push(ch);
  11655. } else if (ch == "{") {
  11656. // start of object
  11657. parentchain.push([activeobject, key]);
  11658. activeobject = {};
  11659. key = undef;
  11660. } else if (ch == "}") {
  11661. // end of object
  11662. parent_key_pair = parentchain.pop();
  11663. parent_key_pair[0][parent_key_pair[1]] = activeobject;
  11664. key = undef;
  11665. activeobject = parent_key_pair[0];
  11666. } else if (ch == "-") {
  11667. sign = -1;
  11668. } else {
  11669. // must be number
  11670. if (key === undef) {
  11671. if (mapping.hasOwnProperty(ch)) {
  11672. keyparts += mapping[ch];
  11673. key = parseInt(keyparts, 16) * sign;
  11674. sign = +1;
  11675. keyparts = "";
  11676. } else {
  11677. keyparts += ch;
  11678. }
  11679. } else {
  11680. if (mapping.hasOwnProperty(ch)) {
  11681. valueparts += mapping[ch];
  11682. activeobject[key] = parseInt(valueparts, 16) * sign;
  11683. sign = +1;
  11684. key = undef;
  11685. valueparts = "";
  11686. } else {
  11687. valueparts += ch;
  11688. }
  11689. }
  11690. }
  11691. } // end while
  11692. return output;
  11693. }; // encoding = 'Unicode'
  11694. // NOT UTF8, NOT UTF16BE/LE, NOT UCS2BE/LE. NO clever BOM behavior
  11695. // Actual 16bit char codes used.
  11696. // no multi-byte logic here
  11697. // Unicode characters to WinAnsiEncoding:
  11698. // {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}
  11699. // as you can see, all Unicode chars are outside of 0-255 range. No char code conflicts.
  11700. // this means that you can give Win cp1252 encoded strings to jsPDF for rendering directly
  11701. // as well as give strings with some (supported by these fonts) Unicode characters and
  11702. // these will be mapped to win cp1252
  11703. // for example, you can send char code (cp1252) 0x80 or (unicode) 0x20AC, getting "Euro" glyph displayed in both cases.
  11704. var encodingBlock = {
  11705. codePages: ["WinAnsiEncoding"],
  11706. WinAnsiEncoding: uncompress("{19m8n201n9q201o9r201s9l201t9m201u8m201w9n201x9o201y8o202k8q202l8r202m9p202q8p20aw8k203k8t203t8v203u9v2cq8s212m9t15m8w15n9w2dw9s16k8u16l9u17s9z17x8y17y9y}")
  11707. },
  11708. encodings = {
  11709. Unicode: {
  11710. Courier: encodingBlock,
  11711. "Courier-Bold": encodingBlock,
  11712. "Courier-BoldOblique": encodingBlock,
  11713. "Courier-Oblique": encodingBlock,
  11714. Helvetica: encodingBlock,
  11715. "Helvetica-Bold": encodingBlock,
  11716. "Helvetica-BoldOblique": encodingBlock,
  11717. "Helvetica-Oblique": encodingBlock,
  11718. "Times-Roman": encodingBlock,
  11719. "Times-Bold": encodingBlock,
  11720. "Times-BoldItalic": encodingBlock,
  11721. "Times-Italic": encodingBlock // , 'Symbol'
  11722. // , 'ZapfDingbats'
  11723. }
  11724. },
  11725. fontMetrics = {
  11726. Unicode: {
  11727. // all sizing numbers are n/fontMetricsFractionOf = one font size unit
  11728. // this means that if fontMetricsFractionOf = 1000, and letter A's width is 476, it's
  11729. // width is 476/1000 or 47.6% of its height (regardless of font size)
  11730. // At this time this value applies to "widths" and "kerning" numbers.
  11731. // char code 0 represents "default" (average) width - use it for chars missing in this table.
  11732. // key 'fof' represents the "fontMetricsFractionOf" value
  11733. "Courier-Oblique": uncompress("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}"),
  11734. "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}}}"),
  11735. "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}}}"),
  11736. Courier: uncompress("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}"),
  11737. "Courier-BoldOblique": uncompress("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}"),
  11738. "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}}}"),
  11739. Symbol: uncompress("{'widths'{k3uaw4r19m3m2k1t2l2l202m2y2n3m2p5n202q6o3k3m2s2l2t2l2v3r2w1t3m3m2y1t2z1wbk2sbl3r'fof'6o3n3m3o3m3p3m3q3m3r3m3s3m3t3m3u1w3v1w3w3r3x3r3y3r3z2wbp3t3l3m5v2l5x2l5z3m2q4yfr3r7v3k7w1o7x3k}'kerning'{'fof'-6o}}"),
  11740. 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}}}"),
  11741. "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}}}"),
  11742. ZapfDingbats: uncompress("{'widths'{k4u2k1w'fof'6o}'kerning'{'fof'-6o}}"),
  11743. "Courier-Bold": uncompress("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}"),
  11744. "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}}}"),
  11745. "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}}}"),
  11746. "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}}}")
  11747. }
  11748. };
  11749. /*
  11750. This event handler is fired when a new jsPDF object is initialized
  11751. This event handler appends metrics data to standard fonts within
  11752. that jsPDF instance. The metrics are mapped over Unicode character
  11753. codes, NOT CIDs or other codes matching the StandardEncoding table of the
  11754. standard PDF fonts.
  11755. Future:
  11756. Also included is the encoding maping table, converting Unicode (UCS-2, UTF-16)
  11757. char codes to StandardEncoding character codes. The encoding table is to be used
  11758. somewhere around "pdfEscape" call.
  11759. */
  11760. API.events.push(["addFont", function (data) {
  11761. var font = data.font;
  11762. var metrics,
  11763. unicode_section,
  11764. encoding = "Unicode",
  11765. encodingBlock;
  11766. metrics = fontMetrics[encoding][font.postScriptName];
  11767. if (metrics) {
  11768. if (font.metadata[encoding]) {
  11769. unicode_section = font.metadata[encoding];
  11770. } else {
  11771. unicode_section = font.metadata[encoding] = {};
  11772. }
  11773. unicode_section.widths = metrics.widths;
  11774. unicode_section.kerning = metrics.kerning;
  11775. }
  11776. encodingBlock = encodings[encoding][font.postScriptName];
  11777. if (encodingBlock) {
  11778. if (font.metadata[encoding]) {
  11779. unicode_section = font.metadata[encoding];
  11780. } else {
  11781. unicode_section = font.metadata[encoding] = {};
  11782. }
  11783. unicode_section.encoding = encodingBlock;
  11784. if (encodingBlock.codePages && encodingBlock.codePages.length) {
  11785. font.encoding = encodingBlock.codePages[0];
  11786. }
  11787. }
  11788. }]); // end of adding event handler
  11789. })(jsPDF.API);
  11790. /**
  11791. * @license
  11792. * Licensed under the MIT License.
  11793. * http://opensource.org/licenses/mit-license
  11794. */
  11795. /**
  11796. * @name ttfsupport
  11797. * @module
  11798. */
  11799. (function (jsPDF, global) {
  11800. jsPDF.API.events.push(["addFont", function (data) {
  11801. var font = data.font;
  11802. var instance = data.instance;
  11803. if (typeof instance !== "undefined" && instance.existsFileInVFS(font.postScriptName)) {
  11804. var file = instance.getFileFromVFS(font.postScriptName);
  11805. if (typeof file !== "string") {
  11806. throw new Error("Font is not stored as string-data in vFS, import fonts or remove declaration doc.addFont('" + font.postScriptName + "').");
  11807. }
  11808. font.metadata = jsPDF.API.TTFFont.open(font.postScriptName, font.fontName, file, font.encoding);
  11809. font.metadata.Unicode = font.metadata.Unicode || {
  11810. encoding: {},
  11811. kerning: {},
  11812. widths: []
  11813. };
  11814. font.metadata.glyIdsUsed = [0];
  11815. } else if (font.isStandardFont === false) {
  11816. throw new Error("Font does not exist in vFS, import fonts or remove declaration doc.addFont('" + font.postScriptName + "').");
  11817. }
  11818. }]); // end of adding event handler
  11819. })(jsPDF, typeof self !== "undefined" && self || typeof global !== "undefined" && global || typeof window !== "undefined" && window || Function("return this")());
  11820. /** @license
  11821. * Copyright (c) 2012 Willow Systems Corporation, willow-systems.com
  11822. *
  11823. *
  11824. * ====================================================================
  11825. */
  11826. /**
  11827. * jsPDF SVG plugin
  11828. *
  11829. * @name svg
  11830. * @module
  11831. */
  11832. (function (jsPDFAPI) {
  11833. /**
  11834. * Parses SVG XML and converts only some of the SVG elements into
  11835. * PDF elements.
  11836. *
  11837. * Supports:
  11838. * paths
  11839. *
  11840. * @name addSvg
  11841. * @public
  11842. * @function
  11843. * @param {string} SVG-Data as Text
  11844. * @param {number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
  11845. * @param {number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
  11846. * @param {number} width of SVG (in units declared at inception of PDF document)
  11847. * @param {number} height of SVG (in units declared at inception of PDF document)
  11848. * @returns {Object} jsPDF-instance
  11849. */
  11850. jsPDFAPI.addSvg = function (svgtext, x, y, w, h) {
  11851. // 'this' is _jsPDF object returned when jsPDF is inited (new jsPDF())
  11852. var undef;
  11853. if (x === undef || y === undef) {
  11854. throw new Error("addSVG needs values for 'x' and 'y'");
  11855. }
  11856. function InjectCSS(cssbody, document) {
  11857. var styletag = document.createElement("style");
  11858. styletag.type = "text/css";
  11859. if (styletag.styleSheet) {
  11860. // ie
  11861. styletag.styleSheet.cssText = cssbody;
  11862. } else {
  11863. // others
  11864. styletag.appendChild(document.createTextNode(cssbody));
  11865. }
  11866. document.getElementsByTagName("head")[0].appendChild(styletag);
  11867. }
  11868. function createWorkerNode(document) {
  11869. var frameID = "childframe",
  11870. // Date.now().toString() + '_' + (Math.random() * 100).toString()
  11871. frame = document.createElement("iframe");
  11872. InjectCSS(".jsPDF_sillysvg_iframe {display:none;position:absolute;}", document);
  11873. frame.name = frameID;
  11874. frame.setAttribute("width", 0);
  11875. frame.setAttribute("height", 0);
  11876. frame.setAttribute("frameborder", "0");
  11877. frame.setAttribute("scrolling", "no");
  11878. frame.setAttribute("seamless", "seamless");
  11879. frame.setAttribute("class", "jsPDF_sillysvg_iframe");
  11880. document.body.appendChild(frame);
  11881. return frame;
  11882. }
  11883. function attachSVGToWorkerNode(svgtext, frame) {
  11884. var framedoc = (frame.contentWindow || frame.contentDocument).document;
  11885. framedoc.write(svgtext);
  11886. framedoc.close();
  11887. return framedoc.getElementsByTagName("svg")[0];
  11888. }
  11889. function convertPathToPDFLinesArgs(path) {
  11890. // - starting coordinate pair
  11891. // - array of arrays of vector shifts (2-len for line, 6 len for bezier)
  11892. // - scale array [horizontal, vertical] ratios
  11893. // - style (stroke, fill, both)
  11894. var x = parseFloat(path[1]),
  11895. y = parseFloat(path[2]),
  11896. vectors = [],
  11897. position = 3,
  11898. len = path.length;
  11899. while (position < len) {
  11900. if (path[position] === "c") {
  11901. 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])]);
  11902. position += 7;
  11903. } else if (path[position] === "l") {
  11904. vectors.push([parseFloat(path[position + 1]), parseFloat(path[position + 2])]);
  11905. position += 3;
  11906. } else {
  11907. position += 1;
  11908. }
  11909. }
  11910. return [x, y, vectors];
  11911. }
  11912. var workernode = createWorkerNode(document),
  11913. svgnode = attachSVGToWorkerNode(svgtext, workernode),
  11914. scale = [1, 1],
  11915. svgw = parseFloat(svgnode.getAttribute("width")),
  11916. svgh = parseFloat(svgnode.getAttribute("height"));
  11917. if (svgw && svgh) {
  11918. // setting both w and h makes image stretch to size.
  11919. // this may distort the image, but fits your demanded size
  11920. if (w && h) {
  11921. scale = [w / svgw, h / svgh];
  11922. } // if only one is set, that value is set as max and SVG
  11923. // is scaled proportionately.
  11924. else if (w) {
  11925. scale = [w / svgw, w / svgw];
  11926. } else if (h) {
  11927. scale = [h / svgh, h / svgh];
  11928. }
  11929. }
  11930. var i,
  11931. l,
  11932. tmp,
  11933. linesargs,
  11934. items = svgnode.childNodes;
  11935. for (i = 0, l = items.length; i < l; i++) {
  11936. tmp = items[i];
  11937. if (tmp.tagName && tmp.tagName.toUpperCase() === "PATH") {
  11938. linesargs = convertPathToPDFLinesArgs(tmp.getAttribute("d").split(" ")); // path start x coordinate
  11939. linesargs[0] = linesargs[0] * scale[0] + x; // where x is upper left X of image
  11940. // path start y coordinate
  11941. linesargs[1] = linesargs[1] * scale[1] + y; // where y is upper left Y of image
  11942. // the rest of lines are vectors. these will adjust with scale value auto.
  11943. this.lines.call(this, linesargs[2], // lines
  11944. linesargs[0], // starting x
  11945. linesargs[1], // starting y
  11946. scale);
  11947. }
  11948. } // clean up
  11949. // workernode.parentNode.removeChild(workernode)
  11950. return this;
  11951. }; //fallback
  11952. jsPDFAPI.addSVG = jsPDFAPI.addSvg;
  11953. /**
  11954. * Parses SVG XML and saves it as image into the PDF.
  11955. *
  11956. * Depends on canvas-element and canvg
  11957. *
  11958. * @name addSvgAsImage
  11959. * @public
  11960. * @function
  11961. * @param {string} SVG-Data as Text
  11962. * @param {number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
  11963. * @param {number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
  11964. * @param {number} width of SVG-Image (in units declared at inception of PDF document)
  11965. * @param {number} height of SVG-Image (in units declared at inception of PDF document)
  11966. * @param {string} alias of SVG-Image (if used multiple times)
  11967. * @param {string} compression of the generated JPEG, can have the values 'NONE', 'FAST', 'MEDIUM' and 'SLOW'
  11968. * @param {number} rotation of the image in degrees (0-359)
  11969. *
  11970. * @returns jsPDF jsPDF-instance
  11971. */
  11972. jsPDFAPI.addSvgAsImage = function (svg, x, y, w, h, alias, compression, rotation) {
  11973. if (isNaN(x) || isNaN(y)) {
  11974. console.error("jsPDF.addSvgAsImage: Invalid coordinates", arguments);
  11975. throw new Error("Invalid coordinates passed to jsPDF.addSvgAsImage");
  11976. }
  11977. if (isNaN(w) || isNaN(h)) {
  11978. console.error("jsPDF.addSvgAsImage: Invalid measurements", arguments);
  11979. throw new Error("Invalid measurements (width and/or height) passed to jsPDF.addSvgAsImage");
  11980. }
  11981. var canvas = document.createElement("canvas");
  11982. canvas.width = w;
  11983. canvas.height = h;
  11984. var ctx = canvas.getContext("2d");
  11985. ctx.fillStyle = "#fff"; /// set white fill style
  11986. ctx.fillRect(0, 0, canvas.width, canvas.height); //load a svg snippet in the canvas with id = 'drawingArea'
  11987. canvg(canvas, svg, {
  11988. ignoreMouse: true,
  11989. ignoreAnimation: true,
  11990. ignoreDimensions: true,
  11991. ignoreClear: true
  11992. });
  11993. this.addImage(canvas.toDataURL("image/jpeg", 1.0), x, y, w, h, compression, rotation);
  11994. return this;
  11995. };
  11996. })(jsPDF.API);
  11997. /**
  11998. * @license
  11999. * ====================================================================
  12000. * Copyright (c) 2013 Eduardo Menezes de Morais, eduardo.morais@usp.br
  12001. *
  12002. *
  12003. * ====================================================================
  12004. */
  12005. /**
  12006. * jsPDF total_pages plugin
  12007. * @name total_pages
  12008. * @module
  12009. */
  12010. (function (jsPDFAPI) {
  12011. /**
  12012. * @name putTotalPages
  12013. * @function
  12014. * @param {string} pageExpression Regular Expression
  12015. * @returns {jsPDF} jsPDF-instance
  12016. */
  12017. jsPDFAPI.putTotalPages = function (pageExpression) {
  12018. var replaceExpression = new RegExp(pageExpression, "g");
  12019. for (var n = 1; n <= this.internal.getNumberOfPages(); n++) {
  12020. for (var i = 0; i < this.internal.pages[n].length; i++) {
  12021. this.internal.pages[n][i] = this.internal.pages[n][i].replace(replaceExpression, this.internal.getNumberOfPages());
  12022. }
  12023. }
  12024. return this;
  12025. };
  12026. })(jsPDF.API);
  12027. /**
  12028. * jsPDF viewerPreferences Plugin
  12029. * @author Aras Abbasi (github.com/arasabbasi)
  12030. * Licensed under the MIT License.
  12031. * http://opensource.org/licenses/mit-license
  12032. */
  12033. /**
  12034. * Adds the ability to set ViewerPreferences and by thus
  12035. * controlling the way the document is to be presented on the
  12036. * screen or in print.
  12037. * @name viewerpreferences
  12038. * @module
  12039. */
  12040. (function (jsPDFAPI) {
  12041. /**
  12042. * Set the ViewerPreferences of the generated PDF
  12043. *
  12044. * @name viewerPreferences
  12045. * @function
  12046. * @public
  12047. * @param {Object} options Array with the ViewerPreferences<br />
  12048. * Example: doc.viewerPreferences({"FitWindow":true});<br />
  12049. * <br />
  12050. * You can set following preferences:<br />
  12051. * <br/>
  12052. * <b>HideToolbar</b> <i>(boolean)</i><br />
  12053. * Default value: false<br />
  12054. * <br />
  12055. * <b>HideMenubar</b> <i>(boolean)</i><br />
  12056. * Default value: false.<br />
  12057. * <br />
  12058. * <b>HideWindowUI</b> <i>(boolean)</i><br />
  12059. * Default value: false.<br />
  12060. * <br />
  12061. * <b>FitWindow</b> <i>(boolean)</i><br />
  12062. * Default value: false.<br />
  12063. * <br />
  12064. * <b>CenterWindow</b> <i>(boolean)</i><br />
  12065. * Default value: false<br />
  12066. * <br />
  12067. * <b>DisplayDocTitle</b> <i>(boolean)</i><br />
  12068. * Default value: false.<br />
  12069. * <br />
  12070. * <b>NonFullScreenPageMode</b> <i>(string)</i><br />
  12071. * Possible values: UseNone, UseOutlines, UseThumbs, UseOC<br />
  12072. * Default value: UseNone<br/>
  12073. * <br />
  12074. * <b>Direction</b> <i>(string)</i><br />
  12075. * Possible values: L2R, R2L<br />
  12076. * Default value: L2R.<br />
  12077. * <br />
  12078. * <b>ViewArea</b> <i>(string)</i><br />
  12079. * Possible values: MediaBox, CropBox, TrimBox, BleedBox, ArtBox<br />
  12080. * Default value: CropBox.<br />
  12081. * <br />
  12082. * <b>ViewClip</b> <i>(string)</i><br />
  12083. * Possible values: MediaBox, CropBox, TrimBox, BleedBox, ArtBox<br />
  12084. * Default value: CropBox<br />
  12085. * <br />
  12086. * <b>PrintArea</b> <i>(string)</i><br />
  12087. * Possible values: MediaBox, CropBox, TrimBox, BleedBox, ArtBox<br />
  12088. * Default value: CropBox<br />
  12089. * <br />
  12090. * <b>PrintClip</b> <i>(string)</i><br />
  12091. * Possible values: MediaBox, CropBox, TrimBox, BleedBox, ArtBox<br />
  12092. * Default value: CropBox.<br />
  12093. * <br />
  12094. * <b>PrintScaling</b> <i>(string)</i><br />
  12095. * Possible values: AppDefault, None<br />
  12096. * Default value: AppDefault.<br />
  12097. * <br />
  12098. * <b>Duplex</b> <i>(string)</i><br />
  12099. * Possible values: Simplex, DuplexFlipLongEdge, DuplexFlipShortEdge
  12100. * Default value: none<br />
  12101. * <br />
  12102. * <b>PickTrayByPDFSize</b> <i>(boolean)</i><br />
  12103. * Default value: false<br />
  12104. * <br />
  12105. * <b>PrintPageRange</b> <i>(Array)</i><br />
  12106. * Example: [[1,5], [7,9]]<br />
  12107. * Default value: as defined by PDF viewer application<br />
  12108. * <br />
  12109. * <b>NumCopies</b> <i>(Number)</i><br />
  12110. * Possible values: 1, 2, 3, 4, 5<br />
  12111. * Default value: 1<br />
  12112. * <br />
  12113. * For more information see the PDF Reference, sixth edition on Page 577
  12114. * @param {boolean} doReset True to reset the settings
  12115. * @function
  12116. * @returns jsPDF jsPDF-instance
  12117. * @example
  12118. * var doc = new jsPDF()
  12119. * doc.text('This is a test', 10, 10)
  12120. * doc.viewerPreferences({'FitWindow': true}, true)
  12121. * doc.save("viewerPreferences.pdf")
  12122. *
  12123. * // Example printing 10 copies, using cropbox, and hiding UI.
  12124. * doc.viewerPreferences({
  12125. * 'HideWindowUI': true,
  12126. * 'PrintArea': 'CropBox',
  12127. * 'NumCopies': 10
  12128. * })
  12129. */
  12130. jsPDFAPI.viewerPreferences = function (options, doReset) {
  12131. options = options || {};
  12132. doReset = doReset || false;
  12133. var configuration;
  12134. var configurationTemplate = {
  12135. HideToolbar: {
  12136. defaultValue: false,
  12137. value: false,
  12138. type: "boolean",
  12139. explicitSet: false,
  12140. valueSet: [true, false],
  12141. pdfVersion: 1.3
  12142. },
  12143. HideMenubar: {
  12144. defaultValue: false,
  12145. value: false,
  12146. type: "boolean",
  12147. explicitSet: false,
  12148. valueSet: [true, false],
  12149. pdfVersion: 1.3
  12150. },
  12151. HideWindowUI: {
  12152. defaultValue: false,
  12153. value: false,
  12154. type: "boolean",
  12155. explicitSet: false,
  12156. valueSet: [true, false],
  12157. pdfVersion: 1.3
  12158. },
  12159. FitWindow: {
  12160. defaultValue: false,
  12161. value: false,
  12162. type: "boolean",
  12163. explicitSet: false,
  12164. valueSet: [true, false],
  12165. pdfVersion: 1.3
  12166. },
  12167. CenterWindow: {
  12168. defaultValue: false,
  12169. value: false,
  12170. type: "boolean",
  12171. explicitSet: false,
  12172. valueSet: [true, false],
  12173. pdfVersion: 1.3
  12174. },
  12175. DisplayDocTitle: {
  12176. defaultValue: false,
  12177. value: false,
  12178. type: "boolean",
  12179. explicitSet: false,
  12180. valueSet: [true, false],
  12181. pdfVersion: 1.4
  12182. },
  12183. NonFullScreenPageMode: {
  12184. defaultValue: "UseNone",
  12185. value: "UseNone",
  12186. type: "name",
  12187. explicitSet: false,
  12188. valueSet: ["UseNone", "UseOutlines", "UseThumbs", "UseOC"],
  12189. pdfVersion: 1.3
  12190. },
  12191. Direction: {
  12192. defaultValue: "L2R",
  12193. value: "L2R",
  12194. type: "name",
  12195. explicitSet: false,
  12196. valueSet: ["L2R", "R2L"],
  12197. pdfVersion: 1.3
  12198. },
  12199. ViewArea: {
  12200. defaultValue: "CropBox",
  12201. value: "CropBox",
  12202. type: "name",
  12203. explicitSet: false,
  12204. valueSet: ["MediaBox", "CropBox", "TrimBox", "BleedBox", "ArtBox"],
  12205. pdfVersion: 1.4
  12206. },
  12207. ViewClip: {
  12208. defaultValue: "CropBox",
  12209. value: "CropBox",
  12210. type: "name",
  12211. explicitSet: false,
  12212. valueSet: ["MediaBox", "CropBox", "TrimBox", "BleedBox", "ArtBox"],
  12213. pdfVersion: 1.4
  12214. },
  12215. PrintArea: {
  12216. defaultValue: "CropBox",
  12217. value: "CropBox",
  12218. type: "name",
  12219. explicitSet: false,
  12220. valueSet: ["MediaBox", "CropBox", "TrimBox", "BleedBox", "ArtBox"],
  12221. pdfVersion: 1.4
  12222. },
  12223. PrintClip: {
  12224. defaultValue: "CropBox",
  12225. value: "CropBox",
  12226. type: "name",
  12227. explicitSet: false,
  12228. valueSet: ["MediaBox", "CropBox", "TrimBox", "BleedBox", "ArtBox"],
  12229. pdfVersion: 1.4
  12230. },
  12231. PrintScaling: {
  12232. defaultValue: "AppDefault",
  12233. value: "AppDefault",
  12234. type: "name",
  12235. explicitSet: false,
  12236. valueSet: ["AppDefault", "None"],
  12237. pdfVersion: 1.6
  12238. },
  12239. Duplex: {
  12240. defaultValue: "",
  12241. value: "none",
  12242. type: "name",
  12243. explicitSet: false,
  12244. valueSet: ["Simplex", "DuplexFlipShortEdge", "DuplexFlipLongEdge", "none"],
  12245. pdfVersion: 1.7
  12246. },
  12247. PickTrayByPDFSize: {
  12248. defaultValue: false,
  12249. value: false,
  12250. type: "boolean",
  12251. explicitSet: false,
  12252. valueSet: [true, false],
  12253. pdfVersion: 1.7
  12254. },
  12255. PrintPageRange: {
  12256. defaultValue: "",
  12257. value: "",
  12258. type: "array",
  12259. explicitSet: false,
  12260. valueSet: null,
  12261. pdfVersion: 1.7
  12262. },
  12263. NumCopies: {
  12264. defaultValue: 1,
  12265. value: 1,
  12266. type: "integer",
  12267. explicitSet: false,
  12268. valueSet: null,
  12269. pdfVersion: 1.7
  12270. }
  12271. };
  12272. var configurationKeys = Object.keys(configurationTemplate);
  12273. var rangeArray = [];
  12274. var i = 0;
  12275. var j = 0;
  12276. var k = 0;
  12277. var isValid = true;
  12278. var method;
  12279. var value;
  12280. function arrayContainsElement(array, element) {
  12281. var iterator;
  12282. var result = false;
  12283. for (iterator = 0; iterator < array.length; iterator += 1) {
  12284. if (array[iterator] === element) {
  12285. result = true;
  12286. }
  12287. }
  12288. return result;
  12289. }
  12290. if (this.internal.viewerpreferences === undefined) {
  12291. this.internal.viewerpreferences = {};
  12292. this.internal.viewerpreferences.configuration = JSON.parse(JSON.stringify(configurationTemplate));
  12293. this.internal.viewerpreferences.isSubscribed = false;
  12294. }
  12295. configuration = this.internal.viewerpreferences.configuration;
  12296. if (options === "reset" || doReset === true) {
  12297. var len = configurationKeys.length;
  12298. for (k = 0; k < len; k += 1) {
  12299. configuration[configurationKeys[k]].value = configuration[configurationKeys[k]].defaultValue;
  12300. configuration[configurationKeys[k]].explicitSet = false;
  12301. }
  12302. }
  12303. if (_typeof(options) === "object") {
  12304. for (method in options) {
  12305. value = options[method];
  12306. if (arrayContainsElement(configurationKeys, method) && value !== undefined) {
  12307. if (configuration[method].type === "boolean" && typeof value === "boolean") {
  12308. configuration[method].value = value;
  12309. } else if (configuration[method].type === "name" && arrayContainsElement(configuration[method].valueSet, value)) {
  12310. configuration[method].value = value;
  12311. } else if (configuration[method].type === "integer" && Number.isInteger(value)) {
  12312. configuration[method].value = value;
  12313. } else if (configuration[method].type === "array") {
  12314. for (i = 0; i < value.length; i += 1) {
  12315. isValid = true;
  12316. if (value[i].length === 1 && typeof value[i][0] === "number") {
  12317. rangeArray.push(String(value[i]));
  12318. } else if (value[i].length > 1) {
  12319. for (j = 0; j < value[i].length; j += 1) {
  12320. if (typeof value[i][j] !== "number") {
  12321. isValid = false;
  12322. }
  12323. }
  12324. if (isValid === true) {
  12325. rangeArray.push(String(value[i].join("-")));
  12326. }
  12327. }
  12328. }
  12329. configuration[method].value = String(rangeArray);
  12330. } else {
  12331. configuration[method].value = configuration[method].defaultValue;
  12332. }
  12333. configuration[method].explicitSet = true;
  12334. }
  12335. }
  12336. }
  12337. if (this.internal.viewerpreferences.isSubscribed === false) {
  12338. this.internal.events.subscribe("putCatalog", function () {
  12339. var pdfDict = [];
  12340. var vPref;
  12341. for (vPref in configuration) {
  12342. if (configuration[vPref].explicitSet === true) {
  12343. if (configuration[vPref].type === "name") {
  12344. pdfDict.push("/" + vPref + " /" + configuration[vPref].value);
  12345. } else {
  12346. pdfDict.push("/" + vPref + " " + configuration[vPref].value);
  12347. }
  12348. }
  12349. }
  12350. if (pdfDict.length !== 0) {
  12351. this.internal.write("/ViewerPreferences\n<<\n" + pdfDict.join("\n") + "\n>>");
  12352. }
  12353. });
  12354. this.internal.viewerpreferences.isSubscribed = true;
  12355. }
  12356. this.internal.viewerpreferences.configuration = configuration;
  12357. return this;
  12358. };
  12359. })(jsPDF.API);
  12360. /** ====================================================================
  12361. * jsPDF XMP metadata plugin
  12362. * Copyright (c) 2016 Jussi Utunen, u-jussi@suomi24.fi
  12363. *
  12364. *
  12365. * ====================================================================
  12366. */
  12367. /*global jsPDF */
  12368. /**
  12369. * @name xmp_metadata
  12370. * @module
  12371. */
  12372. (function (jsPDFAPI) {
  12373. var xmpmetadata = "";
  12374. var xmpnamespaceuri = "";
  12375. var metadata_object_number = "";
  12376. /**
  12377. * Adds XMP formatted metadata to PDF
  12378. *
  12379. * @name addMetadata
  12380. * @function
  12381. * @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.
  12382. * @param {String} namespaceuri Sets the namespace URI for the metadata. Last character should be slash or hash.
  12383. * @returns {jsPDF} jsPDF-instance
  12384. */
  12385. jsPDFAPI.addMetadata = function (metadata, namespaceuri) {
  12386. xmpnamespaceuri = namespaceuri || "http://jspdf.default.namespaceuri/"; //The namespace URI for an XMP name shall not be empty
  12387. xmpmetadata = metadata;
  12388. this.internal.events.subscribe("postPutResources", function () {
  12389. if (!xmpmetadata) {
  12390. metadata_object_number = "";
  12391. } else {
  12392. var xmpmeta_beginning = '<x:xmpmeta xmlns:x="adobe:ns:meta/">';
  12393. 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>';
  12394. var rdf_ending = "</jspdf:metadata></rdf:Description></rdf:RDF>";
  12395. var xmpmeta_ending = "</x:xmpmeta>";
  12396. var utf8_xmpmeta_beginning = unescape(encodeURIComponent(xmpmeta_beginning));
  12397. var utf8_rdf_beginning = unescape(encodeURIComponent(rdf_beginning));
  12398. var utf8_metadata = unescape(encodeURIComponent(xmpmetadata));
  12399. var utf8_rdf_ending = unescape(encodeURIComponent(rdf_ending));
  12400. var utf8_xmpmeta_ending = unescape(encodeURIComponent(xmpmeta_ending));
  12401. var total_len = utf8_rdf_beginning.length + utf8_metadata.length + utf8_rdf_ending.length + utf8_xmpmeta_beginning.length + utf8_xmpmeta_ending.length;
  12402. metadata_object_number = this.internal.newObject();
  12403. this.internal.write("<< /Type /Metadata /Subtype /XML /Length " + total_len + " >>");
  12404. this.internal.write("stream");
  12405. this.internal.write(utf8_xmpmeta_beginning + utf8_rdf_beginning + utf8_metadata + utf8_rdf_ending + utf8_xmpmeta_ending);
  12406. this.internal.write("endstream");
  12407. this.internal.write("endobj");
  12408. }
  12409. });
  12410. this.internal.events.subscribe("putCatalog", function () {
  12411. if (metadata_object_number) {
  12412. this.internal.write("/Metadata " + metadata_object_number + " 0 R");
  12413. }
  12414. });
  12415. return this;
  12416. };
  12417. })(jsPDF.API);
  12418. /**
  12419. * @name utf8
  12420. * @module
  12421. */
  12422. (function (jsPDF, global) {
  12423. var jsPDFAPI = jsPDF.API;
  12424. /**************************************************/
  12425. /* function : toHex */
  12426. /* comment : Replace str with a hex string. */
  12427. /**************************************************/
  12428. function toHex(str) {
  12429. var hex = "";
  12430. for (var i = 0; i < str.length; i++) {
  12431. hex += "" + str.charCodeAt(i).toString(16);
  12432. }
  12433. return hex;
  12434. }
  12435. /***************************************************************************************************/
  12436. /* function : pdfEscape16 */
  12437. /* comment : The character id of a 2-byte string is converted to a hexadecimal number by obtaining */
  12438. /* the corresponding glyph id and width, and then adding padding to the string. */
  12439. /***************************************************************************************************/
  12440. var pdfEscape16 = jsPDFAPI.pdfEscape16 = function (text, font) {
  12441. var widths = font.metadata.Unicode.widths;
  12442. var padz = ["", "0", "00", "000", "0000"];
  12443. var ar = [""];
  12444. for (var i = 0, l = text.length, t; i < l; ++i) {
  12445. t = font.metadata.characterToGlyph(text.charCodeAt(i));
  12446. font.metadata.glyIdsUsed.push(t);
  12447. font.metadata.toUnicode[t] = text.charCodeAt(i);
  12448. if (widths.indexOf(t) == -1) {
  12449. widths.push(t);
  12450. widths.push([parseInt(font.metadata.widthOfGlyph(t), 10)]);
  12451. }
  12452. if (t == "0") {
  12453. //Spaces are not allowed in cmap.
  12454. return ar.join("");
  12455. } else {
  12456. t = t.toString(16);
  12457. ar.push(padz[4 - t.length], t);
  12458. }
  12459. }
  12460. return ar.join("");
  12461. };
  12462. var toUnicodeCmap = function toUnicodeCmap(map) {
  12463. var code, codes, range, unicode, unicodeMap, _i, _len;
  12464. unicodeMap = "/CIDInit /ProcSet findresource begin\n12 dict begin\nbegincmap\n/CIDSystemInfo <<\n /Registry (Adobe)\n /Ordering (UCS)\n /Supplement 0\n>> def\n/CMapName /Adobe-Identity-UCS def\n/CMapType 2 def\n1 begincodespacerange\n<0000><ffff>\nendcodespacerange";
  12465. codes = Object.keys(map).sort(function (a, b) {
  12466. return a - b;
  12467. });
  12468. range = [];
  12469. for (_i = 0, _len = codes.length; _i < _len; _i++) {
  12470. code = codes[_i];
  12471. if (range.length >= 100) {
  12472. unicodeMap += "\n" + range.length + " beginbfchar\n" + range.join("\n") + "\nendbfchar";
  12473. range = [];
  12474. }
  12475. unicode = ("0000" + map[code].toString(16)).slice(-4);
  12476. code = ("0000" + (+code).toString(16)).slice(-4);
  12477. range.push("<" + code + "><" + unicode + ">");
  12478. }
  12479. if (range.length) {
  12480. unicodeMap += "\n" + range.length + " beginbfchar\n" + range.join("\n") + "\nendbfchar\n";
  12481. }
  12482. unicodeMap += "endcmap\nCMapName currentdict /CMap defineresource pop\nend\nend";
  12483. return unicodeMap;
  12484. };
  12485. var identityHFunction = function identityHFunction(font, out, newObject, putStream) {
  12486. if (font.metadata instanceof jsPDF.API.TTFFont && font.encoding === "Identity-H") {
  12487. //Tag with Identity-H
  12488. var widths = font.metadata.Unicode.widths;
  12489. var data = font.metadata.subset.encode(font.metadata.glyIdsUsed, 1);
  12490. var pdfOutput = data;
  12491. var pdfOutput2 = "";
  12492. for (var i = 0; i < pdfOutput.length; i++) {
  12493. pdfOutput2 += String.fromCharCode(pdfOutput[i]);
  12494. }
  12495. var fontTable = newObject();
  12496. out("<<");
  12497. out("/Length " + pdfOutput2.length);
  12498. out("/Length1 " + pdfOutput2.length);
  12499. out(">>");
  12500. putStream(pdfOutput2);
  12501. out("endobj");
  12502. var cmap = newObject();
  12503. var cmapData = toUnicodeCmap(font.metadata.toUnicode);
  12504. out("<<");
  12505. out("/Length " + cmapData.length);
  12506. out("/Length1 " + cmapData.length);
  12507. out(">>");
  12508. putStream(cmapData);
  12509. out("endobj");
  12510. var fontDescriptor = newObject();
  12511. out("<<");
  12512. out("/Type /FontDescriptor");
  12513. out("/FontName /" + font.fontName);
  12514. out("/FontFile2 " + fontTable + " 0 R");
  12515. out("/FontBBox " + jsPDF.API.PDFObject.convert(font.metadata.bbox));
  12516. out("/Flags " + font.metadata.flags);
  12517. out("/StemV " + font.metadata.stemV);
  12518. out("/ItalicAngle " + font.metadata.italicAngle);
  12519. out("/Ascent " + font.metadata.ascender);
  12520. out("/Descent " + font.metadata.decender);
  12521. out("/CapHeight " + font.metadata.capHeight);
  12522. out(">>");
  12523. out("endobj");
  12524. var DescendantFont = newObject();
  12525. out("<<");
  12526. out("/Type /Font");
  12527. out("/BaseFont /" + font.fontName);
  12528. out("/FontDescriptor " + fontDescriptor + " 0 R");
  12529. out("/W " + jsPDF.API.PDFObject.convert(widths));
  12530. out("/CIDToGIDMap /Identity");
  12531. out("/DW 1000");
  12532. out("/Subtype /CIDFontType2");
  12533. out("/CIDSystemInfo");
  12534. out("<<");
  12535. out("/Supplement 0");
  12536. out("/Registry (Adobe)");
  12537. out("/Ordering (" + font.encoding + ")");
  12538. out(">>");
  12539. out(">>");
  12540. out("endobj");
  12541. font.objectNumber = newObject();
  12542. out("<<");
  12543. out("/Type /Font");
  12544. out("/Subtype /Type0");
  12545. out("/ToUnicode " + cmap + " 0 R");
  12546. out("/BaseFont /" + font.fontName);
  12547. out("/Encoding /" + font.encoding);
  12548. out("/DescendantFonts [" + DescendantFont + " 0 R]");
  12549. out(">>");
  12550. out("endobj");
  12551. font.isAlreadyPutted = true;
  12552. }
  12553. };
  12554. jsPDFAPI.events.push(["putFont", function (args) {
  12555. identityHFunction(args.font, args.out, args.newObject, args.putStream);
  12556. }]);
  12557. var winAnsiEncodingFunction = function winAnsiEncodingFunction(font, out, newObject, putStream) {
  12558. if (font.metadata instanceof jsPDF.API.TTFFont && font.encoding === "WinAnsiEncoding") {
  12559. //Tag with WinAnsi encoding
  12560. var widths = font.metadata.Unicode.widths;
  12561. var data = font.metadata.rawData;
  12562. var pdfOutput = data;
  12563. var pdfOutput2 = "";
  12564. for (var i = 0; i < pdfOutput.length; i++) {
  12565. pdfOutput2 += String.fromCharCode(pdfOutput[i]);
  12566. }
  12567. var fontTable = newObject();
  12568. putStream({
  12569. data: pdfOutput2,
  12570. addLength1: true
  12571. });
  12572. out("endobj");
  12573. var cmap = newObject();
  12574. var cmapData = toUnicodeCmap(font.metadata.toUnicode);
  12575. putStream({
  12576. data: cmapData,
  12577. addLength1: true
  12578. });
  12579. out("endobj");
  12580. var fontDescriptor = newObject();
  12581. out("<<");
  12582. out("/Descent " + font.metadata.decender);
  12583. out("/CapHeight " + font.metadata.capHeight);
  12584. out("/StemV " + font.metadata.stemV);
  12585. out("/Type /FontDescriptor");
  12586. out("/FontFile2 " + fontTable + " 0 R");
  12587. out("/Flags 96");
  12588. out("/FontBBox " + jsPDF.API.PDFObject.convert(font.metadata.bbox));
  12589. out("/FontName /" + font.fontName);
  12590. out("/ItalicAngle " + font.metadata.italicAngle);
  12591. out("/Ascent " + font.metadata.ascender);
  12592. out(">>");
  12593. out("endobj");
  12594. font.objectNumber = newObject();
  12595. for (var i = 0; i < font.metadata.hmtx.widths.length; i++) {
  12596. 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.
  12597. }
  12598. out("<</Subtype/TrueType/Type/Font/ToUnicode " + cmap + " 0 R/BaseFont/" + font.fontName + "/FontDescriptor " + fontDescriptor + " 0 R" + "/Encoding/" + font.encoding + " /FirstChar 29 /LastChar 255 /Widths " + jsPDF.API.PDFObject.convert(font.metadata.hmtx.widths) + ">>");
  12599. out("endobj");
  12600. font.isAlreadyPutted = true;
  12601. }
  12602. };
  12603. jsPDFAPI.events.push(["putFont", function (args) {
  12604. winAnsiEncodingFunction(args.font, args.out, args.newObject, args.putStream);
  12605. }]);
  12606. var utf8TextFunction = function utf8TextFunction(args) {
  12607. var text = args.text || "";
  12608. var x = args.x;
  12609. var y = args.y;
  12610. var options = args.options || {};
  12611. var mutex = args.mutex || {};
  12612. var pdfEscape = mutex.pdfEscape;
  12613. var activeFontKey = mutex.activeFontKey;
  12614. var fonts = mutex.fonts;
  12615. var key,
  12616. fontSize = mutex.activeFontSize;
  12617. var str = "",
  12618. s = 0,
  12619. cmapConfirm;
  12620. var strText = "";
  12621. var key = activeFontKey;
  12622. var encoding = fonts[key].encoding;
  12623. if (fonts[key].encoding !== "Identity-H") {
  12624. return {
  12625. text: text,
  12626. x: x,
  12627. y: y,
  12628. options: options,
  12629. mutex: mutex
  12630. };
  12631. }
  12632. strText = text;
  12633. key = activeFontKey;
  12634. if (Object.prototype.toString.call(text) === "[object Array]") {
  12635. strText = text[0];
  12636. }
  12637. for (s = 0; s < strText.length; s += 1) {
  12638. if (fonts[key].metadata.hasOwnProperty("cmap")) {
  12639. cmapConfirm = fonts[key].metadata.cmap.unicode.codeMap[strText[s].charCodeAt(0)];
  12640. /*
  12641. if (Object.prototype.toString.call(text) === '[object Array]') {
  12642. var i = 0;
  12643. // for (i = 0; i < text.length; i += 1) {
  12644. if (Object.prototype.toString.call(text[s]) === '[object Array]') {
  12645. cmapConfirm = fonts[key].metadata.cmap.unicode.codeMap[strText[s][0].charCodeAt(0)]; //Make sure the cmap has the corresponding glyph id
  12646. } else {
  12647. }
  12648. //}
  12649. } else {
  12650. cmapConfirm = fonts[key].metadata.cmap.unicode.codeMap[strText[s].charCodeAt(0)]; //Make sure the cmap has the corresponding glyph id
  12651. }*/
  12652. }
  12653. if (!cmapConfirm) {
  12654. if (strText[s].charCodeAt(0) < 256 && fonts[key].metadata.hasOwnProperty("Unicode")) {
  12655. str += strText[s];
  12656. } else {
  12657. str += "";
  12658. }
  12659. } else {
  12660. str += strText[s];
  12661. }
  12662. }
  12663. var result = "";
  12664. if (parseInt(key.slice(1)) < 14 || encoding === "WinAnsiEncoding") {
  12665. //For the default 13 font
  12666. result = toHex(pdfEscape(str, key));
  12667. } else if (encoding === "Identity-H") {
  12668. result = pdfEscape16(str, fonts[key]);
  12669. }
  12670. mutex.isHex = true;
  12671. return {
  12672. text: result,
  12673. x: x,
  12674. y: y,
  12675. options: options,
  12676. mutex: mutex
  12677. };
  12678. };
  12679. var utf8EscapeFunction = function utf8EscapeFunction(parms) {
  12680. var text = parms.text || "",
  12681. x = parms.x,
  12682. y = parms.y,
  12683. options = parms.options,
  12684. mutex = parms.mutex;
  12685. var lang = options.lang;
  12686. var tmpText = [];
  12687. var args = {
  12688. text: text,
  12689. x: x,
  12690. y: y,
  12691. options: options,
  12692. mutex: mutex
  12693. };
  12694. if (Object.prototype.toString.call(text) === "[object Array]") {
  12695. var i = 0;
  12696. for (i = 0; i < text.length; i += 1) {
  12697. if (Object.prototype.toString.call(text[i]) === "[object Array]") {
  12698. if (text[i].length === 3) {
  12699. tmpText.push([utf8TextFunction(Object.assign({}, args, {
  12700. text: text[i][0]
  12701. })).text, text[i][1], text[i][2]]);
  12702. } else {
  12703. tmpText.push(utf8TextFunction(Object.assign({}, args, {
  12704. text: text[i]
  12705. })).text);
  12706. }
  12707. } else {
  12708. tmpText.push(utf8TextFunction(Object.assign({}, args, {
  12709. text: text[i]
  12710. })).text);
  12711. }
  12712. }
  12713. parms.text = tmpText;
  12714. } else {
  12715. parms.text = utf8TextFunction(Object.assign({}, args, {
  12716. text: text
  12717. })).text;
  12718. }
  12719. };
  12720. jsPDFAPI.events.push(["postProcessText", utf8EscapeFunction]);
  12721. })(jsPDF, typeof self !== "undefined" && self || typeof global !== "undefined" && global || typeof window !== "undefined" && window || Function("return this")());
  12722. /**
  12723. * jsPDF virtual FileSystem functionality
  12724. *
  12725. * Licensed under the MIT License.
  12726. * http://opensource.org/licenses/mit-license
  12727. */
  12728. /**
  12729. * Use the vFS to handle files
  12730. *
  12731. * @name vFS
  12732. * @module
  12733. */
  12734. (function (jsPDFAPI) {
  12735. var vFS = {};
  12736. /**
  12737. * Check if the file exists in the vFS
  12738. *
  12739. * @name existsFileInVFS
  12740. * @function
  12741. * @param {string} Possible filename in the vFS.
  12742. * @returns {boolean}
  12743. * @example
  12744. * doc.existsFileInVFS("someFile.txt");
  12745. */
  12746. jsPDFAPI.existsFileInVFS = function (filename) {
  12747. return vFS.hasOwnProperty(filename);
  12748. };
  12749. /**
  12750. * Add a file to the vFS
  12751. *
  12752. * @name addFileToVFS
  12753. * @function
  12754. * @param {string} filename The name of the file which should be added.
  12755. * @param {string} filecontent The content of the file.
  12756. * @returns {jsPDF}
  12757. * @example
  12758. * doc.addFileToVFS("someFile.txt", "BADFACE1");
  12759. */
  12760. jsPDFAPI.addFileToVFS = function (filename, filecontent) {
  12761. vFS[filename] = filecontent;
  12762. return this;
  12763. };
  12764. /**
  12765. * Get the file from the vFS
  12766. *
  12767. * @name getFileFromVFS
  12768. * @function
  12769. * @returns {string} The name of the file which gets requested.
  12770. * @example
  12771. * doc.getFileFromVFS("someFile.txt");
  12772. */
  12773. jsPDFAPI.getFileFromVFS = function (filename) {
  12774. if (vFS.hasOwnProperty(filename)) {
  12775. return vFS[filename];
  12776. }
  12777. return null;
  12778. };
  12779. })(jsPDF.API);
  12780. /* Blob.js
  12781. * A Blob implementation.
  12782. * 2014-07-24
  12783. *
  12784. * By Eli Grey, http://eligrey.com
  12785. * By Devin Samarin, https://github.com/dsamarin
  12786. * License: X11/MIT
  12787. * See https://github.com/eligrey/Blob.js/blob/master/LICENSE.md
  12788. */
  12789. /*global self, unescape */
  12790. /*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true,
  12791. plusplus: true */
  12792. /*! @source http://purl.eligrey.com/github/Blob.js/blob/master/Blob.js */
  12793. (function (view) {
  12794. view.URL = view.URL || view.webkitURL;
  12795. if (view.Blob && view.URL) {
  12796. try {
  12797. new Blob();
  12798. return;
  12799. } catch (e) {}
  12800. } // Internally we use a BlobBuilder implementation to base Blob off of
  12801. // in order to support older browsers that only have BlobBuilder
  12802. var BlobBuilder = view.BlobBuilder || view.WebKitBlobBuilder || view.MozBlobBuilder || function (view) {
  12803. var get_class = function (object) {
  12804. return Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1];
  12805. },
  12806. FakeBlobBuilder = function BlobBuilder() {
  12807. this.data = [];
  12808. },
  12809. FakeBlob = function Blob(data, type, encoding) {
  12810. this.data = data;
  12811. this.size = data.length;
  12812. this.type = type;
  12813. this.encoding = encoding;
  12814. },
  12815. FBB_proto = FakeBlobBuilder.prototype,
  12816. FB_proto = FakeBlob.prototype,
  12817. FileReaderSync = view.FileReaderSync,
  12818. FileException = function (type) {
  12819. this.code = this[this.name = type];
  12820. },
  12821. 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(" "),
  12822. file_ex_code = file_ex_codes.length,
  12823. real_URL = view.URL || view.webkitURL || view,
  12824. real_create_object_URL = real_URL.createObjectURL,
  12825. real_revoke_object_URL = real_URL.revokeObjectURL,
  12826. URL = real_URL,
  12827. btoa = view.btoa,
  12828. atob = view.atob,
  12829. ArrayBuffer = view.ArrayBuffer,
  12830. Uint8Array = view.Uint8Array,
  12831. origin = /^[\w-]+:\/*\[?[\w\.:-]+\]?(?::[0-9]+)?/;
  12832. FakeBlob.fake = FB_proto.fake = true;
  12833. while (file_ex_code--) {
  12834. FileException.prototype[file_ex_codes[file_ex_code]] = file_ex_code + 1;
  12835. } // Polyfill URL
  12836. if (!real_URL.createObjectURL) {
  12837. URL = view.URL = function (uri) {
  12838. var uri_info = document.createElementNS("http://www.w3.org/1999/xhtml", "a"),
  12839. uri_origin;
  12840. uri_info.href = uri;
  12841. if (!("origin" in uri_info)) {
  12842. if (uri_info.protocol.toLowerCase() === "data:") {
  12843. uri_info.origin = null;
  12844. } else {
  12845. uri_origin = uri.match(origin);
  12846. uri_info.origin = uri_origin && uri_origin[1];
  12847. }
  12848. }
  12849. return uri_info;
  12850. };
  12851. }
  12852. URL.createObjectURL = function (blob) {
  12853. var type = blob.type,
  12854. data_URI_header;
  12855. if (type === null) {
  12856. type = "application/octet-stream";
  12857. }
  12858. if (blob instanceof FakeBlob) {
  12859. data_URI_header = "data:" + type;
  12860. if (blob.encoding === "base64") {
  12861. return data_URI_header + ";base64," + blob.data;
  12862. } else if (blob.encoding === "URI") {
  12863. return data_URI_header + "," + decodeURIComponent(blob.data);
  12864. }
  12865. if (btoa) {
  12866. return data_URI_header + ";base64," + btoa(blob.data);
  12867. } else {
  12868. return data_URI_header + "," + encodeURIComponent(blob.data);
  12869. }
  12870. } else if (real_create_object_URL) {
  12871. return real_create_object_URL.call(real_URL, blob);
  12872. }
  12873. };
  12874. URL.revokeObjectURL = function (object_URL) {
  12875. if (object_URL.substring(0, 5) !== "data:" && real_revoke_object_URL) {
  12876. real_revoke_object_URL.call(real_URL, object_URL);
  12877. }
  12878. };
  12879. FBB_proto.append = function (data
  12880. /*, endings*/
  12881. ) {
  12882. var bb = this.data; // decode data to a binary string
  12883. if (Uint8Array && (data instanceof ArrayBuffer || data instanceof Uint8Array)) {
  12884. var str = "",
  12885. buf = new Uint8Array(data),
  12886. i = 0,
  12887. buf_len = buf.length;
  12888. for (; i < buf_len; i++) {
  12889. str += String.fromCharCode(buf[i]);
  12890. }
  12891. bb.push(str);
  12892. } else if (get_class(data) === "Blob" || get_class(data) === "File") {
  12893. if (FileReaderSync) {
  12894. var fr = new FileReaderSync();
  12895. bb.push(fr.readAsBinaryString(data));
  12896. } else {
  12897. // async FileReader won't work as BlobBuilder is sync
  12898. throw new FileException("NOT_READABLE_ERR");
  12899. }
  12900. } else if (data instanceof FakeBlob) {
  12901. if (data.encoding === "base64" && atob) {
  12902. bb.push(atob(data.data));
  12903. } else if (data.encoding === "URI") {
  12904. bb.push(decodeURIComponent(data.data));
  12905. } else if (data.encoding === "raw") {
  12906. bb.push(data.data);
  12907. }
  12908. } else {
  12909. if (typeof data !== "string") {
  12910. data += ""; // convert unsupported types to strings
  12911. } // decode UTF-16 to binary string
  12912. bb.push(unescape(encodeURIComponent(data)));
  12913. }
  12914. };
  12915. FBB_proto.getBlob = function (type) {
  12916. if (!arguments.length) {
  12917. type = null;
  12918. }
  12919. return new FakeBlob(this.data.join(""), type, "raw");
  12920. };
  12921. FBB_proto.toString = function () {
  12922. return "[object BlobBuilder]";
  12923. };
  12924. FB_proto.slice = function (start, end, type) {
  12925. var args = arguments.length;
  12926. if (args < 3) {
  12927. type = null;
  12928. }
  12929. return new FakeBlob(this.data.slice(start, args > 1 ? end : this.data.length), type, this.encoding);
  12930. };
  12931. FB_proto.toString = function () {
  12932. return "[object Blob]";
  12933. };
  12934. FB_proto.close = function () {
  12935. this.size = 0;
  12936. delete this.data;
  12937. };
  12938. return FakeBlobBuilder;
  12939. }(view);
  12940. view.Blob = function (blobParts, options) {
  12941. var type = options ? options.type || "" : "";
  12942. var builder = new BlobBuilder();
  12943. if (blobParts) {
  12944. for (var i = 0, len = blobParts.length; i < len; i++) {
  12945. if (Uint8Array && blobParts[i] instanceof Uint8Array) {
  12946. builder.append(blobParts[i].buffer);
  12947. } else {
  12948. builder.append(blobParts[i]);
  12949. }
  12950. }
  12951. }
  12952. var blob = builder.getBlob(type);
  12953. if (!blob.slice && blob.webkitSlice) {
  12954. blob.slice = blob.webkitSlice;
  12955. }
  12956. return blob;
  12957. };
  12958. var getPrototypeOf = Object.getPrototypeOf || function (object) {
  12959. return object.__proto__;
  12960. };
  12961. view.Blob.prototype = getPrototypeOf(new view.Blob());
  12962. })(typeof self !== "undefined" && self || typeof window !== "undefined" && window || window.content || window);
  12963. /* FileSaver.js
  12964. * A saveAs() FileSaver implementation.
  12965. * 1.3.2
  12966. * 2016-06-16 18:25:19
  12967. *
  12968. * By Eli Grey, http://eligrey.com
  12969. * License: MIT
  12970. * See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md
  12971. */
  12972. /*global self */
  12973. /*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */
  12974. /*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */
  12975. var saveAs = saveAs || function (view) {
  12976. if (typeof view === "undefined" || typeof navigator !== "undefined" && /MSIE [1-9]\./.test(navigator.userAgent)) {
  12977. return;
  12978. }
  12979. var doc = view.document // only get URL when necessary in case Blob.js hasn't overridden it yet
  12980. ,
  12981. get_URL = function () {
  12982. return view.URL || view.webkitURL || view;
  12983. },
  12984. save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a"),
  12985. can_use_save_link = "download" in save_link,
  12986. click = function (node) {
  12987. var event = new MouseEvent("click");
  12988. node.dispatchEvent(event);
  12989. },
  12990. is_safari = /constructor/i.test(view.HTMLElement) || view.safari,
  12991. is_chrome_ios = /CriOS\/[\d]+/.test(navigator.userAgent),
  12992. throw_outside = function (ex) {
  12993. (view.setImmediate || view.setTimeout)(function () {
  12994. throw ex;
  12995. }, 0);
  12996. },
  12997. force_saveable_type = "application/octet-stream" // the Blob API is fundamentally broken as there is no "downloadfinished" event to subscribe to
  12998. ,
  12999. arbitrary_revoke_timeout = 1000 * 40 // in ms
  13000. ,
  13001. revoke = function (file) {
  13002. var revoker = function () {
  13003. if (typeof file === "string") {
  13004. // file is an object URL
  13005. get_URL().revokeObjectURL(file);
  13006. } else {
  13007. // file is a File
  13008. file.remove();
  13009. }
  13010. };
  13011. setTimeout(revoker, arbitrary_revoke_timeout);
  13012. },
  13013. dispatch = function (filesaver, event_types, event) {
  13014. event_types = [].concat(event_types);
  13015. var i = event_types.length;
  13016. while (i--) {
  13017. var listener = filesaver["on" + event_types[i]];
  13018. if (typeof listener === "function") {
  13019. try {
  13020. listener.call(filesaver, event || filesaver);
  13021. } catch (ex) {
  13022. throw_outside(ex);
  13023. }
  13024. }
  13025. }
  13026. },
  13027. auto_bom = function (blob) {
  13028. // prepend BOM for UTF-8 XML and text/* types (including HTML)
  13029. // note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF
  13030. if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) {
  13031. return new Blob([String.fromCharCode(0xFEFF), blob], {
  13032. type: blob.type
  13033. });
  13034. }
  13035. return blob;
  13036. },
  13037. FileSaver = function (blob, name, no_auto_bom) {
  13038. if (!no_auto_bom) {
  13039. blob = auto_bom(blob);
  13040. } // First try a.download, then web filesystem, then object URLs
  13041. var filesaver = this,
  13042. type = blob.type,
  13043. force = type === force_saveable_type,
  13044. object_url,
  13045. dispatch_all = function () {
  13046. dispatch(filesaver, "writestart progress write writeend".split(" "));
  13047. } // on any filesys errors revert to saving with object URLs
  13048. ,
  13049. fs_error = function () {
  13050. if ((is_chrome_ios || force && is_safari) && view.FileReader) {
  13051. // Safari doesn't allow downloading of blob urls
  13052. var reader = new FileReader();
  13053. reader.onloadend = function () {
  13054. var url = is_chrome_ios ? reader.result : reader.result.replace(/^data:[^;]*;/, 'data:attachment/file;');
  13055. var popup = view.open(url, '_blank');
  13056. if (!popup) view.location.href = url;
  13057. url = undefined; // release reference before dispatching
  13058. filesaver.readyState = filesaver.DONE;
  13059. dispatch_all();
  13060. };
  13061. reader.readAsDataURL(blob);
  13062. filesaver.readyState = filesaver.INIT;
  13063. return;
  13064. } // don't create more object URLs than needed
  13065. if (!object_url) {
  13066. object_url = get_URL().createObjectURL(blob);
  13067. }
  13068. if (force) {
  13069. view.location.href = object_url;
  13070. } else {
  13071. var opened = view.open(object_url, "_blank");
  13072. if (!opened) {
  13073. // Apple does not allow window.open, see https://developer.apple.com/library/safari/documentation/Tools/Conceptual/SafariExtensionGuide/WorkingwithWindowsandTabs/WorkingwithWindowsandTabs.html
  13074. view.location.href = object_url;
  13075. }
  13076. }
  13077. filesaver.readyState = filesaver.DONE;
  13078. dispatch_all();
  13079. revoke(object_url);
  13080. };
  13081. filesaver.readyState = filesaver.INIT;
  13082. if (can_use_save_link) {
  13083. object_url = get_URL().createObjectURL(blob);
  13084. setTimeout(function () {
  13085. save_link.href = object_url;
  13086. save_link.download = name;
  13087. click(save_link);
  13088. dispatch_all();
  13089. revoke(object_url);
  13090. filesaver.readyState = filesaver.DONE;
  13091. });
  13092. return;
  13093. }
  13094. fs_error();
  13095. },
  13096. FS_proto = FileSaver.prototype,
  13097. saveAs = function (blob, name, no_auto_bom) {
  13098. return new FileSaver(blob, name || blob.name || "download", no_auto_bom);
  13099. }; // IE 10+ (native saveAs)
  13100. if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) {
  13101. return function (blob, name, no_auto_bom) {
  13102. name = name || blob.name || "download";
  13103. if (!no_auto_bom) {
  13104. blob = auto_bom(blob);
  13105. }
  13106. return navigator.msSaveOrOpenBlob(blob, name);
  13107. };
  13108. }
  13109. FS_proto.abort = function () {};
  13110. FS_proto.readyState = FS_proto.INIT = 0;
  13111. FS_proto.WRITING = 1;
  13112. FS_proto.DONE = 2;
  13113. FS_proto.error = FS_proto.onwritestart = FS_proto.onprogress = FS_proto.onwrite = FS_proto.onabort = FS_proto.onerror = FS_proto.onwriteend = null;
  13114. return saveAs;
  13115. }(typeof self !== "undefined" && self || typeof window !== "undefined" && window || window.content); // `self` is undefined in Firefox for Android content script context
  13116. // while `this` is nsIContentFrameMessageManager
  13117. // with an attribute `content` that corresponds to the window
  13118. if (typeof module !== "undefined" && module.exports) {
  13119. module.exports.saveAs = saveAs;
  13120. } else if (typeof define !== "undefined" && define !== null && define.amd !== null) {
  13121. define("FileSaver.js", function () {
  13122. return saveAs;
  13123. });
  13124. }
  13125. // (c) Dean McNamee <dean@gmail.com>, 2013.
  13126. //
  13127. // https://github.com/deanm/omggif
  13128. //
  13129. //
  13130. //
  13131. // omggif is a JavaScript implementation of a GIF 89a encoder and decoder,
  13132. // including animation and compression. It does not rely on any specific
  13133. // underlying system, so should run in the browser, Node, or Plask.
  13134. function GifWriter(buf, width, height, gopts) {
  13135. var p = 0;
  13136. var gopts = gopts === undefined ? {} : gopts;
  13137. var loop_count = gopts.loop === undefined ? null : gopts.loop;
  13138. var global_palette = gopts.palette === undefined ? null : gopts.palette;
  13139. if (width <= 0 || height <= 0 || width > 65535 || height > 65535) throw "Width/Height invalid.";
  13140. function check_palette_and_num_colors(palette) {
  13141. var num_colors = palette.length;
  13142. 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.";
  13143. return num_colors;
  13144. } // - Header.
  13145. buf[p++] = 0x47;
  13146. buf[p++] = 0x49;
  13147. buf[p++] = 0x46; // GIF
  13148. buf[p++] = 0x38;
  13149. buf[p++] = 0x39;
  13150. buf[p++] = 0x61; // 89a
  13151. // Handling of Global Color Table (palette) and background index.
  13152. var gp_num_colors_pow2 = 0;
  13153. var background = 0;
  13154. if (global_palette !== null) {
  13155. var gp_num_colors = check_palette_and_num_colors(global_palette);
  13156. while (gp_num_colors >>= 1) ++gp_num_colors_pow2;
  13157. gp_num_colors = 1 << gp_num_colors_pow2;
  13158. --gp_num_colors_pow2;
  13159. if (gopts.background !== undefined) {
  13160. background = gopts.background;
  13161. 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
  13162. // this is probably a mistake and you really want to set it to another
  13163. // slot in the palette. But actually in the end most browsers, etc end
  13164. // up ignoring this almost completely (including for dispose background).
  13165. if (background === 0) throw "Background index explicitly passed as 0.";
  13166. }
  13167. } // - Logical Screen Descriptor.
  13168. // NOTE(deanm): w/h apparently ignored by implementations, but set anyway.
  13169. buf[p++] = width & 0xff;
  13170. buf[p++] = width >> 8 & 0xff;
  13171. buf[p++] = height & 0xff;
  13172. buf[p++] = height >> 8 & 0xff; // NOTE: Indicates 0-bpp original color resolution (unused?).
  13173. buf[p++] = (global_palette !== null ? 0x80 : 0) | // Global Color Table Flag.
  13174. gp_num_colors_pow2; // NOTE: No sort flag (unused?).
  13175. buf[p++] = background; // Background Color Index.
  13176. buf[p++] = 0; // Pixel aspect ratio (unused?).
  13177. // - Global Color Table
  13178. if (global_palette !== null) {
  13179. for (var i = 0, il = global_palette.length; i < il; ++i) {
  13180. var rgb = global_palette[i];
  13181. buf[p++] = rgb >> 16 & 0xff;
  13182. buf[p++] = rgb >> 8 & 0xff;
  13183. buf[p++] = rgb & 0xff;
  13184. }
  13185. }
  13186. if (loop_count !== null) {
  13187. // Netscape block for looping.
  13188. if (loop_count < 0 || loop_count > 65535) throw "Loop count invalid."; // Extension code, label, and length.
  13189. buf[p++] = 0x21;
  13190. buf[p++] = 0xff;
  13191. buf[p++] = 0x0b; // NETSCAPE2.0
  13192. buf[p++] = 0x4e;
  13193. buf[p++] = 0x45;
  13194. buf[p++] = 0x54;
  13195. buf[p++] = 0x53;
  13196. buf[p++] = 0x43;
  13197. buf[p++] = 0x41;
  13198. buf[p++] = 0x50;
  13199. buf[p++] = 0x45;
  13200. buf[p++] = 0x32;
  13201. buf[p++] = 0x2e;
  13202. buf[p++] = 0x30; // Sub-block
  13203. buf[p++] = 0x03;
  13204. buf[p++] = 0x01;
  13205. buf[p++] = loop_count & 0xff;
  13206. buf[p++] = loop_count >> 8 & 0xff;
  13207. buf[p++] = 0x00; // Terminator.
  13208. }
  13209. var ended = false;
  13210. this.addFrame = function (x, y, w, h, indexed_pixels, opts) {
  13211. if (ended === true) {
  13212. --p;
  13213. ended = false;
  13214. } // Un-end.
  13215. opts = opts === undefined ? {} : opts; // TODO(deanm): Bounds check x, y. Do they need to be within the virtual
  13216. // canvas width/height, I imagine?
  13217. if (x < 0 || y < 0 || x > 65535 || y > 65535) throw "x/y invalid.";
  13218. if (w <= 0 || h <= 0 || w > 65535 || h > 65535) throw "Width/Height invalid.";
  13219. if (indexed_pixels.length < w * h) throw "Not enough pixels for the frame size.";
  13220. var using_local_palette = true;
  13221. var palette = opts.palette;
  13222. if (palette === undefined || palette === null) {
  13223. using_local_palette = false;
  13224. palette = global_palette;
  13225. }
  13226. if (palette === undefined || palette === null) throw "Must supply either a local or global palette.";
  13227. var num_colors = check_palette_and_num_colors(palette); // Compute the min_code_size (power of 2), destroying num_colors.
  13228. var min_code_size = 0;
  13229. while (num_colors >>= 1) ++min_code_size;
  13230. num_colors = 1 << min_code_size; // Now we can easily get it back.
  13231. var delay = opts.delay === undefined ? 0 : opts.delay; // From the spec:
  13232. // 0 - No disposal specified. The decoder is
  13233. // not required to take any action.
  13234. // 1 - Do not dispose. The graphic is to be left
  13235. // in place.
  13236. // 2 - Restore to background color. The area used by the
  13237. // graphic must be restored to the background color.
  13238. // 3 - Restore to previous. The decoder is required to
  13239. // restore the area overwritten by the graphic with
  13240. // what was there prior to rendering the graphic.
  13241. // 4-7 - To be defined.
  13242. // NOTE(deanm): Dispose background doesn't really work, apparently most
  13243. // browsers ignore the background palette index and clear to transparency.
  13244. var disposal = opts.disposal === undefined ? 0 : opts.disposal;
  13245. if (disposal < 0 || disposal > 3) // 4-7 is reserved.
  13246. throw "Disposal out of range.";
  13247. var use_transparency = false;
  13248. var transparent_index = 0;
  13249. if (opts.transparent !== undefined && opts.transparent !== null) {
  13250. use_transparency = true;
  13251. transparent_index = opts.transparent;
  13252. if (transparent_index < 0 || transparent_index >= num_colors) throw "Transparent color index.";
  13253. }
  13254. if (disposal !== 0 || use_transparency || delay !== 0) {
  13255. // - Graphics Control Extension
  13256. buf[p++] = 0x21;
  13257. buf[p++] = 0xf9; // Extension / Label.
  13258. buf[p++] = 4; // Byte size.
  13259. buf[p++] = disposal << 2 | (use_transparency === true ? 1 : 0);
  13260. buf[p++] = delay & 0xff;
  13261. buf[p++] = delay >> 8 & 0xff;
  13262. buf[p++] = transparent_index; // Transparent color index.
  13263. buf[p++] = 0; // Block Terminator.
  13264. } // - Image Descriptor
  13265. buf[p++] = 0x2c; // Image Seperator.
  13266. buf[p++] = x & 0xff;
  13267. buf[p++] = x >> 8 & 0xff; // Left.
  13268. buf[p++] = y & 0xff;
  13269. buf[p++] = y >> 8 & 0xff; // Top.
  13270. buf[p++] = w & 0xff;
  13271. buf[p++] = w >> 8 & 0xff;
  13272. buf[p++] = h & 0xff;
  13273. buf[p++] = h >> 8 & 0xff; // NOTE: No sort flag (unused?).
  13274. // TODO(deanm): Support interlace.
  13275. buf[p++] = using_local_palette === true ? 0x80 | min_code_size - 1 : 0; // - Local Color Table
  13276. if (using_local_palette === true) {
  13277. for (var i = 0, il = palette.length; i < il; ++i) {
  13278. var rgb = palette[i];
  13279. buf[p++] = rgb >> 16 & 0xff;
  13280. buf[p++] = rgb >> 8 & 0xff;
  13281. buf[p++] = rgb & 0xff;
  13282. }
  13283. }
  13284. p = GifWriterOutputLZWCodeStream(buf, p, min_code_size < 2 ? 2 : min_code_size, indexed_pixels);
  13285. };
  13286. this.end = function () {
  13287. if (ended === false) {
  13288. buf[p++] = 0x3b; // Trailer.
  13289. ended = true;
  13290. }
  13291. return p;
  13292. };
  13293. } // Main compression routine, palette indexes -> LZW code stream.
  13294. // |index_stream| must have at least one entry.
  13295. function GifWriterOutputLZWCodeStream(buf, p, min_code_size, index_stream) {
  13296. buf[p++] = min_code_size;
  13297. var cur_subblock = p++; // Pointing at the length field.
  13298. var clear_code = 1 << min_code_size;
  13299. var code_mask = clear_code - 1;
  13300. var eoi_code = clear_code + 1;
  13301. var next_code = eoi_code + 1;
  13302. var cur_code_size = min_code_size + 1; // Number of bits per code.
  13303. var cur_shift = 0; // We have at most 12-bit codes, so we should have to hold a max of 19
  13304. // bits here (and then we would write out).
  13305. var cur = 0;
  13306. function emit_bytes_to_buffer(bit_block_size) {
  13307. while (cur_shift >= bit_block_size) {
  13308. buf[p++] = cur & 0xff;
  13309. cur >>= 8;
  13310. cur_shift -= 8;
  13311. if (p === cur_subblock + 256) {
  13312. // Finished a subblock.
  13313. buf[cur_subblock] = 255;
  13314. cur_subblock = p++;
  13315. }
  13316. }
  13317. }
  13318. function emit_code(c) {
  13319. cur |= c << cur_shift;
  13320. cur_shift += cur_code_size;
  13321. emit_bytes_to_buffer(8);
  13322. } // I am not an expert on the topic, and I don't want to write a thesis.
  13323. // However, it is good to outline here the basic algorithm and the few data
  13324. // structures and optimizations here that make this implementation fast.
  13325. // The basic idea behind LZW is to build a table of previously seen runs
  13326. // addressed by a short id (herein called output code). All data is
  13327. // referenced by a code, which represents one or more values from the
  13328. // original input stream. All input bytes can be referenced as the same
  13329. // value as an output code. So if you didn't want any compression, you
  13330. // could more or less just output the original bytes as codes (there are
  13331. // some details to this, but it is the idea). In order to achieve
  13332. // compression, values greater then the input range (codes can be up to
  13333. // 12-bit while input only 8-bit) represent a sequence of previously seen
  13334. // inputs. The decompressor is able to build the same mapping while
  13335. // decoding, so there is always a shared common knowledge between the
  13336. // encoding and decoder, which is also important for "timing" aspects like
  13337. // how to handle variable bit width code encoding.
  13338. //
  13339. // One obvious but very important consequence of the table system is there
  13340. // is always a unique id (at most 12-bits) to map the runs. 'A' might be
  13341. // 4, then 'AA' might be 10, 'AAA' 11, 'AAAA' 12, etc. This relationship
  13342. // can be used for an effecient lookup strategy for the code mapping. We
  13343. // need to know if a run has been seen before, and be able to map that run
  13344. // to the output code. Since we start with known unique ids (input bytes),
  13345. // and then from those build more unique ids (table entries), we can
  13346. // continue this chain (almost like a linked list) to always have small
  13347. // integer values that represent the current byte chains in the encoder.
  13348. // This means instead of tracking the input bytes (AAAABCD) to know our
  13349. // current state, we can track the table entry for AAAABC (it is guaranteed
  13350. // to exist by the nature of the algorithm) and the next character D.
  13351. // Therefor the tuple of (table_entry, byte) is guaranteed to also be
  13352. // unique. This allows us to create a simple lookup key for mapping input
  13353. // sequences to codes (table indices) without having to store or search
  13354. // any of the code sequences. So if 'AAAA' has a table entry of 12, the
  13355. // tuple of ('AAAA', K) for any input byte K will be unique, and can be our
  13356. // key. This leads to a integer value at most 20-bits, which can always
  13357. // fit in an SMI value and be used as a fast sparse array / object key.
  13358. // Output code for the current contents of the index buffer.
  13359. var ib_code = index_stream[0] & code_mask; // Load first input index.
  13360. var code_table = {}; // Key'd on our 20-bit "tuple".
  13361. emit_code(clear_code); // Spec says first code should be a clear code.
  13362. // First index already loaded, process the rest of the stream.
  13363. for (var i = 1, il = index_stream.length; i < il; ++i) {
  13364. var k = index_stream[i] & code_mask;
  13365. var cur_key = ib_code << 8 | k; // (prev, k) unique tuple.
  13366. var cur_code = code_table[cur_key]; // buffer + k.
  13367. // Check if we have to create a new code table entry.
  13368. if (cur_code === undefined) {
  13369. // We don't have buffer + k.
  13370. // Emit index buffer (without k).
  13371. // This is an inline version of emit_code, because this is the core
  13372. // writing routine of the compressor (and V8 cannot inline emit_code
  13373. // because it is a closure here in a different context). Additionally
  13374. // we can call emit_byte_to_buffer less often, because we can have
  13375. // 30-bits (from our 31-bit signed SMI), and we know our codes will only
  13376. // be 12-bits, so can safely have 18-bits there without overflow.
  13377. // emit_code(ib_code);
  13378. cur |= ib_code << cur_shift;
  13379. cur_shift += cur_code_size;
  13380. while (cur_shift >= 8) {
  13381. buf[p++] = cur & 0xff;
  13382. cur >>= 8;
  13383. cur_shift -= 8;
  13384. if (p === cur_subblock + 256) {
  13385. // Finished a subblock.
  13386. buf[cur_subblock] = 255;
  13387. cur_subblock = p++;
  13388. }
  13389. }
  13390. if (next_code === 4096) {
  13391. // Table full, need a clear.
  13392. emit_code(clear_code);
  13393. next_code = eoi_code + 1;
  13394. cur_code_size = min_code_size + 1;
  13395. code_table = {};
  13396. } else {
  13397. // Table not full, insert a new entry.
  13398. // Increase our variable bit code sizes if necessary. This is a bit
  13399. // tricky as it is based on "timing" between the encoding and
  13400. // decoder. From the encoders perspective this should happen after
  13401. // we've already emitted the index buffer and are about to create the
  13402. // first table entry that would overflow our current code bit size.
  13403. if (next_code >= 1 << cur_code_size) ++cur_code_size;
  13404. code_table[cur_key] = next_code++; // Insert into code table.
  13405. }
  13406. ib_code = k; // Index buffer to single input k.
  13407. } else {
  13408. ib_code = cur_code; // Index buffer to sequence in code table.
  13409. }
  13410. }
  13411. emit_code(ib_code); // There will still be something in the index buffer.
  13412. emit_code(eoi_code); // End Of Information.
  13413. // Flush / finalize the sub-blocks stream to the buffer.
  13414. emit_bytes_to_buffer(1); // Finish the sub-blocks, writing out any unfinished lengths and
  13415. // terminating with a sub-block of length 0. If we have already started
  13416. // but not yet used a sub-block it can just become the terminator.
  13417. if (cur_subblock + 1 === p) {
  13418. // Started but unused.
  13419. buf[cur_subblock] = 0;
  13420. } else {
  13421. // Started and used, write length and additional terminator block.
  13422. buf[cur_subblock] = p - cur_subblock - 1;
  13423. buf[p++] = 0;
  13424. }
  13425. return p;
  13426. }
  13427. function GifReader(buf) {
  13428. var p = 0; // - Header (GIF87a or GIF89a).
  13429. if (buf[p++] !== 0x47 || buf[p++] !== 0x49 || buf[p++] !== 0x46 || buf[p++] !== 0x38 || (buf[p++] + 1 & 0xfd) !== 0x38 || buf[p++] !== 0x61) {
  13430. throw "Invalid GIF 87a/89a header.";
  13431. } // - Logical Screen Descriptor.
  13432. var width = buf[p++] | buf[p++] << 8;
  13433. var height = buf[p++] | buf[p++] << 8;
  13434. var pf0 = buf[p++]; // <Packed Fields>.
  13435. var global_palette_flag = pf0 >> 7;
  13436. var num_global_colors_pow2 = pf0 & 0x7;
  13437. var num_global_colors = 1 << num_global_colors_pow2 + 1;
  13438. var background = buf[p++];
  13439. buf[p++]; // Pixel aspect ratio (unused?).
  13440. var global_palette_offset = null;
  13441. if (global_palette_flag) {
  13442. global_palette_offset = p;
  13443. p += num_global_colors * 3; // Seek past palette.
  13444. }
  13445. var no_eof = true;
  13446. var frames = [];
  13447. var delay = 0;
  13448. var transparent_index = null;
  13449. var disposal = 0; // 0 - No disposal specified.
  13450. var loop_count = null;
  13451. this.width = width;
  13452. this.height = height;
  13453. while (no_eof && p < buf.length) {
  13454. switch (buf[p++]) {
  13455. case 0x21:
  13456. // Graphics Control Extension Block
  13457. switch (buf[p++]) {
  13458. case 0xff:
  13459. // Application specific block
  13460. // Try if it's a Netscape block (with animation loop counter).
  13461. if (buf[p] !== 0x0b || // 21 FF already read, check block size.
  13462. // NETSCAPE2.0
  13463. 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
  13464. buf[p + 12] == 0x03 && buf[p + 13] == 0x01 && buf[p + 16] == 0) {
  13465. p += 14;
  13466. loop_count = buf[p++] | buf[p++] << 8;
  13467. p++; // Skip terminator.
  13468. } else {
  13469. // We don't know what it is, just try to get past it.
  13470. p += 12;
  13471. while (true) {
  13472. // Seek through subblocks.
  13473. var block_size = buf[p++];
  13474. if (block_size === 0) break;
  13475. p += block_size;
  13476. }
  13477. }
  13478. break;
  13479. case 0xf9:
  13480. // Graphics Control Extension
  13481. if (buf[p++] !== 0x4 || buf[p + 4] !== 0) throw "Invalid graphics extension block.";
  13482. var pf1 = buf[p++];
  13483. delay = buf[p++] | buf[p++] << 8;
  13484. transparent_index = buf[p++];
  13485. if ((pf1 & 1) === 0) transparent_index = null;
  13486. disposal = pf1 >> 2 & 0x7;
  13487. p++; // Skip terminator.
  13488. break;
  13489. case 0xfe:
  13490. // Comment Extension.
  13491. while (true) {
  13492. // Seek through subblocks.
  13493. var block_size = buf[p++];
  13494. if (block_size === 0) break; // console.log(buf.slice(p, p+block_size).toString('ascii'));
  13495. p += block_size;
  13496. }
  13497. break;
  13498. default:
  13499. throw "Unknown graphic control label: 0x" + buf[p - 1].toString(16);
  13500. }
  13501. break;
  13502. case 0x2c:
  13503. // Image Descriptor.
  13504. var x = buf[p++] | buf[p++] << 8;
  13505. var y = buf[p++] | buf[p++] << 8;
  13506. var w = buf[p++] | buf[p++] << 8;
  13507. var h = buf[p++] | buf[p++] << 8;
  13508. var pf2 = buf[p++];
  13509. var local_palette_flag = pf2 >> 7;
  13510. var interlace_flag = pf2 >> 6 & 1;
  13511. var num_local_colors_pow2 = pf2 & 0x7;
  13512. var num_local_colors = 1 << num_local_colors_pow2 + 1;
  13513. var palette_offset = global_palette_offset;
  13514. var has_local_palette = false;
  13515. if (local_palette_flag) {
  13516. var has_local_palette = true;
  13517. palette_offset = p; // Override with local palette.
  13518. p += num_local_colors * 3; // Seek past palette.
  13519. }
  13520. var data_offset = p;
  13521. p++; // codesize
  13522. while (true) {
  13523. var block_size = buf[p++];
  13524. if (block_size === 0) break;
  13525. p += block_size;
  13526. }
  13527. frames.push({
  13528. x: x,
  13529. y: y,
  13530. width: w,
  13531. height: h,
  13532. has_local_palette: has_local_palette,
  13533. palette_offset: palette_offset,
  13534. data_offset: data_offset,
  13535. data_length: p - data_offset,
  13536. transparent_index: transparent_index,
  13537. interlaced: !!interlace_flag,
  13538. delay: delay,
  13539. disposal: disposal
  13540. });
  13541. break;
  13542. case 0x3b:
  13543. // Trailer Marker (end of file).
  13544. no_eof = false;
  13545. break;
  13546. default:
  13547. throw "Unknown gif block: 0x" + buf[p - 1].toString(16);
  13548. break;
  13549. }
  13550. }
  13551. this.numFrames = function () {
  13552. return frames.length;
  13553. };
  13554. this.loopCount = function () {
  13555. return loop_count;
  13556. };
  13557. this.frameInfo = function (frame_num) {
  13558. if (frame_num < 0 || frame_num >= frames.length) throw "Frame index out of range.";
  13559. return frames[frame_num];
  13560. };
  13561. this.decodeAndBlitFrameBGRA = function (frame_num, pixels) {
  13562. var frame = this.frameInfo(frame_num);
  13563. var num_pixels = frame.width * frame.height;
  13564. var index_stream = new Uint8Array(num_pixels); // At most 8-bit indices.
  13565. GifReaderLZWOutputIndexStream(buf, frame.data_offset, index_stream, num_pixels);
  13566. var palette_offset = frame.palette_offset; // NOTE(deanm): It seems to be much faster to compare index to 256 than
  13567. // to === null. Not sure why, but CompareStub_EQ_STRICT shows up high in
  13568. // the profile, not sure if it's related to using a Uint8Array.
  13569. var trans = frame.transparent_index;
  13570. if (trans === null) trans = 256; // We are possibly just blitting to a portion of the entire frame.
  13571. // That is a subrect within the framerect, so the additional pixels
  13572. // must be skipped over after we finished a scanline.
  13573. var framewidth = frame.width;
  13574. var framestride = width - framewidth;
  13575. var xleft = framewidth; // Number of subrect pixels left in scanline.
  13576. // Output indicies of the top left and bottom right corners of the subrect.
  13577. var opbeg = (frame.y * width + frame.x) * 4;
  13578. var opend = ((frame.y + frame.height) * width + frame.x) * 4;
  13579. var op = opbeg;
  13580. var scanstride = framestride * 4; // Use scanstride to skip past the rows when interlacing. This is skipping
  13581. // 7 rows for the first two passes, then 3 then 1.
  13582. if (frame.interlaced === true) {
  13583. scanstride += (framewidth + framestride) * 4 * 7; // Pass 1.
  13584. }
  13585. var interlaceskip = 8; // Tracking the row interval in the current pass.
  13586. for (var i = 0, il = index_stream.length; i < il; ++i) {
  13587. var index = index_stream[i];
  13588. if (xleft === 0) {
  13589. // Beginning of new scan line
  13590. op += scanstride;
  13591. xleft = framewidth;
  13592. if (op >= opend) {
  13593. // Catch the wrap to switch passes when interlacing.
  13594. scanstride = framestride + (framewidth + framestride) * 4 * (interlaceskip - 1); // interlaceskip / 2 * 4 is interlaceskip << 1.
  13595. op = opbeg + (framewidth + framestride) * (interlaceskip << 1);
  13596. interlaceskip >>= 1;
  13597. }
  13598. }
  13599. if (index === trans) {
  13600. op += 4;
  13601. } else {
  13602. var r = buf[palette_offset + index * 3];
  13603. var g = buf[palette_offset + index * 3 + 1];
  13604. var b = buf[palette_offset + index * 3 + 2];
  13605. pixels[op++] = b;
  13606. pixels[op++] = g;
  13607. pixels[op++] = r;
  13608. pixels[op++] = 255;
  13609. }
  13610. --xleft;
  13611. }
  13612. }; // I will go to copy and paste hell one day...
  13613. this.decodeAndBlitFrameRGBA = function (frame_num, pixels) {
  13614. var frame = this.frameInfo(frame_num);
  13615. var num_pixels = frame.width * frame.height;
  13616. var index_stream = new Uint8Array(num_pixels); // At most 8-bit indices.
  13617. GifReaderLZWOutputIndexStream(buf, frame.data_offset, index_stream, num_pixels);
  13618. var palette_offset = frame.palette_offset; // NOTE(deanm): It seems to be much faster to compare index to 256 than
  13619. // to === null. Not sure why, but CompareStub_EQ_STRICT shows up high in
  13620. // the profile, not sure if it's related to using a Uint8Array.
  13621. var trans = frame.transparent_index;
  13622. if (trans === null) trans = 256; // We are possibly just blitting to a portion of the entire frame.
  13623. // That is a subrect within the framerect, so the additional pixels
  13624. // must be skipped over after we finished a scanline.
  13625. var framewidth = frame.width;
  13626. var framestride = width - framewidth;
  13627. var xleft = framewidth; // Number of subrect pixels left in scanline.
  13628. // Output indicies of the top left and bottom right corners of the subrect.
  13629. var opbeg = (frame.y * width + frame.x) * 4;
  13630. var opend = ((frame.y + frame.height) * width + frame.x) * 4;
  13631. var op = opbeg;
  13632. var scanstride = framestride * 4; // Use scanstride to skip past the rows when interlacing. This is skipping
  13633. // 7 rows for the first two passes, then 3 then 1.
  13634. if (frame.interlaced === true) {
  13635. scanstride += (framewidth + framestride) * 4 * 7; // Pass 1.
  13636. }
  13637. var interlaceskip = 8; // Tracking the row interval in the current pass.
  13638. for (var i = 0, il = index_stream.length; i < il; ++i) {
  13639. var index = index_stream[i];
  13640. if (xleft === 0) {
  13641. // Beginning of new scan line
  13642. op += scanstride;
  13643. xleft = framewidth;
  13644. if (op >= opend) {
  13645. // Catch the wrap to switch passes when interlacing.
  13646. scanstride = framestride + (framewidth + framestride) * 4 * (interlaceskip - 1); // interlaceskip / 2 * 4 is interlaceskip << 1.
  13647. op = opbeg + (framewidth + framestride) * (interlaceskip << 1);
  13648. interlaceskip >>= 1;
  13649. }
  13650. }
  13651. if (index === trans) {
  13652. op += 4;
  13653. } else {
  13654. var r = buf[palette_offset + index * 3];
  13655. var g = buf[palette_offset + index * 3 + 1];
  13656. var b = buf[palette_offset + index * 3 + 2];
  13657. pixels[op++] = r;
  13658. pixels[op++] = g;
  13659. pixels[op++] = b;
  13660. pixels[op++] = 255;
  13661. }
  13662. --xleft;
  13663. }
  13664. };
  13665. }
  13666. function GifReaderLZWOutputIndexStream(code_stream, p, output, output_length) {
  13667. var min_code_size = code_stream[p++];
  13668. var clear_code = 1 << min_code_size;
  13669. var eoi_code = clear_code + 1;
  13670. var next_code = eoi_code + 1;
  13671. var cur_code_size = min_code_size + 1; // Number of bits per code.
  13672. // NOTE: This shares the same name as the encoder, but has a different
  13673. // meaning here. Here this masks each code coming from the code stream.
  13674. var code_mask = (1 << cur_code_size) - 1;
  13675. var cur_shift = 0;
  13676. var cur = 0;
  13677. var op = 0; // Output pointer.
  13678. var subblock_size = code_stream[p++]; // TODO(deanm): Would using a TypedArray be any faster? At least it would
  13679. // solve the fast mode / backing store uncertainty.
  13680. // var code_table = Array(4096);
  13681. var code_table = new Int32Array(4096); // Can be signed, we only use 20 bits.
  13682. var prev_code = null; // Track code-1.
  13683. while (true) {
  13684. // Read up to two bytes, making sure we always 12-bits for max sized code.
  13685. while (cur_shift < 16) {
  13686. if (subblock_size === 0) break; // No more data to be read.
  13687. cur |= code_stream[p++] << cur_shift;
  13688. cur_shift += 8;
  13689. if (subblock_size === 1) {
  13690. // Never let it get to 0 to hold logic above.
  13691. subblock_size = code_stream[p++]; // Next subblock.
  13692. } else {
  13693. --subblock_size;
  13694. }
  13695. } // TODO(deanm): We should never really get here, we should have received
  13696. // and EOI.
  13697. if (cur_shift < cur_code_size) break;
  13698. var code = cur & code_mask;
  13699. cur >>= cur_code_size;
  13700. cur_shift -= cur_code_size; // TODO(deanm): Maybe should check that the first code was a clear code,
  13701. // at least this is what you're supposed to do. But actually our encoder
  13702. // now doesn't emit a clear code first anyway.
  13703. if (code === clear_code) {
  13704. // We don't actually have to clear the table. This could be a good idea
  13705. // for greater error checking, but we don't really do any anyway. We
  13706. // will just track it with next_code and overwrite old entries.
  13707. next_code = eoi_code + 1;
  13708. cur_code_size = min_code_size + 1;
  13709. code_mask = (1 << cur_code_size) - 1; // Don't update prev_code ?
  13710. prev_code = null;
  13711. continue;
  13712. } else if (code === eoi_code) {
  13713. break;
  13714. } // We have a similar situation as the decoder, where we want to store
  13715. // variable length entries (code table entries), but we want to do in a
  13716. // faster manner than an array of arrays. The code below stores sort of a
  13717. // linked list within the code table, and then "chases" through it to
  13718. // construct the dictionary entries. When a new entry is created, just the
  13719. // last byte is stored, and the rest (prefix) of the entry is only
  13720. // referenced by its table entry. Then the code chases through the
  13721. // prefixes until it reaches a single byte code. We have to chase twice,
  13722. // first to compute the length, and then to actually copy the data to the
  13723. // output (backwards, since we know the length). The alternative would be
  13724. // storing something in an intermediate stack, but that doesn't make any
  13725. // more sense. I implemented an approach where it also stored the length
  13726. // in the code table, although it's a bit tricky because you run out of
  13727. // bits (12 + 12 + 8), but I didn't measure much improvements (the table
  13728. // entries are generally not the long). Even when I created benchmarks for
  13729. // very long table entries the complexity did not seem worth it.
  13730. // The code table stores the prefix entry in 12 bits and then the suffix
  13731. // byte in 8 bits, so each entry is 20 bits.
  13732. var chase_code = code < next_code ? code : prev_code; // Chase what we will output, either {CODE} or {CODE-1}.
  13733. var chase_length = 0;
  13734. var chase = chase_code;
  13735. while (chase > clear_code) {
  13736. chase = code_table[chase] >> 8;
  13737. ++chase_length;
  13738. }
  13739. var k = chase;
  13740. var op_end = op + chase_length + (chase_code !== code ? 1 : 0);
  13741. if (op_end > output_length) {
  13742. console.log("Warning, gif stream longer than expected.");
  13743. return;
  13744. } // Already have the first byte from the chase, might as well write it fast.
  13745. output[op++] = k;
  13746. op += chase_length;
  13747. var b = op; // Track pointer, writing backwards.
  13748. if (chase_code !== code) // The case of emitting {CODE-1} + k.
  13749. output[op++] = k;
  13750. chase = chase_code;
  13751. while (chase_length--) {
  13752. chase = code_table[chase];
  13753. output[--b] = chase & 0xff; // Write backwards.
  13754. chase >>= 8; // Pull down to the prefix code.
  13755. }
  13756. if (prev_code !== null && next_code < 4096) {
  13757. code_table[next_code++] = prev_code << 8 | k; // TODO(deanm): Figure out this clearing vs code growth logic better. I
  13758. // have an feeling that it should just happen somewhere else, for now it
  13759. // is awkward between when we grow past the max and then hit a clear code.
  13760. // For now just check if we hit the max 12-bits (then a clear code should
  13761. // follow, also of course encoded in 12-bits).
  13762. if (next_code >= code_mask + 1 && cur_code_size < 12) {
  13763. ++cur_code_size;
  13764. code_mask = code_mask << 1 | 1;
  13765. }
  13766. }
  13767. prev_code = code;
  13768. }
  13769. if (op !== output_length) {
  13770. console.log("Warning, gif stream shorter than expected.");
  13771. }
  13772. return output;
  13773. }
  13774. try {
  13775. } catch (e) {} // CommonJS.
  13776. /*
  13777. * Copyright (c) 2012 chick307 <chick307@gmail.com>
  13778. *
  13779. * Licensed under the MIT License.
  13780. * http://opensource.org/licenses/mit-license
  13781. */
  13782. (function (jsPDF, callback) {
  13783. jsPDF.API.adler32cs = callback();
  13784. })(jsPDF, function () {
  13785. var _hasArrayBuffer = typeof ArrayBuffer === "function" && typeof Uint8Array === "function";
  13786. var _Buffer = null,
  13787. _isBuffer = function () {
  13788. if (!_hasArrayBuffer) return function _isBuffer() {
  13789. return false;
  13790. };
  13791. return function _isBuffer(value) {
  13792. return value instanceof ArrayBuffer || _Buffer !== null && value instanceof _Buffer;
  13793. };
  13794. }();
  13795. var _utf8ToBinary = function () {
  13796. if (_Buffer !== null) {
  13797. return function _utf8ToBinary(utf8String) {
  13798. return new _Buffer(utf8String, "utf8").toString("binary");
  13799. };
  13800. } else {
  13801. return function _utf8ToBinary(utf8String) {
  13802. return unescape(encodeURIComponent(utf8String));
  13803. };
  13804. }
  13805. }();
  13806. var MOD = 65521;
  13807. var _update = function _update(checksum, binaryString) {
  13808. var a = checksum & 0xffff,
  13809. b = checksum >>> 16;
  13810. for (var i = 0, length = binaryString.length; i < length; i++) {
  13811. a = (a + (binaryString.charCodeAt(i) & 0xff)) % MOD;
  13812. b = (b + a) % MOD;
  13813. }
  13814. return (b << 16 | a) >>> 0;
  13815. };
  13816. var _updateUint8Array = function _updateUint8Array(checksum, uint8Array) {
  13817. var a = checksum & 0xffff,
  13818. b = checksum >>> 16;
  13819. for (var i = 0, length = uint8Array.length; i < length; i++) {
  13820. a = (a + uint8Array[i]) % MOD;
  13821. b = (b + a) % MOD;
  13822. }
  13823. return (b << 16 | a) >>> 0;
  13824. };
  13825. var exports = {};
  13826. var Adler32 = exports.Adler32 = function () {
  13827. var ctor = function Adler32(checksum) {
  13828. if (!(this instanceof ctor)) {
  13829. throw new TypeError("Constructor cannot called be as a function.");
  13830. }
  13831. if (!isFinite(checksum = checksum == null ? 1 : +checksum)) {
  13832. throw new Error("First arguments needs to be a finite number.");
  13833. }
  13834. this.checksum = checksum >>> 0;
  13835. };
  13836. var proto = ctor.prototype = {};
  13837. proto.constructor = ctor;
  13838. ctor.from = function (from) {
  13839. from.prototype = proto;
  13840. return from;
  13841. }(function from(binaryString) {
  13842. if (!(this instanceof ctor)) {
  13843. throw new TypeError("Constructor cannot called be as a function.");
  13844. }
  13845. if (binaryString == null) throw new Error("First argument needs to be a string.");
  13846. this.checksum = _update(1, binaryString.toString());
  13847. });
  13848. ctor.fromUtf8 = function (fromUtf8) {
  13849. fromUtf8.prototype = proto;
  13850. return fromUtf8;
  13851. }(function fromUtf8(utf8String) {
  13852. if (!(this instanceof ctor)) {
  13853. throw new TypeError("Constructor cannot called be as a function.");
  13854. }
  13855. if (utf8String == null) throw new Error("First argument needs to be a string.");
  13856. var binaryString = _utf8ToBinary(utf8String.toString());
  13857. this.checksum = _update(1, binaryString);
  13858. });
  13859. if (_hasArrayBuffer) {
  13860. ctor.fromBuffer = function (fromBuffer) {
  13861. fromBuffer.prototype = proto;
  13862. return fromBuffer;
  13863. }(function fromBuffer(buffer) {
  13864. if (!(this instanceof ctor)) {
  13865. throw new TypeError("Constructor cannot called be as a function.");
  13866. }
  13867. if (!_isBuffer(buffer)) throw new Error("First argument needs to be ArrayBuffer.");
  13868. var array = new Uint8Array(buffer);
  13869. return this.checksum = _updateUint8Array(1, array);
  13870. });
  13871. }
  13872. proto.update = function update(binaryString) {
  13873. if (binaryString == null) throw new Error("First argument needs to be a string.");
  13874. binaryString = binaryString.toString();
  13875. return this.checksum = _update(this.checksum, binaryString);
  13876. };
  13877. proto.updateUtf8 = function updateUtf8(utf8String) {
  13878. if (utf8String == null) throw new Error("First argument needs to be a string.");
  13879. var binaryString = _utf8ToBinary(utf8String.toString());
  13880. return this.checksum = _update(this.checksum, binaryString);
  13881. };
  13882. if (_hasArrayBuffer) {
  13883. proto.updateBuffer = function updateBuffer(buffer) {
  13884. if (!_isBuffer(buffer)) throw new Error("First argument needs to be ArrayBuffer.");
  13885. var array = new Uint8Array(buffer);
  13886. return this.checksum = _updateUint8Array(this.checksum, array);
  13887. };
  13888. }
  13889. proto.clone = function clone() {
  13890. return new Adler32(this.checksum);
  13891. };
  13892. return ctor;
  13893. }();
  13894. exports.from = function from(binaryString) {
  13895. if (binaryString == null) throw new Error("First argument needs to be a string.");
  13896. return _update(1, binaryString.toString());
  13897. };
  13898. exports.fromUtf8 = function fromUtf8(utf8String) {
  13899. if (utf8String == null) throw new Error("First argument needs to be a string.");
  13900. var binaryString = _utf8ToBinary(utf8String.toString());
  13901. return _update(1, binaryString);
  13902. };
  13903. if (_hasArrayBuffer) {
  13904. exports.fromBuffer = function fromBuffer(buffer) {
  13905. if (!_isBuffer(buffer)) throw new Error("First argument need to be ArrayBuffer.");
  13906. var array = new Uint8Array(buffer);
  13907. return _updateUint8Array(1, array);
  13908. };
  13909. }
  13910. return exports;
  13911. });
  13912. /*
  13913. Copyright (c) 2008, Adobe Systems Incorporated
  13914. All rights reserved.
  13915. Redistribution and use in source and binary forms, with or without
  13916. modification, are permitted provided that the following conditions are
  13917. met:
  13918. * Redistributions of source code must retain the above copyright notice,
  13919. this list of conditions and the following disclaimer.
  13920. * Redistributions in binary form must reproduce the above copyright
  13921. notice, this list of conditions and the following disclaimer in the
  13922. documentation and/or other materials provided with the distribution.
  13923. * Neither the name of Adobe Systems Incorporated nor the names of its
  13924. contributors may be used to endorse or promote products derived from
  13925. this software without specific prior written permission.
  13926. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  13927. IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  13928. THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  13929. PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  13930. CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  13931. EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  13932. PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  13933. PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  13934. LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  13935. NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  13936. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  13937. */
  13938. /**
  13939. * @author shaozilee
  13940. *
  13941. * Bmp format decoder,support 1bit 4bit 8bit 24bit bmp
  13942. *
  13943. */
  13944. /*
  13945. Copyright (c) 2013 Gildas Lormeau. All rights reserved.
  13946. Redistribution and use in source and binary forms, with or without
  13947. modification, are permitted provided that the following conditions are met:
  13948. 1. Redistributions of source code must retain the above copyright notice,
  13949. this list of conditions and the following disclaimer.
  13950. 2. Redistributions in binary form must reproduce the above copyright
  13951. notice, this list of conditions and the following disclaimer in
  13952. the documentation and/or other materials provided with the distribution.
  13953. 3. The names of the authors may not be used to endorse or promote products
  13954. derived from this software without specific prior written permission.
  13955. THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
  13956. INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  13957. FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
  13958. INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
  13959. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  13960. LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
  13961. OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  13962. LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  13963. NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  13964. EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  13965. */
  13966. /*
  13967. * This program is based on JZlib 1.0.2 ymnk, JCraft,Inc.
  13968. * JZlib is based on zlib-1.1.3, so all credit should go authors
  13969. * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
  13970. * and contributors of zlib.
  13971. */
  13972. (function (global) {
  13973. var MAX_BITS = 15;
  13974. var D_CODES = 30;
  13975. var BL_CODES = 19;
  13976. var LENGTH_CODES = 29;
  13977. var LITERALS = 256;
  13978. var L_CODES = LITERALS + 1 + LENGTH_CODES;
  13979. var HEAP_SIZE = 2 * L_CODES + 1;
  13980. var END_BLOCK = 256; // Bit length codes must not exceed MAX_BL_BITS bits
  13981. var MAX_BL_BITS = 7; // repeat previous bit length 3-6 times (2 bits of repeat count)
  13982. var REP_3_6 = 16; // repeat a zero length 3-10 times (3 bits of repeat count)
  13983. var REPZ_3_10 = 17; // repeat a zero length 11-138 times (7 bits of repeat count)
  13984. var REPZ_11_138 = 18; // The lengths of the bit length codes are sent in order of decreasing
  13985. // probability, to avoid transmitting the lengths for unused bit
  13986. // length codes.
  13987. var Buf_size = 8 * 2; // JZlib version : "1.0.2"
  13988. var Z_DEFAULT_COMPRESSION = -1; // compression strategy
  13989. var Z_FILTERED = 1;
  13990. var Z_HUFFMAN_ONLY = 2;
  13991. var Z_DEFAULT_STRATEGY = 0;
  13992. var Z_NO_FLUSH = 0;
  13993. var Z_PARTIAL_FLUSH = 1;
  13994. var Z_FULL_FLUSH = 3;
  13995. var Z_FINISH = 4;
  13996. var Z_OK = 0;
  13997. var Z_STREAM_END = 1;
  13998. var Z_NEED_DICT = 2;
  13999. var Z_STREAM_ERROR = -2;
  14000. var Z_DATA_ERROR = -3;
  14001. var Z_BUF_ERROR = -5; // Tree
  14002. // see definition of array dist_code below
  14003. 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];
  14004. function Tree() {
  14005. var that = this; // dyn_tree; // the dynamic tree
  14006. // max_code; // largest code with non zero frequency
  14007. // stat_desc; // the corresponding static tree
  14008. // Compute the optimal bit lengths for a tree and update the total bit
  14009. // length
  14010. // for the current block.
  14011. // IN assertion: the fields freq and dad are set, heap[heap_max] and
  14012. // above are the tree nodes sorted by increasing frequency.
  14013. // OUT assertions: the field len is set to the optimal bit length, the
  14014. // array bl_count contains the frequencies for each bit length.
  14015. // The length opt_len is updated; static_len is also updated if stree is
  14016. // not null.
  14017. function gen_bitlen(s) {
  14018. var tree = that.dyn_tree;
  14019. var stree = that.stat_desc.static_tree;
  14020. var extra = that.stat_desc.extra_bits;
  14021. var base = that.stat_desc.extra_base;
  14022. var max_length = that.stat_desc.max_length;
  14023. var h; // heap index
  14024. var n, m; // iterate over the tree elements
  14025. var bits; // bit length
  14026. var xbits; // extra bits
  14027. var f; // frequency
  14028. var overflow = 0; // number of elements with bit length too large
  14029. for (bits = 0; bits <= MAX_BITS; bits++) s.bl_count[bits] = 0; // In a first pass, compute the optimal bit lengths (which may
  14030. // overflow in the case of the bit length tree).
  14031. tree[s.heap[s.heap_max] * 2 + 1] = 0; // root of the heap
  14032. for (h = s.heap_max + 1; h < HEAP_SIZE; h++) {
  14033. n = s.heap[h];
  14034. bits = tree[tree[n * 2 + 1] * 2 + 1] + 1;
  14035. if (bits > max_length) {
  14036. bits = max_length;
  14037. overflow++;
  14038. }
  14039. tree[n * 2 + 1] = bits; // We overwrite tree[n*2+1] which is no longer needed
  14040. if (n > that.max_code) continue; // not a leaf node
  14041. s.bl_count[bits]++;
  14042. xbits = 0;
  14043. if (n >= base) xbits = extra[n - base];
  14044. f = tree[n * 2];
  14045. s.opt_len += f * (bits + xbits);
  14046. if (stree) s.static_len += f * (stree[n * 2 + 1] + xbits);
  14047. }
  14048. if (overflow === 0) return; // This happens for example on obj2 and pic of the Calgary corpus
  14049. // Find the first bit length which could increase:
  14050. do {
  14051. bits = max_length - 1;
  14052. while (s.bl_count[bits] === 0) bits--;
  14053. s.bl_count[bits]--; // move one leaf down the tree
  14054. s.bl_count[bits + 1] += 2; // move one overflow item as its brother
  14055. s.bl_count[max_length]--; // The brother of the overflow item also moves one step up,
  14056. // but this does not affect bl_count[max_length]
  14057. overflow -= 2;
  14058. } while (overflow > 0);
  14059. for (bits = max_length; bits !== 0; bits--) {
  14060. n = s.bl_count[bits];
  14061. while (n !== 0) {
  14062. m = s.heap[--h];
  14063. if (m > that.max_code) continue;
  14064. if (tree[m * 2 + 1] != bits) {
  14065. s.opt_len += (bits - tree[m * 2 + 1]) * tree[m * 2];
  14066. tree[m * 2 + 1] = bits;
  14067. }
  14068. n--;
  14069. }
  14070. }
  14071. } // Reverse the first len bits of a code, using straightforward code (a
  14072. // faster
  14073. // method would use a table)
  14074. // IN assertion: 1 <= len <= 15
  14075. function bi_reverse(code, // the value to invert
  14076. len // its bit length
  14077. ) {
  14078. var res = 0;
  14079. do {
  14080. res |= code & 1;
  14081. code >>>= 1;
  14082. res <<= 1;
  14083. } while (--len > 0);
  14084. return res >>> 1;
  14085. } // Generate the codes for a given tree and bit counts (which need not be
  14086. // optimal).
  14087. // IN assertion: the array bl_count contains the bit length statistics for
  14088. // the given tree and the field len is set for all tree elements.
  14089. // OUT assertion: the field code is set for all tree elements of non
  14090. // zero code length.
  14091. function gen_codes(tree, // the tree to decorate
  14092. max_code, // largest code with non zero frequency
  14093. bl_count // number of codes at each bit length
  14094. ) {
  14095. var next_code = []; // next code value for each
  14096. // bit length
  14097. var code = 0; // running code value
  14098. var bits; // bit index
  14099. var n; // code index
  14100. var len; // The distribution counts are first used to generate the code values
  14101. // without bit reversal.
  14102. for (bits = 1; bits <= MAX_BITS; bits++) {
  14103. next_code[bits] = code = code + bl_count[bits - 1] << 1;
  14104. } // Check that the bit counts in bl_count are consistent. The last code
  14105. // must be all ones.
  14106. // Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
  14107. // "inconsistent bit counts");
  14108. // Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
  14109. for (n = 0; n <= max_code; n++) {
  14110. len = tree[n * 2 + 1];
  14111. if (len === 0) continue; // Now reverse the bits
  14112. tree[n * 2] = bi_reverse(next_code[len]++, len);
  14113. }
  14114. } // Construct one Huffman tree and assigns the code bit strings and lengths.
  14115. // Update the total bit length for the current block.
  14116. // IN assertion: the field freq is set for all tree elements.
  14117. // OUT assertions: the fields len and code are set to the optimal bit length
  14118. // and corresponding code. The length opt_len is updated; static_len is
  14119. // also updated if stree is not null. The field max_code is set.
  14120. that.build_tree = function (s) {
  14121. var tree = that.dyn_tree;
  14122. var stree = that.stat_desc.static_tree;
  14123. var elems = that.stat_desc.elems;
  14124. var n, m; // iterate over heap elements
  14125. var max_code = -1; // largest code with non zero frequency
  14126. var node; // new node being created
  14127. // Construct the initial heap, with least frequent element in
  14128. // heap[1]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
  14129. // heap[0] is not used.
  14130. s.heap_len = 0;
  14131. s.heap_max = HEAP_SIZE;
  14132. for (n = 0; n < elems; n++) {
  14133. if (tree[n * 2] !== 0) {
  14134. s.heap[++s.heap_len] = max_code = n;
  14135. s.depth[n] = 0;
  14136. } else {
  14137. tree[n * 2 + 1] = 0;
  14138. }
  14139. } // The pkzip format requires that at least one distance code exists,
  14140. // and that at least one bit should be sent even if there is only one
  14141. // possible code. So to avoid special checks later on we force at least
  14142. // two codes of non zero frequency.
  14143. while (s.heap_len < 2) {
  14144. node = s.heap[++s.heap_len] = max_code < 2 ? ++max_code : 0;
  14145. tree[node * 2] = 1;
  14146. s.depth[node] = 0;
  14147. s.opt_len--;
  14148. if (stree) s.static_len -= stree[node * 2 + 1]; // node is 0 or 1 so it does not have extra bits
  14149. }
  14150. that.max_code = max_code; // The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
  14151. // establish sub-heaps of increasing lengths:
  14152. 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
  14153. // frequent nodes.
  14154. node = elems; // next internal node of the tree
  14155. do {
  14156. // n = node of least frequency
  14157. n = s.heap[1];
  14158. s.heap[1] = s.heap[s.heap_len--];
  14159. s.pqdownheap(tree, 1);
  14160. m = s.heap[1]; // m = node of next least frequency
  14161. s.heap[--s.heap_max] = n; // keep the nodes sorted by frequency
  14162. s.heap[--s.heap_max] = m; // Create a new node father of n and m
  14163. tree[node * 2] = tree[n * 2] + tree[m * 2];
  14164. s.depth[node] = Math.max(s.depth[n], s.depth[m]) + 1;
  14165. tree[n * 2 + 1] = tree[m * 2 + 1] = node; // and insert the new node in the heap
  14166. s.heap[1] = node++;
  14167. s.pqdownheap(tree, 1);
  14168. } while (s.heap_len >= 2);
  14169. s.heap[--s.heap_max] = s.heap[1]; // At this point, the fields freq and dad are set. We can now
  14170. // generate the bit lengths.
  14171. gen_bitlen(s); // The field len is now set, we can generate the bit codes
  14172. gen_codes(tree, that.max_code, s.bl_count);
  14173. };
  14174. }
  14175. 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];
  14176. 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];
  14177. 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
  14178. // must not have side effects. _dist_code[256] and _dist_code[257] are never
  14179. // used.
  14180. Tree.d_code = function (dist) {
  14181. return dist < 256 ? _dist_code[dist] : _dist_code[256 + (dist >>> 7)];
  14182. }; // extra bits for each length code
  14183. 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
  14184. 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
  14185. Tree.extra_blbits = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7];
  14186. Tree.bl_order = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]; // StaticTree
  14187. function StaticTree(static_tree, extra_bits, extra_base, elems, max_length) {
  14188. var that = this;
  14189. that.static_tree = static_tree;
  14190. that.extra_bits = extra_bits;
  14191. that.extra_base = extra_base;
  14192. that.elems = elems;
  14193. that.max_length = max_length;
  14194. }
  14195. 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];
  14196. 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];
  14197. StaticTree.static_l_desc = new StaticTree(StaticTree.static_ltree, Tree.extra_lbits, LITERALS + 1, L_CODES, MAX_BITS);
  14198. StaticTree.static_d_desc = new StaticTree(StaticTree.static_dtree, Tree.extra_dbits, 0, D_CODES, MAX_BITS);
  14199. StaticTree.static_bl_desc = new StaticTree(null, Tree.extra_blbits, 0, BL_CODES, MAX_BL_BITS); // Deflate
  14200. var MAX_MEM_LEVEL = 9;
  14201. var DEF_MEM_LEVEL = 8;
  14202. function Config(good_length, max_lazy, nice_length, max_chain, func) {
  14203. var that = this;
  14204. that.good_length = good_length;
  14205. that.max_lazy = max_lazy;
  14206. that.nice_length = nice_length;
  14207. that.max_chain = max_chain;
  14208. that.func = func;
  14209. }
  14210. var STORED = 0;
  14211. var FAST = 1;
  14212. var SLOW = 2;
  14213. 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)];
  14214. var z_errmsg = ["need dictionary", // Z_NEED_DICT
  14215. // 2
  14216. "stream end", // Z_STREAM_END 1
  14217. "", // Z_OK 0
  14218. "", // Z_ERRNO (-1)
  14219. "stream error", // Z_STREAM_ERROR (-2)
  14220. "data error", // Z_DATA_ERROR (-3)
  14221. "", // Z_MEM_ERROR (-4)
  14222. "buffer error", // Z_BUF_ERROR (-5)
  14223. "", // Z_VERSION_ERROR (-6)
  14224. ""]; // block not completed, need more input or more output
  14225. var NeedMore = 0; // block flush performed
  14226. var BlockDone = 1; // finish started, need only more output at next deflate
  14227. var FinishStarted = 2; // finish done, accept no more input or output
  14228. var FinishDone = 3; // preset dictionary flag in zlib header
  14229. var PRESET_DICT = 0x20;
  14230. var INIT_STATE = 42;
  14231. var BUSY_STATE = 113;
  14232. var FINISH_STATE = 666; // The deflate compression method
  14233. var Z_DEFLATED = 8;
  14234. var STORED_BLOCK = 0;
  14235. var STATIC_TREES = 1;
  14236. var DYN_TREES = 2;
  14237. var MIN_MATCH = 3;
  14238. var MAX_MATCH = 258;
  14239. var MIN_LOOKAHEAD = MAX_MATCH + MIN_MATCH + 1;
  14240. function smaller(tree, n, m, depth) {
  14241. var tn2 = tree[n * 2];
  14242. var tm2 = tree[m * 2];
  14243. return tn2 < tm2 || tn2 == tm2 && depth[n] <= depth[m];
  14244. }
  14245. function Deflate() {
  14246. var that = this;
  14247. var strm; // pointer back to this zlib stream
  14248. var status; // as the name implies
  14249. // pending_buf; // output still pending
  14250. var pending_buf_size; // size of pending_buf
  14251. var last_flush; // value of flush param for previous deflate call
  14252. var w_size; // LZ77 window size (32K by default)
  14253. var w_bits; // log2(w_size) (8..16)
  14254. var w_mask; // w_size - 1
  14255. var window; // Sliding window. Input bytes are read into the second half of the window,
  14256. // and move to the first half later to keep a dictionary of at least wSize
  14257. // bytes. With this organization, matches are limited to a distance of
  14258. // wSize-MAX_MATCH bytes, but this ensures that IO is always
  14259. // performed with a length multiple of the block size. Also, it limits
  14260. // the window size to 64K, which is quite useful on MSDOS.
  14261. // To do: use the user input buffer as sliding window.
  14262. var window_size; // Actual size of window: 2*wSize, except when the user input buffer
  14263. // is directly used as sliding window.
  14264. var prev; // Link to older string with same hash index. To limit the size of this
  14265. // array to 64K, this link is maintained only for the last 32K strings.
  14266. // An index in this array is thus a window index modulo 32K.
  14267. var head; // Heads of the hash chains or NIL.
  14268. var ins_h; // hash index of string to be inserted
  14269. var hash_size; // number of elements in hash table
  14270. var hash_bits; // log2(hash_size)
  14271. var hash_mask; // hash_size-1
  14272. // Number of bits by which ins_h must be shifted at each input
  14273. // step. It must be such that after MIN_MATCH steps, the oldest
  14274. // byte no longer takes part in the hash key, that is:
  14275. // hash_shift * MIN_MATCH >= hash_bits
  14276. var hash_shift; // Window position at the beginning of the current output block. Gets
  14277. // negative when the window is moved backwards.
  14278. var block_start;
  14279. var match_length; // length of best match
  14280. var prev_match; // previous match
  14281. var match_available; // set if previous match exists
  14282. var strstart; // start of string to insert
  14283. var match_start; // start of matching string
  14284. var lookahead; // number of valid bytes ahead in window
  14285. // Length of the best match at previous step. Matches not greater than this
  14286. // are discarded. This is used in the lazy match evaluation.
  14287. var prev_length; // To speed up deflation, hash chains are never searched beyond this
  14288. // length. A higher limit improves compression ratio but degrades the speed.
  14289. var max_chain_length; // Attempt to find a better match only when the current match is strictly
  14290. // smaller than this value. This mechanism is used only for compression
  14291. // levels >= 4.
  14292. var max_lazy_match; // Insert new strings in the hash table only if the match length is not
  14293. // greater than this length. This saves time but degrades compression.
  14294. // max_insert_length is used only for compression levels <= 3.
  14295. var level; // compression level (1..9)
  14296. var strategy; // favor or force Huffman coding
  14297. // Use a faster search when the previous match is longer than this
  14298. var good_match; // Stop searching when current match exceeds this
  14299. var nice_match;
  14300. var dyn_ltree; // literal and length tree
  14301. var dyn_dtree; // distance tree
  14302. var bl_tree; // Huffman tree for bit lengths
  14303. var l_desc = new Tree(); // desc for literal tree
  14304. var d_desc = new Tree(); // desc for distance tree
  14305. var bl_desc = new Tree(); // desc for bit length tree
  14306. // that.heap_len; // number of elements in the heap
  14307. // that.heap_max; // element of largest frequency
  14308. // The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
  14309. // The same heap array is used to build all trees.
  14310. // Depth of each subtree used as tie breaker for trees of equal frequency
  14311. that.depth = [];
  14312. var l_buf; // index for literals or lengths */
  14313. // Size of match buffer for literals/lengths. There are 4 reasons for
  14314. // limiting lit_bufsize to 64K:
  14315. // - frequencies can be kept in 16 bit counters
  14316. // - if compression is not successful for the first block, all input
  14317. // data is still in the window so we can still emit a stored block even
  14318. // when input comes from standard input. (This can also be done for
  14319. // all blocks if lit_bufsize is not greater than 32K.)
  14320. // - if compression is not successful for a file smaller than 64K, we can
  14321. // even emit a stored file instead of a stored block (saving 5 bytes).
  14322. // This is applicable only for zip (not gzip or zlib).
  14323. // - creating new Huffman trees less frequently may not provide fast
  14324. // adaptation to changes in the input data statistics. (Take for
  14325. // example a binary file with poorly compressible code followed by
  14326. // a highly compressible string table.) Smaller buffer sizes give
  14327. // fast adaptation but have of course the overhead of transmitting
  14328. // trees more frequently.
  14329. // - I can't count above 4
  14330. var lit_bufsize;
  14331. var last_lit; // running index in l_buf
  14332. // Buffer for distances. To simplify the code, d_buf and l_buf have
  14333. // the same number of elements. To use different lengths, an extra flag
  14334. // array would be necessary.
  14335. var d_buf; // index of pendig_buf
  14336. // that.opt_len; // bit length of current block with optimal trees
  14337. // that.static_len; // bit length of current block with static trees
  14338. var matches; // number of string matches in current block
  14339. var last_eob_len; // bit length of EOB code for last block
  14340. // Output buffer. bits are inserted starting at the bottom (least
  14341. // significant bits).
  14342. var bi_buf; // Number of valid bits in bi_buf. All bits above the last valid bit
  14343. // are always zero.
  14344. var bi_valid; // number of codes at each bit length for an optimal tree
  14345. that.bl_count = []; // heap used to build the Huffman trees
  14346. that.heap = [];
  14347. dyn_ltree = [];
  14348. dyn_dtree = [];
  14349. bl_tree = [];
  14350. function lm_init() {
  14351. var i;
  14352. window_size = 2 * w_size;
  14353. head[hash_size - 1] = 0;
  14354. for (i = 0; i < hash_size - 1; i++) {
  14355. head[i] = 0;
  14356. } // Set the default configuration parameters:
  14357. max_lazy_match = config_table[level].max_lazy;
  14358. good_match = config_table[level].good_length;
  14359. nice_match = config_table[level].nice_length;
  14360. max_chain_length = config_table[level].max_chain;
  14361. strstart = 0;
  14362. block_start = 0;
  14363. lookahead = 0;
  14364. match_length = prev_length = MIN_MATCH - 1;
  14365. match_available = 0;
  14366. ins_h = 0;
  14367. }
  14368. function init_block() {
  14369. var i; // Initialize the trees.
  14370. for (i = 0; i < L_CODES; i++) dyn_ltree[i * 2] = 0;
  14371. for (i = 0; i < D_CODES; i++) dyn_dtree[i * 2] = 0;
  14372. for (i = 0; i < BL_CODES; i++) bl_tree[i * 2] = 0;
  14373. dyn_ltree[END_BLOCK * 2] = 1;
  14374. that.opt_len = that.static_len = 0;
  14375. last_lit = matches = 0;
  14376. } // Initialize the tree data structures for a new zlib stream.
  14377. function tr_init() {
  14378. l_desc.dyn_tree = dyn_ltree;
  14379. l_desc.stat_desc = StaticTree.static_l_desc;
  14380. d_desc.dyn_tree = dyn_dtree;
  14381. d_desc.stat_desc = StaticTree.static_d_desc;
  14382. bl_desc.dyn_tree = bl_tree;
  14383. bl_desc.stat_desc = StaticTree.static_bl_desc;
  14384. bi_buf = 0;
  14385. bi_valid = 0;
  14386. last_eob_len = 8; // enough lookahead for inflate
  14387. // Initialize the first block of the first file:
  14388. init_block();
  14389. } // Restore the heap property by moving down the tree starting at node k,
  14390. // exchanging a node with the smallest of its two sons if necessary,
  14391. // stopping
  14392. // when the heap property is re-established (each father smaller than its
  14393. // two sons).
  14394. that.pqdownheap = function (tree, // the tree to restore
  14395. k // node to move down
  14396. ) {
  14397. var heap = that.heap;
  14398. var v = heap[k];
  14399. var j = k << 1; // left son of k
  14400. while (j <= that.heap_len) {
  14401. // Set j to the smallest of the two sons:
  14402. if (j < that.heap_len && smaller(tree, heap[j + 1], heap[j], that.depth)) {
  14403. j++;
  14404. } // Exit if v is smaller than both sons
  14405. if (smaller(tree, v, heap[j], that.depth)) break; // Exchange v with the smallest son
  14406. heap[k] = heap[j];
  14407. k = j; // And continue down the tree, setting j to the left son of k
  14408. j <<= 1;
  14409. }
  14410. heap[k] = v;
  14411. }; // Scan a literal or distance tree to determine the frequencies of the codes
  14412. // in the bit length tree.
  14413. function scan_tree(tree, // the tree to be scanned
  14414. max_code // and its largest code of non zero frequency
  14415. ) {
  14416. var n; // iterates over all tree elements
  14417. var prevlen = -1; // last emitted length
  14418. var curlen; // length of current code
  14419. var nextlen = tree[0 * 2 + 1]; // length of next code
  14420. var count = 0; // repeat count of the current code
  14421. var max_count = 7; // max repeat count
  14422. var min_count = 4; // min repeat count
  14423. if (nextlen === 0) {
  14424. max_count = 138;
  14425. min_count = 3;
  14426. }
  14427. tree[(max_code + 1) * 2 + 1] = 0xffff; // guard
  14428. for (n = 0; n <= max_code; n++) {
  14429. curlen = nextlen;
  14430. nextlen = tree[(n + 1) * 2 + 1];
  14431. if (++count < max_count && curlen == nextlen) {
  14432. continue;
  14433. } else if (count < min_count) {
  14434. bl_tree[curlen * 2] += count;
  14435. } else if (curlen !== 0) {
  14436. if (curlen != prevlen) bl_tree[curlen * 2]++;
  14437. bl_tree[REP_3_6 * 2]++;
  14438. } else if (count <= 10) {
  14439. bl_tree[REPZ_3_10 * 2]++;
  14440. } else {
  14441. bl_tree[REPZ_11_138 * 2]++;
  14442. }
  14443. count = 0;
  14444. prevlen = curlen;
  14445. if (nextlen === 0) {
  14446. max_count = 138;
  14447. min_count = 3;
  14448. } else if (curlen == nextlen) {
  14449. max_count = 6;
  14450. min_count = 3;
  14451. } else {
  14452. max_count = 7;
  14453. min_count = 4;
  14454. }
  14455. }
  14456. } // Construct the Huffman tree for the bit lengths and return the index in
  14457. // bl_order of the last bit length code to send.
  14458. function build_bl_tree() {
  14459. var max_blindex; // index of last bit length code of non zero freq
  14460. // Determine the bit length frequencies for literal and distance trees
  14461. scan_tree(dyn_ltree, l_desc.max_code);
  14462. scan_tree(dyn_dtree, d_desc.max_code); // Build the bit length tree:
  14463. bl_desc.build_tree(that); // opt_len now includes the length of the tree representations, except
  14464. // the lengths of the bit lengths codes and the 5+5+4 bits for the
  14465. // counts.
  14466. // Determine the number of bit length codes to send. The pkzip format
  14467. // requires that at least 4 bit length codes be sent. (appnote.txt says
  14468. // 3 but the actual value used is 4.)
  14469. for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) {
  14470. if (bl_tree[Tree.bl_order[max_blindex] * 2 + 1] !== 0) break;
  14471. } // Update opt_len to include the bit length tree and counts
  14472. that.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4;
  14473. return max_blindex;
  14474. } // Output a byte on the stream.
  14475. // IN assertion: there is enough room in pending_buf.
  14476. function put_byte(p) {
  14477. that.pending_buf[that.pending++] = p;
  14478. }
  14479. function put_short(w) {
  14480. put_byte(w & 0xff);
  14481. put_byte(w >>> 8 & 0xff);
  14482. }
  14483. function putShortMSB(b) {
  14484. put_byte(b >> 8 & 0xff);
  14485. put_byte(b & 0xff & 0xff);
  14486. }
  14487. function send_bits(value, length) {
  14488. var val,
  14489. len = length;
  14490. if (bi_valid > Buf_size - len) {
  14491. val = value; // bi_buf |= (val << bi_valid);
  14492. bi_buf |= val << bi_valid & 0xffff;
  14493. put_short(bi_buf);
  14494. bi_buf = val >>> Buf_size - bi_valid;
  14495. bi_valid += len - Buf_size;
  14496. } else {
  14497. // bi_buf |= (value) << bi_valid;
  14498. bi_buf |= value << bi_valid & 0xffff;
  14499. bi_valid += len;
  14500. }
  14501. }
  14502. function send_code(c, tree) {
  14503. var c2 = c * 2;
  14504. send_bits(tree[c2] & 0xffff, tree[c2 + 1] & 0xffff);
  14505. } // Send a literal or distance tree in compressed form, using the codes in
  14506. // bl_tree.
  14507. function send_tree(tree, // the tree to be sent
  14508. max_code // and its largest code of non zero frequency
  14509. ) {
  14510. var n; // iterates over all tree elements
  14511. var prevlen = -1; // last emitted length
  14512. var curlen; // length of current code
  14513. var nextlen = tree[0 * 2 + 1]; // length of next code
  14514. var count = 0; // repeat count of the current code
  14515. var max_count = 7; // max repeat count
  14516. var min_count = 4; // min repeat count
  14517. if (nextlen === 0) {
  14518. max_count = 138;
  14519. min_count = 3;
  14520. }
  14521. for (n = 0; n <= max_code; n++) {
  14522. curlen = nextlen;
  14523. nextlen = tree[(n + 1) * 2 + 1];
  14524. if (++count < max_count && curlen == nextlen) {
  14525. continue;
  14526. } else if (count < min_count) {
  14527. do {
  14528. send_code(curlen, bl_tree);
  14529. } while (--count !== 0);
  14530. } else if (curlen !== 0) {
  14531. if (curlen != prevlen) {
  14532. send_code(curlen, bl_tree);
  14533. count--;
  14534. }
  14535. send_code(REP_3_6, bl_tree);
  14536. send_bits(count - 3, 2);
  14537. } else if (count <= 10) {
  14538. send_code(REPZ_3_10, bl_tree);
  14539. send_bits(count - 3, 3);
  14540. } else {
  14541. send_code(REPZ_11_138, bl_tree);
  14542. send_bits(count - 11, 7);
  14543. }
  14544. count = 0;
  14545. prevlen = curlen;
  14546. if (nextlen === 0) {
  14547. max_count = 138;
  14548. min_count = 3;
  14549. } else if (curlen == nextlen) {
  14550. max_count = 6;
  14551. min_count = 3;
  14552. } else {
  14553. max_count = 7;
  14554. min_count = 4;
  14555. }
  14556. }
  14557. } // Send the header for a block using dynamic Huffman trees: the counts, the
  14558. // lengths of the bit length codes, the literal tree and the distance tree.
  14559. // IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
  14560. function send_all_trees(lcodes, dcodes, blcodes) {
  14561. var rank; // index in bl_order
  14562. send_bits(lcodes - 257, 5); // not +255 as stated in appnote.txt
  14563. send_bits(dcodes - 1, 5);
  14564. send_bits(blcodes - 4, 4); // not -3 as stated in appnote.txt
  14565. for (rank = 0; rank < blcodes; rank++) {
  14566. send_bits(bl_tree[Tree.bl_order[rank] * 2 + 1], 3);
  14567. }
  14568. send_tree(dyn_ltree, lcodes - 1); // literal tree
  14569. send_tree(dyn_dtree, dcodes - 1); // distance tree
  14570. } // Flush the bit buffer, keeping at most 7 bits in it.
  14571. function bi_flush() {
  14572. if (bi_valid == 16) {
  14573. put_short(bi_buf);
  14574. bi_buf = 0;
  14575. bi_valid = 0;
  14576. } else if (bi_valid >= 8) {
  14577. put_byte(bi_buf & 0xff);
  14578. bi_buf >>>= 8;
  14579. bi_valid -= 8;
  14580. }
  14581. } // Send one empty static block to give enough lookahead for inflate.
  14582. // This takes 10 bits, of which 7 may remain in the bit buffer.
  14583. // The current inflate code requires 9 bits of lookahead. If the
  14584. // last two codes for the previous block (real code plus EOB) were coded
  14585. // on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
  14586. // the last real code. In this case we send two empty static blocks instead
  14587. // of one. (There are no problems if the previous block is stored or fixed.)
  14588. // To simplify the code, we assume the worst case of last real code encoded
  14589. // on one bit only.
  14590. function _tr_align() {
  14591. send_bits(STATIC_TREES << 1, 3);
  14592. send_code(END_BLOCK, StaticTree.static_ltree);
  14593. bi_flush(); // Of the 10 bits for the empty block, we have already sent
  14594. // (10 - bi_valid) bits. The lookahead for the last real code (before
  14595. // the EOB of the previous block) was thus at least one plus the length
  14596. // of the EOB plus what we have just sent of the empty static block.
  14597. if (1 + last_eob_len + 10 - bi_valid < 9) {
  14598. send_bits(STATIC_TREES << 1, 3);
  14599. send_code(END_BLOCK, StaticTree.static_ltree);
  14600. bi_flush();
  14601. }
  14602. last_eob_len = 7;
  14603. } // Save the match info and tally the frequency counts. Return true if
  14604. // the current block must be flushed.
  14605. function _tr_tally(dist, // distance of matched string
  14606. lc // match length-MIN_MATCH or unmatched char (if dist==0)
  14607. ) {
  14608. var out_length, in_length, dcode;
  14609. that.pending_buf[d_buf + last_lit * 2] = dist >>> 8 & 0xff;
  14610. that.pending_buf[d_buf + last_lit * 2 + 1] = dist & 0xff;
  14611. that.pending_buf[l_buf + last_lit] = lc & 0xff;
  14612. last_lit++;
  14613. if (dist === 0) {
  14614. // lc is the unmatched char
  14615. dyn_ltree[lc * 2]++;
  14616. } else {
  14617. matches++; // Here, lc is the match length - MIN_MATCH
  14618. dist--; // dist = match distance - 1
  14619. dyn_ltree[(Tree._length_code[lc] + LITERALS + 1) * 2]++;
  14620. dyn_dtree[Tree.d_code(dist) * 2]++;
  14621. }
  14622. if ((last_lit & 0x1fff) === 0 && level > 2) {
  14623. // Compute an upper bound for the compressed length
  14624. out_length = last_lit * 8;
  14625. in_length = strstart - block_start;
  14626. for (dcode = 0; dcode < D_CODES; dcode++) {
  14627. out_length += dyn_dtree[dcode * 2] * (5 + Tree.extra_dbits[dcode]);
  14628. }
  14629. out_length >>>= 3;
  14630. if (matches < Math.floor(last_lit / 2) && out_length < Math.floor(in_length / 2)) return true;
  14631. }
  14632. return last_lit == lit_bufsize - 1; // We avoid equality with lit_bufsize because of wraparound at 64K
  14633. // on 16 bit machines and because stored blocks are restricted to
  14634. // 64K-1 bytes.
  14635. } // Send the block data compressed using the given Huffman trees
  14636. function compress_block(ltree, dtree) {
  14637. var dist; // distance of matched string
  14638. var lc; // match length or unmatched char (if dist === 0)
  14639. var lx = 0; // running index in l_buf
  14640. var code; // the code to send
  14641. var extra; // number of extra bits to send
  14642. if (last_lit !== 0) {
  14643. do {
  14644. dist = that.pending_buf[d_buf + lx * 2] << 8 & 0xff00 | that.pending_buf[d_buf + lx * 2 + 1] & 0xff;
  14645. lc = that.pending_buf[l_buf + lx] & 0xff;
  14646. lx++;
  14647. if (dist === 0) {
  14648. send_code(lc, ltree); // send a literal byte
  14649. } else {
  14650. // Here, lc is the match length - MIN_MATCH
  14651. code = Tree._length_code[lc];
  14652. send_code(code + LITERALS + 1, ltree); // send the length
  14653. // code
  14654. extra = Tree.extra_lbits[code];
  14655. if (extra !== 0) {
  14656. lc -= Tree.base_length[code];
  14657. send_bits(lc, extra); // send the extra length bits
  14658. }
  14659. dist--; // dist is now the match distance - 1
  14660. code = Tree.d_code(dist);
  14661. send_code(code, dtree); // send the distance code
  14662. extra = Tree.extra_dbits[code];
  14663. if (extra !== 0) {
  14664. dist -= Tree.base_dist[code];
  14665. send_bits(dist, extra); // send the extra distance bits
  14666. }
  14667. } // literal or match pair ?
  14668. // Check that the overlay between pending_buf and d_buf+l_buf is
  14669. // ok:
  14670. } while (lx < last_lit);
  14671. }
  14672. send_code(END_BLOCK, ltree);
  14673. last_eob_len = ltree[END_BLOCK * 2 + 1];
  14674. } // Flush the bit buffer and align the output on a byte boundary
  14675. function bi_windup() {
  14676. if (bi_valid > 8) {
  14677. put_short(bi_buf);
  14678. } else if (bi_valid > 0) {
  14679. put_byte(bi_buf & 0xff);
  14680. }
  14681. bi_buf = 0;
  14682. bi_valid = 0;
  14683. } // Copy a stored block, storing first the length and its
  14684. // one's complement if requested.
  14685. function copy_block(buf, // the input data
  14686. len, // its length
  14687. header // true if block header must be written
  14688. ) {
  14689. bi_windup(); // align on byte boundary
  14690. last_eob_len = 8; // enough lookahead for inflate
  14691. if (header) {
  14692. put_short(len);
  14693. put_short(~len);
  14694. }
  14695. that.pending_buf.set(window.subarray(buf, buf + len), that.pending);
  14696. that.pending += len;
  14697. } // Send a stored block
  14698. function _tr_stored_block(buf, // input block
  14699. stored_len, // length of input block
  14700. eof // true if this is the last block for a file
  14701. ) {
  14702. send_bits((STORED_BLOCK << 1) + (eof ? 1 : 0), 3); // send block type
  14703. copy_block(buf, stored_len, true); // with header
  14704. } // Determine the best encoding for the current block: dynamic trees, static
  14705. // trees or store, and output the encoded block to the zip file.
  14706. function _tr_flush_block(buf, // input block, or NULL if too old
  14707. stored_len, // length of input block
  14708. eof // true if this is the last block for a file
  14709. ) {
  14710. var opt_lenb, static_lenb; // opt_len and static_len in bytes
  14711. var max_blindex = 0; // index of last bit length code of non zero freq
  14712. // Build the Huffman trees unless a stored block is forced
  14713. if (level > 0) {
  14714. // Construct the literal and distance trees
  14715. l_desc.build_tree(that);
  14716. d_desc.build_tree(that); // At this point, opt_len and static_len are the total bit lengths
  14717. // of
  14718. // the compressed block data, excluding the tree representations.
  14719. // Build the bit length tree for the above two trees, and get the
  14720. // index
  14721. // in bl_order of the last bit length code to send.
  14722. max_blindex = build_bl_tree(); // Determine the best encoding. Compute first the block length in
  14723. // bytes
  14724. opt_lenb = that.opt_len + 3 + 7 >>> 3;
  14725. static_lenb = that.static_len + 3 + 7 >>> 3;
  14726. if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
  14727. } else {
  14728. opt_lenb = static_lenb = stored_len + 5; // force a stored block
  14729. }
  14730. if (stored_len + 4 <= opt_lenb && buf != -1) {
  14731. // 4: two words for the lengths
  14732. // The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
  14733. // Otherwise we can't have processed more than WSIZE input bytes
  14734. // since
  14735. // the last block flush, because compression would have been
  14736. // successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
  14737. // transform a block into a stored block.
  14738. _tr_stored_block(buf, stored_len, eof);
  14739. } else if (static_lenb == opt_lenb) {
  14740. send_bits((STATIC_TREES << 1) + (eof ? 1 : 0), 3);
  14741. compress_block(StaticTree.static_ltree, StaticTree.static_dtree);
  14742. } else {
  14743. send_bits((DYN_TREES << 1) + (eof ? 1 : 0), 3);
  14744. send_all_trees(l_desc.max_code + 1, d_desc.max_code + 1, max_blindex + 1);
  14745. compress_block(dyn_ltree, dyn_dtree);
  14746. } // The above check is made mod 2^32, for files larger than 512 MB
  14747. // and uLong implemented on 32 bits.
  14748. init_block();
  14749. if (eof) {
  14750. bi_windup();
  14751. }
  14752. }
  14753. function flush_block_only(eof) {
  14754. _tr_flush_block(block_start >= 0 ? block_start : -1, strstart - block_start, eof);
  14755. block_start = strstart;
  14756. strm.flush_pending();
  14757. } // Fill the window when the lookahead becomes insufficient.
  14758. // Updates strstart and lookahead.
  14759. //
  14760. // IN assertion: lookahead < MIN_LOOKAHEAD
  14761. // OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
  14762. // At least one byte has been read, or avail_in === 0; reads are
  14763. // performed for at least two bytes (required for the zip translate_eol
  14764. // option -- not supported here).
  14765. function fill_window() {
  14766. var n, m;
  14767. var p;
  14768. var more; // Amount of free space at the end of the window.
  14769. do {
  14770. more = window_size - lookahead - strstart; // Deal with !@#$% 64K limit:
  14771. if (more === 0 && strstart === 0 && lookahead === 0) {
  14772. more = w_size;
  14773. } else if (more == -1) {
  14774. // Very unlikely, but possible on 16 bit machine if strstart ==
  14775. // 0
  14776. // and lookahead == 1 (input done one byte at time)
  14777. more--; // If the window is almost full and there is insufficient
  14778. // lookahead,
  14779. // move the upper half to the lower one to make room in the
  14780. // upper half.
  14781. } else if (strstart >= w_size + w_size - MIN_LOOKAHEAD) {
  14782. window.set(window.subarray(w_size, w_size + w_size), 0);
  14783. match_start -= w_size;
  14784. strstart -= w_size; // we now have strstart >= MAX_DIST
  14785. block_start -= w_size; // Slide the hash table (could be avoided with 32 bit values
  14786. // at the expense of memory usage). We slide even when level ==
  14787. // 0
  14788. // to keep the hash table consistent if we switch back to level
  14789. // > 0
  14790. // later. (Using level 0 permanently is not an optimal usage of
  14791. // zlib, so we don't care about this pathological case.)
  14792. n = hash_size;
  14793. p = n;
  14794. do {
  14795. m = head[--p] & 0xffff;
  14796. head[p] = m >= w_size ? m - w_size : 0;
  14797. } while (--n !== 0);
  14798. n = w_size;
  14799. p = n;
  14800. do {
  14801. m = prev[--p] & 0xffff;
  14802. prev[p] = m >= w_size ? m - w_size : 0; // If n is not on any hash chain, prev[n] is garbage but
  14803. // its value will never be used.
  14804. } while (--n !== 0);
  14805. more += w_size;
  14806. }
  14807. if (strm.avail_in === 0) return; // If there was no sliding:
  14808. // strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
  14809. // more == window_size - lookahead - strstart
  14810. // => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
  14811. // => more >= window_size - 2*WSIZE + 2
  14812. // In the BIG_MEM or MMAP case (not yet supported),
  14813. // window_size == input_size + MIN_LOOKAHEAD &&
  14814. // strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
  14815. // Otherwise, window_size == 2*WSIZE so more >= 2.
  14816. // If there was sliding, more >= WSIZE. So in all cases, more >= 2.
  14817. n = strm.read_buf(window, strstart + lookahead, more);
  14818. lookahead += n; // Initialize the hash value now that we have some input:
  14819. if (lookahead >= MIN_MATCH) {
  14820. ins_h = window[strstart] & 0xff;
  14821. ins_h = (ins_h << hash_shift ^ window[strstart + 1] & 0xff) & hash_mask;
  14822. } // If the whole input has less than MIN_MATCH bytes, ins_h is
  14823. // garbage,
  14824. // but this is not important since only literal bytes will be
  14825. // emitted.
  14826. } while (lookahead < MIN_LOOKAHEAD && strm.avail_in !== 0);
  14827. } // Copy without compression as much as possible from the input stream,
  14828. // return
  14829. // the current block state.
  14830. // This function does not insert new strings in the dictionary since
  14831. // uncompressible data is probably not useful. This function is used
  14832. // only for the level=0 compression option.
  14833. // NOTE: this function should be optimized to avoid extra copying from
  14834. // window to pending_buf.
  14835. function deflate_stored(flush) {
  14836. // Stored blocks are limited to 0xffff bytes, pending_buf is limited
  14837. // to pending_buf_size, and each stored block has a 5 byte header:
  14838. var max_block_size = 0xffff;
  14839. var max_start;
  14840. if (max_block_size > pending_buf_size - 5) {
  14841. max_block_size = pending_buf_size - 5;
  14842. } // Copy as much as possible from input to output:
  14843. while (true) {
  14844. // Fill the window as much as possible:
  14845. if (lookahead <= 1) {
  14846. fill_window();
  14847. if (lookahead === 0 && flush == Z_NO_FLUSH) return NeedMore;
  14848. if (lookahead === 0) break; // flush the current block
  14849. }
  14850. strstart += lookahead;
  14851. lookahead = 0; // Emit a stored block if pending_buf will be full:
  14852. max_start = block_start + max_block_size;
  14853. if (strstart === 0 || strstart >= max_start) {
  14854. // strstart === 0 is possible when wraparound on 16-bit machine
  14855. lookahead = strstart - max_start;
  14856. strstart = max_start;
  14857. flush_block_only(false);
  14858. if (strm.avail_out === 0) return NeedMore;
  14859. } // Flush if we may have to slide, otherwise block_start may become
  14860. // negative and the data will be gone:
  14861. if (strstart - block_start >= w_size - MIN_LOOKAHEAD) {
  14862. flush_block_only(false);
  14863. if (strm.avail_out === 0) return NeedMore;
  14864. }
  14865. }
  14866. flush_block_only(flush == Z_FINISH);
  14867. if (strm.avail_out === 0) return flush == Z_FINISH ? FinishStarted : NeedMore;
  14868. return flush == Z_FINISH ? FinishDone : BlockDone;
  14869. }
  14870. function longest_match(cur_match) {
  14871. var chain_length = max_chain_length; // max hash chain length
  14872. var scan = strstart; // current string
  14873. var match; // matched string
  14874. var len; // length of current match
  14875. var best_len = prev_length; // best match length so far
  14876. var limit = strstart > w_size - MIN_LOOKAHEAD ? strstart - (w_size - MIN_LOOKAHEAD) : 0;
  14877. var _nice_match = nice_match; // Stop when cur_match becomes <= limit. To simplify the code,
  14878. // we prevent matches with the string of window index 0.
  14879. var wmask = w_mask;
  14880. var strend = strstart + MAX_MATCH;
  14881. var scan_end1 = window[scan + best_len - 1];
  14882. var scan_end = window[scan + best_len]; // The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of
  14883. // 16.
  14884. // It is easy to get rid of this optimization if necessary.
  14885. // Do not waste too much time if we already have a good match:
  14886. if (prev_length >= good_match) {
  14887. chain_length >>= 2;
  14888. } // Do not look for matches beyond the end of the input. This is
  14889. // necessary
  14890. // to make deflate deterministic.
  14891. if (_nice_match > lookahead) _nice_match = lookahead;
  14892. do {
  14893. match = cur_match; // Skip to next match if the match length cannot increase
  14894. // or if the match length is less than 2:
  14895. 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
  14896. // again later. (This heuristic is not always a win.)
  14897. // It is not necessary to compare scan[2] and match[2] since they
  14898. // are always equal when the other bytes match, given that
  14899. // the hash keys are equal and that HASH_BITS >= 8.
  14900. scan += 2;
  14901. match++; // We check for insufficient lookahead only every 8th comparison;
  14902. // the 256th check will be made at strstart+258.
  14903. 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);
  14904. len = MAX_MATCH - (strend - scan);
  14905. scan = strend - MAX_MATCH;
  14906. if (len > best_len) {
  14907. match_start = cur_match;
  14908. best_len = len;
  14909. if (len >= _nice_match) break;
  14910. scan_end1 = window[scan + best_len - 1];
  14911. scan_end = window[scan + best_len];
  14912. }
  14913. } while ((cur_match = prev[cur_match & wmask] & 0xffff) > limit && --chain_length !== 0);
  14914. if (best_len <= lookahead) return best_len;
  14915. return lookahead;
  14916. } // Compress as much as possible from the input stream, return the current
  14917. // block state.
  14918. // This function does not perform lazy evaluation of matches and inserts
  14919. // new strings in the dictionary only for unmatched strings or for short
  14920. // matches. It is used only for the fast compression options.
  14921. function deflate_fast(flush) {
  14922. // short hash_head = 0; // head of the hash chain
  14923. var hash_head = 0; // head of the hash chain
  14924. var bflush; // set if current block must be flushed
  14925. while (true) {
  14926. // Make sure that we always have enough lookahead, except
  14927. // at the end of the input file. We need MAX_MATCH bytes
  14928. // for the next match, plus MIN_MATCH bytes to insert the
  14929. // string following the next match.
  14930. if (lookahead < MIN_LOOKAHEAD) {
  14931. fill_window();
  14932. if (lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
  14933. return NeedMore;
  14934. }
  14935. if (lookahead === 0) break; // flush the current block
  14936. } // Insert the string window[strstart .. strstart+2] in the
  14937. // dictionary, and set hash_head to the head of the hash chain:
  14938. if (lookahead >= MIN_MATCH) {
  14939. ins_h = (ins_h << hash_shift ^ window[strstart + (MIN_MATCH - 1)] & 0xff) & hash_mask; // prev[strstart&w_mask]=hash_head=head[ins_h];
  14940. hash_head = head[ins_h] & 0xffff;
  14941. prev[strstart & w_mask] = head[ins_h];
  14942. head[ins_h] = strstart;
  14943. } // Find the longest match, discarding those <= prev_length.
  14944. // At this point we have always match_length < MIN_MATCH
  14945. if (hash_head !== 0 && (strstart - hash_head & 0xffff) <= w_size - MIN_LOOKAHEAD) {
  14946. // To simplify the code, we prevent matches with the string
  14947. // of window index 0 (in particular we have to avoid a match
  14948. // of the string with itself at the start of the input file).
  14949. if (strategy != Z_HUFFMAN_ONLY) {
  14950. match_length = longest_match(hash_head);
  14951. } // longest_match() sets match_start
  14952. }
  14953. if (match_length >= MIN_MATCH) {
  14954. // check_match(strstart, match_start, match_length);
  14955. bflush = _tr_tally(strstart - match_start, match_length - MIN_MATCH);
  14956. lookahead -= match_length; // Insert new strings in the hash table only if the match length
  14957. // is not too large. This saves time but degrades compression.
  14958. if (match_length <= max_lazy_match && lookahead >= MIN_MATCH) {
  14959. match_length--; // string at strstart already in hash table
  14960. do {
  14961. strstart++;
  14962. ins_h = (ins_h << hash_shift ^ window[strstart + (MIN_MATCH - 1)] & 0xff) & hash_mask; // prev[strstart&w_mask]=hash_head=head[ins_h];
  14963. hash_head = head[ins_h] & 0xffff;
  14964. prev[strstart & w_mask] = head[ins_h];
  14965. head[ins_h] = strstart; // strstart never exceeds WSIZE-MAX_MATCH, so there are
  14966. // always MIN_MATCH bytes ahead.
  14967. } while (--match_length !== 0);
  14968. strstart++;
  14969. } else {
  14970. strstart += match_length;
  14971. match_length = 0;
  14972. ins_h = window[strstart] & 0xff;
  14973. ins_h = (ins_h << hash_shift ^ window[strstart + 1] & 0xff) & hash_mask; // If lookahead < MIN_MATCH, ins_h is garbage, but it does
  14974. // not
  14975. // matter since it will be recomputed at next deflate call.
  14976. }
  14977. } else {
  14978. // No match, output a literal byte
  14979. bflush = _tr_tally(0, window[strstart] & 0xff);
  14980. lookahead--;
  14981. strstart++;
  14982. }
  14983. if (bflush) {
  14984. flush_block_only(false);
  14985. if (strm.avail_out === 0) return NeedMore;
  14986. }
  14987. }
  14988. flush_block_only(flush == Z_FINISH);
  14989. if (strm.avail_out === 0) {
  14990. if (flush == Z_FINISH) return FinishStarted;else return NeedMore;
  14991. }
  14992. return flush == Z_FINISH ? FinishDone : BlockDone;
  14993. } // Same as above, but achieves better compression. We use a lazy
  14994. // evaluation for matches: a match is finally adopted only if there is
  14995. // no better match at the next window position.
  14996. function deflate_slow(flush) {
  14997. // short hash_head = 0; // head of hash chain
  14998. var hash_head = 0; // head of hash chain
  14999. var bflush; // set if current block must be flushed
  15000. var max_insert; // Process the input block.
  15001. while (true) {
  15002. // Make sure that we always have enough lookahead, except
  15003. // at the end of the input file. We need MAX_MATCH bytes
  15004. // for the next match, plus MIN_MATCH bytes to insert the
  15005. // string following the next match.
  15006. if (lookahead < MIN_LOOKAHEAD) {
  15007. fill_window();
  15008. if (lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
  15009. return NeedMore;
  15010. }
  15011. if (lookahead === 0) break; // flush the current block
  15012. } // Insert the string window[strstart .. strstart+2] in the
  15013. // dictionary, and set hash_head to the head of the hash chain:
  15014. if (lookahead >= MIN_MATCH) {
  15015. ins_h = (ins_h << hash_shift ^ window[strstart + (MIN_MATCH - 1)] & 0xff) & hash_mask; // prev[strstart&w_mask]=hash_head=head[ins_h];
  15016. hash_head = head[ins_h] & 0xffff;
  15017. prev[strstart & w_mask] = head[ins_h];
  15018. head[ins_h] = strstart;
  15019. } // Find the longest match, discarding those <= prev_length.
  15020. prev_length = match_length;
  15021. prev_match = match_start;
  15022. match_length = MIN_MATCH - 1;
  15023. if (hash_head !== 0 && prev_length < max_lazy_match && (strstart - hash_head & 0xffff) <= w_size - MIN_LOOKAHEAD) {
  15024. // To simplify the code, we prevent matches with the string
  15025. // of window index 0 (in particular we have to avoid a match
  15026. // of the string with itself at the start of the input file).
  15027. if (strategy != Z_HUFFMAN_ONLY) {
  15028. match_length = longest_match(hash_head);
  15029. } // longest_match() sets match_start
  15030. if (match_length <= 5 && (strategy == Z_FILTERED || match_length == MIN_MATCH && strstart - match_start > 4096)) {
  15031. // If prev_match is also MIN_MATCH, match_start is garbage
  15032. // but we will ignore the current match anyway.
  15033. match_length = MIN_MATCH - 1;
  15034. }
  15035. } // If there was a match at the previous step and the current
  15036. // match is not better, output the previous match:
  15037. if (prev_length >= MIN_MATCH && match_length <= prev_length) {
  15038. max_insert = strstart + lookahead - MIN_MATCH; // Do not insert strings in hash table beyond this.
  15039. // check_match(strstart-1, prev_match, prev_length);
  15040. bflush = _tr_tally(strstart - 1 - prev_match, prev_length - MIN_MATCH); // Insert in hash table all strings up to the end of the match.
  15041. // strstart-1 and strstart are already inserted. If there is not
  15042. // enough lookahead, the last two strings are not inserted in
  15043. // the hash table.
  15044. lookahead -= prev_length - 1;
  15045. prev_length -= 2;
  15046. do {
  15047. if (++strstart <= max_insert) {
  15048. ins_h = (ins_h << hash_shift ^ window[strstart + (MIN_MATCH - 1)] & 0xff) & hash_mask; // prev[strstart&w_mask]=hash_head=head[ins_h];
  15049. hash_head = head[ins_h] & 0xffff;
  15050. prev[strstart & w_mask] = head[ins_h];
  15051. head[ins_h] = strstart;
  15052. }
  15053. } while (--prev_length !== 0);
  15054. match_available = 0;
  15055. match_length = MIN_MATCH - 1;
  15056. strstart++;
  15057. if (bflush) {
  15058. flush_block_only(false);
  15059. if (strm.avail_out === 0) return NeedMore;
  15060. }
  15061. } else if (match_available !== 0) {
  15062. // If there was no match at the previous position, output a
  15063. // single literal. If there was a match but the current match
  15064. // is longer, truncate the previous match to a single literal.
  15065. bflush = _tr_tally(0, window[strstart - 1] & 0xff);
  15066. if (bflush) {
  15067. flush_block_only(false);
  15068. }
  15069. strstart++;
  15070. lookahead--;
  15071. if (strm.avail_out === 0) return NeedMore;
  15072. } else {
  15073. // There is no previous match to compare with, wait for
  15074. // the next step to decide.
  15075. match_available = 1;
  15076. strstart++;
  15077. lookahead--;
  15078. }
  15079. }
  15080. if (match_available !== 0) {
  15081. bflush = _tr_tally(0, window[strstart - 1] & 0xff);
  15082. match_available = 0;
  15083. }
  15084. flush_block_only(flush == Z_FINISH);
  15085. if (strm.avail_out === 0) {
  15086. if (flush == Z_FINISH) return FinishStarted;else return NeedMore;
  15087. }
  15088. return flush == Z_FINISH ? FinishDone : BlockDone;
  15089. }
  15090. function deflateReset(strm) {
  15091. strm.total_in = strm.total_out = 0;
  15092. strm.msg = null; //
  15093. that.pending = 0;
  15094. that.pending_out = 0;
  15095. status = BUSY_STATE;
  15096. last_flush = Z_NO_FLUSH;
  15097. tr_init();
  15098. lm_init();
  15099. return Z_OK;
  15100. }
  15101. that.deflateInit = function (strm, _level, bits, _method, memLevel, _strategy) {
  15102. if (!_method) _method = Z_DEFLATED;
  15103. if (!memLevel) memLevel = DEF_MEM_LEVEL;
  15104. if (!_strategy) _strategy = Z_DEFAULT_STRATEGY; // byte[] my_version=ZLIB_VERSION;
  15105. //
  15106. // if (!version || version[0] != my_version[0]
  15107. // || stream_size != sizeof(z_stream)) {
  15108. // return Z_VERSION_ERROR;
  15109. // }
  15110. strm.msg = null;
  15111. if (_level == Z_DEFAULT_COMPRESSION) _level = 6;
  15112. if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || _method != Z_DEFLATED || bits < 9 || bits > 15 || _level < 0 || _level > 9 || _strategy < 0 || _strategy > Z_HUFFMAN_ONLY) {
  15113. return Z_STREAM_ERROR;
  15114. }
  15115. strm.dstate = that;
  15116. w_bits = bits;
  15117. w_size = 1 << w_bits;
  15118. w_mask = w_size - 1;
  15119. hash_bits = memLevel + 7;
  15120. hash_size = 1 << hash_bits;
  15121. hash_mask = hash_size - 1;
  15122. hash_shift = Math.floor((hash_bits + MIN_MATCH - 1) / MIN_MATCH);
  15123. window = new Uint8Array(w_size * 2);
  15124. prev = [];
  15125. head = [];
  15126. lit_bufsize = 1 << memLevel + 6; // 16K elements by default
  15127. // We overlay pending_buf and d_buf+l_buf. This works since the average
  15128. // output size for (length,distance) codes is <= 24 bits.
  15129. that.pending_buf = new Uint8Array(lit_bufsize * 4);
  15130. pending_buf_size = lit_bufsize * 4;
  15131. d_buf = Math.floor(lit_bufsize / 2);
  15132. l_buf = (1 + 2) * lit_bufsize;
  15133. level = _level;
  15134. strategy = _strategy;
  15135. return deflateReset(strm);
  15136. };
  15137. that.deflateEnd = function () {
  15138. if (status != INIT_STATE && status != BUSY_STATE && status != FINISH_STATE) {
  15139. return Z_STREAM_ERROR;
  15140. } // Deallocate in reverse order of allocations:
  15141. that.pending_buf = null;
  15142. head = null;
  15143. prev = null;
  15144. window = null; // free
  15145. that.dstate = null;
  15146. return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
  15147. };
  15148. that.deflateParams = function (strm, _level, _strategy) {
  15149. var err = Z_OK;
  15150. if (_level == Z_DEFAULT_COMPRESSION) {
  15151. _level = 6;
  15152. }
  15153. if (_level < 0 || _level > 9 || _strategy < 0 || _strategy > Z_HUFFMAN_ONLY) {
  15154. return Z_STREAM_ERROR;
  15155. }
  15156. if (config_table[level].func != config_table[_level].func && strm.total_in !== 0) {
  15157. // Flush the last buffer:
  15158. err = strm.deflate(Z_PARTIAL_FLUSH);
  15159. }
  15160. if (level != _level) {
  15161. level = _level;
  15162. max_lazy_match = config_table[level].max_lazy;
  15163. good_match = config_table[level].good_length;
  15164. nice_match = config_table[level].nice_length;
  15165. max_chain_length = config_table[level].max_chain;
  15166. }
  15167. strategy = _strategy;
  15168. return err;
  15169. };
  15170. that.deflateSetDictionary = function (strm, dictionary, dictLength) {
  15171. var length = dictLength;
  15172. var n,
  15173. index = 0;
  15174. if (!dictionary || status != INIT_STATE) return Z_STREAM_ERROR;
  15175. if (length < MIN_MATCH) return Z_OK;
  15176. if (length > w_size - MIN_LOOKAHEAD) {
  15177. length = w_size - MIN_LOOKAHEAD;
  15178. index = dictLength - length; // use the tail of the dictionary
  15179. }
  15180. window.set(dictionary.subarray(index, index + length), 0);
  15181. strstart = length;
  15182. block_start = length; // Insert all strings in the hash table (except for the last two bytes).
  15183. // s->lookahead stays null, so s->ins_h will be recomputed at the next
  15184. // call of fill_window.
  15185. ins_h = window[0] & 0xff;
  15186. ins_h = (ins_h << hash_shift ^ window[1] & 0xff) & hash_mask;
  15187. for (n = 0; n <= length - MIN_MATCH; n++) {
  15188. ins_h = (ins_h << hash_shift ^ window[n + (MIN_MATCH - 1)] & 0xff) & hash_mask;
  15189. prev[n & w_mask] = head[ins_h];
  15190. head[ins_h] = n;
  15191. }
  15192. return Z_OK;
  15193. };
  15194. that.deflate = function (_strm, flush) {
  15195. var i, header, level_flags, old_flush, bstate;
  15196. if (flush > Z_FINISH || flush < 0) {
  15197. return Z_STREAM_ERROR;
  15198. }
  15199. if (!_strm.next_out || !_strm.next_in && _strm.avail_in !== 0 || status == FINISH_STATE && flush != Z_FINISH) {
  15200. _strm.msg = z_errmsg[Z_NEED_DICT - Z_STREAM_ERROR];
  15201. return Z_STREAM_ERROR;
  15202. }
  15203. if (_strm.avail_out === 0) {
  15204. _strm.msg = z_errmsg[Z_NEED_DICT - Z_BUF_ERROR];
  15205. return Z_BUF_ERROR;
  15206. }
  15207. strm = _strm; // just in case
  15208. old_flush = last_flush;
  15209. last_flush = flush; // Write the zlib header
  15210. if (status == INIT_STATE) {
  15211. header = Z_DEFLATED + (w_bits - 8 << 4) << 8;
  15212. level_flags = (level - 1 & 0xff) >> 1;
  15213. if (level_flags > 3) level_flags = 3;
  15214. header |= level_flags << 6;
  15215. if (strstart !== 0) header |= PRESET_DICT;
  15216. header += 31 - header % 31;
  15217. status = BUSY_STATE;
  15218. putShortMSB(header);
  15219. } // Flush as much pending output as possible
  15220. if (that.pending !== 0) {
  15221. strm.flush_pending();
  15222. if (strm.avail_out === 0) {
  15223. // console.log(" avail_out==0");
  15224. // Since avail_out is 0, deflate will be called again with
  15225. // more output space, but possibly with both pending and
  15226. // avail_in equal to zero. There won't be anything to do,
  15227. // but this is not an error situation so make sure we
  15228. // return OK instead of BUF_ERROR at next call of deflate:
  15229. last_flush = -1;
  15230. return Z_OK;
  15231. } // Make sure there is something to do and avoid duplicate
  15232. // consecutive
  15233. // flushes. For repeated and useless calls with Z_FINISH, we keep
  15234. // returning Z_STREAM_END instead of Z_BUFF_ERROR.
  15235. } else if (strm.avail_in === 0 && flush <= old_flush && flush != Z_FINISH) {
  15236. strm.msg = z_errmsg[Z_NEED_DICT - Z_BUF_ERROR];
  15237. return Z_BUF_ERROR;
  15238. } // User must not provide more input after the first FINISH:
  15239. if (status == FINISH_STATE && strm.avail_in !== 0) {
  15240. _strm.msg = z_errmsg[Z_NEED_DICT - Z_BUF_ERROR];
  15241. return Z_BUF_ERROR;
  15242. } // Start a new block or continue the current one.
  15243. if (strm.avail_in !== 0 || lookahead !== 0 || flush != Z_NO_FLUSH && status != FINISH_STATE) {
  15244. bstate = -1;
  15245. switch (config_table[level].func) {
  15246. case STORED:
  15247. bstate = deflate_stored(flush);
  15248. break;
  15249. case FAST:
  15250. bstate = deflate_fast(flush);
  15251. break;
  15252. case SLOW:
  15253. bstate = deflate_slow(flush);
  15254. break;
  15255. default:
  15256. }
  15257. if (bstate == FinishStarted || bstate == FinishDone) {
  15258. status = FINISH_STATE;
  15259. }
  15260. if (bstate == NeedMore || bstate == FinishStarted) {
  15261. if (strm.avail_out === 0) {
  15262. last_flush = -1; // avoid BUF_ERROR next call, see above
  15263. }
  15264. return Z_OK; // If flush != Z_NO_FLUSH && avail_out === 0, the next call
  15265. // of deflate should use the same flush parameter to make sure
  15266. // that the flush is complete. So we don't have to output an
  15267. // empty block here, this will be done at next call. This also
  15268. // ensures that for a very small output buffer, we emit at most
  15269. // one empty block.
  15270. }
  15271. if (bstate == BlockDone) {
  15272. if (flush == Z_PARTIAL_FLUSH) {
  15273. _tr_align();
  15274. } else {
  15275. // FULL_FLUSH or SYNC_FLUSH
  15276. _tr_stored_block(0, 0, false); // For a full flush, this empty block will be recognized
  15277. // as a special marker by inflate_sync().
  15278. if (flush == Z_FULL_FLUSH) {
  15279. // state.head[s.hash_size-1]=0;
  15280. for (i = 0; i < hash_size
  15281. /*-1*/
  15282. ; i++) // forget history
  15283. head[i] = 0;
  15284. }
  15285. }
  15286. strm.flush_pending();
  15287. if (strm.avail_out === 0) {
  15288. last_flush = -1; // avoid BUF_ERROR at next call, see above
  15289. return Z_OK;
  15290. }
  15291. }
  15292. }
  15293. if (flush != Z_FINISH) return Z_OK;
  15294. return Z_STREAM_END;
  15295. };
  15296. } // ZStream
  15297. function ZStream() {
  15298. var that = this;
  15299. that.next_in_index = 0;
  15300. that.next_out_index = 0; // that.next_in; // next input byte
  15301. that.avail_in = 0; // number of bytes available at next_in
  15302. that.total_in = 0; // total nb of input bytes read so far
  15303. // that.next_out; // next output byte should be put there
  15304. that.avail_out = 0; // remaining free space at next_out
  15305. that.total_out = 0; // total nb of bytes output so far
  15306. // that.msg;
  15307. // that.dstate;
  15308. }
  15309. ZStream.prototype = {
  15310. deflateInit: function (level, bits) {
  15311. var that = this;
  15312. that.dstate = new Deflate();
  15313. if (!bits) bits = MAX_BITS;
  15314. return that.dstate.deflateInit(that, level, bits);
  15315. },
  15316. deflate: function (flush) {
  15317. var that = this;
  15318. if (!that.dstate) {
  15319. return Z_STREAM_ERROR;
  15320. }
  15321. return that.dstate.deflate(that, flush);
  15322. },
  15323. deflateEnd: function () {
  15324. var that = this;
  15325. if (!that.dstate) return Z_STREAM_ERROR;
  15326. var ret = that.dstate.deflateEnd();
  15327. that.dstate = null;
  15328. return ret;
  15329. },
  15330. deflateParams: function (level, strategy) {
  15331. var that = this;
  15332. if (!that.dstate) return Z_STREAM_ERROR;
  15333. return that.dstate.deflateParams(that, level, strategy);
  15334. },
  15335. deflateSetDictionary: function (dictionary, dictLength) {
  15336. var that = this;
  15337. if (!that.dstate) return Z_STREAM_ERROR;
  15338. return that.dstate.deflateSetDictionary(that, dictionary, dictLength);
  15339. },
  15340. // Read a new buffer from the current input stream, update the
  15341. // total number of bytes read. All deflate() input goes through
  15342. // this function so some applications may wish to modify it to avoid
  15343. // allocating a large strm->next_in buffer and copying from it.
  15344. // (See also flush_pending()).
  15345. read_buf: function (buf, start, size) {
  15346. var that = this;
  15347. var len = that.avail_in;
  15348. if (len > size) len = size;
  15349. if (len === 0) return 0;
  15350. that.avail_in -= len;
  15351. buf.set(that.next_in.subarray(that.next_in_index, that.next_in_index + len), start);
  15352. that.next_in_index += len;
  15353. that.total_in += len;
  15354. return len;
  15355. },
  15356. // Flush as much pending output as possible. All deflate() output goes
  15357. // through this function so some applications may wish to modify it
  15358. // to avoid allocating a large strm->next_out buffer and copying into it.
  15359. // (See also read_buf()).
  15360. flush_pending: function () {
  15361. var that = this;
  15362. var len = that.dstate.pending;
  15363. if (len > that.avail_out) len = that.avail_out;
  15364. if (len === 0) return; // if (that.dstate.pending_buf.length <= that.dstate.pending_out || that.next_out.length <= that.next_out_index
  15365. // || that.dstate.pending_buf.length < (that.dstate.pending_out + len) || that.next_out.length < (that.next_out_index +
  15366. // len)) {
  15367. // console.log(that.dstate.pending_buf.length + ", " + that.dstate.pending_out + ", " + that.next_out.length + ", " +
  15368. // that.next_out_index + ", " + len);
  15369. // console.log("avail_out=" + that.avail_out);
  15370. // }
  15371. that.next_out.set(that.dstate.pending_buf.subarray(that.dstate.pending_out, that.dstate.pending_out + len), that.next_out_index);
  15372. that.next_out_index += len;
  15373. that.dstate.pending_out += len;
  15374. that.total_out += len;
  15375. that.avail_out -= len;
  15376. that.dstate.pending -= len;
  15377. if (that.dstate.pending === 0) {
  15378. that.dstate.pending_out = 0;
  15379. }
  15380. }
  15381. }; // Deflater
  15382. function Deflater(options) {
  15383. var that = this;
  15384. var z = new ZStream();
  15385. var bufsize = 512;
  15386. var flush = Z_NO_FLUSH;
  15387. var buf = new Uint8Array(bufsize);
  15388. var level = options ? options.level : Z_DEFAULT_COMPRESSION;
  15389. if (typeof level == "undefined") level = Z_DEFAULT_COMPRESSION;
  15390. z.deflateInit(level);
  15391. z.next_out = buf;
  15392. that.append = function (data, onprogress) {
  15393. var err,
  15394. buffers = [],
  15395. lastIndex = 0,
  15396. bufferIndex = 0,
  15397. bufferSize = 0,
  15398. array;
  15399. if (!data.length) return;
  15400. z.next_in_index = 0;
  15401. z.next_in = data;
  15402. z.avail_in = data.length;
  15403. do {
  15404. z.next_out_index = 0;
  15405. z.avail_out = bufsize;
  15406. err = z.deflate(flush);
  15407. if (err != Z_OK) throw new Error("deflating: " + z.msg);
  15408. 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)));
  15409. bufferSize += z.next_out_index;
  15410. if (onprogress && z.next_in_index > 0 && z.next_in_index != lastIndex) {
  15411. onprogress(z.next_in_index);
  15412. lastIndex = z.next_in_index;
  15413. }
  15414. } while (z.avail_in > 0 || z.avail_out === 0);
  15415. array = new Uint8Array(bufferSize);
  15416. buffers.forEach(function (chunk) {
  15417. array.set(chunk, bufferIndex);
  15418. bufferIndex += chunk.length;
  15419. });
  15420. return array;
  15421. };
  15422. that.flush = function () {
  15423. var err,
  15424. buffers = [],
  15425. bufferIndex = 0,
  15426. bufferSize = 0,
  15427. array;
  15428. do {
  15429. z.next_out_index = 0;
  15430. z.avail_out = bufsize;
  15431. err = z.deflate(Z_FINISH);
  15432. if (err != Z_STREAM_END && err != Z_OK) throw new Error("deflating: " + z.msg);
  15433. if (bufsize - z.avail_out > 0) buffers.push(new Uint8Array(buf.subarray(0, z.next_out_index)));
  15434. bufferSize += z.next_out_index;
  15435. } while (z.avail_in > 0 || z.avail_out === 0);
  15436. z.deflateEnd();
  15437. array = new Uint8Array(bufferSize);
  15438. buffers.forEach(function (chunk) {
  15439. array.set(chunk, bufferIndex);
  15440. bufferIndex += chunk.length;
  15441. });
  15442. return array;
  15443. };
  15444. } // 'zip' may not be defined in z-worker and some tests
  15445. var env = global.zip || global;
  15446. env.Deflater = env._jzlib_Deflater = Deflater;
  15447. })(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
  15448. // while `this` is nsIContentFrameMessageManager
  15449. // with an attribute `content` that corresponds to the window
  15450. /**
  15451. * A class to parse color values
  15452. * @author Stoyan Stefanov <sstoo@gmail.com>
  15453. * @link http://www.phpied.com/rgb-color-parser-in-javascript/
  15454. * @license Use it if you like it
  15455. */
  15456. (function (global) {
  15457. function RGBColor(color_string) {
  15458. this.ok = false; // strip any leading #
  15459. if (color_string.charAt(0) == "#") {
  15460. // remove # if any
  15461. color_string = color_string.substr(1, 6);
  15462. }
  15463. color_string = color_string.replace(/ /g, "");
  15464. color_string = color_string.toLowerCase();
  15465. var channels; // before getting into regexps, try simple matches
  15466. // and overwrite the input
  15467. var simple_colors = {
  15468. aliceblue: "f0f8ff",
  15469. antiquewhite: "faebd7",
  15470. aqua: "00ffff",
  15471. aquamarine: "7fffd4",
  15472. azure: "f0ffff",
  15473. beige: "f5f5dc",
  15474. bisque: "ffe4c4",
  15475. black: "000000",
  15476. blanchedalmond: "ffebcd",
  15477. blue: "0000ff",
  15478. blueviolet: "8a2be2",
  15479. brown: "a52a2a",
  15480. burlywood: "deb887",
  15481. cadetblue: "5f9ea0",
  15482. chartreuse: "7fff00",
  15483. chocolate: "d2691e",
  15484. coral: "ff7f50",
  15485. cornflowerblue: "6495ed",
  15486. cornsilk: "fff8dc",
  15487. crimson: "dc143c",
  15488. cyan: "00ffff",
  15489. darkblue: "00008b",
  15490. darkcyan: "008b8b",
  15491. darkgoldenrod: "b8860b",
  15492. darkgray: "a9a9a9",
  15493. darkgreen: "006400",
  15494. darkkhaki: "bdb76b",
  15495. darkmagenta: "8b008b",
  15496. darkolivegreen: "556b2f",
  15497. darkorange: "ff8c00",
  15498. darkorchid: "9932cc",
  15499. darkred: "8b0000",
  15500. darksalmon: "e9967a",
  15501. darkseagreen: "8fbc8f",
  15502. darkslateblue: "483d8b",
  15503. darkslategray: "2f4f4f",
  15504. darkturquoise: "00ced1",
  15505. darkviolet: "9400d3",
  15506. deeppink: "ff1493",
  15507. deepskyblue: "00bfff",
  15508. dimgray: "696969",
  15509. dodgerblue: "1e90ff",
  15510. feldspar: "d19275",
  15511. firebrick: "b22222",
  15512. floralwhite: "fffaf0",
  15513. forestgreen: "228b22",
  15514. fuchsia: "ff00ff",
  15515. gainsboro: "dcdcdc",
  15516. ghostwhite: "f8f8ff",
  15517. gold: "ffd700",
  15518. goldenrod: "daa520",
  15519. gray: "808080",
  15520. green: "008000",
  15521. greenyellow: "adff2f",
  15522. honeydew: "f0fff0",
  15523. hotpink: "ff69b4",
  15524. indianred: "cd5c5c",
  15525. indigo: "4b0082",
  15526. ivory: "fffff0",
  15527. khaki: "f0e68c",
  15528. lavender: "e6e6fa",
  15529. lavenderblush: "fff0f5",
  15530. lawngreen: "7cfc00",
  15531. lemonchiffon: "fffacd",
  15532. lightblue: "add8e6",
  15533. lightcoral: "f08080",
  15534. lightcyan: "e0ffff",
  15535. lightgoldenrodyellow: "fafad2",
  15536. lightgrey: "d3d3d3",
  15537. lightgreen: "90ee90",
  15538. lightpink: "ffb6c1",
  15539. lightsalmon: "ffa07a",
  15540. lightseagreen: "20b2aa",
  15541. lightskyblue: "87cefa",
  15542. lightslateblue: "8470ff",
  15543. lightslategray: "778899",
  15544. lightsteelblue: "b0c4de",
  15545. lightyellow: "ffffe0",
  15546. lime: "00ff00",
  15547. limegreen: "32cd32",
  15548. linen: "faf0e6",
  15549. magenta: "ff00ff",
  15550. maroon: "800000",
  15551. mediumaquamarine: "66cdaa",
  15552. mediumblue: "0000cd",
  15553. mediumorchid: "ba55d3",
  15554. mediumpurple: "9370d8",
  15555. mediumseagreen: "3cb371",
  15556. mediumslateblue: "7b68ee",
  15557. mediumspringgreen: "00fa9a",
  15558. mediumturquoise: "48d1cc",
  15559. mediumvioletred: "c71585",
  15560. midnightblue: "191970",
  15561. mintcream: "f5fffa",
  15562. mistyrose: "ffe4e1",
  15563. moccasin: "ffe4b5",
  15564. navajowhite: "ffdead",
  15565. navy: "000080",
  15566. oldlace: "fdf5e6",
  15567. olive: "808000",
  15568. olivedrab: "6b8e23",
  15569. orange: "ffa500",
  15570. orangered: "ff4500",
  15571. orchid: "da70d6",
  15572. palegoldenrod: "eee8aa",
  15573. palegreen: "98fb98",
  15574. paleturquoise: "afeeee",
  15575. palevioletred: "d87093",
  15576. papayawhip: "ffefd5",
  15577. peachpuff: "ffdab9",
  15578. peru: "cd853f",
  15579. pink: "ffc0cb",
  15580. plum: "dda0dd",
  15581. powderblue: "b0e0e6",
  15582. purple: "800080",
  15583. red: "ff0000",
  15584. rosybrown: "bc8f8f",
  15585. royalblue: "4169e1",
  15586. saddlebrown: "8b4513",
  15587. salmon: "fa8072",
  15588. sandybrown: "f4a460",
  15589. seagreen: "2e8b57",
  15590. seashell: "fff5ee",
  15591. sienna: "a0522d",
  15592. silver: "c0c0c0",
  15593. skyblue: "87ceeb",
  15594. slateblue: "6a5acd",
  15595. slategray: "708090",
  15596. snow: "fffafa",
  15597. springgreen: "00ff7f",
  15598. steelblue: "4682b4",
  15599. tan: "d2b48c",
  15600. teal: "008080",
  15601. thistle: "d8bfd8",
  15602. tomato: "ff6347",
  15603. turquoise: "40e0d0",
  15604. violet: "ee82ee",
  15605. violetred: "d02090",
  15606. wheat: "f5deb3",
  15607. white: "ffffff",
  15608. whitesmoke: "f5f5f5",
  15609. yellow: "ffff00",
  15610. yellowgreen: "9acd32"
  15611. };
  15612. for (var key in simple_colors) {
  15613. if (color_string == key) {
  15614. color_string = simple_colors[key];
  15615. }
  15616. } // emd of simple type-in colors
  15617. // array of color definition objects
  15618. var color_defs = [{
  15619. re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,
  15620. example: ["rgb(123, 234, 45)", "rgb(255,234,245)"],
  15621. process: function (bits) {
  15622. return [parseInt(bits[1]), parseInt(bits[2]), parseInt(bits[3])];
  15623. }
  15624. }, {
  15625. re: /^(\w{2})(\w{2})(\w{2})$/,
  15626. example: ["#00ff00", "336699"],
  15627. process: function (bits) {
  15628. return [parseInt(bits[1], 16), parseInt(bits[2], 16), parseInt(bits[3], 16)];
  15629. }
  15630. }, {
  15631. re: /^(\w{1})(\w{1})(\w{1})$/,
  15632. example: ["#fb0", "f0f"],
  15633. process: function (bits) {
  15634. return [parseInt(bits[1] + bits[1], 16), parseInt(bits[2] + bits[2], 16), parseInt(bits[3] + bits[3], 16)];
  15635. }
  15636. }]; // search through the definitions to find a match
  15637. for (var i = 0; i < color_defs.length; i++) {
  15638. var re = color_defs[i].re;
  15639. var processor = color_defs[i].process;
  15640. var bits = re.exec(color_string);
  15641. if (bits) {
  15642. channels = processor(bits);
  15643. this.r = channels[0];
  15644. this.g = channels[1];
  15645. this.b = channels[2];
  15646. this.ok = true;
  15647. }
  15648. } // validate/cleanup values
  15649. this.r = this.r < 0 || isNaN(this.r) ? 0 : this.r > 255 ? 255 : this.r;
  15650. this.g = this.g < 0 || isNaN(this.g) ? 0 : this.g > 255 ? 255 : this.g;
  15651. this.b = this.b < 0 || isNaN(this.b) ? 0 : this.b > 255 ? 255 : this.b; // some getters
  15652. this.toRGB = function () {
  15653. return "rgb(" + this.r + ", " + this.g + ", " + this.b + ")";
  15654. };
  15655. this.toHex = function () {
  15656. var r = this.r.toString(16);
  15657. var g = this.g.toString(16);
  15658. var b = this.b.toString(16);
  15659. if (r.length == 1) r = "0" + r;
  15660. if (g.length == 1) g = "0" + g;
  15661. if (b.length == 1) b = "0" + b;
  15662. return "#" + r + g + b;
  15663. }; // help
  15664. this.getHelpXML = function () {
  15665. var examples = new Array(); // add regexps
  15666. for (var i = 0; i < color_defs.length; i++) {
  15667. var example = color_defs[i].example;
  15668. for (var j = 0; j < example.length; j++) {
  15669. examples[examples.length] = example[j];
  15670. }
  15671. } // add type-in colors
  15672. for (var sc in simple_colors) {
  15673. examples[examples.length] = sc;
  15674. }
  15675. var xml = document.createElement("ul");
  15676. xml.setAttribute("id", "rgbcolor-examples");
  15677. for (var i = 0; i < examples.length; i++) {
  15678. try {
  15679. var list_item = document.createElement("li");
  15680. var list_color = new RGBColor(examples[i]);
  15681. var example_div = document.createElement("div");
  15682. example_div.style.cssText = "margin: 3px; " + "border: 1px solid black; " + "background:" + list_color.toHex() + "; " + "color:" + list_color.toHex();
  15683. example_div.appendChild(document.createTextNode("test"));
  15684. var list_item_value = document.createTextNode(" " + examples[i] + " -> " + list_color.toRGB() + " -> " + list_color.toHex());
  15685. list_item.appendChild(example_div);
  15686. list_item.appendChild(list_item_value);
  15687. xml.appendChild(list_item);
  15688. } catch (e) {}
  15689. }
  15690. return xml;
  15691. };
  15692. }
  15693. global.RGBColor = RGBColor;
  15694. })(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
  15695. // while `this` is nsIContentFrameMessageManager
  15696. // with an attribute `content` that corresponds to the window
  15697. /************************************************
  15698. * Title : custom font *
  15699. * Start Data : 2017. 01. 22. *
  15700. * Comment : TEXT API *
  15701. ************************************************/
  15702. /******************************
  15703. * jsPDF extension API Design *
  15704. * ****************************/
  15705. (function (jsPDF) {
  15706. var PLUS = "+".charCodeAt(0);
  15707. var SLASH = "/".charCodeAt(0);
  15708. var NUMBER = "0".charCodeAt(0);
  15709. var LOWER = "a".charCodeAt(0);
  15710. var UPPER = "A".charCodeAt(0);
  15711. var PLUS_URL_SAFE = "-".charCodeAt(0);
  15712. var SLASH_URL_SAFE = "_".charCodeAt(0);
  15713. /*****************************************************************/
  15714. /* function : b64ToByteArray */
  15715. /* comment : Base64 encoded TTF file contents (b64) are decoded */
  15716. /* by Byte array and stored. */
  15717. /*****************************************************************/
  15718. var b64ToByteArray = function (b64) {
  15719. var i, j, l, tmp, placeHolders, arr;
  15720. if (b64.length % 4 > 0) {
  15721. throw new Error("Invalid string. Length must be a multiple of 4");
  15722. } // the number of equal signs (place holders)
  15723. // if there are two placeholders, than the two characters before it
  15724. // represent one byte
  15725. // if there is only one, then the three characters before it represent 2 bytes
  15726. // this is just a cheap hack to not do indexOf twice
  15727. var len = b64.length;
  15728. placeHolders = "=" === b64.charAt(len - 2) ? 2 : "=" === b64.charAt(len - 1) ? 1 : 0; // base64 is 4/3 + up to two characters of the original data
  15729. arr = new Uint8Array(b64.length * 3 / 4 - placeHolders); // if there are placeholders, only get up to the last complete 4 chars
  15730. l = placeHolders > 0 ? b64.length - 4 : b64.length;
  15731. var L = 0;
  15732. function push(v) {
  15733. arr[L++] = v;
  15734. }
  15735. for (i = 0, j = 0; i < l; i += 4, j += 3) {
  15736. tmp = decode(b64.charAt(i)) << 18 | decode(b64.charAt(i + 1)) << 12 | decode(b64.charAt(i + 2)) << 6 | decode(b64.charAt(i + 3));
  15737. push((tmp & 0xff0000) >> 16);
  15738. push((tmp & 0xff00) >> 8);
  15739. push(tmp & 0xff);
  15740. }
  15741. if (placeHolders === 2) {
  15742. tmp = decode(b64.charAt(i)) << 2 | decode(b64.charAt(i + 1)) >> 4;
  15743. push(tmp & 0xff);
  15744. } else if (placeHolders === 1) {
  15745. tmp = decode(b64.charAt(i)) << 10 | decode(b64.charAt(i + 1)) << 4 | decode(b64.charAt(i + 2)) >> 2;
  15746. push(tmp >> 8 & 0xff);
  15747. push(tmp & 0xff);
  15748. }
  15749. return arr;
  15750. };
  15751. /***************************************************************/
  15752. /* function : decode */
  15753. /* comment : Change the base64 encoded font's content to match */
  15754. /* the base64 index value. */
  15755. /***************************************************************/
  15756. var decode = function (elt) {
  15757. var code = elt.charCodeAt(0);
  15758. if (code === PLUS || code === PLUS_URL_SAFE) return 62; // '+'
  15759. if (code === SLASH || code === SLASH_URL_SAFE) return 63; // '/'
  15760. if (code < NUMBER) return -1; //no match
  15761. if (code < NUMBER + 10) return code - NUMBER + 26 + 26;
  15762. if (code < UPPER + 26) return code - UPPER;
  15763. if (code < LOWER + 26) return code - LOWER + 26;
  15764. };
  15765. jsPDF.API.TTFFont = function () {
  15766. /************************************************************************/
  15767. /* function : open */
  15768. /* comment : Decode the encoded ttf content and create a TTFFont object. */
  15769. /************************************************************************/
  15770. TTFFont.open = function (filename, name, vfs, encoding) {
  15771. var contents;
  15772. if (typeof vfs !== "string") {
  15773. throw new Error("Invalid argument supplied in TTFFont.open");
  15774. }
  15775. contents = b64ToByteArray(vfs);
  15776. return new TTFFont(contents, name, encoding);
  15777. };
  15778. /***************************************************************/
  15779. /* function : TTFFont gernerator */
  15780. /* comment : Decode TTF contents are parsed, Data, */
  15781. /* Subset object is created, and registerTTF function is called.*/
  15782. /***************************************************************/
  15783. function TTFFont(rawData, name, encoding) {
  15784. var data;
  15785. this.rawData = rawData;
  15786. data = this.contents = new Data(rawData);
  15787. this.contents.pos = 4;
  15788. if (data.readString(4) === "ttcf") {
  15789. if (!name) {
  15790. throw new Error("Must specify a font name for TTC files.");
  15791. }
  15792. throw new Error("Font " + name + " not found in TTC file.");
  15793. } else {
  15794. data.pos = 0;
  15795. this.parse();
  15796. this.subset = new Subset(this);
  15797. this.registerTTF();
  15798. }
  15799. }
  15800. /********************************************************/
  15801. /* function : parse */
  15802. /* comment : TTF Parses the file contents by each table.*/
  15803. /********************************************************/
  15804. TTFFont.prototype.parse = function () {
  15805. this.directory = new Directory(this.contents);
  15806. this.head = new HeadTable(this);
  15807. this.name = new NameTable(this);
  15808. this.cmap = new CmapTable(this);
  15809. this.toUnicode = new Map();
  15810. this.hhea = new HheaTable(this);
  15811. this.maxp = new MaxpTable(this);
  15812. this.hmtx = new HmtxTable(this);
  15813. this.post = new PostTable(this);
  15814. this.os2 = new OS2Table(this);
  15815. this.loca = new LocaTable(this);
  15816. this.glyf = new GlyfTable(this);
  15817. this.ascender = this.os2.exists && this.os2.ascender || this.hhea.ascender;
  15818. this.decender = this.os2.exists && this.os2.decender || this.hhea.decender;
  15819. this.lineGap = this.os2.exists && this.os2.lineGap || this.hhea.lineGap;
  15820. return this.bbox = [this.head.xMin, this.head.yMin, this.head.xMax, this.head.yMax];
  15821. };
  15822. /***************************************************************/
  15823. /* function : registerTTF */
  15824. /* comment : Get the value to assign pdf font descriptors. */
  15825. /***************************************************************/
  15826. TTFFont.prototype.registerTTF = function () {
  15827. var e, hi, low, raw, _ref;
  15828. this.scaleFactor = 1000.0 / this.head.unitsPerEm;
  15829. this.bbox = function () {
  15830. var _i, _len, _ref, _results;
  15831. _ref = this.bbox;
  15832. _results = [];
  15833. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  15834. e = _ref[_i];
  15835. _results.push(Math.round(e * this.scaleFactor));
  15836. }
  15837. return _results;
  15838. }.call(this);
  15839. this.stemV = 0;
  15840. if (this.post.exists) {
  15841. raw = this.post.italic_angle;
  15842. hi = raw >> 16;
  15843. low = raw & 0xff;
  15844. if (hi & 0x8000 !== 0) {
  15845. hi = -((hi ^ 0xffff) + 1);
  15846. }
  15847. this.italicAngle = +("" + hi + "." + low);
  15848. } else {
  15849. this.italicAngle = 0;
  15850. }
  15851. this.ascender = Math.round(this.ascender * this.scaleFactor);
  15852. this.decender = Math.round(this.decender * this.scaleFactor);
  15853. this.lineGap = Math.round(this.lineGap * this.scaleFactor);
  15854. this.capHeight = this.os2.exists && this.os2.capHeight || this.ascender;
  15855. this.xHeight = this.os2.exists && this.os2.xHeight || 0;
  15856. this.familyClass = (this.os2.exists && this.os2.familyClass || 0) >> 8;
  15857. this.isSerif = (_ref = this.familyClass) === 1 || _ref === 2 || _ref === 3 || _ref === 4 || _ref === 5 || _ref === 7;
  15858. this.isScript = this.familyClass === 10;
  15859. this.flags = 0;
  15860. if (this.post.isFixedPitch) {
  15861. this.flags |= 1 << 0;
  15862. }
  15863. if (this.isSerif) {
  15864. this.flags |= 1 << 1;
  15865. }
  15866. if (this.isScript) {
  15867. this.flags |= 1 << 3;
  15868. }
  15869. if (this.italicAngle !== 0) {
  15870. this.flags |= 1 << 6;
  15871. }
  15872. this.flags |= 1 << 5;
  15873. if (!this.cmap.unicode) {
  15874. throw new Error("No unicode cmap for font");
  15875. }
  15876. };
  15877. TTFFont.prototype.characterToGlyph = function (character) {
  15878. var _ref;
  15879. return ((_ref = this.cmap.unicode) != null ? _ref.codeMap[character] : void 0) || 0;
  15880. };
  15881. TTFFont.prototype.widthOfGlyph = function (glyph) {
  15882. var scale;
  15883. scale = 1000.0 / this.head.unitsPerEm;
  15884. return this.hmtx.forGlyph(glyph).advance * scale;
  15885. };
  15886. TTFFont.prototype.widthOfString = function (string, size, charSpace) {
  15887. var charCode, i, scale, width, _i, _ref, charSpace;
  15888. string = "" + string;
  15889. width = 0;
  15890. for (i = _i = 0, _ref = string.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
  15891. charCode = string.charCodeAt(i);
  15892. width += this.widthOfGlyph(this.characterToGlyph(charCode)) + charSpace * (1000 / size) || 0;
  15893. }
  15894. scale = size / 1000;
  15895. return width * scale;
  15896. };
  15897. TTFFont.prototype.lineHeight = function (size, includeGap) {
  15898. var gap;
  15899. if (includeGap == null) {
  15900. includeGap = false;
  15901. }
  15902. gap = includeGap ? this.lineGap : 0;
  15903. return (this.ascender + gap - this.decender) / 1000 * size;
  15904. };
  15905. return TTFFont;
  15906. }();
  15907. /************************************************************************************************/
  15908. /* function : Data */
  15909. /* comment : The ttf data decoded and stored in an array is read and written to the Data object.*/
  15910. /************************************************************************************************/
  15911. var Data = function () {
  15912. function Data(data) {
  15913. this.data = data != null ? data : [];
  15914. this.pos = 0;
  15915. this.length = this.data.length;
  15916. }
  15917. Data.prototype.readByte = function () {
  15918. return this.data[this.pos++];
  15919. };
  15920. Data.prototype.writeByte = function (byte) {
  15921. return this.data[this.pos++] = byte;
  15922. };
  15923. Data.prototype.readUInt32 = function () {
  15924. var b1, b2, b3, b4;
  15925. b1 = this.readByte() * 0x1000000;
  15926. b2 = this.readByte() << 16;
  15927. b3 = this.readByte() << 8;
  15928. b4 = this.readByte();
  15929. return b1 + b2 + b3 + b4;
  15930. };
  15931. Data.prototype.writeUInt32 = function (val) {
  15932. this.writeByte(val >>> 24 & 0xff);
  15933. this.writeByte(val >> 16 & 0xff);
  15934. this.writeByte(val >> 8 & 0xff);
  15935. return this.writeByte(val & 0xff);
  15936. };
  15937. Data.prototype.readInt32 = function () {
  15938. var int;
  15939. int = this.readUInt32();
  15940. if (int >= 0x80000000) {
  15941. return int - 0x100000000;
  15942. } else {
  15943. return int;
  15944. }
  15945. };
  15946. Data.prototype.writeInt32 = function (val) {
  15947. if (val < 0) {
  15948. val += 0x100000000;
  15949. }
  15950. return this.writeUInt32(val);
  15951. };
  15952. Data.prototype.readUInt16 = function () {
  15953. var b1, b2;
  15954. b1 = this.readByte() << 8;
  15955. b2 = this.readByte();
  15956. return b1 | b2;
  15957. };
  15958. Data.prototype.writeUInt16 = function (val) {
  15959. this.writeByte(val >> 8 & 0xff);
  15960. return this.writeByte(val & 0xff);
  15961. };
  15962. Data.prototype.readInt16 = function () {
  15963. var int;
  15964. int = this.readUInt16();
  15965. if (int >= 0x8000) {
  15966. return int - 0x10000;
  15967. } else {
  15968. return int;
  15969. }
  15970. };
  15971. Data.prototype.writeInt16 = function (val) {
  15972. if (val < 0) {
  15973. val += 0x10000;
  15974. }
  15975. return this.writeUInt16(val);
  15976. };
  15977. Data.prototype.readString = function (length) {
  15978. var i, ret, _i;
  15979. ret = [];
  15980. for (i = _i = 0; 0 <= length ? _i < length : _i > length; i = 0 <= length ? ++_i : --_i) {
  15981. ret[i] = String.fromCharCode(this.readByte());
  15982. }
  15983. return ret.join("");
  15984. };
  15985. Data.prototype.writeString = function (val) {
  15986. var i, _i, _ref, _results;
  15987. _results = [];
  15988. for (i = _i = 0, _ref = val.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
  15989. _results.push(this.writeByte(val.charCodeAt(i)));
  15990. }
  15991. return _results;
  15992. };
  15993. /*Data.prototype.stringAt = function (pos, length) {
  15994. this.pos = pos;
  15995. return this.readString(length);
  15996. };*/
  15997. Data.prototype.readShort = function () {
  15998. return this.readInt16();
  15999. };
  16000. Data.prototype.writeShort = function (val) {
  16001. return this.writeInt16(val);
  16002. };
  16003. Data.prototype.readLongLong = function () {
  16004. var b1, b2, b3, b4, b5, b6, b7, b8;
  16005. b1 = this.readByte();
  16006. b2 = this.readByte();
  16007. b3 = this.readByte();
  16008. b4 = this.readByte();
  16009. b5 = this.readByte();
  16010. b6 = this.readByte();
  16011. b7 = this.readByte();
  16012. b8 = this.readByte();
  16013. if (b1 & 0x80) {
  16014. 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;
  16015. }
  16016. return b1 * 0x100000000000000 + b2 * 0x1000000000000 + b3 * 0x10000000000 + b4 * 0x100000000 + b5 * 0x1000000 + b6 * 0x10000 + b7 * 0x100 + b8;
  16017. };
  16018. Data.prototype.writeLongLong = function (val) {
  16019. var high, low;
  16020. high = Math.floor(val / 0x100000000);
  16021. low = val & 0xffffffff;
  16022. this.writeByte(high >> 24 & 0xff);
  16023. this.writeByte(high >> 16 & 0xff);
  16024. this.writeByte(high >> 8 & 0xff);
  16025. this.writeByte(high & 0xff);
  16026. this.writeByte(low >> 24 & 0xff);
  16027. this.writeByte(low >> 16 & 0xff);
  16028. this.writeByte(low >> 8 & 0xff);
  16029. return this.writeByte(low & 0xff);
  16030. };
  16031. Data.prototype.readInt = function () {
  16032. return this.readInt32();
  16033. };
  16034. Data.prototype.writeInt = function (val) {
  16035. return this.writeInt32(val);
  16036. };
  16037. /*Data.prototype.slice = function (start, end) {
  16038. return this.data.slice(start, end);
  16039. };*/
  16040. Data.prototype.read = function (bytes) {
  16041. var buf, i, _i;
  16042. buf = [];
  16043. for (i = _i = 0; 0 <= bytes ? _i < bytes : _i > bytes; i = 0 <= bytes ? ++_i : --_i) {
  16044. buf.push(this.readByte());
  16045. }
  16046. return buf;
  16047. };
  16048. Data.prototype.write = function (bytes) {
  16049. var byte, _i, _len, _results;
  16050. _results = [];
  16051. for (_i = 0, _len = bytes.length; _i < _len; _i++) {
  16052. byte = bytes[_i];
  16053. _results.push(this.writeByte(byte));
  16054. }
  16055. return _results;
  16056. };
  16057. return Data;
  16058. }();
  16059. var Directory = function () {
  16060. var checksum;
  16061. /*****************************************************************************************************/
  16062. /* function : Directory generator */
  16063. /* comment : Initialize the offset, tag, length, and checksum for each table for the font to be used.*/
  16064. /*****************************************************************************************************/
  16065. function Directory(data) {
  16066. var entry, i, _i, _ref;
  16067. this.scalarType = data.readInt();
  16068. this.tableCount = data.readShort();
  16069. this.searchRange = data.readShort();
  16070. this.entrySelector = data.readShort();
  16071. this.rangeShift = data.readShort();
  16072. this.tables = {};
  16073. for (i = _i = 0, _ref = this.tableCount; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
  16074. entry = {
  16075. tag: data.readString(4),
  16076. checksum: data.readInt(),
  16077. offset: data.readInt(),
  16078. length: data.readInt()
  16079. };
  16080. this.tables[entry.tag] = entry;
  16081. }
  16082. }
  16083. /********************************************************************************************************/
  16084. /* function : encode */
  16085. /* comment : It encodes and stores the font table object and information used for the directory object. */
  16086. /********************************************************************************************************/
  16087. Directory.prototype.encode = function (tables) {
  16088. var adjustment, directory, directoryLength, entrySelector, headOffset, log2, offset, rangeShift, searchRange, sum, table, tableCount, tableData, tag;
  16089. tableCount = Object.keys(tables).length;
  16090. log2 = Math.log(2);
  16091. searchRange = Math.floor(Math.log(tableCount) / log2) * 16;
  16092. entrySelector = Math.floor(searchRange / log2);
  16093. rangeShift = tableCount * 16 - searchRange;
  16094. directory = new Data();
  16095. directory.writeInt(this.scalarType);
  16096. directory.writeShort(tableCount);
  16097. directory.writeShort(searchRange);
  16098. directory.writeShort(entrySelector);
  16099. directory.writeShort(rangeShift);
  16100. directoryLength = tableCount * 16;
  16101. offset = directory.pos + directoryLength;
  16102. headOffset = null;
  16103. tableData = [];
  16104. for (tag in tables) {
  16105. table = tables[tag];
  16106. directory.writeString(tag);
  16107. directory.writeInt(checksum(table));
  16108. directory.writeInt(offset);
  16109. directory.writeInt(table.length);
  16110. tableData = tableData.concat(table);
  16111. if (tag === "head") {
  16112. headOffset = offset;
  16113. }
  16114. offset += table.length;
  16115. while (offset % 4) {
  16116. tableData.push(0);
  16117. offset++;
  16118. }
  16119. }
  16120. directory.write(tableData);
  16121. sum = checksum(directory.data);
  16122. adjustment = 0xb1b0afba - sum;
  16123. directory.pos = headOffset + 8;
  16124. directory.writeUInt32(adjustment);
  16125. return directory.data;
  16126. };
  16127. /***************************************************************/
  16128. /* function : checksum */
  16129. /* comment : Duplicate the table for the tag. */
  16130. /***************************************************************/
  16131. checksum = function (data) {
  16132. var i, sum, tmp, _i, _ref;
  16133. data = __slice.call(data);
  16134. while (data.length % 4) {
  16135. data.push(0);
  16136. }
  16137. tmp = new Data(data);
  16138. sum = 0;
  16139. for (i = _i = 0, _ref = data.length; _i < _ref; i = _i += 4) {
  16140. sum += tmp.readUInt32();
  16141. }
  16142. return sum & 0xffffffff;
  16143. };
  16144. return Directory;
  16145. }();
  16146. var Table,
  16147. __hasProp = {}.hasOwnProperty,
  16148. __extends = function (child, parent) {
  16149. for (var key in parent) {
  16150. if (__hasProp.call(parent, key)) child[key] = parent[key];
  16151. }
  16152. function ctor() {
  16153. this.constructor = child;
  16154. }
  16155. ctor.prototype = parent.prototype;
  16156. child.prototype = new ctor();
  16157. child.__super__ = parent.prototype;
  16158. return child;
  16159. };
  16160. /***************************************************************/
  16161. /* function : Table */
  16162. /* comment : Save info for each table, and parse the table. */
  16163. /***************************************************************/
  16164. Table = function () {
  16165. function Table(file) {
  16166. var info;
  16167. this.file = file;
  16168. info = this.file.directory.tables[this.tag];
  16169. this.exists = !!info;
  16170. if (info) {
  16171. this.offset = info.offset, this.length = info.length;
  16172. this.parse(this.file.contents);
  16173. }
  16174. }
  16175. Table.prototype.parse = function () {};
  16176. Table.prototype.encode = function () {};
  16177. Table.prototype.raw = function () {
  16178. if (!this.exists) {
  16179. return null;
  16180. }
  16181. this.file.contents.pos = this.offset;
  16182. return this.file.contents.read(this.length);
  16183. };
  16184. return Table;
  16185. }();
  16186. var HeadTable = function (_super) {
  16187. __extends(HeadTable, _super);
  16188. function HeadTable() {
  16189. return HeadTable.__super__.constructor.apply(this, arguments);
  16190. }
  16191. HeadTable.prototype.tag = "head";
  16192. HeadTable.prototype.parse = function (data) {
  16193. data.pos = this.offset;
  16194. this.version = data.readInt();
  16195. this.revision = data.readInt();
  16196. this.checkSumAdjustment = data.readInt();
  16197. this.magicNumber = data.readInt();
  16198. this.flags = data.readShort();
  16199. this.unitsPerEm = data.readShort();
  16200. this.created = data.readLongLong();
  16201. this.modified = data.readLongLong();
  16202. this.xMin = data.readShort();
  16203. this.yMin = data.readShort();
  16204. this.xMax = data.readShort();
  16205. this.yMax = data.readShort();
  16206. this.macStyle = data.readShort();
  16207. this.lowestRecPPEM = data.readShort();
  16208. this.fontDirectionHint = data.readShort();
  16209. this.indexToLocFormat = data.readShort();
  16210. return this.glyphDataFormat = data.readShort();
  16211. };
  16212. HeadTable.prototype.encode = function (indexToLocFormat) {
  16213. var table;
  16214. table = new Data();
  16215. table.writeInt(this.version);
  16216. table.writeInt(this.revision);
  16217. table.writeInt(this.checkSumAdjustment);
  16218. table.writeInt(this.magicNumber);
  16219. table.writeShort(this.flags);
  16220. table.writeShort(this.unitsPerEm);
  16221. table.writeLongLong(this.created);
  16222. table.writeLongLong(this.modified);
  16223. table.writeShort(this.xMin);
  16224. table.writeShort(this.yMin);
  16225. table.writeShort(this.xMax);
  16226. table.writeShort(this.yMax);
  16227. table.writeShort(this.macStyle);
  16228. table.writeShort(this.lowestRecPPEM);
  16229. table.writeShort(this.fontDirectionHint);
  16230. table.writeShort(indexToLocFormat);
  16231. table.writeShort(this.glyphDataFormat);
  16232. return table.data;
  16233. };
  16234. return HeadTable;
  16235. }(Table);
  16236. /************************************************************************************/
  16237. /* function : CmapEntry */
  16238. /* comment : Cmap Initializes and encodes object information (required by pdf spec).*/
  16239. /************************************************************************************/
  16240. var CmapEntry = function () {
  16241. function CmapEntry(data, offset) {
  16242. var code, count, endCode, glyphId, glyphIds, i, idDelta, idRangeOffset, index, saveOffset, segCount, segCountX2, start, startCode, tail, _i, _j, _k, _len;
  16243. this.platformID = data.readUInt16();
  16244. this.encodingID = data.readShort();
  16245. this.offset = offset + data.readInt();
  16246. saveOffset = data.pos;
  16247. data.pos = this.offset;
  16248. this.format = data.readUInt16();
  16249. this.length = data.readUInt16();
  16250. this.language = data.readUInt16();
  16251. this.isUnicode = this.platformID === 3 && this.encodingID === 1 && this.format === 4 || this.platformID === 0 && this.format === 4;
  16252. this.codeMap = {};
  16253. switch (this.format) {
  16254. case 0:
  16255. for (i = _i = 0; _i < 256; i = ++_i) {
  16256. this.codeMap[i] = data.readByte();
  16257. }
  16258. break;
  16259. case 4:
  16260. segCountX2 = data.readUInt16();
  16261. segCount = segCountX2 / 2;
  16262. data.pos += 6;
  16263. endCode = function () {
  16264. var _j, _results;
  16265. _results = [];
  16266. for (i = _j = 0; 0 <= segCount ? _j < segCount : _j > segCount; i = 0 <= segCount ? ++_j : --_j) {
  16267. _results.push(data.readUInt16());
  16268. }
  16269. return _results;
  16270. }();
  16271. data.pos += 2;
  16272. startCode = function () {
  16273. var _j, _results;
  16274. _results = [];
  16275. for (i = _j = 0; 0 <= segCount ? _j < segCount : _j > segCount; i = 0 <= segCount ? ++_j : --_j) {
  16276. _results.push(data.readUInt16());
  16277. }
  16278. return _results;
  16279. }();
  16280. idDelta = function () {
  16281. var _j, _results;
  16282. _results = [];
  16283. for (i = _j = 0; 0 <= segCount ? _j < segCount : _j > segCount; i = 0 <= segCount ? ++_j : --_j) {
  16284. _results.push(data.readUInt16());
  16285. }
  16286. return _results;
  16287. }();
  16288. idRangeOffset = function () {
  16289. var _j, _results;
  16290. _results = [];
  16291. for (i = _j = 0; 0 <= segCount ? _j < segCount : _j > segCount; i = 0 <= segCount ? ++_j : --_j) {
  16292. _results.push(data.readUInt16());
  16293. }
  16294. return _results;
  16295. }();
  16296. count = (this.length - data.pos + this.offset) / 2;
  16297. glyphIds = function () {
  16298. var _j, _results;
  16299. _results = [];
  16300. for (i = _j = 0; 0 <= count ? _j < count : _j > count; i = 0 <= count ? ++_j : --_j) {
  16301. _results.push(data.readUInt16());
  16302. }
  16303. return _results;
  16304. }();
  16305. for (i = _j = 0, _len = endCode.length; _j < _len; i = ++_j) {
  16306. tail = endCode[i];
  16307. start = startCode[i];
  16308. for (code = _k = start; start <= tail ? _k <= tail : _k >= tail; code = start <= tail ? ++_k : --_k) {
  16309. if (idRangeOffset[i] === 0) {
  16310. glyphId = code + idDelta[i];
  16311. } else {
  16312. index = idRangeOffset[i] / 2 + (code - start) - (segCount - i);
  16313. glyphId = glyphIds[index] || 0;
  16314. if (glyphId !== 0) {
  16315. glyphId += idDelta[i];
  16316. }
  16317. }
  16318. this.codeMap[code] = glyphId & 0xffff;
  16319. }
  16320. }
  16321. }
  16322. data.pos = saveOffset;
  16323. }
  16324. CmapEntry.encode = function (charmap, encoding) {
  16325. 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;
  16326. subtable = new Data();
  16327. codes = Object.keys(charmap).sort(function (a, b) {
  16328. return a - b;
  16329. });
  16330. switch (encoding) {
  16331. case "macroman":
  16332. id = 0;
  16333. indexes = function () {
  16334. var _i, _results;
  16335. _results = [];
  16336. for (i = _i = 0; _i < 256; i = ++_i) {
  16337. _results.push(0);
  16338. }
  16339. return _results;
  16340. }();
  16341. map = {
  16342. 0: 0
  16343. };
  16344. codeMap = {};
  16345. for (_i = 0, _len = codes.length; _i < _len; _i++) {
  16346. code = codes[_i];
  16347. if (map[_name = charmap[code]] == null) {
  16348. map[_name] = ++id;
  16349. }
  16350. codeMap[code] = {
  16351. old: charmap[code],
  16352. new: map[charmap[code]]
  16353. };
  16354. indexes[code] = map[charmap[code]];
  16355. }
  16356. subtable.writeUInt16(1);
  16357. subtable.writeUInt16(0);
  16358. subtable.writeUInt32(12);
  16359. subtable.writeUInt16(0);
  16360. subtable.writeUInt16(262);
  16361. subtable.writeUInt16(0);
  16362. subtable.write(indexes);
  16363. return result = {
  16364. charMap: codeMap,
  16365. subtable: subtable.data,
  16366. maxGlyphID: id + 1
  16367. };
  16368. case "unicode":
  16369. startCodes = [];
  16370. endCodes = [];
  16371. nextID = 0;
  16372. map = {};
  16373. charMap = {};
  16374. last = diff = null;
  16375. for (_j = 0, _len1 = codes.length; _j < _len1; _j++) {
  16376. code = codes[_j];
  16377. old = charmap[code];
  16378. if (map[old] == null) {
  16379. map[old] = ++nextID;
  16380. }
  16381. charMap[code] = {
  16382. old: old,
  16383. new: map[old]
  16384. };
  16385. delta = map[old] - code;
  16386. if (last == null || delta !== diff) {
  16387. if (last) {
  16388. endCodes.push(last);
  16389. }
  16390. startCodes.push(code);
  16391. diff = delta;
  16392. }
  16393. last = code;
  16394. }
  16395. if (last) {
  16396. endCodes.push(last);
  16397. }
  16398. endCodes.push(0xffff);
  16399. startCodes.push(0xffff);
  16400. segCount = startCodes.length;
  16401. segCountX2 = segCount * 2;
  16402. searchRange = 2 * Math.pow(Math.log(segCount) / Math.LN2, 2);
  16403. entrySelector = Math.log(searchRange / 2) / Math.LN2;
  16404. rangeShift = 2 * segCount - searchRange;
  16405. deltas = [];
  16406. rangeOffsets = [];
  16407. glyphIDs = [];
  16408. for (i = _k = 0, _len2 = startCodes.length; _k < _len2; i = ++_k) {
  16409. startCode = startCodes[i];
  16410. endCode = endCodes[i];
  16411. if (startCode === 0xffff) {
  16412. deltas.push(0);
  16413. rangeOffsets.push(0);
  16414. break;
  16415. }
  16416. startGlyph = charMap[startCode]["new"];
  16417. if (startCode - startGlyph >= 0x8000) {
  16418. deltas.push(0);
  16419. rangeOffsets.push(2 * (glyphIDs.length + segCount - i));
  16420. for (code = _l = startCode; startCode <= endCode ? _l <= endCode : _l >= endCode; code = startCode <= endCode ? ++_l : --_l) {
  16421. glyphIDs.push(charMap[code]["new"]);
  16422. }
  16423. } else {
  16424. deltas.push(startGlyph - startCode);
  16425. rangeOffsets.push(0);
  16426. }
  16427. }
  16428. subtable.writeUInt16(3);
  16429. subtable.writeUInt16(1);
  16430. subtable.writeUInt32(12);
  16431. subtable.writeUInt16(4);
  16432. subtable.writeUInt16(16 + segCount * 8 + glyphIDs.length * 2);
  16433. subtable.writeUInt16(0);
  16434. subtable.writeUInt16(segCountX2);
  16435. subtable.writeUInt16(searchRange);
  16436. subtable.writeUInt16(entrySelector);
  16437. subtable.writeUInt16(rangeShift);
  16438. for (_m = 0, _len3 = endCodes.length; _m < _len3; _m++) {
  16439. code = endCodes[_m];
  16440. subtable.writeUInt16(code);
  16441. }
  16442. subtable.writeUInt16(0);
  16443. for (_n = 0, _len4 = startCodes.length; _n < _len4; _n++) {
  16444. code = startCodes[_n];
  16445. subtable.writeUInt16(code);
  16446. }
  16447. for (_o = 0, _len5 = deltas.length; _o < _len5; _o++) {
  16448. delta = deltas[_o];
  16449. subtable.writeUInt16(delta);
  16450. }
  16451. for (_p = 0, _len6 = rangeOffsets.length; _p < _len6; _p++) {
  16452. offset = rangeOffsets[_p];
  16453. subtable.writeUInt16(offset);
  16454. }
  16455. for (_q = 0, _len7 = glyphIDs.length; _q < _len7; _q++) {
  16456. id = glyphIDs[_q];
  16457. subtable.writeUInt16(id);
  16458. }
  16459. return result = {
  16460. charMap: charMap,
  16461. subtable: subtable.data,
  16462. maxGlyphID: nextID + 1
  16463. };
  16464. }
  16465. };
  16466. return CmapEntry;
  16467. }();
  16468. var CmapTable = function (_super) {
  16469. __extends(CmapTable, _super);
  16470. function CmapTable() {
  16471. return CmapTable.__super__.constructor.apply(this, arguments);
  16472. }
  16473. CmapTable.prototype.tag = "cmap";
  16474. CmapTable.prototype.parse = function (data) {
  16475. var entry, i, tableCount, _i;
  16476. data.pos = this.offset;
  16477. this.version = data.readUInt16();
  16478. tableCount = data.readUInt16();
  16479. this.tables = [];
  16480. this.unicode = null;
  16481. for (i = _i = 0; 0 <= tableCount ? _i < tableCount : _i > tableCount; i = 0 <= tableCount ? ++_i : --_i) {
  16482. entry = new CmapEntry(data, this.offset);
  16483. this.tables.push(entry);
  16484. if (entry.isUnicode) {
  16485. if (this.unicode == null) {
  16486. this.unicode = entry;
  16487. }
  16488. }
  16489. }
  16490. return true;
  16491. };
  16492. /*************************************************************************/
  16493. /* function : encode */
  16494. /* comment : Encode the cmap table corresponding to the input character. */
  16495. /*************************************************************************/
  16496. CmapTable.encode = function (charmap, encoding) {
  16497. var result, table;
  16498. if (encoding == null) {
  16499. encoding = "macroman";
  16500. }
  16501. result = CmapEntry.encode(charmap, encoding);
  16502. table = new Data();
  16503. table.writeUInt16(0);
  16504. table.writeUInt16(1);
  16505. result.table = table.data.concat(result.subtable);
  16506. return result;
  16507. };
  16508. return CmapTable;
  16509. }(Table);
  16510. var HheaTable = function (_super) {
  16511. __extends(HheaTable, _super);
  16512. function HheaTable() {
  16513. return HheaTable.__super__.constructor.apply(this, arguments);
  16514. }
  16515. HheaTable.prototype.tag = "hhea";
  16516. HheaTable.prototype.parse = function (data) {
  16517. data.pos = this.offset;
  16518. this.version = data.readInt();
  16519. this.ascender = data.readShort();
  16520. this.decender = data.readShort();
  16521. this.lineGap = data.readShort();
  16522. this.advanceWidthMax = data.readShort();
  16523. this.minLeftSideBearing = data.readShort();
  16524. this.minRightSideBearing = data.readShort();
  16525. this.xMaxExtent = data.readShort();
  16526. this.caretSlopeRise = data.readShort();
  16527. this.caretSlopeRun = data.readShort();
  16528. this.caretOffset = data.readShort();
  16529. data.pos += 4 * 2;
  16530. this.metricDataFormat = data.readShort();
  16531. return this.numberOfMetrics = data.readUInt16();
  16532. };
  16533. /*HheaTable.prototype.encode = function (ids) {
  16534. var i, table, _i, _ref;
  16535. table = new Data;
  16536. table.writeInt(this.version);
  16537. table.writeShort(this.ascender);
  16538. table.writeShort(this.decender);
  16539. table.writeShort(this.lineGap);
  16540. table.writeShort(this.advanceWidthMax);
  16541. table.writeShort(this.minLeftSideBearing);
  16542. table.writeShort(this.minRightSideBearing);
  16543. table.writeShort(this.xMaxExtent);
  16544. table.writeShort(this.caretSlopeRise);
  16545. table.writeShort(this.caretSlopeRun);
  16546. table.writeShort(this.caretOffset);
  16547. for (i = _i = 0, _ref = 4 * 2; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
  16548. table.writeByte(0);
  16549. }
  16550. table.writeShort(this.metricDataFormat);
  16551. table.writeUInt16(ids.length);
  16552. return table.data;
  16553. };*/
  16554. return HheaTable;
  16555. }(Table);
  16556. var OS2Table = function (_super) {
  16557. __extends(OS2Table, _super);
  16558. function OS2Table() {
  16559. return OS2Table.__super__.constructor.apply(this, arguments);
  16560. }
  16561. OS2Table.prototype.tag = "OS/2";
  16562. OS2Table.prototype.parse = function (data) {
  16563. var i;
  16564. data.pos = this.offset;
  16565. this.version = data.readUInt16();
  16566. this.averageCharWidth = data.readShort();
  16567. this.weightClass = data.readUInt16();
  16568. this.widthClass = data.readUInt16();
  16569. this.type = data.readShort();
  16570. this.ySubscriptXSize = data.readShort();
  16571. this.ySubscriptYSize = data.readShort();
  16572. this.ySubscriptXOffset = data.readShort();
  16573. this.ySubscriptYOffset = data.readShort();
  16574. this.ySuperscriptXSize = data.readShort();
  16575. this.ySuperscriptYSize = data.readShort();
  16576. this.ySuperscriptXOffset = data.readShort();
  16577. this.ySuperscriptYOffset = data.readShort();
  16578. this.yStrikeoutSize = data.readShort();
  16579. this.yStrikeoutPosition = data.readShort();
  16580. this.familyClass = data.readShort();
  16581. this.panose = function () {
  16582. var _i, _results;
  16583. _results = [];
  16584. for (i = _i = 0; _i < 10; i = ++_i) {
  16585. _results.push(data.readByte());
  16586. }
  16587. return _results;
  16588. }();
  16589. this.charRange = function () {
  16590. var _i, _results;
  16591. _results = [];
  16592. for (i = _i = 0; _i < 4; i = ++_i) {
  16593. _results.push(data.readInt());
  16594. }
  16595. return _results;
  16596. }();
  16597. this.vendorID = data.readString(4);
  16598. this.selection = data.readShort();
  16599. this.firstCharIndex = data.readShort();
  16600. this.lastCharIndex = data.readShort();
  16601. if (this.version > 0) {
  16602. this.ascent = data.readShort();
  16603. this.descent = data.readShort();
  16604. this.lineGap = data.readShort();
  16605. this.winAscent = data.readShort();
  16606. this.winDescent = data.readShort();
  16607. this.codePageRange = function () {
  16608. var _i, _results;
  16609. _results = [];
  16610. for (i = _i = 0; _i < 2; i = ++_i) {
  16611. _results.push(data.readInt());
  16612. }
  16613. return _results;
  16614. }();
  16615. if (this.version > 1) {
  16616. this.xHeight = data.readShort();
  16617. this.capHeight = data.readShort();
  16618. this.defaultChar = data.readShort();
  16619. this.breakChar = data.readShort();
  16620. return this.maxContext = data.readShort();
  16621. }
  16622. }
  16623. };
  16624. /*OS2Table.prototype.encode = function () {
  16625. return this.raw();
  16626. };*/
  16627. return OS2Table;
  16628. }(Table);
  16629. var PostTable = function (_super) {
  16630. __extends(PostTable, _super);
  16631. function PostTable() {
  16632. return PostTable.__super__.constructor.apply(this, arguments);
  16633. }
  16634. PostTable.prototype.tag = "post";
  16635. PostTable.prototype.parse = function (data) {
  16636. var i, length, numberOfGlyphs, _i, _results;
  16637. data.pos = this.offset;
  16638. this.format = data.readInt();
  16639. this.italicAngle = data.readInt();
  16640. this.underlinePosition = data.readShort();
  16641. this.underlineThickness = data.readShort();
  16642. this.isFixedPitch = data.readInt();
  16643. this.minMemType42 = data.readInt();
  16644. this.maxMemType42 = data.readInt();
  16645. this.minMemType1 = data.readInt();
  16646. this.maxMemType1 = data.readInt();
  16647. switch (this.format) {
  16648. case 0x00010000:
  16649. break;
  16650. case 0x00020000:
  16651. numberOfGlyphs = data.readUInt16();
  16652. this.glyphNameIndex = [];
  16653. for (i = _i = 0; 0 <= numberOfGlyphs ? _i < numberOfGlyphs : _i > numberOfGlyphs; i = 0 <= numberOfGlyphs ? ++_i : --_i) {
  16654. this.glyphNameIndex.push(data.readUInt16());
  16655. }
  16656. this.names = [];
  16657. _results = [];
  16658. while (data.pos < this.offset + this.length) {
  16659. length = data.readByte();
  16660. _results.push(this.names.push(data.readString(length)));
  16661. }
  16662. return _results;
  16663. break;
  16664. case 0x00025000:
  16665. numberOfGlyphs = data.readUInt16();
  16666. return this.offsets = data.read(numberOfGlyphs);
  16667. case 0x00030000:
  16668. break;
  16669. case 0x00040000:
  16670. return this.map = function () {
  16671. var _j, _ref, _results1;
  16672. _results1 = [];
  16673. for (i = _j = 0, _ref = this.file.maxp.numGlyphs; 0 <= _ref ? _j < _ref : _j > _ref; i = 0 <= _ref ? ++_j : --_j) {
  16674. _results1.push(data.readUInt32());
  16675. }
  16676. return _results1;
  16677. }.call(this);
  16678. }
  16679. };
  16680. return PostTable;
  16681. }(Table);
  16682. /*********************************************************************************************************/
  16683. /* function : NameEntry */
  16684. /* comment : Store copyright information, platformID, encodingID, and languageID in the NameEntry object.*/
  16685. /*********************************************************************************************************/
  16686. var NameEntry = function () {
  16687. function NameEntry(raw, entry) {
  16688. this.raw = raw;
  16689. this.length = raw.length;
  16690. this.platformID = entry.platformID;
  16691. this.encodingID = entry.encodingID;
  16692. this.languageID = entry.languageID;
  16693. }
  16694. return NameEntry;
  16695. }();
  16696. var NameTable = function (_super) {
  16697. __extends(NameTable, _super);
  16698. function NameTable() {
  16699. return NameTable.__super__.constructor.apply(this, arguments);
  16700. }
  16701. NameTable.prototype.tag = "name";
  16702. NameTable.prototype.parse = function (data) {
  16703. var count, entries, entry, format, i, name, stringOffset, strings, text, _i, _j, _len, _name;
  16704. data.pos = this.offset;
  16705. format = data.readShort();
  16706. count = data.readShort();
  16707. stringOffset = data.readShort();
  16708. entries = [];
  16709. for (i = _i = 0; 0 <= count ? _i < count : _i > count; i = 0 <= count ? ++_i : --_i) {
  16710. entries.push({
  16711. platformID: data.readShort(),
  16712. encodingID: data.readShort(),
  16713. languageID: data.readShort(),
  16714. nameID: data.readShort(),
  16715. length: data.readShort(),
  16716. offset: this.offset + stringOffset + data.readShort()
  16717. });
  16718. }
  16719. strings = {};
  16720. for (i = _j = 0, _len = entries.length; _j < _len; i = ++_j) {
  16721. entry = entries[i];
  16722. data.pos = entry.offset;
  16723. text = data.readString(entry.length);
  16724. name = new NameEntry(text, entry);
  16725. if (strings[_name = entry.nameID] == null) {
  16726. strings[_name] = [];
  16727. }
  16728. strings[entry.nameID].push(name);
  16729. }
  16730. this.strings = strings;
  16731. this.copyright = strings[0];
  16732. this.fontFamily = strings[1];
  16733. this.fontSubfamily = strings[2];
  16734. this.uniqueSubfamily = strings[3];
  16735. this.fontName = strings[4];
  16736. this.version = strings[5];
  16737. try {
  16738. this.postscriptName = strings[6][0].raw.replace(/[\x00-\x19\x80-\xff]/g, "");
  16739. } catch (e) {
  16740. this.postscriptName = strings[4][0].raw.replace(/[\x00-\x19\x80-\xff]/g, "");
  16741. }
  16742. this.trademark = strings[7];
  16743. this.manufacturer = strings[8];
  16744. this.designer = strings[9];
  16745. this.description = strings[10];
  16746. this.vendorUrl = strings[11];
  16747. this.designerUrl = strings[12];
  16748. this.license = strings[13];
  16749. this.licenseUrl = strings[14];
  16750. this.preferredFamily = strings[15];
  16751. this.preferredSubfamily = strings[17];
  16752. this.compatibleFull = strings[18];
  16753. return this.sampleText = strings[19];
  16754. };
  16755. /*NameTable.prototype.encode = function () {
  16756. var id, list, nameID, nameTable, postscriptName, strCount, strTable, string, strings, table, val, _i, _len, _ref;
  16757. strings = {};
  16758. _ref = this.strings;
  16759. for (id in _ref) {
  16760. val = _ref[id];
  16761. strings[id] = val;
  16762. }
  16763. postscriptName = new NameEntry("" + subsetTag + "+" + this.postscriptName, {
  16764. platformID: 1
  16765. , encodingID: 0
  16766. , languageID: 0
  16767. });
  16768. strings[6] = [postscriptName];
  16769. subsetTag = successorOf(subsetTag);
  16770. strCount = 0;
  16771. for (id in strings) {
  16772. list = strings[id];
  16773. if (list != null) {
  16774. strCount += list.length;
  16775. }
  16776. }
  16777. table = new Data;
  16778. strTable = new Data;
  16779. table.writeShort(0);
  16780. table.writeShort(strCount);
  16781. table.writeShort(6 + 12 * strCount);
  16782. for (nameID in strings) {
  16783. list = strings[nameID];
  16784. if (list != null) {
  16785. for (_i = 0, _len = list.length; _i < _len; _i++) {
  16786. string = list[_i];
  16787. table.writeShort(string.platformID);
  16788. table.writeShort(string.encodingID);
  16789. table.writeShort(string.languageID);
  16790. table.writeShort(nameID);
  16791. table.writeShort(string.length);
  16792. table.writeShort(strTable.pos);
  16793. strTable.writeString(string.raw);
  16794. }
  16795. }
  16796. }
  16797. return nameTable = {
  16798. postscriptName: postscriptName.raw
  16799. , table: table.data.concat(strTable.data)
  16800. };
  16801. };*/
  16802. return NameTable;
  16803. }(Table);
  16804. var MaxpTable = function (_super) {
  16805. __extends(MaxpTable, _super);
  16806. function MaxpTable() {
  16807. return MaxpTable.__super__.constructor.apply(this, arguments);
  16808. }
  16809. MaxpTable.prototype.tag = "maxp";
  16810. MaxpTable.prototype.parse = function (data) {
  16811. data.pos = this.offset;
  16812. this.version = data.readInt();
  16813. this.numGlyphs = data.readUInt16();
  16814. this.maxPoints = data.readUInt16();
  16815. this.maxContours = data.readUInt16();
  16816. this.maxCompositePoints = data.readUInt16();
  16817. this.maxComponentContours = data.readUInt16();
  16818. this.maxZones = data.readUInt16();
  16819. this.maxTwilightPoints = data.readUInt16();
  16820. this.maxStorage = data.readUInt16();
  16821. this.maxFunctionDefs = data.readUInt16();
  16822. this.maxInstructionDefs = data.readUInt16();
  16823. this.maxStackElements = data.readUInt16();
  16824. this.maxSizeOfInstructions = data.readUInt16();
  16825. this.maxComponentElements = data.readUInt16();
  16826. return this.maxComponentDepth = data.readUInt16();
  16827. };
  16828. /*MaxpTable.prototype.encode = function (ids) {
  16829. var table;
  16830. table = new Data;
  16831. table.writeInt(this.version);
  16832. table.writeUInt16(ids.length);
  16833. table.writeUInt16(this.maxPoints);
  16834. table.writeUInt16(this.maxContours);
  16835. table.writeUInt16(this.maxCompositePoints);
  16836. table.writeUInt16(this.maxComponentContours);
  16837. table.writeUInt16(this.maxZones);
  16838. table.writeUInt16(this.maxTwilightPoints);
  16839. table.writeUInt16(this.maxStorage);
  16840. table.writeUInt16(this.maxFunctionDefs);
  16841. table.writeUInt16(this.maxInstructionDefs);
  16842. table.writeUInt16(this.maxStackElements);
  16843. table.writeUInt16(this.maxSizeOfInstructions);
  16844. table.writeUInt16(this.maxComponentElements);
  16845. table.writeUInt16(this.maxComponentDepth);
  16846. return table.data;
  16847. };*/
  16848. return MaxpTable;
  16849. }(Table);
  16850. var HmtxTable = function (_super) {
  16851. __extends(HmtxTable, _super);
  16852. function HmtxTable() {
  16853. return HmtxTable.__super__.constructor.apply(this, arguments);
  16854. }
  16855. HmtxTable.prototype.tag = "hmtx";
  16856. HmtxTable.prototype.parse = function (data) {
  16857. var i, last, lsbCount, m, _i, _j, _ref, _results;
  16858. data.pos = this.offset;
  16859. this.metrics = [];
  16860. for (i = _i = 0, _ref = this.file.hhea.numberOfMetrics; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
  16861. this.metrics.push({
  16862. advance: data.readUInt16(),
  16863. lsb: data.readInt16()
  16864. });
  16865. }
  16866. lsbCount = this.file.maxp.numGlyphs - this.file.hhea.numberOfMetrics;
  16867. this.leftSideBearings = function () {
  16868. var _j, _results;
  16869. _results = [];
  16870. for (i = _j = 0; 0 <= lsbCount ? _j < lsbCount : _j > lsbCount; i = 0 <= lsbCount ? ++_j : --_j) {
  16871. _results.push(data.readInt16());
  16872. }
  16873. return _results;
  16874. }();
  16875. this.widths = function () {
  16876. var _j, _len, _ref1, _results;
  16877. _ref1 = this.metrics;
  16878. _results = [];
  16879. for (_j = 0, _len = _ref1.length; _j < _len; _j++) {
  16880. m = _ref1[_j];
  16881. _results.push(m.advance);
  16882. }
  16883. return _results;
  16884. }.call(this);
  16885. last = this.widths[this.widths.length - 1];
  16886. _results = [];
  16887. for (i = _j = 0; 0 <= lsbCount ? _j < lsbCount : _j > lsbCount; i = 0 <= lsbCount ? ++_j : --_j) {
  16888. _results.push(this.widths.push(last));
  16889. }
  16890. return _results;
  16891. };
  16892. /***************************************************************/
  16893. /* function : forGlyph */
  16894. /* comment : Returns the advance width and lsb for this glyph. */
  16895. /***************************************************************/
  16896. HmtxTable.prototype.forGlyph = function (id) {
  16897. var metrics;
  16898. if (id in this.metrics) {
  16899. return this.metrics[id];
  16900. }
  16901. return metrics = {
  16902. advance: this.metrics[this.metrics.length - 1].advance,
  16903. lsb: this.leftSideBearings[id - this.metrics.length]
  16904. };
  16905. };
  16906. /*HmtxTable.prototype.encode = function (mapping) {
  16907. var id, metric, table, _i, _len;
  16908. table = new Data;
  16909. for (_i = 0, _len = mapping.length; _i < _len; _i++) {
  16910. id = mapping[_i];
  16911. metric = this.forGlyph(id);
  16912. table.writeUInt16(metric.advance);
  16913. table.writeUInt16(metric.lsb);
  16914. }
  16915. return table.data;
  16916. };*/
  16917. return HmtxTable;
  16918. }(Table);
  16919. var __slice = [].slice;
  16920. var GlyfTable = function (_super) {
  16921. __extends(GlyfTable, _super);
  16922. function GlyfTable() {
  16923. return GlyfTable.__super__.constructor.apply(this, arguments);
  16924. }
  16925. GlyfTable.prototype.tag = "glyf";
  16926. GlyfTable.prototype.parse = function (data) {
  16927. return this.cache = {};
  16928. };
  16929. GlyfTable.prototype.glyphFor = function (id) {
  16930. id = id;
  16931. var data, index, length, loca, numberOfContours, raw, xMax, xMin, yMax, yMin;
  16932. if (id in this.cache) {
  16933. return this.cache[id];
  16934. }
  16935. loca = this.file.loca;
  16936. data = this.file.contents;
  16937. index = loca.indexOf(id);
  16938. length = loca.lengthOf(id);
  16939. if (length === 0) {
  16940. return this.cache[id] = null;
  16941. }
  16942. data.pos = this.offset + index;
  16943. raw = new Data(data.read(length));
  16944. numberOfContours = raw.readShort();
  16945. xMin = raw.readShort();
  16946. yMin = raw.readShort();
  16947. xMax = raw.readShort();
  16948. yMax = raw.readShort();
  16949. if (numberOfContours === -1) {
  16950. this.cache[id] = new CompoundGlyph(raw, xMin, yMin, xMax, yMax);
  16951. } else {
  16952. this.cache[id] = new SimpleGlyph(raw, numberOfContours, xMin, yMin, xMax, yMax);
  16953. }
  16954. return this.cache[id];
  16955. };
  16956. GlyfTable.prototype.encode = function (glyphs, mapping, old2new) {
  16957. var glyph, id, offsets, table, _i, _len;
  16958. table = [];
  16959. offsets = [];
  16960. for (_i = 0, _len = mapping.length; _i < _len; _i++) {
  16961. id = mapping[_i];
  16962. glyph = glyphs[id];
  16963. offsets.push(table.length);
  16964. if (glyph) {
  16965. table = table.concat(glyph.encode(old2new));
  16966. }
  16967. }
  16968. offsets.push(table.length);
  16969. return {
  16970. table: table,
  16971. offsets: offsets
  16972. };
  16973. };
  16974. return GlyfTable;
  16975. }(Table);
  16976. var SimpleGlyph = function () {
  16977. /**************************************************************************/
  16978. /* function : SimpleGlyph */
  16979. /* comment : Stores raw, xMin, yMin, xMax, and yMax values for this glyph.*/
  16980. /**************************************************************************/
  16981. function SimpleGlyph(raw, numberOfContours, xMin, yMin, xMax, yMax) {
  16982. this.raw = raw;
  16983. this.numberOfContours = numberOfContours;
  16984. this.xMin = xMin;
  16985. this.yMin = yMin;
  16986. this.xMax = xMax;
  16987. this.yMax = yMax;
  16988. this.compound = false;
  16989. }
  16990. SimpleGlyph.prototype.encode = function () {
  16991. return this.raw.data;
  16992. };
  16993. return SimpleGlyph;
  16994. }();
  16995. var CompoundGlyph = function () {
  16996. 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;
  16997. ARG_1_AND_2_ARE_WORDS = 0x0001;
  16998. WE_HAVE_A_SCALE = 0x0008;
  16999. MORE_COMPONENTS = 0x0020;
  17000. WE_HAVE_AN_X_AND_Y_SCALE = 0x0040;
  17001. WE_HAVE_A_TWO_BY_TWO = 0x0080;
  17002. /********************************************************************************************************************/
  17003. /* function : CompoundGlypg generator */
  17004. /* comment : It stores raw, xMin, yMin, xMax, yMax, glyph id, and glyph offset for the corresponding compound glyph.*/
  17005. /********************************************************************************************************************/
  17006. function CompoundGlyph(raw, xMin, yMin, xMax, yMax) {
  17007. var data, flags;
  17008. this.raw = raw;
  17009. this.xMin = xMin;
  17010. this.yMin = yMin;
  17011. this.xMax = xMax;
  17012. this.yMax = yMax;
  17013. this.compound = true;
  17014. this.glyphIDs = [];
  17015. this.glyphOffsets = [];
  17016. data = this.raw;
  17017. while (true) {
  17018. flags = data.readShort();
  17019. this.glyphOffsets.push(data.pos);
  17020. this.glyphIDs.push(data.readShort());
  17021. if (!(flags & MORE_COMPONENTS)) {
  17022. break;
  17023. }
  17024. if (flags & ARG_1_AND_2_ARE_WORDS) {
  17025. data.pos += 4;
  17026. } else {
  17027. data.pos += 2;
  17028. }
  17029. if (flags & WE_HAVE_A_TWO_BY_TWO) {
  17030. data.pos += 8;
  17031. } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) {
  17032. data.pos += 4;
  17033. } else if (flags & WE_HAVE_A_SCALE) {
  17034. data.pos += 2;
  17035. }
  17036. }
  17037. }
  17038. /****************************************************************************************************************/
  17039. /* function : CompoundGlypg encode */
  17040. /* comment : After creating a table for the characters you typed, you call directory.encode to encode the table.*/
  17041. /****************************************************************************************************************/
  17042. CompoundGlyph.prototype.encode = function (mapping) {
  17043. var i, id, result, _i, _len, _ref;
  17044. result = new Data(__slice.call(this.raw.data));
  17045. _ref = this.glyphIDs;
  17046. for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
  17047. id = _ref[i];
  17048. result.pos = this.glyphOffsets[i];
  17049. }
  17050. return result.data;
  17051. };
  17052. return CompoundGlyph;
  17053. }();
  17054. var LocaTable = function (_super) {
  17055. __extends(LocaTable, _super);
  17056. function LocaTable() {
  17057. return LocaTable.__super__.constructor.apply(this, arguments);
  17058. }
  17059. LocaTable.prototype.tag = "loca";
  17060. LocaTable.prototype.parse = function (data) {
  17061. var format, i;
  17062. data.pos = this.offset;
  17063. format = this.file.head.indexToLocFormat;
  17064. if (format === 0) {
  17065. return this.offsets = function () {
  17066. var _i, _ref, _results;
  17067. _results = [];
  17068. for (i = _i = 0, _ref = this.length; _i < _ref; i = _i += 2) {
  17069. _results.push(data.readUInt16() * 2);
  17070. }
  17071. return _results;
  17072. }.call(this);
  17073. } else {
  17074. return this.offsets = function () {
  17075. var _i, _ref, _results;
  17076. _results = [];
  17077. for (i = _i = 0, _ref = this.length; _i < _ref; i = _i += 4) {
  17078. _results.push(data.readUInt32());
  17079. }
  17080. return _results;
  17081. }.call(this);
  17082. }
  17083. };
  17084. LocaTable.prototype.indexOf = function (id) {
  17085. return this.offsets[id];
  17086. };
  17087. LocaTable.prototype.lengthOf = function (id) {
  17088. return this.offsets[id + 1] - this.offsets[id];
  17089. };
  17090. LocaTable.prototype.encode = function (offsets, activeGlyphs) {
  17091. var LocaTable = new Uint32Array(this.offsets.length);
  17092. var glyfPtr = 0;
  17093. var listGlyf = 0;
  17094. for (var k = 0; k < LocaTable.length; ++k) {
  17095. LocaTable[k] = glyfPtr;
  17096. if (listGlyf < activeGlyphs.length && activeGlyphs[listGlyf] == k) {
  17097. ++listGlyf;
  17098. LocaTable[k] = glyfPtr;
  17099. var start = this.offsets[k];
  17100. var len = this.offsets[k + 1] - start;
  17101. if (len > 0) {
  17102. glyfPtr += len;
  17103. }
  17104. }
  17105. }
  17106. var newLocaTable = new Array(LocaTable.length * 4);
  17107. for (var j = 0; j < LocaTable.length; ++j) {
  17108. newLocaTable[4 * j + 3] = LocaTable[j] & 0x000000ff;
  17109. newLocaTable[4 * j + 2] = (LocaTable[j] & 0x0000ff00) >> 8;
  17110. newLocaTable[4 * j + 1] = (LocaTable[j] & 0x00ff0000) >> 16;
  17111. newLocaTable[4 * j] = (LocaTable[j] & 0xff000000) >> 24;
  17112. }
  17113. return newLocaTable;
  17114. };
  17115. return LocaTable;
  17116. }(Table);
  17117. /************************************************************************************/
  17118. /* function : invert */
  17119. /* comment : Change the object's (key: value) to create an object with (value: key).*/
  17120. /************************************************************************************/
  17121. var invert = function (object) {
  17122. var key, ret, val;
  17123. ret = {};
  17124. for (key in object) {
  17125. val = object[key];
  17126. ret[val] = key;
  17127. }
  17128. return ret;
  17129. };
  17130. /*var successorOf = function (input) {
  17131. var added, alphabet, carry, i, index, isUpperCase, last, length, next, result;
  17132. alphabet = 'abcdefghijklmnopqrstuvwxyz';
  17133. length = alphabet.length;
  17134. result = input;
  17135. i = input.length;
  17136. while (i >= 0) {
  17137. last = input.charAt(--i);
  17138. if (isNaN(last)) {
  17139. index = alphabet.indexOf(last.toLowerCase());
  17140. if (index === -1) {
  17141. next = last;
  17142. carry = true;
  17143. }
  17144. else {
  17145. next = alphabet.charAt((index + 1) % length);
  17146. isUpperCase = last === last.toUpperCase();
  17147. if (isUpperCase) {
  17148. next = next.toUpperCase();
  17149. }
  17150. carry = index + 1 >= length;
  17151. if (carry && i === 0) {
  17152. added = isUpperCase ? 'A' : 'a';
  17153. result = added + next + result.slice(1);
  17154. break;
  17155. }
  17156. }
  17157. }
  17158. else {
  17159. next = +last + 1;
  17160. carry = next > 9;
  17161. if (carry) {
  17162. next = 0;
  17163. }
  17164. if (carry && i === 0) {
  17165. result = '1' + next + result.slice(1);
  17166. break;
  17167. }
  17168. }
  17169. result = result.slice(0, i) + next + result.slice(i + 1);
  17170. if (!carry) {
  17171. break;
  17172. }
  17173. }
  17174. return result;
  17175. };*/
  17176. var Subset = function () {
  17177. function Subset(font) {
  17178. this.font = font;
  17179. this.subset = {};
  17180. this.unicodes = {};
  17181. this.next = 33;
  17182. }
  17183. /*Subset.prototype.use = function (character) {
  17184. var i, _i, _ref;
  17185. if (typeof character === 'string') {
  17186. for (i = _i = 0, _ref = character.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
  17187. this.use(character.charCodeAt(i));
  17188. }
  17189. return;
  17190. }
  17191. if (!this.unicodes[character]) {
  17192. this.subset[this.next] = character;
  17193. return this.unicodes[character] = this.next++;
  17194. }
  17195. };*/
  17196. /*Subset.prototype.encodeText = function (text) {
  17197. var char, i, string, _i, _ref;
  17198. string = '';
  17199. for (i = _i = 0, _ref = text.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
  17200. char = this.unicodes[text.charCodeAt(i)];
  17201. string += String.fromCharCode(char);
  17202. }
  17203. return string;
  17204. };*/
  17205. /***************************************************************/
  17206. /* function : generateCmap */
  17207. /* comment : Returns the unicode cmap for this font. */
  17208. /***************************************************************/
  17209. Subset.prototype.generateCmap = function () {
  17210. var mapping, roman, unicode, unicodeCmap, _ref;
  17211. unicodeCmap = this.font.cmap.tables[0].codeMap;
  17212. mapping = {};
  17213. _ref = this.subset;
  17214. for (roman in _ref) {
  17215. unicode = _ref[roman];
  17216. mapping[roman] = unicodeCmap[unicode];
  17217. }
  17218. return mapping;
  17219. };
  17220. /*Subset.prototype.glyphIDs = function () {
  17221. var ret, roman, unicode, unicodeCmap, val, _ref;
  17222. unicodeCmap = this.font.cmap.tables[0].codeMap;
  17223. ret = [0];
  17224. _ref = this.subset;
  17225. for (roman in _ref) {
  17226. unicode = _ref[roman];
  17227. val = unicodeCmap[unicode];
  17228. if ((val != null) && __indexOf.call(ret, val) < 0) {
  17229. ret.push(val);
  17230. }
  17231. }
  17232. return ret.sort();
  17233. };*/
  17234. /******************************************************************/
  17235. /* function : glyphsFor */
  17236. /* comment : Returns simple glyph objects for the input character.*/
  17237. /******************************************************************/
  17238. Subset.prototype.glyphsFor = function (glyphIDs) {
  17239. var additionalIDs, glyph, glyphs, id, _i, _len, _ref;
  17240. glyphs = {};
  17241. for (_i = 0, _len = glyphIDs.length; _i < _len; _i++) {
  17242. id = glyphIDs[_i];
  17243. glyphs[id] = this.font.glyf.glyphFor(id);
  17244. }
  17245. additionalIDs = [];
  17246. for (id in glyphs) {
  17247. glyph = glyphs[id];
  17248. if (glyph != null ? glyph.compound : void 0) {
  17249. additionalIDs.push.apply(additionalIDs, glyph.glyphIDs);
  17250. }
  17251. }
  17252. if (additionalIDs.length > 0) {
  17253. _ref = this.glyphsFor(additionalIDs);
  17254. for (id in _ref) {
  17255. glyph = _ref[id];
  17256. glyphs[id] = glyph;
  17257. }
  17258. }
  17259. return glyphs;
  17260. };
  17261. /***************************************************************/
  17262. /* function : encode */
  17263. /* comment : Encode various tables for the characters you use. */
  17264. /***************************************************************/
  17265. Subset.prototype.encode = function (glyID, indexToLocFormat) {
  17266. var cmap, code, glyf, glyphs, id, ids, loca, new2old, newIDs, nextGlyphID, old2new, oldID, oldIDs, tables, _ref;
  17267. cmap = CmapTable.encode(this.generateCmap(), "unicode");
  17268. glyphs = this.glyphsFor(glyID);
  17269. old2new = {
  17270. 0: 0
  17271. };
  17272. _ref = cmap.charMap;
  17273. for (code in _ref) {
  17274. ids = _ref[code];
  17275. old2new[ids.old] = ids["new"];
  17276. }
  17277. nextGlyphID = cmap.maxGlyphID;
  17278. for (oldID in glyphs) {
  17279. if (!(oldID in old2new)) {
  17280. old2new[oldID] = nextGlyphID++;
  17281. }
  17282. }
  17283. new2old = invert(old2new);
  17284. newIDs = Object.keys(new2old).sort(function (a, b) {
  17285. return a - b;
  17286. });
  17287. oldIDs = function () {
  17288. var _i, _len, _results;
  17289. _results = [];
  17290. for (_i = 0, _len = newIDs.length; _i < _len; _i++) {
  17291. id = newIDs[_i];
  17292. _results.push(new2old[id]);
  17293. }
  17294. return _results;
  17295. }();
  17296. glyf = this.font.glyf.encode(glyphs, oldIDs, old2new);
  17297. loca = this.font.loca.encode(glyf.offsets, oldIDs);
  17298. tables = {
  17299. cmap: this.font.cmap.raw(),
  17300. glyf: glyf.table,
  17301. loca: loca,
  17302. hmtx: this.font.hmtx.raw(),
  17303. hhea: this.font.hhea.raw(),
  17304. maxp: this.font.maxp.raw(),
  17305. post: this.font.post.raw(),
  17306. name: this.font.name.raw(),
  17307. head: this.font.head.encode(indexToLocFormat)
  17308. };
  17309. if (this.font.os2.exists) {
  17310. tables["OS/2"] = this.font.os2.raw();
  17311. }
  17312. return this.font.directory.encode(tables);
  17313. };
  17314. return Subset;
  17315. }();
  17316. jsPDF.API.PDFObject = function () {
  17317. var pad;
  17318. function PDFObject() {}
  17319. pad = function (str, length) {
  17320. return (Array(length + 1).join("0") + str).slice(-length);
  17321. };
  17322. /*****************************************************************************/
  17323. /* function : convert */
  17324. /* comment :Converts pdf tag's / FontBBox and array values in / W to strings */
  17325. /*****************************************************************************/
  17326. PDFObject.convert = function (object) {
  17327. var e, items, key, out, val;
  17328. if (Array.isArray(object)) {
  17329. items = function () {
  17330. var _i, _len, _results;
  17331. _results = [];
  17332. for (_i = 0, _len = object.length; _i < _len; _i++) {
  17333. e = object[_i];
  17334. _results.push(PDFObject.convert(e));
  17335. }
  17336. return _results;
  17337. }().join(" ");
  17338. return "[" + items + "]";
  17339. } else if (typeof object === "string") {
  17340. return "/" + object;
  17341. } else if (object != null ? object.isString : void 0) {
  17342. return "(" + object + ")";
  17343. } else if (object instanceof Date) {
  17344. 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)";
  17345. } else if ({}.toString.call(object) === "[object Object]") {
  17346. out = ["<<"];
  17347. for (key in object) {
  17348. val = object[key];
  17349. out.push("/" + key + " " + PDFObject.convert(val));
  17350. }
  17351. out.push(">>");
  17352. return out.join("\n");
  17353. } else {
  17354. return "" + object;
  17355. }
  17356. };
  17357. return PDFObject;
  17358. }();
  17359. })(jsPDF);
  17360. // Generated by CoffeeScript 1.4.0
  17361. /*
  17362. # PNG.js
  17363. # Copyright (c) 2011 Devon Govett
  17364. # MIT LICENSE
  17365. #
  17366. #
  17367. */
  17368. (function (global) {
  17369. var PNG;
  17370. PNG = function () {
  17371. var APNG_BLEND_OP_SOURCE, APNG_DISPOSE_OP_BACKGROUND, APNG_DISPOSE_OP_PREVIOUS, makeImage, scratchCanvas, scratchCtx;
  17372. PNG.load = function (url, canvas, callback) {
  17373. var xhr;
  17374. if (typeof canvas === "function") {
  17375. callback = canvas;
  17376. }
  17377. xhr = new XMLHttpRequest();
  17378. xhr.open("GET", url, true);
  17379. xhr.responseType = "arraybuffer";
  17380. xhr.onload = function () {
  17381. var data, png;
  17382. data = new Uint8Array(xhr.response || xhr.mozResponseArrayBuffer);
  17383. png = new PNG(data);
  17384. if (typeof (canvas != null ? canvas.getContext : void 0) === "function") {
  17385. png.render(canvas);
  17386. }
  17387. return typeof callback === "function" ? callback(png) : void 0;
  17388. };
  17389. return xhr.send(null);
  17390. };
  17391. APNG_DISPOSE_OP_BACKGROUND = 1;
  17392. APNG_DISPOSE_OP_PREVIOUS = 2;
  17393. APNG_BLEND_OP_SOURCE = 0;
  17394. function PNG(data) {
  17395. var chunkSize, colors, palLen, delayDen, delayNum, frame, i, index, key, section, palShort, text, _i, _j, _ref;
  17396. this.data = data;
  17397. this.pos = 8;
  17398. this.palette = [];
  17399. this.imgData = [];
  17400. this.transparency = {};
  17401. this.animation = null;
  17402. this.text = {};
  17403. frame = null;
  17404. while (true) {
  17405. chunkSize = this.readUInt32();
  17406. section = function () {
  17407. var _i, _results;
  17408. _results = [];
  17409. for (i = _i = 0; _i < 4; i = ++_i) {
  17410. _results.push(String.fromCharCode(this.data[this.pos++]));
  17411. }
  17412. return _results;
  17413. }.call(this).join("");
  17414. switch (section) {
  17415. case "IHDR":
  17416. this.width = this.readUInt32();
  17417. this.height = this.readUInt32();
  17418. this.bits = this.data[this.pos++];
  17419. this.colorType = this.data[this.pos++];
  17420. this.compressionMethod = this.data[this.pos++];
  17421. this.filterMethod = this.data[this.pos++];
  17422. this.interlaceMethod = this.data[this.pos++];
  17423. break;
  17424. case "acTL":
  17425. this.animation = {
  17426. numFrames: this.readUInt32(),
  17427. numPlays: this.readUInt32() || Infinity,
  17428. frames: []
  17429. };
  17430. break;
  17431. case "PLTE":
  17432. this.palette = this.read(chunkSize);
  17433. break;
  17434. case "fcTL":
  17435. if (frame) {
  17436. this.animation.frames.push(frame);
  17437. }
  17438. this.pos += 4;
  17439. frame = {
  17440. width: this.readUInt32(),
  17441. height: this.readUInt32(),
  17442. xOffset: this.readUInt32(),
  17443. yOffset: this.readUInt32()
  17444. };
  17445. delayNum = this.readUInt16();
  17446. delayDen = this.readUInt16() || 100;
  17447. frame.delay = 1000 * delayNum / delayDen;
  17448. frame.disposeOp = this.data[this.pos++];
  17449. frame.blendOp = this.data[this.pos++];
  17450. frame.data = [];
  17451. break;
  17452. case "IDAT":
  17453. case "fdAT":
  17454. if (section === "fdAT") {
  17455. this.pos += 4;
  17456. chunkSize -= 4;
  17457. }
  17458. data = (frame != null ? frame.data : void 0) || this.imgData;
  17459. for (i = _i = 0; 0 <= chunkSize ? _i < chunkSize : _i > chunkSize; i = 0 <= chunkSize ? ++_i : --_i) {
  17460. data.push(this.data[this.pos++]);
  17461. }
  17462. break;
  17463. case "tRNS":
  17464. this.transparency = {};
  17465. switch (this.colorType) {
  17466. case 3:
  17467. palLen = this.palette.length / 3;
  17468. this.transparency.indexed = this.read(chunkSize);
  17469. if (this.transparency.indexed.length > palLen) throw new Error("More transparent colors than palette size");
  17470. /*
  17471. * According to the PNG spec trns should be increased to the same size as palette if shorter
  17472. */
  17473. //palShort = 255 - this.transparency.indexed.length;
  17474. palShort = palLen - this.transparency.indexed.length;
  17475. if (palShort > 0) {
  17476. for (i = _j = 0; 0 <= palShort ? _j < palShort : _j > palShort; i = 0 <= palShort ? ++_j : --_j) {
  17477. this.transparency.indexed.push(255);
  17478. }
  17479. }
  17480. break;
  17481. case 0:
  17482. this.transparency.grayscale = this.read(chunkSize)[0];
  17483. break;
  17484. case 2:
  17485. this.transparency.rgb = this.read(chunkSize);
  17486. }
  17487. break;
  17488. case "tEXt":
  17489. text = this.read(chunkSize);
  17490. index = text.indexOf(0);
  17491. key = String.fromCharCode.apply(String, text.slice(0, index));
  17492. this.text[key] = String.fromCharCode.apply(String, text.slice(index + 1));
  17493. break;
  17494. case "IEND":
  17495. if (frame) {
  17496. this.animation.frames.push(frame);
  17497. }
  17498. this.colors = function () {
  17499. switch (this.colorType) {
  17500. case 0:
  17501. case 3:
  17502. case 4:
  17503. return 1;
  17504. case 2:
  17505. case 6:
  17506. return 3;
  17507. }
  17508. }.call(this);
  17509. this.hasAlphaChannel = (_ref = this.colorType) === 4 || _ref === 6;
  17510. colors = this.colors + (this.hasAlphaChannel ? 1 : 0);
  17511. this.pixelBitlength = this.bits * colors;
  17512. this.colorSpace = function () {
  17513. switch (this.colors) {
  17514. case 1:
  17515. return "DeviceGray";
  17516. case 3:
  17517. return "DeviceRGB";
  17518. }
  17519. }.call(this);
  17520. this.imgData = new Uint8Array(this.imgData);
  17521. return;
  17522. default:
  17523. this.pos += chunkSize;
  17524. }
  17525. this.pos += 4;
  17526. if (this.pos > this.data.length) {
  17527. throw new Error("Incomplete or corrupt PNG file");
  17528. }
  17529. }
  17530. return;
  17531. }
  17532. PNG.prototype.read = function (bytes) {
  17533. var i, _i, _results;
  17534. _results = [];
  17535. for (i = _i = 0; 0 <= bytes ? _i < bytes : _i > bytes; i = 0 <= bytes ? ++_i : --_i) {
  17536. _results.push(this.data[this.pos++]);
  17537. }
  17538. return _results;
  17539. };
  17540. PNG.prototype.readUInt32 = function () {
  17541. var b1, b2, b3, b4;
  17542. b1 = this.data[this.pos++] << 24;
  17543. b2 = this.data[this.pos++] << 16;
  17544. b3 = this.data[this.pos++] << 8;
  17545. b4 = this.data[this.pos++];
  17546. return b1 | b2 | b3 | b4;
  17547. };
  17548. PNG.prototype.readUInt16 = function () {
  17549. var b1, b2;
  17550. b1 = this.data[this.pos++] << 8;
  17551. b2 = this.data[this.pos++];
  17552. return b1 | b2;
  17553. };
  17554. PNG.prototype.decodePixels = function (data) {
  17555. var pixelBytes = this.pixelBitlength / 8;
  17556. var fullPixels = new Uint8Array(this.width * this.height * pixelBytes);
  17557. var pos = 0;
  17558. var _this = this;
  17559. if (data == null) {
  17560. data = this.imgData;
  17561. }
  17562. if (data.length === 0) {
  17563. return new Uint8Array(0);
  17564. }
  17565. data = new FlateStream(data);
  17566. data = data.getBytes();
  17567. function pass(x0, y0, dx, dy) {
  17568. var abyte, c, col, i, left, length, p, pa, paeth, pb, pc, pixels, row, scanlineLength, upper, upperLeft, _i, _j, _k, _l, _m;
  17569. var w = Math.ceil((_this.width - x0) / dx),
  17570. h = Math.ceil((_this.height - y0) / dy);
  17571. var isFull = _this.width == w && _this.height == h;
  17572. scanlineLength = pixelBytes * w;
  17573. pixels = isFull ? fullPixels : new Uint8Array(scanlineLength * h);
  17574. length = data.length;
  17575. row = 0;
  17576. c = 0;
  17577. while (row < h && pos < length) {
  17578. switch (data[pos++]) {
  17579. case 0:
  17580. for (i = _i = 0; _i < scanlineLength; i = _i += 1) {
  17581. pixels[c++] = data[pos++];
  17582. }
  17583. break;
  17584. case 1:
  17585. for (i = _j = 0; _j < scanlineLength; i = _j += 1) {
  17586. abyte = data[pos++];
  17587. left = i < pixelBytes ? 0 : pixels[c - pixelBytes];
  17588. pixels[c++] = (abyte + left) % 256;
  17589. }
  17590. break;
  17591. case 2:
  17592. for (i = _k = 0; _k < scanlineLength; i = _k += 1) {
  17593. abyte = data[pos++];
  17594. col = (i - i % pixelBytes) / pixelBytes;
  17595. upper = row && pixels[(row - 1) * scanlineLength + col * pixelBytes + i % pixelBytes];
  17596. pixels[c++] = (upper + abyte) % 256;
  17597. }
  17598. break;
  17599. case 3:
  17600. for (i = _l = 0; _l < scanlineLength; i = _l += 1) {
  17601. abyte = data[pos++];
  17602. col = (i - i % pixelBytes) / pixelBytes;
  17603. left = i < pixelBytes ? 0 : pixels[c - pixelBytes];
  17604. upper = row && pixels[(row - 1) * scanlineLength + col * pixelBytes + i % pixelBytes];
  17605. pixels[c++] = (abyte + Math.floor((left + upper) / 2)) % 256;
  17606. }
  17607. break;
  17608. case 4:
  17609. for (i = _m = 0; _m < scanlineLength; i = _m += 1) {
  17610. abyte = data[pos++];
  17611. col = (i - i % pixelBytes) / pixelBytes;
  17612. left = i < pixelBytes ? 0 : pixels[c - pixelBytes];
  17613. if (row === 0) {
  17614. upper = upperLeft = 0;
  17615. } else {
  17616. upper = pixels[(row - 1) * scanlineLength + col * pixelBytes + i % pixelBytes];
  17617. upperLeft = col && pixels[(row - 1) * scanlineLength + (col - 1) * pixelBytes + i % pixelBytes];
  17618. }
  17619. p = left + upper - upperLeft;
  17620. pa = Math.abs(p - left);
  17621. pb = Math.abs(p - upper);
  17622. pc = Math.abs(p - upperLeft);
  17623. if (pa <= pb && pa <= pc) {
  17624. paeth = left;
  17625. } else if (pb <= pc) {
  17626. paeth = upper;
  17627. } else {
  17628. paeth = upperLeft;
  17629. }
  17630. pixels[c++] = (abyte + paeth) % 256;
  17631. }
  17632. break;
  17633. default:
  17634. throw new Error("Invalid filter algorithm: " + data[pos - 1]);
  17635. }
  17636. if (!isFull) {
  17637. var fullPos = ((y0 + row * dy) * _this.width + x0) * pixelBytes;
  17638. var partPos = row * scanlineLength;
  17639. for (i = 0; i < w; i += 1) {
  17640. for (var j = 0; j < pixelBytes; j += 1) fullPixels[fullPos++] = pixels[partPos++];
  17641. fullPos += (dx - 1) * pixelBytes;
  17642. }
  17643. }
  17644. row++;
  17645. }
  17646. }
  17647. if (_this.interlaceMethod == 1) {
  17648. /*
  17649. 1 6 4 6 2 6 4 6
  17650. 7 7 7 7 7 7 7 7
  17651. 5 6 5 6 5 6 5 6
  17652. 7 7 7 7 7 7 7 7
  17653. 3 6 4 6 3 6 4 6
  17654. 7 7 7 7 7 7 7 7
  17655. 5 6 5 6 5 6 5 6
  17656. 7 7 7 7 7 7 7 7
  17657. */
  17658. pass(0, 0, 8, 8); // 1
  17659. /* NOTE these seem to follow the pattern:
  17660. * pass(x, 0, 2*x, 2*x);
  17661. * pass(0, x, x, 2*x);
  17662. * with x being 4, 2, 1.
  17663. */
  17664. pass(4, 0, 8, 8); // 2
  17665. pass(0, 4, 4, 8); // 3
  17666. pass(2, 0, 4, 4); // 4
  17667. pass(0, 2, 2, 4); // 5
  17668. pass(1, 0, 2, 2); // 6
  17669. pass(0, 1, 1, 2); // 7
  17670. } else {
  17671. pass(0, 0, 1, 1);
  17672. }
  17673. return fullPixels;
  17674. };
  17675. PNG.prototype.decodePalette = function () {
  17676. var c, i, length, palette, pos, ret, transparency, _i, _ref, _ref1;
  17677. palette = this.palette;
  17678. transparency = this.transparency.indexed || [];
  17679. ret = new Uint8Array((transparency.length || 0) + palette.length);
  17680. pos = 0;
  17681. length = palette.length;
  17682. c = 0;
  17683. for (i = _i = 0, _ref = palette.length; _i < _ref; i = _i += 3) {
  17684. ret[pos++] = palette[i];
  17685. ret[pos++] = palette[i + 1];
  17686. ret[pos++] = palette[i + 2];
  17687. ret[pos++] = (_ref1 = transparency[c++]) != null ? _ref1 : 255;
  17688. }
  17689. return ret;
  17690. };
  17691. PNG.prototype.copyToImageData = function (imageData, pixels) {
  17692. var alpha, colors, data, i, input, j, k, length, palette, v, _ref;
  17693. colors = this.colors;
  17694. palette = null;
  17695. alpha = this.hasAlphaChannel;
  17696. if (this.palette.length) {
  17697. palette = (_ref = this._decodedPalette) != null ? _ref : this._decodedPalette = this.decodePalette();
  17698. colors = 4;
  17699. alpha = true;
  17700. }
  17701. data = imageData.data || imageData;
  17702. length = data.length;
  17703. input = palette || pixels;
  17704. i = j = 0;
  17705. if (colors === 1) {
  17706. while (i < length) {
  17707. k = palette ? pixels[i / 4] * 4 : j;
  17708. v = input[k++];
  17709. data[i++] = v;
  17710. data[i++] = v;
  17711. data[i++] = v;
  17712. data[i++] = alpha ? input[k++] : 255;
  17713. j = k;
  17714. }
  17715. } else {
  17716. while (i < length) {
  17717. k = palette ? pixels[i / 4] * 4 : j;
  17718. data[i++] = input[k++];
  17719. data[i++] = input[k++];
  17720. data[i++] = input[k++];
  17721. data[i++] = alpha ? input[k++] : 255;
  17722. j = k;
  17723. }
  17724. }
  17725. };
  17726. PNG.prototype.decode = function () {
  17727. var ret;
  17728. ret = new Uint8Array(this.width * this.height * 4);
  17729. this.copyToImageData(ret, this.decodePixels());
  17730. return ret;
  17731. };
  17732. try {
  17733. scratchCanvas = global.document.createElement("canvas");
  17734. scratchCtx = scratchCanvas.getContext("2d");
  17735. } catch (e) {
  17736. return -1;
  17737. }
  17738. makeImage = function (imageData) {
  17739. var img;
  17740. scratchCtx.width = imageData.width;
  17741. scratchCtx.height = imageData.height;
  17742. scratchCtx.clearRect(0, 0, imageData.width, imageData.height);
  17743. scratchCtx.putImageData(imageData, 0, 0);
  17744. img = new Image();
  17745. img.src = scratchCanvas.toDataURL();
  17746. return img;
  17747. };
  17748. PNG.prototype.decodeFrames = function (ctx) {
  17749. var frame, i, imageData, pixels, _i, _len, _ref, _results;
  17750. if (!this.animation) {
  17751. return;
  17752. }
  17753. _ref = this.animation.frames;
  17754. _results = [];
  17755. for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
  17756. frame = _ref[i];
  17757. imageData = ctx.createImageData(frame.width, frame.height);
  17758. pixels = this.decodePixels(new Uint8Array(frame.data));
  17759. this.copyToImageData(imageData, pixels);
  17760. frame.imageData = imageData;
  17761. _results.push(frame.image = makeImage(imageData));
  17762. }
  17763. return _results;
  17764. };
  17765. PNG.prototype.renderFrame = function (ctx, number) {
  17766. var frame, frames, prev;
  17767. frames = this.animation.frames;
  17768. frame = frames[number];
  17769. prev = frames[number - 1];
  17770. if (number === 0) {
  17771. ctx.clearRect(0, 0, this.width, this.height);
  17772. }
  17773. if ((prev != null ? prev.disposeOp : void 0) === APNG_DISPOSE_OP_BACKGROUND) {
  17774. ctx.clearRect(prev.xOffset, prev.yOffset, prev.width, prev.height);
  17775. } else if ((prev != null ? prev.disposeOp : void 0) === APNG_DISPOSE_OP_PREVIOUS) {
  17776. ctx.putImageData(prev.imageData, prev.xOffset, prev.yOffset);
  17777. }
  17778. if (frame.blendOp === APNG_BLEND_OP_SOURCE) {
  17779. ctx.clearRect(frame.xOffset, frame.yOffset, frame.width, frame.height);
  17780. }
  17781. return ctx.drawImage(frame.image, frame.xOffset, frame.yOffset);
  17782. };
  17783. PNG.prototype.animate = function (ctx) {
  17784. var doFrame,
  17785. frameNumber,
  17786. frames,
  17787. numFrames,
  17788. numPlays,
  17789. _ref,
  17790. _this = this;
  17791. frameNumber = 0;
  17792. _ref = this.animation, numFrames = _ref.numFrames, frames = _ref.frames, numPlays = _ref.numPlays;
  17793. return (doFrame = function () {
  17794. var f, frame;
  17795. f = frameNumber++ % numFrames;
  17796. frame = frames[f];
  17797. _this.renderFrame(ctx, f);
  17798. if (numFrames > 1 && frameNumber / numFrames < numPlays) {
  17799. return _this.animation._timeout = setTimeout(doFrame, frame.delay);
  17800. }
  17801. })();
  17802. };
  17803. PNG.prototype.stopAnimation = function () {
  17804. var _ref;
  17805. return clearTimeout((_ref = this.animation) != null ? _ref._timeout : void 0);
  17806. };
  17807. PNG.prototype.render = function (canvas) {
  17808. var ctx, data;
  17809. if (canvas._png) {
  17810. canvas._png.stopAnimation();
  17811. }
  17812. canvas._png = this;
  17813. canvas.width = this.width;
  17814. canvas.height = this.height;
  17815. ctx = canvas.getContext("2d");
  17816. if (this.animation) {
  17817. this.decodeFrames(ctx);
  17818. return this.animate(ctx);
  17819. } else {
  17820. data = ctx.createImageData(this.width, this.height);
  17821. this.copyToImageData(data, this.decodePixels());
  17822. return ctx.putImageData(data, 0, 0);
  17823. }
  17824. };
  17825. return PNG;
  17826. }();
  17827. global.PNG = PNG;
  17828. })(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
  17829. // while `this` is nsIContentFrameMessageManager
  17830. // with an attribute `content` that corresponds to the window
  17831. /*
  17832. * Extracted from pdf.js
  17833. * https://github.com/andreasgal/pdf.js
  17834. *
  17835. * Copyright (c) 2011 Mozilla Foundation
  17836. *
  17837. * Contributors: Andreas Gal <gal@mozilla.com>
  17838. * Chris G Jones <cjones@mozilla.com>
  17839. * Shaon Barman <shaon.barman@gmail.com>
  17840. * Vivien Nicolas <21@vingtetun.org>
  17841. * Justin D'Arcangelo <justindarc@gmail.com>
  17842. * Yury Delendik
  17843. *
  17844. *
  17845. */
  17846. var DecodeStream = function () {
  17847. function constructor() {
  17848. this.pos = 0;
  17849. this.bufferLength = 0;
  17850. this.eof = false;
  17851. this.buffer = null;
  17852. }
  17853. constructor.prototype = {
  17854. ensureBuffer: function decodestream_ensureBuffer(requested) {
  17855. var buffer = this.buffer;
  17856. var current = buffer ? buffer.byteLength : 0;
  17857. if (requested < current) return buffer;
  17858. var size = 512;
  17859. while (size < requested) size <<= 1;
  17860. var buffer2 = new Uint8Array(size);
  17861. for (var i = 0; i < current; ++i) buffer2[i] = buffer[i];
  17862. return this.buffer = buffer2;
  17863. },
  17864. getByte: function decodestream_getByte() {
  17865. var pos = this.pos;
  17866. while (this.bufferLength <= pos) {
  17867. if (this.eof) return null;
  17868. this.readBlock();
  17869. }
  17870. return this.buffer[this.pos++];
  17871. },
  17872. getBytes: function decodestream_getBytes(length) {
  17873. var pos = this.pos;
  17874. if (length) {
  17875. this.ensureBuffer(pos + length);
  17876. var end = pos + length;
  17877. while (!this.eof && this.bufferLength < end) this.readBlock();
  17878. var bufEnd = this.bufferLength;
  17879. if (end > bufEnd) end = bufEnd;
  17880. } else {
  17881. while (!this.eof) this.readBlock();
  17882. var end = this.bufferLength;
  17883. }
  17884. this.pos = end;
  17885. return this.buffer.subarray(pos, end);
  17886. },
  17887. lookChar: function decodestream_lookChar() {
  17888. var pos = this.pos;
  17889. while (this.bufferLength <= pos) {
  17890. if (this.eof) return null;
  17891. this.readBlock();
  17892. }
  17893. return String.fromCharCode(this.buffer[this.pos]);
  17894. },
  17895. getChar: function decodestream_getChar() {
  17896. var pos = this.pos;
  17897. while (this.bufferLength <= pos) {
  17898. if (this.eof) return null;
  17899. this.readBlock();
  17900. }
  17901. return String.fromCharCode(this.buffer[this.pos++]);
  17902. },
  17903. makeSubStream: function decodestream_makeSubstream(start, length, dict) {
  17904. var end = start + length;
  17905. while (this.bufferLength <= end && !this.eof) this.readBlock();
  17906. return new Stream(this.buffer, start, length, dict);
  17907. },
  17908. skip: function decodestream_skip(n) {
  17909. if (!n) n = 1;
  17910. this.pos += n;
  17911. },
  17912. reset: function decodestream_reset() {
  17913. this.pos = 0;
  17914. }
  17915. };
  17916. return constructor;
  17917. }();
  17918. var FlateStream = function () {
  17919. if (typeof Uint32Array === "undefined") {
  17920. return undefined;
  17921. }
  17922. var codeLenCodeMap = new Uint32Array([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]);
  17923. 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]);
  17924. 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]);
  17925. 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];
  17926. 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];
  17927. function error(e) {
  17928. throw new Error(e);
  17929. }
  17930. function constructor(bytes) {
  17931. //var bytes = stream.getBytes();
  17932. var bytesPos = 0;
  17933. var cmf = bytes[bytesPos++];
  17934. var flg = bytes[bytesPos++];
  17935. if (cmf == -1 || flg == -1) error("Invalid header in flate stream");
  17936. if ((cmf & 0x0f) != 0x08) error("Unknown compression method in flate stream");
  17937. if (((cmf << 8) + flg) % 31 != 0) error("Bad FCHECK in flate stream");
  17938. if (flg & 0x20) error("FDICT bit set in flate stream");
  17939. this.bytes = bytes;
  17940. this.bytesPos = bytesPos;
  17941. this.codeSize = 0;
  17942. this.codeBuf = 0;
  17943. DecodeStream.call(this);
  17944. }
  17945. constructor.prototype = Object.create(DecodeStream.prototype);
  17946. constructor.prototype.getBits = function (bits) {
  17947. var codeSize = this.codeSize;
  17948. var codeBuf = this.codeBuf;
  17949. var bytes = this.bytes;
  17950. var bytesPos = this.bytesPos;
  17951. var b;
  17952. while (codeSize < bits) {
  17953. if (typeof (b = bytes[bytesPos++]) == "undefined") error("Bad encoding in flate stream");
  17954. codeBuf |= b << codeSize;
  17955. codeSize += 8;
  17956. }
  17957. b = codeBuf & (1 << bits) - 1;
  17958. this.codeBuf = codeBuf >> bits;
  17959. this.codeSize = codeSize -= bits;
  17960. this.bytesPos = bytesPos;
  17961. return b;
  17962. };
  17963. constructor.prototype.getCode = function (table) {
  17964. var codes = table[0];
  17965. var maxLen = table[1];
  17966. var codeSize = this.codeSize;
  17967. var codeBuf = this.codeBuf;
  17968. var bytes = this.bytes;
  17969. var bytesPos = this.bytesPos;
  17970. while (codeSize < maxLen) {
  17971. var b;
  17972. if (typeof (b = bytes[bytesPos++]) == "undefined") error("Bad encoding in flate stream");
  17973. codeBuf |= b << codeSize;
  17974. codeSize += 8;
  17975. }
  17976. var code = codes[codeBuf & (1 << maxLen) - 1];
  17977. var codeLen = code >> 16;
  17978. var codeVal = code & 0xffff;
  17979. if (codeSize == 0 || codeSize < codeLen || codeLen == 0) error("Bad encoding in flate stream");
  17980. this.codeBuf = codeBuf >> codeLen;
  17981. this.codeSize = codeSize - codeLen;
  17982. this.bytesPos = bytesPos;
  17983. return codeVal;
  17984. };
  17985. constructor.prototype.generateHuffmanTable = function (lengths) {
  17986. var n = lengths.length; // find max code length
  17987. var maxLen = 0;
  17988. for (var i = 0; i < n; ++i) {
  17989. if (lengths[i] > maxLen) maxLen = lengths[i];
  17990. } // build the table
  17991. var size = 1 << maxLen;
  17992. var codes = new Uint32Array(size);
  17993. for (var len = 1, code = 0, skip = 2; len <= maxLen; ++len, code <<= 1, skip <<= 1) {
  17994. for (var val = 0; val < n; ++val) {
  17995. if (lengths[val] == len) {
  17996. // bit-reverse the code
  17997. var code2 = 0;
  17998. var t = code;
  17999. for (var i = 0; i < len; ++i) {
  18000. code2 = code2 << 1 | t & 1;
  18001. t >>= 1;
  18002. } // fill the table entries
  18003. for (var i = code2; i < size; i += skip) codes[i] = len << 16 | val;
  18004. ++code;
  18005. }
  18006. }
  18007. }
  18008. return [codes, maxLen];
  18009. };
  18010. constructor.prototype.readBlock = function () {
  18011. function repeat(stream, array, len, offset, what) {
  18012. var repeat = stream.getBits(len) + offset;
  18013. while (repeat-- > 0) array[i++] = what;
  18014. } // read block header
  18015. var hdr = this.getBits(3);
  18016. if (hdr & 1) this.eof = true;
  18017. hdr >>= 1;
  18018. if (hdr == 0) {
  18019. // uncompressed block
  18020. var bytes = this.bytes;
  18021. var bytesPos = this.bytesPos;
  18022. var b;
  18023. if (typeof (b = bytes[bytesPos++]) == "undefined") error("Bad block header in flate stream");
  18024. var blockLen = b;
  18025. if (typeof (b = bytes[bytesPos++]) == "undefined") error("Bad block header in flate stream");
  18026. blockLen |= b << 8;
  18027. if (typeof (b = bytes[bytesPos++]) == "undefined") error("Bad block header in flate stream");
  18028. var check = b;
  18029. if (typeof (b = bytes[bytesPos++]) == "undefined") error("Bad block header in flate stream");
  18030. check |= b << 8;
  18031. if (check != (~blockLen & 0xffff)) error("Bad uncompressed block length in flate stream");
  18032. this.codeBuf = 0;
  18033. this.codeSize = 0;
  18034. var bufferLength = this.bufferLength;
  18035. var buffer = this.ensureBuffer(bufferLength + blockLen);
  18036. var end = bufferLength + blockLen;
  18037. this.bufferLength = end;
  18038. for (var n = bufferLength; n < end; ++n) {
  18039. if (typeof (b = bytes[bytesPos++]) == "undefined") {
  18040. this.eof = true;
  18041. break;
  18042. }
  18043. buffer[n] = b;
  18044. }
  18045. this.bytesPos = bytesPos;
  18046. return;
  18047. }
  18048. var litCodeTable;
  18049. var distCodeTable;
  18050. if (hdr == 1) {
  18051. // compressed block, fixed codes
  18052. litCodeTable = fixedLitCodeTab;
  18053. distCodeTable = fixedDistCodeTab;
  18054. } else if (hdr == 2) {
  18055. // compressed block, dynamic codes
  18056. var numLitCodes = this.getBits(5) + 257;
  18057. var numDistCodes = this.getBits(5) + 1;
  18058. var numCodeLenCodes = this.getBits(4) + 4; // build the code lengths code table
  18059. var codeLenCodeLengths = Array(codeLenCodeMap.length);
  18060. var i = 0;
  18061. while (i < numCodeLenCodes) codeLenCodeLengths[codeLenCodeMap[i++]] = this.getBits(3);
  18062. var codeLenCodeTab = this.generateHuffmanTable(codeLenCodeLengths); // build the literal and distance code tables
  18063. var len = 0;
  18064. var i = 0;
  18065. var codes = numLitCodes + numDistCodes;
  18066. var codeLengths = new Array(codes);
  18067. while (i < codes) {
  18068. var code = this.getCode(codeLenCodeTab);
  18069. if (code == 16) {
  18070. repeat(this, codeLengths, 2, 3, len);
  18071. } else if (code == 17) {
  18072. repeat(this, codeLengths, 3, 3, len = 0);
  18073. } else if (code == 18) {
  18074. repeat(this, codeLengths, 7, 11, len = 0);
  18075. } else {
  18076. codeLengths[i++] = len = code;
  18077. }
  18078. }
  18079. litCodeTable = this.generateHuffmanTable(codeLengths.slice(0, numLitCodes));
  18080. distCodeTable = this.generateHuffmanTable(codeLengths.slice(numLitCodes, codes));
  18081. } else {
  18082. error("Unknown block type in flate stream");
  18083. }
  18084. var buffer = this.buffer;
  18085. var limit = buffer ? buffer.length : 0;
  18086. var pos = this.bufferLength;
  18087. while (true) {
  18088. var code1 = this.getCode(litCodeTable);
  18089. if (code1 < 256) {
  18090. if (pos + 1 >= limit) {
  18091. buffer = this.ensureBuffer(pos + 1);
  18092. limit = buffer.length;
  18093. }
  18094. buffer[pos++] = code1;
  18095. continue;
  18096. }
  18097. if (code1 == 256) {
  18098. this.bufferLength = pos;
  18099. return;
  18100. }
  18101. code1 -= 257;
  18102. code1 = lengthDecode[code1];
  18103. var code2 = code1 >> 16;
  18104. if (code2 > 0) code2 = this.getBits(code2);
  18105. var len = (code1 & 0xffff) + code2;
  18106. code1 = this.getCode(distCodeTable);
  18107. code1 = distDecode[code1];
  18108. code2 = code1 >> 16;
  18109. if (code2 > 0) code2 = this.getBits(code2);
  18110. var dist = (code1 & 0xffff) + code2;
  18111. if (pos + len >= limit) {
  18112. buffer = this.ensureBuffer(pos + len);
  18113. limit = buffer.length;
  18114. }
  18115. for (var k = 0; k < len; ++k, ++pos) buffer[pos] = buffer[pos - dist];
  18116. }
  18117. };
  18118. return constructor;
  18119. }();
  18120. exports.default = jsPDF;
  18121. var _default2 = exports.default;
  18122. function rewire($stub) {
  18123. exports.default = $stub;
  18124. }
  18125. function restore() {
  18126. exports.default = _default2;
  18127. }
  18128. exports.rewire = rewire;
  18129. exports.restore = restore;
  18130. Object.defineProperty(exports, '__esModule', { value: true });
  18131. })));