123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231 |
- <?php
- require_once __DIR__ . '/../MpdfException.php';
- define("_OTL_OLD_SPEC_COMPAT_1", true);
- define("_DICT_NODE_TYPE_SPLIT", 0x01);
- define("_DICT_NODE_TYPE_LINEAR", 0x02);
- define("_DICT_INTERMEDIATE_MATCH", 0x03);
- define("_DICT_FINAL_MATCH", 0x04);
- class otl
- {
- var $mpdf;
- var $arabLeftJoining;
- var $arabRightJoining;
- var $arabTransparentJoin;
- var $arabTransparent;
- var $GSUBdata;
- var $GPOSdata;
- var $GSUBfont;
- var $fontkey;
- var $ttfOTLdata;
- var $glyphIDtoUni;
- var $_pos;
- var $GSUB_offset;
- var $GPOS_offset;
- var $MarkAttachmentType;
- var $MarkGlyphSets;
- var $GlyphClassMarks;
- var $GlyphClassLigatures;
- var $GlyphClassBases;
- var $GlyphClassComponents;
- var $Ignores;
- var $LuCoverage;
- var $OTLdata;
- var $assocLigs;
- var $assocMarks;
- var $shaper;
- var $restrictToSyllable;
- var $lbdicts;
- var $LuDataCache;
- var $debugOTL = false;
- public function __construct(mPDF $mpdf)
- {
- $this->mpdf = $mpdf;
- $this->arabic_initialise();
- $this->current_fh = '';
- $this->lbdicts = array();
- $this->LuDataCache = array();
- }
- function applyOTL($str, $useOTL)
- {
- $this->OTLdata = array();
- if (trim($str) == '') {
- return $str;
- }
- if (!$useOTL) {
- return $str;
- }
-
-
- $this->fontkey = $this->mpdf->CurrentFont['fontkey'];
- $this->glyphIDtoUni = $this->mpdf->CurrentFont['glyphIDtoUni'];
- if (!isset($this->GDEFdata[$this->fontkey])) {
- include(_MPDF_TTFONTDATAPATH . $this->fontkey . '.GDEFdata.php');
- $this->GSUB_offset = $this->GDEFdata[$this->fontkey]['GSUB_offset'] = $GSUB_offset;
- $this->GPOS_offset = $this->GDEFdata[$this->fontkey]['GPOS_offset'] = $GPOS_offset;
- $this->GSUB_length = $this->GDEFdata[$this->fontkey]['GSUB_length'] = $GSUB_length;
- $this->MarkAttachmentType = $this->GDEFdata[$this->fontkey]['MarkAttachmentType'] = $MarkAttachmentType;
- $this->MarkGlyphSets = $this->GDEFdata[$this->fontkey]['MarkGlyphSets'] = $MarkGlyphSets;
- $this->GlyphClassMarks = $this->GDEFdata[$this->fontkey]['GlyphClassMarks'] = $GlyphClassMarks;
- $this->GlyphClassLigatures = $this->GDEFdata[$this->fontkey]['GlyphClassLigatures'] = $GlyphClassLigatures;
- $this->GlyphClassComponents = $this->GDEFdata[$this->fontkey]['GlyphClassComponents'] = $GlyphClassComponents;
- $this->GlyphClassBases = $this->GDEFdata[$this->fontkey]['GlyphClassBases'] = $GlyphClassBases;
- } else {
- $this->GSUB_offset = $this->GDEFdata[$this->fontkey]['GSUB_offset'];
- $this->GPOS_offset = $this->GDEFdata[$this->fontkey]['GPOS_offset'];
- $this->GSUB_length = $this->GDEFdata[$this->fontkey]['GSUB_length'];
- $this->MarkAttachmentType = $this->GDEFdata[$this->fontkey]['MarkAttachmentType'];
- $this->MarkGlyphSets = $this->GDEFdata[$this->fontkey]['MarkGlyphSets'];
- $this->GlyphClassMarks = $this->GDEFdata[$this->fontkey]['GlyphClassMarks'];
- $this->GlyphClassLigatures = $this->GDEFdata[$this->fontkey]['GlyphClassLigatures'];
- $this->GlyphClassComponents = $this->GDEFdata[$this->fontkey]['GlyphClassComponents'];
- $this->GlyphClassBases = $this->GDEFdata[$this->fontkey]['GlyphClassBases'];
- }
-
-
- $earr = $this->mpdf->UTF8StringToArray($str, false);
- $scriptblock = 0;
- $scriptblocks = array();
- $scriptblocks[0] = 0;
- $vstr = '';
- $OTLdata = array();
- $subchunk = 0;
- $charctr = 0;
- foreach ($earr as $char) {
- $ucd_record = UCDN::get_ucd_record($char);
- $sbl = $ucd_record[6];
-
- if ($char == 1757) {
- $sbl = UCDN::SCRIPT_ARABIC;
- }
- if ($sbl && $sbl != 40 && $sbl != 102) {
- if ($scriptblock == 0) {
- $scriptblock = $sbl;
- $scriptblocks[$subchunk] = $scriptblock;
- } else if ($scriptblock > 0 && $scriptblock != $sbl) {
-
-
- $subchunk++;
- $scriptblock = $sbl;
- $charctr = 0;
- $scriptblocks[$subchunk] = $scriptblock;
- }
- }
- $OTLdata[$subchunk][$charctr]['general_category'] = $ucd_record[0];
- $OTLdata[$subchunk][$charctr]['bidi_type'] = $ucd_record[2];
-
-
-
-
-
-
- $charasstr = $this->unicode_hex($char);
- if (strpos($this->GlyphClassMarks, $charasstr) !== false) {
- $OTLdata[$subchunk][$charctr]['group'] = 'M';
- } else if ($char == 32 || $char == 12288) {
- $OTLdata[$subchunk][$charctr]['group'] = 'S';
- }
- else {
- $OTLdata[$subchunk][$charctr]['group'] = 'C';
- }
- $OTLdata[$subchunk][$charctr]['uni'] = $char;
- $OTLdata[$subchunk][$charctr]['hex'] = $charasstr;
- $charctr++;
- }
-
- for ($sch = 0; $sch <= $subchunk; $sch++) {
- $this->OTLdata = $OTLdata[$sch];
- $scriptblock = $scriptblocks[$sch];
-
-
-
- if (UCDN::SCRIPT_DEVANAGARI <= $scriptblock && $scriptblock <= UCDN::SCRIPT_MALAYALAM) {
- $this->shaper = "I";
- }
- else if ($scriptblock == UCDN::SCRIPT_ARABIC || $scriptblock == UCDN::SCRIPT_SYRIAC) {
- $this->shaper = "A";
- }
- else if ($scriptblock == UCDN::SCRIPT_NKO || $scriptblock == UCDN::SCRIPT_MANDAIC) {
- $this->shaper = "A";
- }
- else if ($scriptblock == UCDN::SCRIPT_KHMER) {
- $this->shaper = "K";
- }
- else if ($scriptblock == UCDN::SCRIPT_THAI) {
- $this->shaper = "T";
- }
- else if ($scriptblock == UCDN::SCRIPT_LAO) {
- $this->shaper = "L";
- }
- else if ($scriptblock == UCDN::SCRIPT_SINHALA) {
- $this->shaper = "S";
- }
- else if ($scriptblock == UCDN::SCRIPT_MYANMAR) {
- $this->shaper = "M";
- }
- else if ($scriptblock == UCDN::SCRIPT_NEW_TAI_LUE) {
- $this->shaper = "E";
- }
- else if ($scriptblock == UCDN::SCRIPT_CHAM) {
- $this->shaper = "E";
- }
- else if ($scriptblock == UCDN::SCRIPT_TAI_THAM) {
- $this->shaper = "E";
- }
- else
- $this->shaper = "";
-
- $scripttag = UCDN::$uni_scriptblock[$scriptblock];
- $GSUBscriptTag = '';
- $GSUBlangsys = '';
- $GPOSscriptTag = '';
- $GPOSlangsys = '';
- $is_old_spec = false;
- $ScriptLang = $this->mpdf->CurrentFont['GSUBScriptLang'];
- if (count($ScriptLang)) {
- list($GSUBscriptTag, $is_old_spec) = $this->_getOTLscriptTag($ScriptLang, $scripttag, $scriptblock, $this->shaper, $useOTL, 'GSUB');
- if ($this->mpdf->fontLanguageOverride && strpos($ScriptLang[$GSUBscriptTag], $this->mpdf->fontLanguageOverride) !== false) {
- $GSUBlangsys = str_pad($this->mpdf->fontLanguageOverride, 4);
- } else if ($GSUBscriptTag && isset($ScriptLang[$GSUBscriptTag]) && $ScriptLang[$GSUBscriptTag] != '') {
- $GSUBlangsys = $this->_getOTLLangTag($this->mpdf->currentLang, $ScriptLang[$GSUBscriptTag]);
- }
- }
- $ScriptLang = $this->mpdf->CurrentFont['GPOSScriptLang'];
-
- if ($GSUBscriptTag && $GSUBlangsys && isset($ScriptLang[$GSUBscriptTag]) && strpos($ScriptLang[$GSUBscriptTag], $GSUBlangsys) !== false) {
- $GPOSlangsys = $GSUBlangsys;
- $GPOSscriptTag = $GSUBscriptTag;
- }
-
-
- else if (count($ScriptLang)) {
- list($GPOSscriptTag, $dummy) = $this->_getOTLscriptTag($ScriptLang, $scripttag, $scriptblock, $this->shaper, $useOTL, 'GPOS');
- if ($GPOSscriptTag && $this->mpdf->fontLanguageOverride && strpos($ScriptLang[$GPOSscriptTag], $this->mpdf->fontLanguageOverride) !== false) {
- $GPOSlangsys = str_pad($this->mpdf->fontLanguageOverride, 4);
- } else if ($GPOSscriptTag && isset($ScriptLang[$GPOSscriptTag]) && $ScriptLang[$GPOSscriptTag] != '') {
- $GPOSlangsys = $this->_getOTLLangTag($this->mpdf->currentLang, $ScriptLang[$GPOSscriptTag]);
- }
- }
-
-
- if (isset($this->mpdf->overrideOTLsettings) && isset($this->mpdf->overrideOTLsettings[$this->fontkey])) {
- $GSUBscriptTag = $GPOSscriptTag = $this->mpdf->overrideOTLsettings[$this->fontkey]['script'];
- $GSUBlangsys = $GPOSlangsys = $this->mpdf->overrideOTLsettings[$this->fontkey]['lang'];
- }
-
- if (!$GSUBscriptTag && !$GSUBlangsys && !$GPOSscriptTag && !$GPOSlangsys) {
-
- for ($i = 0; $i < count($this->OTLdata); $i++) {
- if ($this->OTLdata[$i]['uni'] == 8204 || $this->OTLdata[$i]['uni'] == 8205) {
- array_splice($this->OTLdata, $i, 1);
- }
- }
- $this->schOTLdata[$sch] = $this->OTLdata;
- $this->OTLdata = array();
- continue;
- }
-
- if ($this->shaper == 'M' && $GSUBscriptTag != 'mym2') {
- $this->shaper = '';
- }
- $GSUBFeatures = (isset($this->mpdf->CurrentFont['GSUBFeatures'][$GSUBscriptTag][$GSUBlangsys]) ? $this->mpdf->CurrentFont['GSUBFeatures'][$GSUBscriptTag][$GSUBlangsys] : false);
- $GPOSFeatures = (isset($this->mpdf->CurrentFont['GPOSFeatures'][$GPOSscriptTag][$GPOSlangsys]) ? $this->mpdf->CurrentFont['GPOSFeatures'][$GPOSscriptTag][$GPOSlangsys] : false);
- $this->assocLigs = array();
- $this->assocMarks = array();
- if (!isset($this->GDEFdata[$this->fontkey]['GSUBGPOStables'])) {
- $this->ttfOTLdata = $this->GDEFdata[$this->fontkey]['GSUBGPOStables'] = file_get_contents(_MPDF_TTFONTDATAPATH . $this->fontkey . '.GSUBGPOStables.dat', 'rb');
- if (!$this->ttfOTLdata) {
- throw new MpdfException('Can\'t open file ' . _MPDF_TTFONTDATAPATH . $this->fontkey . '.GSUBGPOStables.dat');
- }
- } else {
- $this->ttfOTLdata = $this->GDEFdata[$this->fontkey]['GSUBGPOStables'];
- }
- if ($this->debugOTL) {
- $this->_dumpproc('BEGIN', '-', '-', '-', '-', -1, '-', 0);
- }
-
- if ($this->mpdf->useDictionaryLBR && ($this->shaper == "K" || $this->shaper == "T" || $this->shaper == "L")) {
-
- $this->SEAlineBreaking();
- }
-
- else if ($this->mpdf->useTibetanLBR && $scriptblock == UCDN::SCRIPT_TIBETAN) {
-
- $this->TibetanlineBreaking();
- }
- if (($useOTL & 0xFF) && $GSUBscriptTag && $GSUBlangsys && $GSUBFeatures) {
-
-
- $this->GSUBfont = $this->fontkey . '.GSUB.' . $GSUBscriptTag . '.' . $GSUBlangsys;
- if (!isset($this->GSUBdata[$this->GSUBfont])) {
- if (file_exists(_MPDF_TTFONTDATAPATH . $this->mpdf->CurrentFont['fontkey'] . '.GSUB.' . $GSUBscriptTag . '.' . $GSUBlangsys . '.php')) {
- include_once(_MPDF_TTFONTDATAPATH . $this->mpdf->CurrentFont['fontkey'] . '.GSUB.' . $GSUBscriptTag . '.' . $GSUBlangsys . '.php');
- $this->GSUBdata[$this->GSUBfont]['rtlSUB'] = $rtlSUB;
- $this->GSUBdata[$this->GSUBfont]['finals'] = $finals;
- if ($this->shaper == 'I') {
- $this->GSUBdata[$this->GSUBfont]['rphf'] = $rphf;
- $this->GSUBdata[$this->GSUBfont]['half'] = $half;
- $this->GSUBdata[$this->GSUBfont]['pref'] = $pref;
- $this->GSUBdata[$this->GSUBfont]['blwf'] = $blwf;
- $this->GSUBdata[$this->GSUBfont]['pstf'] = $pstf;
- }
- } else {
- $this->GSUBdata[$this->GSUBfont] = array('rtlSUB' => array(), 'rphf' => array(), 'rphf' => array(),
- 'pref' => array(), 'blwf' => array(), 'pstf' => array(), 'finals' => ''
- );
- }
- }
- if (!isset($this->GSUBdata[$this->fontkey])) {
- include(_MPDF_TTFONTDATAPATH . $this->fontkey . '.GSUBdata.php');
- $this->GSLuCoverage = $this->GSUBdata[$this->fontkey]['GSLuCoverage'] = $GSLuCoverage;
- } else {
- $this->GSLuCoverage = $this->GSUBdata[$this->fontkey]['GSLuCoverage'];
- }
- $this->GSUBLookups = $this->mpdf->CurrentFont['GSUBLookups'];
-
-
- if ($this->shaper == 'A') {
-
-
-
- $tags = 'locl ccmp';
- $omittags = '';
- $usetags = $tags;
- if (!empty($this->mpdf->OTLtags)) {
- $usetags = $this->_applyTagSettings($tags, $GSUBFeatures, $omittags, true);
- }
- $this->_applyGSUBrules($usetags, $GSUBscriptTag, $GSUBlangsys);
-
-
-
-
-
- $tags = 'isol fina fin2 fin3 medi med2 init';
- $omittags = '';
- $usetags = $tags;
- if (!empty($this->mpdf->OTLtags)) {
- $usetags = $this->_applyTagSettings($tags, $GSUBFeatures, $omittags, true);
- }
- $this->arabGlyphs = $this->GSUBdata[$this->GSUBfont]['rtlSUB'];
- $gcms = explode("| ", $this->GlyphClassMarks);
- $gcm = array();
- foreach ($gcms AS $g) {
- $gcm[hexdec($g)] = 1;
- }
- $this->arabTransparentJoin = $this->arabTransparent + $gcm;
- $this->arabic_shaper($usetags, $GSUBscriptTag);
-
-
-
-
- for ($i = 0; $i < count($this->OTLdata); $i++) {
-
-
-
-
-
- if ($this->OTLdata[$i]['uni'] == 0x0640) {
- $this->OTLdata[$i]['GPOSinfo']['kashida'] = 8;
- }
-
-
-
-
- else if ($this->OTLdata[$i]['uni'] == 0xFEB3 || $this->OTLdata[$i]['uni'] == 0xFEB4 || $this->OTLdata[$i]['uni'] == 0xFEBB || $this->OTLdata[$i]['uni'] == 0xFEBC) {
- $checkpos = $i + 1;
- while (isset($this->OTLdata[$checkpos]) && strpos($this->GlyphClassMarks, $this->OTLdata[$checkpos]['hex']) !== false) {
- $checkpos++;
- }
- if (isset($this->OTLdata[$checkpos])) {
- $this->OTLdata[$checkpos]['GPOSinfo']['kashida'] = 7;
- }
- }
-
-
-
-
- else if ($this->OTLdata[$i]['uni'] == 0xFE94 || $this->OTLdata[$i]['uni'] == 0xFEA2 || $this->OTLdata[$i]['uni'] == 0xFEAA) {
- $this->OTLdata[$i]['GPOSinfo']['kashida'] = 6;
- }
-
-
-
-
- else if ($this->OTLdata[$i]['uni'] == 0xFE8E || $this->OTLdata[$i]['uni'] == 0xFEC2 || $this->OTLdata[$i]['uni'] == 0xFEDE || $this->OTLdata[$i]['uni'] == 0xFEDA || $this->OTLdata[$i]['uni'] == 0xFB93) {
- $this->OTLdata[$i]['GPOSinfo']['kashida'] = 5;
- }
-
-
-
-
-
- else if ($this->OTLdata[$i]['uni'] == 0xFEAE || $this->OTLdata[$i]['uni'] == 0xFEF2 || $this->OTLdata[$i]['uni'] == 0xFEF0 || $this->OTLdata[$i]['uni'] == 0xFEF4 || $this->OTLdata[$i]['uni'] == 0xFBE9 || $this->OTLdata[$i]['uni'] == 0xFBFD || $this->OTLdata[$i]['uni'] == 0xFBFF
- ) {
- $checkpos = $i - 1;
- while (isset($this->OTLdata[$checkpos]) && strpos($this->GlyphClassMarks, $this->OTLdata[$checkpos]['hex']) !== false) {
- $checkpos--;
- }
- if (isset($this->OTLdata[$checkpos]) && $this->OTLdata[$checkpos]['uni'] == 0xFE92) {
- $this->OTLdata[$checkpos]['GPOSinfo']['kashida'] = 4;
- }
- }
-
-
-
-
- else if ($this->OTLdata[$i]['uni'] == 0xFEEE || $this->OTLdata[$i]['uni'] == 0xFECA || $this->OTLdata[$i]['uni'] == 0xFED6 || $this->OTLdata[$i]['uni'] == 0xFED2) {
- $this->OTLdata[$i]['GPOSinfo']['kashida'] = 3;
- }
-
-
-
-
-
- if (!isset($this->OTLdata[$i]['GPOSinfo']['kashida'])) {
- if (strpos($this->GSUBdata[$this->GSUBfont]['finals'], $this->OTLdata[$i]['hex']) !== false) {
- $this->OTLdata[$i]['GPOSinfo']['kashida'] = 2;
- } else if (strpos('0FEAE 0FEF0 0FEF2', $this->OTLdata[$i]['hex']) !== false) {
- $this->OTLdata[$i]['GPOSinfo']['kashida'] = 1;
- }
- }
- }
-
-
-
- $tags = 'rlig calt liga clig mset';
- $omittags = 'locl ccmp nukt akhn rphf rkrf pref blwf abvf half pstf cfar vatu cjct init medi fina isol med2 fin2 fin3 ljmo vjmo tjmo';
- $usetags = $tags;
- if (!empty($this->mpdf->OTLtags)) {
- $usetags = $this->_applyTagSettings($tags, $GSUBFeatures, $omittags, false);
- }
- $ts = explode(' ', $usetags);
- foreach ($ts AS $ut) {
- $this->_applyGSUBrules($ut, $GSUBscriptTag, $GSUBlangsys);
- }
-
-
-
-
- for ($ptr = 1; $ptr < count($this->OTLdata); $ptr++) {
- if ($this->OTLdata[$ptr]['general_category'] == UCDN::UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK && $this->OTLdata[$ptr - 1]['uni'] == 32) {
- $this->OTLdata[$ptr - 1]['uni'] = 0xa0;
- $this->OTLdata[$ptr - 1]['hex'] = '000A0';
- }
- }
- }
-
-
- else if ($this->shaper == 'I' || $this->shaper == 'K' || $this->shaper == 'S') {
- $this->restrictToSyllable = true;
-
-
-
-
- for ($ptr = 0; $ptr < count($this->OTLdata); $ptr++) {
- $char = $this->OTLdata[$ptr]['uni'];
- $sub = INDIC::decompose_indic($char);
- if ($sub) {
- $newinfo = array();
- for ($i = 0; $i < count($sub); $i++) {
- $newinfo[$i] = array();
- $ucd_record = UCDN::get_ucd_record($sub[$i]);
- $newinfo[$i]['general_category'] = $ucd_record[0];
- $newinfo[$i]['bidi_type'] = $ucd_record[2];
- $charasstr = $this->unicode_hex($sub[$i]);
- if (strpos($this->GlyphClassMarks, $charasstr) !== false) {
- $newinfo[$i]['group'] = 'M';
- } else {
- $newinfo[$i]['group'] = 'C';
- }
- $newinfo[$i]['uni'] = $sub[$i];
- $newinfo[$i]['hex'] = $charasstr;
- }
- array_splice($this->OTLdata, $ptr, 1, $newinfo);
- $ptr += count($sub) - 1;
- }
-
- if ($this->shaper == 'I') {
- if ($char == 0x09AF && isset($this->OTLdata[$ptr + 1]) && $this->OTLdata[$ptr + 1]['uni'] == 0x09BC) {
- $sub = 0x09DF;
- $newinfo = array();
- $newinfo[0] = array();
- $ucd_record = UCDN::get_ucd_record($sub);
- $newinfo[0]['general_category'] = $ucd_record[0];
- $newinfo[0]['bidi_type'] = $ucd_record[2];
- $newinfo[0]['group'] = 'C';
- $newinfo[0]['uni'] = $sub;
- $newinfo[0]['hex'] = $this->unicode_hex($sub);
- array_splice($this->OTLdata, $ptr, 2, $newinfo);
- }
- }
- }
-
-
-
- $indic_category_string = '';
- foreach ($this->OTLdata AS $eid => $c) {
- INDIC::set_indic_properties($this->OTLdata[$eid], $scriptblock);
-
-
-
- $indic_category_string .= INDIC::$indic_category_char[$this->OTLdata[$eid]['indic_category']];
- }
- $broken_syllables = false;
- if ($this->shaper == 'I') {
- INDIC::set_syllables($this->OTLdata, $indic_category_string, $broken_syllables);
- } else if ($this->shaper == 'S') {
- INDIC::set_syllables_sinhala($this->OTLdata, $indic_category_string, $broken_syllables);
- } else if ($this->shaper == 'K') {
- INDIC::set_syllables_khmer($this->OTLdata, $indic_category_string, $broken_syllables);
- }
- $indic_category_string = '';
-
-
-
-
-
-
- $indic_config = INDIC::$indic_configs[$scriptblock];
- $dottedcircle = false;
- if ($broken_syllables) {
- if ($this->mpdf->_charDefined($this->mpdf->fonts[$this->fontkey]['cw'], 0x25CC)) {
- $dottedcircle = array();
- $ucd_record = UCDN::get_ucd_record(0x25CC);
- $dottedcircle[0]['general_category'] = $ucd_record[0];
- $dottedcircle[0]['bidi_type'] = $ucd_record[2];
- $dottedcircle[0]['group'] = 'C';
- $dottedcircle[0]['uni'] = 0x25CC;
- $dottedcircle[0]['indic_category'] = INDIC::OT_DOTTEDCIRCLE;
- $dottedcircle[0]['indic_position'] = INDIC::POS_BASE_C;
- $dottedcircle[0]['hex'] = '025CC';
- }
- }
- INDIC::initial_reordering($this->OTLdata, $this->GSUBdata[$this->GSUBfont], $broken_syllables, $indic_config, $scriptblock, $is_old_spec, $dottedcircle);
-
-
-
- if ($this->shaper == 'I' || $this->shaper == 'S') {
- $tags = 'locl ccmp nukt akhn rphf rkrf pref blwf half pstf vatu cjct';
- } else if ($this->shaper == 'K') {
- $tags = 'locl ccmp pref blwf abvf pstf cfar';
- }
- $this->_applyGSUBrulesIndic($tags, $GSUBscriptTag, $GSUBlangsys, $is_old_spec);
-
-
-
-
-
-
- INDIC::final_reordering($this->OTLdata, $this->GSUBdata[$this->GSUBfont], $indic_config, $scriptblock, $is_old_spec);
-
-
-
- if ($this->shaper == 'I' || $this->shaper == 'S') {
- $tags = 'init';
- $this->_applyGSUBrulesIndic($tags, $GSUBscriptTag, $GSUBlangsys, $is_old_spec);
- }
-
-
-
- $tags = 'pres abvs blws psts haln rlig calt liga clig mset';
- $omittags = 'locl ccmp nukt akhn rphf rkrf pref blwf abvf half pstf cfar vatu cjct init medi fina isol med2 fin2 fin3 ljmo vjmo tjmo';
- $usetags = $tags;
- if (!empty($this->mpdf->OTLtags)) {
- $usetags = $this->_applyTagSettings($tags, $GSUBFeatures, $omittags, false);
- }
- if ($this->shaper == 'K') {
- $this->_applyGSUBrulesSingly($usetags, $GSUBscriptTag, $GSUBlangsys);
- } else {
- $this->_applyGSUBrules($usetags, $GSUBscriptTag, $GSUBlangsys);
- }
- $this->restrictToSyllable = false;
- }
-
-
-
- else if ($this->shaper == 'M') {
- $this->restrictToSyllable = true;
-
-
-
- $myanmar_category_string = '';
- foreach ($this->OTLdata AS $eid => $c) {
- MYANMAR::set_myanmar_properties($this->OTLdata[$eid]);
- $myanmar_category_string .= MYANMAR::$myanmar_category_char[$this->OTLdata[$eid]['myanmar_category']];
- }
- $broken_syllables = false;
- MYANMAR::set_syllables($this->OTLdata, $myanmar_category_string, $broken_syllables);
- $myanmar_category_string = '';
-
-
-
- $dottedcircle = false;
- if ($broken_syllables) {
- if ($this->mpdf->_charDefined($this->mpdf->fonts[$this->fontkey]['cw'], 0x25CC)) {
- $dottedcircle = array();
- $ucd_record = UCDN::get_ucd_record(0x25CC);
- $dottedcircle[0]['general_category'] = $ucd_record[0];
- $dottedcircle[0]['bidi_type'] = $ucd_record[2];
- $dottedcircle[0]['group'] = 'C';
- $dottedcircle[0]['uni'] = 0x25CC;
- $dottedcircle[0]['myanmar_category'] = MYANMAR::OT_DOTTEDCIRCLE;
- $dottedcircle[0]['myanmar_position'] = MYANMAR::POS_BASE_C;
- $dottedcircle[0]['hex'] = '025CC';
- }
- }
- MYANMAR::reordering($this->OTLdata, $this->GSUBdata[$this->GSUBfont], $broken_syllables, $dottedcircle);
-
-
-
- $tags = 'locl ccmp rphf pref blwf pstf';
- $this->_applyGSUBrulesMyanmar($tags, $GSUBscriptTag, $GSUBlangsys);
-
-
-
- $tags = 'pres abvs blws psts haln rlig calt liga clig mset';
- $omittags = 'locl ccmp nukt akhn rphf rkrf pref blwf abvf half pstf cfar vatu cjct init medi fina isol med2 fin2 fin3 ljmo vjmo tjmo';
- $usetags = $tags;
- if (!empty($this->mpdf->OTLtags)) {
- $usetags = $this->_applyTagSettings($tags, $GSUBFeatures, $omittags, false);
- }
- $this->_applyGSUBrules($usetags, $GSUBscriptTag, $GSUBlangsys);
- $this->restrictToSyllable = false;
- }
-
-
- else if ($this->shaper == 'E') {
-
- $this->restrictToSyllable = true;
-
-
-
- $sea_category_string = '';
- foreach ($this->OTLdata AS $eid => $c) {
- SEA::set_sea_properties($this->OTLdata[$eid], $scriptblock);
-
-
-
- $sea_category_string .= SEA::$sea_category_char[$this->OTLdata[$eid]['sea_category']];
- }
- $broken_syllables = false;
- SEA::set_syllables($this->OTLdata, $sea_category_string, $broken_syllables);
- $sea_category_string = '';
-
-
-
- $tags = 'locl ccmp';
- $this->_applyGSUBrulesSingly($tags, $GSUBscriptTag, $GSUBlangsys);
-
-
-
-
-
-
- $dottedcircle = false;
- if ($broken_syllables) {
- if ($this->mpdf->_charDefined($this->mpdf->fonts[$this->fontkey]['cw'], 0x25CC)) {
- $dottedcircle = array();
- $ucd_record = UCDN::get_ucd_record(0x25CC);
- $dottedcircle[0]['general_category'] = $ucd_record[0];
- $dottedcircle[0]['bidi_type'] = $ucd_record[2];
- $dottedcircle[0]['group'] = 'C';
- $dottedcircle[0]['uni'] = 0x25CC;
- $dottedcircle[0]['sea_category'] = SEA::OT_GB;
- $dottedcircle[0]['sea_position'] = SEA::POS_BASE_C;
- $dottedcircle[0]['hex'] = '025CC';
- }
- }
- SEA::initial_reordering($this->OTLdata, $this->GSUBdata[$this->GSUBfont], $broken_syllables, $scriptblock, $dottedcircle);
-
-
-
- $tags = 'pref abvf blwf pstf';
- $this->_applyGSUBrulesSingly($tags, $GSUBscriptTag, $GSUBlangsys);
-
-
-
- SEA::final_reordering($this->OTLdata, $this->GSUBdata[$this->GSUBfont], $scriptblock);
-
-
-
- $tags = 'pres abvs blws psts';
- $omittags = 'locl ccmp nukt akhn rphf rkrf pref blwf abvf half pstf cfar vatu cjct init medi fina isol med2 fin2 fin3 ljmo vjmo tjmo';
- $usetags = $tags;
- if (!empty($this->mpdf->OTLtags)) {
- $usetags = $this->_applyTagSettings($tags, $GSUBFeatures, $omittags, false);
- }
- $this->_applyGSUBrules($usetags, $GSUBscriptTag, $GSUBlangsys);
- $this->restrictToSyllable = false;
- }
-
-
- else {
-
-
-
-
-
- if ($this->shaper == 'T' || $this->shaper == 'L') {
- for ($ptr = 0; $ptr < count($this->OTLdata); $ptr++) {
- $char = $this->OTLdata[$ptr]['uni'];
- if (($char & ~0x0080) == 0x0E33) {
- $NIKHAHIT = $char + 0x1A;
- $SARA_AA = $char - 1;
- $sub = array($SARA_AA, $NIKHAHIT);
- $newinfo = array();
- $ucd_record = UCDN::get_ucd_record($sub[0]);
- $newinfo[0]['general_category'] = $ucd_record[0];
- $newinfo[0]['bidi_type'] = $ucd_record[2];
- $charasstr = $this->unicode_hex($sub[0]);
- if (strpos($this->GlyphClassMarks, $charasstr) !== false) {
- $newinfo[0]['group'] = 'M';
- } else {
- $newinfo[0]['group'] = 'C';
- }
- $newinfo[0]['uni'] = $sub[0];
- $newinfo[0]['hex'] = $charasstr;
- $this->OTLdata[$ptr] = $newinfo[0];
- $ntones = 0;
-
- while (isset($this->OTLdata[$ptr - 1 - $ntones]) && (
- ($this->OTLdata[$ptr - 1 - $ntones]['uni'] & ~0x0080) == 0x0E31 ||
- (($this->OTLdata[$ptr - 1 - $ntones]['uni'] & ~0x0080) >= 0x0E34 &&
- ($this->OTLdata[$ptr - 1 - $ntones]['uni'] & ~0x0080) <= 0x0E37) ||
- (($this->OTLdata[$ptr - 1 - $ntones]['uni'] & ~0x0080) >= 0x0E47 &&
- ($this->OTLdata[$ptr - 1 - $ntones]['uni'] & ~0x0080) <= 0x0E4E)
- )
- ) {
- $ntones++;
- }
- $newinfo = array();
- $ucd_record = UCDN::get_ucd_record($sub[1]);
- $newinfo[0]['general_category'] = $ucd_record[0];
- $newinfo[0]['bidi_type'] = $ucd_record[2];
- $charasstr = $this->unicode_hex($sub[1]);
- if (strpos($this->GlyphClassMarks, $charasstr) !== false) {
- $newinfo[0]['group'] = 'M';
- } else {
- $newinfo[0]['group'] = 'C';
- }
- $newinfo[0]['uni'] = $sub[1];
- $newinfo[0]['hex'] = $charasstr;
-
- array_splice($this->OTLdata, $ptr - $ntones, 0, $newinfo);
- $ptr++;
- }
- }
- }
- if ($scriptblock == UCDN::SCRIPT_TIBETAN) {
-
-
-
-
-
-
-
-
-
-
- for ($ptr = 0; $ptr < count($this->OTLdata) - 1; $ptr++) {
- if (INDIC::in_range($this->OTLdata[$ptr]['uni'], 0x0F20, 0x0F33) && $this->OTLdata[$ptr + 1]['uni'] == 0x0F3F) {
- $tmp = $this->OTLdata[$ptr + 1];
- $this->OTLdata[$ptr + 1] = $this->OTLdata[$ptr];
- $this->OTLdata[$ptr] = $tmp;
- }
- }
-
-
-
-
- }
-
-
-
- $tags = 'locl ccmp pref blwf abvf pstf pres abvs blws psts haln rlig calt liga clig mset RQD';
-
-
-
-
- $omittags = '';
- $useGSUBtags = $tags;
- if (!empty($this->mpdf->OTLtags)) {
- $useGSUBtags = $this->_applyTagSettings($tags, $GSUBFeatures, $omittags, false);
- }
-
- if (!(($this->mpdf->textvar & FC_SMALLCAPS) && $scriptblock == UCDN::SCRIPT_LATIN && strpos($useGSUBtags, 'smcp') === false)) {
- $this->_applyGSUBrules($useGSUBtags, $GSUBscriptTag, $GSUBlangsys);
- }
- }
- }
-
-
-
- if (($this->shaper == "K" || $this->shaper == "T" || $this->shaper == "L") || $scriptblock == UCDN::SCRIPT_TIBETAN) {
-
- $newinfo = array();
-
- $newinfo[0] = array(
- 'general_category' => UCDN::UNICODE_GENERAL_CATEGORY_FORMAT,
- 'bidi_type' => UCDN::BIDI_CLASS_BN,
- 'group' => 'S', 'uni' => 0x200B, 'hex' => '0200B');
-
- for ($i = count($this->OTLdata) - 1; $i > 0; $i--) {
-
- if (isset($this->OTLdata[$i]['wordend']) && $this->OTLdata[$i]['wordend'] &&
- isset($this->OTLdata[$i + 1]['uni']) && (!isset($this->OTLdata[$i + 1]['syllable']) || !isset($this->OTLdata[$i + 1]['syllable']) || $this->OTLdata[$i + 1]['syllable'] != $this->OTLdata[$i]['syllable'])) {
- array_splice($this->OTLdata, $i + 1, 0, $newinfo);
- $this->_updateLigatureMarks($i, 1);
- } else if ($this->OTLdata[$i]['uni'] == 0x2e) {
- array_splice($this->OTLdata, $i + 1, 0, $newinfo);
- $this->_updateLigatureMarks($i, 1);
- }
- }
- }
-
-
- if ($this->shaper == 'I' || $this->shaper == 'S' || $this->shaper == 'A' || $this->shaper == 'K' || $this->shaper == 'M') {
-
- for ($i = 0; $i < count($this->OTLdata); $i++) {
- if ($this->OTLdata[$i]['uni'] == 8204 || $this->OTLdata[$i]['uni'] == 8205) {
- array_splice($this->OTLdata, $i, 1);
- $this->_updateLigatureMarks($i, -1);
- }
- }
- }
- if (($useOTL & 0xFF) && $GPOSscriptTag && $GPOSlangsys && $GPOSFeatures) {
- $this->Entry = array();
- $this->Exit = array();
-
-
- if (!isset($this->GPOSdata[$this->fontkey])) {
- include(_MPDF_TTFONTDATAPATH . $this->mpdf->CurrentFont['fontkey'] . '.GPOSdata.php');
- $this->LuCoverage = $this->GPOSdata[$this->fontkey]['LuCoverage'] = $LuCoverage;
- } else {
- $this->LuCoverage = $this->GPOSdata[$this->fontkey]['LuCoverage'];
- }
- $this->GPOSLookups = $this->mpdf->CurrentFont['GPOSLookups'];
-
-
- $tags = 'abvm blwm mark mkmk curs cpsp dist requ';
-
-
-
-
-
- if ($scriptblock != UCDN::SCRIPT_LATIN) {
- $tags .= ' kern';
- }
- $omittags = '';
- $usetags = $tags;
- if (!empty($this->mpdf->OTLtags)) {
- $usetags = $this->_applyTagSettings($tags, $GPOSFeatures, $omittags, false);
- }
-
-
- $LookupList = array();
- foreach ($GPOSFeatures AS $tag => $arr) {
- if (strpos($usetags, $tag) !== false) {
- foreach ($arr AS $lu) {
- $LookupList[$lu] = $tag;
- }
- }
- }
- ksort($LookupList);
-
-
-
- if (!(($this->mpdf->textvar & FC_SMALLCAPS) && $scriptblock == UCDN::SCRIPT_LATIN && strpos($useGSUBtags, 'smcp') === false)) {
- $this->_applyGPOSrules($LookupList, $is_old_spec);
-
- }
-
-
- if (count($this->Entry) || count($this->Exit)) {
-
- $incurs = false;
- for ($i = (count($this->OTLdata) - 1); $i >= 0; $i--) {
- if (isset($this->Entry[$i]) && isset($this->Entry[$i]['Y']) && $this->Entry[$i]['dir'] == 'RTL') {
- $nextbase = $i - 1;
- while (isset($this->OTLdata[$nextbase]['hex']) && strpos($this->GlyphClassMarks, $this->OTLdata[$nextbase]['hex']) !== false) {
- $nextbase--;
- }
- if (isset($this->Exit[$nextbase]) && isset($this->Exit[$nextbase]['Y'])) {
- $diff = $this->Entry[$i]['Y'] - $this->Exit[$nextbase]['Y'];
- if ($incurs === false) {
- $incurs = $diff;
- } else {
- $incurs += $diff;
- }
- for ($j = ($i - 1); $j >= $nextbase; $j--) {
- if (isset($this->OTLdata[$j]['GPOSinfo']['YPlacement'])) {
- $this->OTLdata[$j]['GPOSinfo']['YPlacement'] += $incurs;
- } else {
- $this->OTLdata[$j]['GPOSinfo']['YPlacement'] = $incurs;
- }
- }
- if (isset($this->Exit[$i]['X']) && isset($this->Entry[$nextbase]['X'])) {
- $adj = -($this->Entry[$i]['X'] - $this->Exit[$nextbase]['X']);
-
-
- if (isset($this->OTLdata[$nextbase + 1]['GPOSinfo']['XAdvance'])) {
- $this->OTLdata[$nextbase + 1]['GPOSinfo']['XAdvance'] += $adj;
- } else {
- $this->OTLdata[$nextbase + 1]['GPOSinfo']['XAdvance'] = $adj;
- }
- }
- } else {
- $incurs = false;
- }
- } else if (strpos($this->GlyphClassMarks, $this->OTLdata[$i]['hex']) !== false) {
- continue;
- }
- else {
- $incurs = false;
- }
- }
-
- $incurs = false;
- for ($i = 0; $i < count($this->OTLdata); $i++) {
- if (isset($this->Exit[$i]) && isset($this->Exit[$i]['Y']) && $this->Exit[$i]['dir'] == 'LTR') {
- $nextbase = $i + 1;
- while (strpos($this->GlyphClassMarks, $this->OTLdata[$nextbase]['hex']) !== false) {
- $nextbase++;
- }
- if (isset($this->Entry[$nextbase]) && isset($this->Entry[$nextbase]['Y'])) {
- $diff = $this->Exit[$i]['Y'] - $this->Entry[$nextbase]['Y'];
- if ($incurs === false) {
- $incurs = $diff;
- } else {
- $incurs += $diff;
- }
- for ($j = ($i + 1); $j <= $nextbase; $j++) {
- if (isset($this->OTLdata[$j]['GPOSinfo']['YPlacement'])) {
- $this->OTLdata[$j]['GPOSinfo']['YPlacement'] += $incurs;
- } else {
- $this->OTLdata[$j]['GPOSinfo']['YPlacement'] = $incurs;
- }
- }
- if (isset($this->Exit[$i]['X']) && isset($this->Entry[$nextbase]['X'])) {
- $adj = -($this->Exit[$i]['X'] - $this->Entry[$nextbase]['X']);
-
-
- if (isset($this->OTLdata[$nextbase]['GPOSinfo']['XAdvance'])) {
- $this->OTLdata[$nextbase]['GPOSinfo']['XAdvance'] += $adj;
- } else {
- $this->OTLdata[$nextbase]['GPOSinfo']['XAdvance'] = $adj;
- }
- }
- } else {
- $incurs = false;
- }
- } else if (strpos($this->GlyphClassMarks, $this->OTLdata[$i]['hex']) !== false) {
- continue;
- }
- else {
- $incurs = false;
- }
- }
- }
- }
- if ($this->debugOTL) {
- $this->_dumpproc('END', '-', '-', '-', '-', 0, '-', 0);
- exit;
- }
- $this->schOTLdata[$sch] = $this->OTLdata;
- $this->OTLdata = array();
- }
-
-
- $newGPOSinfo = array();
- $newOTLdata = array();
- $newchar_data = array();
- $newgroup = '';
- $e = '';
- $ectr = 0;
- for ($sch = 0; $sch <= $subchunk; $sch++) {
- for ($i = 0; $i < count($this->schOTLdata[$sch]); $i++) {
- if (isset($this->schOTLdata[$sch][$i]['GPOSinfo'])) {
- $newGPOSinfo[$ectr] = $this->schOTLdata[$sch][$i]['GPOSinfo'];
- }
- $newchar_data[$ectr] = array('bidi_class' => $this->schOTLdata[$sch][$i]['bidi_type'], 'uni' => $this->schOTLdata[$sch][$i]['uni']);
- $newgroup .= $this->schOTLdata[$sch][$i]['group'];
- $e.=code2utf($this->schOTLdata[$sch][$i]['uni']);
- if (isset($this->mpdf->CurrentFont['subset'])) {
- $this->mpdf->CurrentFont['subset'][$this->schOTLdata[$sch][$i]['uni']] = $this->schOTLdata[$sch][$i]['uni'];
- }
- $ectr++;
- }
- }
- $this->OTLdata['GPOSinfo'] = $newGPOSinfo;
- $this->OTLdata['char_data'] = $newchar_data;
- $this->OTLdata['group'] = $newgroup;
-
- return $e;
- }
- function _applyTagSettings($tags, $Features, $omittags = '', $onlytags = false)
- {
- if (empty($this->mpdf->OTLtags['Plus']) && empty($this->mpdf->OTLtags['Minus']) && empty($this->mpdf->OTLtags['FFPlus']) && empty($this->mpdf->OTLtags['FFMinus'])) {
- return $tags;
- }
-
- $usetags = $tags;
-
-
-
- $fp = $fm = $ffp = $ffm = '';
-
- if (isset($this->mpdf->OTLtags['Plus']))
- $fp = $this->mpdf->OTLtags['Plus'];
- preg_match_all('/([a-zA-Z0-9]{4})/', $fp, $m);
- for ($i = 0; $i < count($m[0]); $i++) {
- $t = $m[1][$i];
-
- if (isset($Features[$t]) && strpos($omittags, $t) === false && (!$onlytags || strpos($tags, $t) !== false )) {
- $usetags .= ' ' . $t;
- }
- }
-
- if (isset($this->mpdf->OTLtags['Minus']))
- $fm = $this->mpdf->OTLtags['Minus'];
- preg_match_all('/([a-zA-Z0-9]{4})/', $fm, $m);
- for ($i = 0; $i < count($m[0]); $i++) {
- $t = $m[1][$i];
-
- if (isset($Features[$t]) && strpos($omittags, $t) === false && (!$onlytags || strpos($tags, $t) !== false )) {
- $usetags = str_replace($t, '', $usetags);
- }
- }
-
- if (isset($this->mpdf->OTLtags['FFPlus']))
- $ffp = $this->mpdf->OTLtags['FFPlus'];
- preg_match_all('/([a-zA-Z0-9]{4})([\d+]*)/', $ffp, $m);
- for ($i = 0; $i < count($m[0]); $i++) {
- $t = $m[1][$i];
-
- if (isset($Features[$t]) && strpos($omittags, $t) === false && (!$onlytags || strpos($tags, $t) !== false )) {
- $usetags .= ' ' . $m[0][$i];
- }
- }
-
- if (isset($this->mpdf->OTLtags['FFMinus']))
- $ffm = $this->mpdf->OTLtags['FFMinus'];
- preg_match_all('/([a-zA-Z0-9]{4})/', $ffm, $m);
- for ($i = 0; $i < count($m[0]); $i++) {
- $t = $m[1][$i];
-
- if (isset($Features[$t]) && strpos($omittags, $t) === false && (!$onlytags || strpos($tags, $t) !== false )) {
- $usetags = str_replace($t, '', $usetags);
- }
- }
- return $usetags;
- }
- function _applyGSUBrules($usetags, $scriptTag, $langsys)
- {
-
-
-
-
- $GSUBFeatures = $this->mpdf->CurrentFont['GSUBFeatures'][$scriptTag][$langsys];
- $LookupList = array();
- foreach ($GSUBFeatures AS $tag => $arr) {
- if (strpos($usetags, $tag) !== false) {
- foreach ($arr AS $lu) {
- $LookupList[$lu] = $tag;
- }
- }
- }
- ksort($LookupList);
- foreach ($LookupList AS $lu => $tag) {
- $Type = $this->GSUBLookups[$lu]['Type'];
- $Flag = $this->GSUBLookups[$lu]['Flag'];
- $MarkFilteringSet = $this->GSUBLookups[$lu]['MarkFilteringSet'];
- $tagInt = 1;
- if (preg_match('/' . $tag . '([0-9]{1,2})/', $usetags, $m)) {
- $tagInt = $m[1];
- }
- $ptr = 0;
-
- while ($ptr < (count($this->OTLdata))) {
- $currGlyph = $this->OTLdata[$ptr]['hex'];
- $currGID = $this->OTLdata[$ptr]['uni'];
- $shift = 1;
- foreach ($this->GSUBLookups[$lu]['Subtables'] AS $c => $subtable_offset) {
-
- if (isset($this->GSLuCoverage[$lu][$c][$currGID])) {
-
- $shift = $this->_applyGSUBsubtable($lu, $c, $ptr, $currGlyph, $currGID, ($subtable_offset - $this->GSUB_offset), $Type, $Flag, $MarkFilteringSet, $this->GSLuCoverage[$lu][$c], 0, $tag, 0, $tagInt);
- if ($shift) {
- break;
- }
- }
- }
- if ($shift == 0) {
- $shift = 1;
- }
- $ptr += $shift;
- }
- }
- }
- function _applyGSUBrulesSingly($usetags, $scriptTag, $langsys)
- {
-
- $GSUBFeatures = $this->mpdf->CurrentFont['GSUBFeatures'][$scriptTag][$langsys];
- $tags = explode(' ', $usetags);
- foreach ($tags AS $usetag) {
- $LookupList = array();
- foreach ($GSUBFeatures AS $tag => $arr) {
- if (strpos($usetags, $tag) !== false) {
- foreach ($arr AS $lu) {
- $LookupList[$lu] = $tag;
- }
- }
- }
- ksort($LookupList);
- $ptr = 0;
-
- while ($ptr < (count($this->OTLdata))) {
- $currGlyph = $this->OTLdata[$ptr]['hex'];
- $currGID = $this->OTLdata[$ptr]['uni'];
- $shift = 1;
- foreach ($LookupList AS $lu => $tag) {
- $Type = $this->GSUBLookups[$lu]['Type'];
- $Flag = $this->GSUBLookups[$lu]['Flag'];
- $MarkFilteringSet = $this->GSUBLookups[$lu]['MarkFilteringSet'];
- $tagInt = 1;
- if (preg_match('/' . $tag . '([0-9]{1,2})/', $usetags, $m)) {
- $tagInt = $m[1];
- }
- foreach ($this->GSUBLookups[$lu]['Subtables'] AS $c => $subtable_offset) {
-
- if (isset($this->GSLuCoverage[$lu][$c][$currGID])) {
-
- $shift = $this->_applyGSUBsubtable($lu, $c, $ptr, $currGlyph, $currGID, ($subtable_offset - $this->GSUB_offset), $Type, $Flag, $MarkFilteringSet, $this->GSLuCoverage[$lu][$c], 0, $tag, 0, $tagInt);
- if ($shift) {
- break 2;
- }
- }
- }
- }
- if ($shift == 0) {
- $shift = 1;
- }
- $ptr += $shift;
- }
- }
- }
- function _applyGSUBrulesMyanmar($usetags, $scriptTag, $langsys)
- {
-
-
- $GSUBFeatures = $this->mpdf->CurrentFont['GSUBFeatures'][$scriptTag][$langsys];
-
-
- $tags = explode(' ', $usetags);
- foreach ($tags AS $usetag) {
- $LookupList = array();
- foreach ($GSUBFeatures AS $tag => $arr) {
- if ($tag == $usetag) {
- foreach ($arr AS $lu) {
- $LookupList[$lu] = $tag;
- }
- }
- }
- ksort($LookupList);
- foreach ($LookupList AS $lu => $tag) {
- $Type = $this->GSUBLookups[$lu]['Type'];
- $Flag = $this->GSUBLookups[$lu]['Flag'];
- $MarkFilteringSet = $this->GSUBLookups[$lu]['MarkFilteringSet'];
- $tagInt = 1;
- if (preg_match('/' . $tag . '([0-9]{1,2})/', $usetags, $m)) {
- $tagInt = $m[1];
- }
- $ptr = 0;
-
- while ($ptr < (count($this->OTLdata))) {
- $currGlyph = $this->OTLdata[$ptr]['hex'];
- $currGID = $this->OTLdata[$ptr]['uni'];
- $shift = 1;
- foreach ($this->GSUBLookups[$lu]['Subtables'] AS $c => $subtable_offset) {
-
- if (isset($this->GSLuCoverage[$lu][$c][$currGID])) {
-
- $shift = $this->_applyGSUBsubtable($lu, $c, $ptr, $currGlyph, $currGID, ($subtable_offset - $this->GSUB_offset), $Type, $Flag, $MarkFilteringSet, $this->GSLuCoverage[$lu][$c], 0, $usetag, 0, $tagInt);
- if ($shift) {
- break;
- }
- }
- }
- if ($shift == 0) {
- $shift = 1;
- }
- $ptr += $shift;
- }
- }
- }
- }
- function _applyGSUBrulesIndic($usetags, $scriptTag, $langsys, $is_old_spec)
- {
-
-
-
- $GSUBFeatures = $this->mpdf->CurrentFont['GSUBFeatures'][$scriptTag][$langsys];
-
-
- $tags = explode(' ', $usetags);
- foreach ($tags AS $usetag) {
- $LookupList = array();
- foreach ($GSUBFeatures AS $tag => $arr) {
- if ($tag == $usetag) {
- foreach ($arr AS $lu) {
- $LookupList[$lu] = $tag;
- }
- }
- }
- ksort($LookupList);
- foreach ($LookupList AS $lu => $tag) {
- $Type = $this->GSUBLookups[$lu]['Type'];
- $Flag = $this->GSUBLookups[$lu]['Flag'];
- $MarkFilteringSet = $this->GSUBLookups[$lu]['MarkFilteringSet'];
- $tagInt = 1;
- if (preg_match('/' . $tag . '([0-9]{1,2})/', $usetags, $m)) {
- $tagInt = $m[1];
- }
- $ptr = 0;
-
- while ($ptr < (count($this->OTLdata))) {
- $currGlyph = $this->OTLdata[$ptr]['hex'];
- $currGID = $this->OTLdata[$ptr]['uni'];
- $shift = 1;
- foreach ($this->GSUBLookups[$lu]['Subtables'] AS $c => $subtable_offset) {
-
- if (isset($this->GSLuCoverage[$lu][$c][$currGID])) {
- if (strpos('rphf pref blwf half pstf cfar init', $usetag) !== false) {
- $mask = 0;
- switch ($usetag) {
- case 'rphf': $mask = (1 << (INDIC::RPHF));
- break;
- case 'pref': $mask = (1 << (INDIC::PREF));
- break;
- case 'blwf': $mask = (1 << (INDIC::BLWF));
- break;
- case 'half': $mask = (1 << (INDIC::HALF));
- break;
- case 'pstf': $mask = (1 << (INDIC::PSTF));
- break;
- case 'cfar': $mask = (1 << (INDIC::CFAR));
- break;
- case 'init': $mask = (1 << (INDIC::INIT));
- break;
- }
- if (!($this->OTLdata[$ptr]['mask'] & $mask)) {
- continue;
- }
- }
-
- $shift = $this->_applyGSUBsubtable($lu, $c, $ptr, $currGlyph, $currGID, ($subtable_offset - $this->GSUB_offset), $Type, $Flag, $MarkFilteringSet, $this->GSLuCoverage[$lu][$c], 0, $usetag, $is_old_spec, $tagInt);
- if ($shift) {
- break;
- }
- }
-
-
-
-
-
-
- else if (_OTL_OLD_SPEC_COMPAT_1 && $Type == 4 && !$is_old_spec && strpos('0094D 009CD 00A4D 00ACD 00B4D 00BCD 00C4D 00CCD 00D4D', $currGlyph) !== false) {
-
- if (strpos('pref blwf pstf', $usetag) !== false) {
- $mask = 0;
- switch ($usetag) {
- case 'pref': $mask = (1 << (INDIC::PREF));
- break;
- case 'blwf': $mask = (1 << (INDIC::BLWF));
- break;
- case 'pstf': $mask = (1 << (INDIC::PSTF));
- break;
- }
- if (!($this->OTLdata[$ptr]['mask'] & $mask)) {
- continue;
- }
- $nextGlyph = $this->OTLdata[$ptr + 1]['hex'];
- $nextGID = $this->OTLdata[$ptr + 1]['uni'];
- if (isset($this->GSLuCoverage[$lu][$c][$nextGID])) {
-
- $shift = $this->_applyGSUBsubtableSpecial($lu, $c, $ptr, $currGlyph, $currGID, $nextGlyph, $nextGID, ($subtable_offset - $this->GSUB_offset), $Type, $this->GSLuCoverage[$lu][$c]);
- if ($shift) {
- break;
- }
- }
- }
- }
- }
- if ($shift == 0) {
- $shift = 1;
- }
- $ptr += $shift;
- }
- }
- }
- }
- function _applyGSUBsubtableSpecial($lookupID, $subtable, $ptr, $currGlyph, $currGID, $nextGlyph, $nextGID, $subtable_offset, $Type, $LuCoverage)
- {
-
-
-
-
-
- $this->seek($subtable_offset);
- $SubstFormat = $this->read_ushort();
-
-
-
-
-
-
- $Coverage = $subtable_offset + $this->read_ushort();
- $NextGlyphPos = $LuCoverage[$nextGID];
- $LigSetCount = $this->read_short();
- $this->skip($NextGlyphPos * 2);
- $LigSet = $subtable_offset + $this->read_short();
- $this->seek($LigSet);
- $LigCount = $this->read_short();
-
- $LigatureOffset = array();
- for ($g = 0; $g < $LigCount; $g++) {
- $LigatureOffset[$g] = $LigSet + $this->read_ushort();
- }
- for ($g = 0; $g < $LigCount; $g++) {
-
- $this->seek($LigatureOffset[$g]);
- $LigGlyph = $this->read_ushort();
- $substitute = $this->glyphToChar($LigGlyph);
- $CompCount = $this->read_ushort();
- if ($CompCount != 2) {
- return 0;
- }
- $gid = $this->read_ushort();
- $checkGlyph = $this->glyphToChar($gid);
- if ($currGID == $checkGlyph) {
- $match = true;
- } else {
- $match = false;
- break;
- }
- $GlyphPos = array();
- $GlyphPos[] = $ptr;
- $GlyphPos[] = $ptr + 1;
- if ($match) {
- $shift = $this->GSUBsubstitute($ptr, $substitute, 4, $GlyphPos);
- if ($shift)
- return 1;
- }
- }
- return 0;
- }
- function _applyGSUBsubtable($lookupID, $subtable, $ptr, $currGlyph, $currGID, $subtable_offset, $Type, $Flag, $MarkFilteringSet, $LuCoverage, $level = 0, $currentTag, $is_old_spec, $tagInt)
- {
- $ignore = $this->_getGCOMignoreString($Flag, $MarkFilteringSet);
-
- $this->seek($subtable_offset);
- $SubstFormat = $this->read_ushort();
-
-
-
- if ($Type == 1) {
-
- if ($this->_checkGCOMignore($Flag, $currGlyph, $MarkFilteringSet)) {
- return 0;
- }
- $CoverageOffset = $subtable_offset + $this->read_ushort();
- $GlyphPos = $LuCoverage[$currGID];
-
-
-
- if ($SubstFormat == 1) {
- $DeltaGlyphID = $this->read_short();
- $this->seek($CoverageOffset);
- $glyphs = $this->_getCoverageGID();
- $GlyphID = $glyphs[$GlyphPos] + $DeltaGlyphID;
- }
-
-
-
- else if ($SubstFormat == 2) {
- $GlyphCount = $this->read_ushort();
- $this->skip($GlyphPos * 2);
- $GlyphID = $this->read_ushort();
- }
- $substitute = $this->glyphToChar($GlyphID);
- $shift = $this->GSUBsubstitute($ptr, $substitute, $Type);
- if ($this->debugOTL && $shift) {
- $this->_dumpproc('GSUB', $lookupID, $subtable, $Type, $SubstFormat, $ptr, $currGlyph, $level);
- }
- if ($shift)
- return 1;
- return 0;
- }
-
-
-
- else if ($Type == 2) {
-
- if ($this->_checkGCOMignore($Flag, $currGlyph, $MarkFilteringSet)) {
- return 0;
- }
- $Coverage = $subtable_offset + $this->read_ushort();
- $GlyphPos = $LuCoverage[$currGID];
- $this->skip(2);
- $this->skip($GlyphPos * 2);
- $Sequences = $subtable_offset + $this->read_short();
- $this->seek($Sequences);
- $GlyphCount = $this->read_short();
- $SubstituteGlyphs = array();
- for ($g = 0; $g < $GlyphCount; $g++) {
- $sgid = $this->read_ushort();
- $SubstituteGlyphs[] = $this->glyphToChar($sgid);
- }
- $shift = $this->GSUBsubstitute($ptr, $SubstituteGlyphs, $Type);
- if ($this->debugOTL && $shift) {
- $this->_dumpproc('GSUB', $lookupID, $subtable, $Type, $SubstFormat, $ptr, $currGlyph, $level);
- }
- if ($shift)
- return $shift;
- return 0;
- }
-
-
-
- else if ($Type == 3) {
-
- if ($this->_checkGCOMignore($Flag, $currGlyph, $MarkFilteringSet)) {
- return 0;
- }
- $Coverage = $subtable_offset + $this->read_ushort();
- $AlternateSetCount = $this->read_short();
-
-
-
-
- $alt = 1;
- if ($tagInt > 1) {
- $alt = $tagInt;
- }
-
- if ($alt == 0) {
- return 0;
- }
- $GlyphPos = $LuCoverage[$currGID];
- $this->skip($GlyphPos * 2);
- $AlternateSets = $subtable_offset + $this->read_short();
- $this->seek($AlternateSets);
- $AlternateGlyphCount = $this->read_short();
- if ($alt > $AlternateGlyphCount) {
- return 0;
- }
- $this->skip(($alt - 1) * 2);
- $GlyphID = $this->read_ushort();
- $substitute = $this->glyphToChar($GlyphID);
- $shift = $this->GSUBsubstitute($ptr, $substitute, $Type);
- if ($this->debugOTL && $shift) {
- $this->_dumpproc('GSUB', $lookupID, $subtable, $Type, $SubstFormat, $ptr, $currGlyph, $level);
- }
- if ($shift)
- return 1;
- return 0;
- }
-
-
-
- else if ($Type == 4) {
-
- if ($this->_checkGCOMignore($Flag, $currGlyph, $MarkFilteringSet)) {
- return 0;
- }
- $Coverage = $subtable_offset + $this->read_ushort();
- $FirstGlyphPos = $LuCoverage[$currGID];
- $LigSetCount = $this->read_short();
- $this->skip($FirstGlyphPos * 2);
- $LigSet = $subtable_offset + $this->read_short();
- $this->seek($LigSet);
- $LigCount = $this->read_short();
-
- $LigatureOffset = array();
- for ($g = 0; $g < $LigCount; $g++) {
- $LigatureOffset[$g] = $LigSet + $this->read_ushort();
- }
- for ($g = 0; $g < $LigCount; $g++) {
-
- $this->seek($LigatureOffset[$g]);
- $LigGlyph = $this->read_ushort();
- $substitute = $this->glyphToChar($LigGlyph);
- $CompCount = $this->read_ushort();
- $spos = $ptr;
- $match = true;
- $GlyphPos = array();
- $GlyphPos[] = $spos;
- for ($l = 1; $l < $CompCount; $l++) {
- $gid = $this->read_ushort();
- $checkGlyph = $this->glyphToChar($gid);
- $spos++;
-
- while (isset($this->OTLdata[$spos]) && strpos($ignore, $this->OTLdata[$spos]['hex']) !== false) {
- $spos++;
- }
- if (isset($this->OTLdata[$spos]) && $this->OTLdata[$spos]['uni'] == $checkGlyph) {
- $GlyphPos[] = $spos;
- } else {
- $match = false;
- break;
- }
- }
- if ($match) {
- $shift = $this->GSUBsubstitute($ptr, $substitute, $Type, $GlyphPos);
- if ($this->debugOTL && $shift) {
- $this->_dumpproc('GSUB', $lookupID, $subtable, $Type, $SubstFormat, $ptr, $currGlyph, $level);
- }
- if ($shift)
- return ($spos - $ptr + 1 - ($CompCount - 1));
- }
- }
- return 0;
- }
-
-
-
- else if ($Type == 5) {
-
-
-
- if ($SubstFormat == 1) {
- $CoverageTableOffset = $subtable_offset + $this->read_ushort();
- $SubRuleSetCount = $this->read_ushort();
- $SubRuleSetOffset = array();
- for ($b = 0; $b < $SubRuleSetCount; $b++) {
- $offset = $this->read_ushort();
- if ($offset == 0x0000) {
- $SubRuleSetOffset[] = $offset;
- } else {
- $SubRuleSetOffset[] = $subtable_offset + $offset;
- }
- }
-
-
- $GlyphPos = $LuCoverage[$currGID];
- if ($SubRuleSetOffset[$GlyphPos] > 0) {
- $this->seek($SubRuleSetOffset[$GlyphPos]);
- $SubRuleCnt = $this->read_ushort();
- $SubRule = array();
- for ($b = 0; $b < $SubRuleCnt; $b++) {
- $SubRule[$b] = $SubRuleSetOffset[$GlyphPos] + $this->read_ushort();
- }
- for ($b = 0; $b < $SubRuleCnt; $b++) {
- $this->seek($SubRule[$b]);
- $InputGlyphCount = $this->read_ushort();
- $SubstCount = $this->read_ushort();
- $Backtrack = array();
- $Lookahead = array();
- $Input = array();
- $Input[0] = $this->OTLdata[$ptr]['uni'];
- for ($r = 1; $r < $InputGlyphCount; $r++) {
- $gid = $this->read_ushort();
- $Input[$r] = $this->glyphToChar($gid);
- }
- $matched = $this->checkContextMatch($Input, $Backtrack, $Lookahead, $ignore, $ptr);
- if ($matched) {
- if ($this->debugOTL) {
- $this->_dumpproc('GSUB', $lookupID, $subtable, $Type, $SubstFormat, $ptr, $currGlyph, $level);
- }
- for ($p = 0; $p < $SubstCount; $p++) {
- $SequenceIndex[$p] = $this->read_ushort();
- $LookupListIndex[$p] = $this->read_ushort();
- }
- for ($p = 0; $p < $SubstCount; $p++) {
-
- if ($SequenceIndex[$p] >= $InputGlyphCount) {
- continue;
- }
- $lu = $LookupListIndex[$p];
- $luType = $this->GSUBLookups[$lu]['Type'];
- $luFlag = $this->GSUBLookups[$lu]['Flag'];
- $luMarkFilteringSet = $this->GSUBLookups[$lu]['MarkFilteringSet'];
- $luptr = $matched[$SequenceIndex[$p]];
- $lucurrGlyph = $this->OTLdata[$luptr]['hex'];
- $lucurrGID = $this->OTLdata[$luptr]['uni'];
- foreach ($this->GSUBLookups[$lu]['Subtables'] AS $luc => $lusubtable_offset) {
- $shift = $this->_applyGSUBsubtable($lu, $luc, $luptr, $lucurrGlyph, $lucurrGID, ($lusubtable_offset - $this->GSUB_offset), $luType, $luFlag, $luMarkFilteringSet, $this->GSLuCoverage[$lu][$luc], 1, $currentTag, $is_old_spec, $tagInt);
- if ($shift) {
- break;
- }
- }
- }
- if (!defined("OMIT_OTL_FIX_3") || OMIT_OTL_FIX_3 != 1) {
- return $shift;
- }
- else
- return $InputGlyphCount;
- }
- }
- }
- return 0;
- }
-
-
-
-
- else if ($SubstFormat == 2) {
- $CoverageTableOffset = $subtable_offset + $this->read_ushort();
- $InputClassDefOffset = $subtable_offset + $this->read_ushort();
- $SubClassSetCnt = $this->read_ushort();
- $SubClassSetOffset = array();
- for ($b = 0; $b < $SubClassSetCnt; $b++) {
- $offset = $this->read_ushort();
- if ($offset == 0x0000) {
- $SubClassSetOffset[] = $offset;
- } else {
- $SubClassSetOffset[] = $subtable_offset + $offset;
- }
- }
- $InputClasses = $this->_getClasses($InputClassDefOffset);
- for ($s = 0; $s < $SubClassSetCnt; $s++) {
-
- if ($SubClassSetOffset[$s] > 0 && isset($InputClasses[$s][$currGID])) {
- $this->seek($SubClassSetOffset[$s]);
- $SubClassRuleCnt = $this->read_ushort();
- $SubClassRule = array();
- for ($b = 0; $b < $SubClassRuleCnt; $b++) {
- $SubClassRule[$b] = $SubClassSetOffset[$s] + $this->read_ushort();
- }
- for ($b = 0; $b < $SubClassRuleCnt; $b++) {
- $this->seek($SubClassRule[$b]);
- $InputGlyphCount = $this->read_ushort();
- $SubstCount = $this->read_ushort();
- $Input = array();
- for ($r = 1; $r < $InputGlyphCount; $r++) {
- $Input[$r] = $this->read_ushort();
- }
- $inputClass = $s;
- $inputGlyphs = array();
- $inputGlyphs[0] = $InputClasses[$inputClass];
- if ($InputGlyphCount > 1) {
-
- for ($gcl = 1; $gcl < $InputGlyphCount; $gcl++) {
- $classindex = $Input[$gcl];
- if (isset($InputClasses[$classindex])) {
- $inputGlyphs[$gcl] = $InputClasses[$classindex];
- } else {
- $inputGlyphs[$gcl] = '';
- }
- }
- }
-
- $class0excl = array();
- for ($gc = 1; $gc <= count($InputClasses); $gc++) {
- if (is_array($InputClasses[$gc]))
- $class0excl = $class0excl + $InputClasses[$gc];
- }
- $backtrackGlyphs = array();
- $lookaheadGlyphs = array();
- $matched = $this->checkContextMatchMultipleUni($inputGlyphs, $backtrackGlyphs, $lookaheadGlyphs, $ignore, $ptr, $class0excl);
- if ($matched) {
- if ($this->debugOTL) {
- $this->_dumpproc('GSUB', $lookupID, $subtable, $Type, $SubstFormat, $ptr, $currGlyph, $level);
- }
- for ($p = 0; $p < $SubstCount; $p++) {
- $SequenceIndex[$p] = $this->read_ushort();
- $LookupListIndex[$p] = $this->read_ushort();
- }
- for ($p = 0; $p < $SubstCount; $p++) {
-
- if ($SequenceIndex[$p] >= $InputGlyphCount) {
- continue;
- }
- $lu = $LookupListIndex[$p];
- $luType = $this->GSUBLookups[$lu]['Type'];
- $luFlag = $this->GSUBLookups[$lu]['Flag'];
- $luMarkFilteringSet = $this->GSUBLookups[$lu]['MarkFilteringSet'];
- $luptr = $matched[$SequenceIndex[$p]];
- $lucurrGlyph = $this->OTLdata[$luptr]['hex'];
- $lucurrGID = $this->OTLdata[$luptr]['uni'];
- foreach ($this->GSUBLookups[$lu]['Subtables'] AS $luc => $lusubtable_offset) {
- $shift = $this->_applyGSUBsubtable($lu, $luc, $luptr, $lucurrGlyph, $lucurrGID, ($lusubtable_offset - $this->GSUB_offset), $luType, $luFlag, $luMarkFilteringSet, $this->GSLuCoverage[$lu][$luc], 1, $currentTag, $is_old_spec, $tagInt);
- if ($shift) {
- break;
- }
- }
- }
- if (!defined("OMIT_OTL_FIX_3") || OMIT_OTL_FIX_3 != 1) {
- return $shift;
- }
- else
- return $InputGlyphCount;
- }
- }
- }
- }
- return 0;
- }
-
-
-
-
- else if ($SubstFormat == 3) {
- throw new MpdfException("GSUB Lookup Type " . $Type . " Format " . $SubstFormat . " not TESTED YET.");
- }
- }
-
-
-
- else if ($Type == 6) {
-
-
-
-
- if ($SubstFormat == 1) {
- $Coverage = $subtable_offset + $this->read_ushort();
- $GlyphPos = $LuCoverage[$currGID];
- $ChainSubRuleSetCount = $this->read_ushort();
-
- $this->skip($GlyphPos * 2);
- $ChainSubRuleSet = $subtable_offset + $this->read_ushort();
- $this->seek($ChainSubRuleSet);
- $ChainSubRuleCount = $this->read_ushort();
- for ($s = 0; $s < $ChainSubRuleCount; $s++) {
- $ChainSubRule[$s] = $ChainSubRuleSet + $this->read_ushort();
- }
- for ($s = 0; $s < $ChainSubRuleCount; $s++) {
- $this->seek($ChainSubRule[$s]);
- $BacktrackGlyphCount = $this->read_ushort();
- $Backtrack = array();
- for ($b = 0; $b < $BacktrackGlyphCount; $b++) {
- $gid = $this->read_ushort();
- $Backtrack[] = $this->glyphToChar($gid);
- }
- $Input = array();
- $Input[0] = $this->OTLdata[$ptr]['uni'];
- $InputGlyphCount = $this->read_ushort();
- for ($b = 1; $b < $InputGlyphCount; $b++) {
- $gid = $this->read_ushort();
- $Input[$b] = $this->glyphToChar($gid);
- }
- $LookaheadGlyphCount = $this->read_ushort();
- $Lookahead = array();
- for ($b = 0; $b < $LookaheadGlyphCount; $b++) {
- $gid = $this->read_ushort();
- $Lookahead[] = $this->glyphToChar($gid);
- }
- $matched = $this->checkContextMatch($Input, $Backtrack, $Lookahead, $ignore, $ptr);
- if ($matched) {
- if ($this->debugOTL) {
- $this->_dumpproc('GSUB', $lookupID, $subtable, $Type, $SubstFormat, $ptr, $currGlyph, $level);
- }
- $SubstCount = $this->read_ushort();
- for ($p = 0; $p < $SubstCount; $p++) {
-
- $SubstLookupRecord[$p]['SequenceIndex'] = $this->read_ushort();
- $SubstLookupRecord[$p]['LookupListIndex'] = $this->read_ushort();
- }
- for ($p = 0; $p < $SubstCount; $p++) {
-
- if ($SubstLookupRecord[$p]['SequenceIndex'] >= $InputGlyphCount) {
- continue;
- }
- $lu = $SubstLookupRecord[$p]['LookupListIndex'];
- $luType = $this->GSUBLookups[$lu]['Type'];
- $luFlag = $this->GSUBLookups[$lu]['Flag'];
- $luMarkFilteringSet = $this->GSUBLookups[$lu]['MarkFilteringSet'];
- $luptr = $matched[$SubstLookupRecord[$p]['SequenceIndex']];
- $lucurrGlyph = $this->OTLdata[$luptr]['hex'];
- $lucurrGID = $this->OTLdata[$luptr]['uni'];
- foreach ($this->GSUBLookups[$lu]['Subtables'] AS $luc => $lusubtable_offset) {
- $shift = $this->_applyGSUBsubtable($lu, $luc, $luptr, $lucurrGlyph, $lucurrGID, ($lusubtable_offset - $this->GSUB_offset), $luType, $luFlag, $luMarkFilteringSet, $this->GSLuCoverage[$lu][$luc], 1, $currentTag, $is_old_spec, $tagInt);
- if ($shift) {
- break;
- }
- }
- }
- if (!defined("OMIT_OTL_FIX_3") || OMIT_OTL_FIX_3 != 1) {
- return $shift;
- }
- else
- return $InputGlyphCount;
- }
- }
- return 0;
- }
-
-
-
-
- else if ($SubstFormat == 2) {
-
- $CoverageTableOffset = $subtable_offset + $this->read_ushort();
- $BacktrackClassDefOffset = $subtable_offset + $this->read_ushort();
- $InputClassDefOffset = $subtable_offset + $this->read_ushort();
- $LookaheadClassDefOffset = $subtable_offset + $this->read_ushort();
- $ChainSubClassSetCnt = $this->read_ushort();
- $ChainSubClassSetOffset = array();
- for ($b = 0; $b < $ChainSubClassSetCnt; $b++) {
- $offset = $this->read_ushort();
- if ($offset == 0x0000) {
- $ChainSubClassSetOffset[] = $offset;
- } else {
- $ChainSubClassSetOffset[] = $subtable_offset + $offset;
- }
- }
- $BacktrackClasses = $this->_getClasses($BacktrackClassDefOffset);
- $InputClasses = $this->_getClasses($InputClassDefOffset);
- $LookaheadClasses = $this->_getClasses($LookaheadClassDefOffset);
- for ($s = 0; $s < $ChainSubClassSetCnt; $s++) {
-
- if ($ChainSubClassSetOffset[$s] > 0 && isset($InputClasses[$s][$currGID])) {
- $this->seek($ChainSubClassSetOffset[$s]);
- $ChainSubClassRuleCnt = $this->read_ushort();
- $ChainSubClassRule = array();
- for ($b = 0; $b < $ChainSubClassRuleCnt; $b++) {
- $ChainSubClassRule[$b] = $ChainSubClassSetOffset[$s] + $this->read_ushort();
- }
- for ($b = 0; $b < $ChainSubClassRuleCnt; $b++) {
- $this->seek($ChainSubClassRule[$b]);
- $BacktrackGlyphCount = $this->read_ushort();
- for ($r = 0; $r < $BacktrackGlyphCount; $r++) {
- $Backtrack[$r] = $this->read_ushort();
- }
- $InputGlyphCount = $this->read_ushort();
- for ($r = 1; $r < $InputGlyphCount; $r++) {
- $Input[$r] = $this->read_ushort();
- }
- $LookaheadGlyphCount = $this->read_ushort();
- for ($r = 0; $r < $LookaheadGlyphCount; $r++) {
- $Lookahead[$r] = $this->read_ushort();
- }
-
-
-
-
-
-
- $inputClass = $s;
- $inputGlyphs = array();
- $inputGlyphs[0] = $InputClasses[$inputClass];
- if ($InputGlyphCount > 1) {
-
- for ($gcl = 1; $gcl < $InputGlyphCount; $gcl++) {
- $classindex = $Input[$gcl];
- if (isset($InputClasses[$classindex])) {
- $inputGlyphs[$gcl] = $InputClasses[$classindex];
- } else {
- $inputGlyphs[$gcl] = '';
- }
- }
- }
-
- $class0excl = array();
- for ($gc = 1; $gc <= count($InputClasses); $gc++) {
- if (isset($InputClasses[$gc]))
- $class0excl = $class0excl + $InputClasses[$gc];
- }
- if ($BacktrackGlyphCount) {
- for ($gcl = 0; $gcl < $BacktrackGlyphCount; $gcl++) {
- $classindex = $Backtrack[$gcl];
- if (isset($BacktrackClasses[$classindex])) {
- $backtrackGlyphs[$gcl] = $BacktrackClasses[$classindex];
- } else {
- $backtrackGlyphs[$gcl] = '';
- }
- }
- } else {
- $backtrackGlyphs = array();
- }
-
- $bclass0excl = array();
- for ($gc = 1; $gc <= count($BacktrackClasses); $gc++) {
- if (isset($BacktrackClasses[$gc]))
- $bclass0excl = $bclass0excl + $BacktrackClasses[$gc];
- }
- if ($LookaheadGlyphCount) {
- for ($gcl = 0; $gcl < $LookaheadGlyphCount; $gcl++) {
- $classindex = $Lookahead[$gcl];
- if (isset($LookaheadClasses[$classindex])) {
- $lookaheadGlyphs[$gcl] = $LookaheadClasses[$classindex];
- } else {
- $lookaheadGlyphs[$gcl] = '';
- }
- }
- } else {
- $lookaheadGlyphs = array();
- }
-
- $lclass0excl = array();
- for ($gc = 1; $gc <= count($LookaheadClasses); $gc++) {
- if (isset($LookaheadClasses[$gc]))
- $lclass0excl = $lclass0excl + $LookaheadClasses[$gc];
- }
- $matched = $this->checkContextMatchMultipleUni($inputGlyphs, $backtrackGlyphs, $lookaheadGlyphs, $ignore, $ptr, $class0excl, $bclass0excl, $lclass0excl);
- if ($matched) {
- if ($this->debugOTL) {
- $this->_dumpproc('GSUB', $lookupID, $subtable, $Type, $SubstFormat, $ptr, $currGlyph, $level);
- }
- $SubstCount = $this->read_ushort();
- for ($p = 0; $p < $SubstCount; $p++) {
- $SequenceIndex[$p] = $this->read_ushort();
- $LookupListIndex[$p] = $this->read_ushort();
- }
- for ($p = 0; $p < $SubstCount; $p++) {
-
- if ($SequenceIndex[$p] >= $InputGlyphCount) {
- continue;
- }
- $lu = $LookupListIndex[$p];
- $luType = $this->GSUBLookups[$lu]['Type'];
- $luFlag = $this->GSUBLookups[$lu]['Flag'];
- $luMarkFilteringSet = $this->GSUBLookups[$lu]['MarkFilteringSet'];
- $luptr = $matched[$SequenceIndex[$p]];
- $lucurrGlyph = $this->OTLdata[$luptr]['hex'];
- $lucurrGID = $this->OTLdata[$luptr]['uni'];
- foreach ($this->GSUBLookups[$lu]['Subtables'] AS $luc => $lusubtable_offset) {
- $shift = $this->_applyGSUBsubtable($lu, $luc, $luptr, $lucurrGlyph, $lucurrGID, ($lusubtable_offset - $this->GSUB_offset), $luType, $luFlag, $luMarkFilteringSet, $this->GSLuCoverage[$lu][$luc], 1, $currentTag, $is_old_spec, $tagInt);
- if ($shift) {
- break;
- }
- }
- }
- if (!defined("OMIT_OTL_FIX_3") || OMIT_OTL_FIX_3 != 1) {
- return $shift;
- }
- else
- return $InputGlyphCount;
- }
- }
- }
- }
- return 0;
- }
-
-
-
-
- else if ($SubstFormat == 3) {
- $BacktrackGlyphCount = $this->read_ushort();
- for ($b = 0; $b < $BacktrackGlyphCount; $b++) {
- $CoverageBacktrackOffset[] = $subtable_offset + $this->read_ushort();
- }
- $InputGlyphCount = $this->read_ushort();
- for ($b = 0; $b < $InputGlyphCount; $b++) {
- $CoverageInputOffset[] = $subtable_offset + $this->read_ushort();
- }
- $LookaheadGlyphCount = $this->read_ushort();
- for ($b = 0; $b < $LookaheadGlyphCount; $b++) {
- $CoverageLookaheadOffset[] = $subtable_offset + $this->read_ushort();
- }
- $SubstCount = $this->read_ushort();
- $save_pos = $this->_pos;
- $CoverageBacktrackGlyphs = array();
- for ($b = 0; $b < $BacktrackGlyphCount; $b++) {
- $this->seek($CoverageBacktrackOffset[$b]);
- $glyphs = $this->_getCoverage();
- $CoverageBacktrackGlyphs[$b] = implode("|", $glyphs);
- }
- $CoverageInputGlyphs = array();
- for ($b = 0; $b < $InputGlyphCount; $b++) {
- $this->seek($CoverageInputOffset[$b]);
- $glyphs = $this->_getCoverage();
- $CoverageInputGlyphs[$b] = implode("|", $glyphs);
- }
- $CoverageLookaheadGlyphs = array();
- for ($b = 0; $b < $LookaheadGlyphCount; $b++) {
- $this->seek($CoverageLookaheadOffset[$b]);
- $glyphs = $this->_getCoverage();
- $CoverageLookaheadGlyphs[$b] = implode("|", $glyphs);
- }
- $matched = $this->checkContextMatchMultiple($CoverageInputGlyphs, $CoverageBacktrackGlyphs, $CoverageLookaheadGlyphs, $ignore, $ptr);
- if ($matched) {
- if ($this->debugOTL) {
- $this->_dumpproc('GSUB', $lookupID, $subtable, $Type, $SubstFormat, $ptr, $currGlyph, $level);
- }
- $this->seek($save_pos);
- for ($p = 0; $p < $SubstCount; $p++) {
-
- $SubstLookupRecord[$p]['SequenceIndex'] = $this->read_ushort();
- $SubstLookupRecord[$p]['LookupListIndex'] = $this->read_ushort();
- }
- for ($p = 0; $p < $SubstCount; $p++) {
-
- if ($SubstLookupRecord[$p]['SequenceIndex'] >= $InputGlyphCount) {
- continue;
- }
- $lu = $SubstLookupRecord[$p]['LookupListIndex'];
- $luType = $this->GSUBLookups[$lu]['Type'];
- $luFlag = $this->GSUBLookups[$lu]['Flag'];
- $luMarkFilteringSet = $this->GSUBLookups[$lu]['MarkFilteringSet'];
- $luptr = $matched[$SubstLookupRecord[$p]['SequenceIndex']];
- $lucurrGlyph = $this->OTLdata[$luptr]['hex'];
- $lucurrGID = $this->OTLdata[$luptr]['uni'];
- foreach ($this->GSUBLookups[$lu]['Subtables'] AS $luc => $lusubtable_offset) {
- $shift = $this->_applyGSUBsubtable($lu, $luc, $luptr, $lucurrGlyph, $lucurrGID, ($lusubtable_offset - $this->GSUB_offset), $luType, $luFlag, $luMarkFilteringSet, $this->GSLuCoverage[$lu][$luc], 1, $currentTag, $is_old_spec, $tagInt);
- if ($shift) {
- break;
- }
- }
- }
- if (!defined("OMIT_OTL_FIX_3") || OMIT_OTL_FIX_3 != 1) {
- return (isset($shift) ? $shift : 0);
- }
- else
- return $InputGlyphCount;
- }
- return 0;
- }
- }
- else {
- throw new MpdfException("GSUB Lookup Type " . $Type . " not supported.");
- }
- }
- function _updateLigatureMarks($pos, $n)
- {
- if ($n > 0) {
-
-
-
-
-
- for ($p = count($this->OTLdata) - 1; $p >= ($pos + $n); $p--) {
- if (isset($this->assocLigs[$p])) {
- $tmp = $this->assocLigs[$p];
- unset($this->assocLigs[$p]);
- $this->assocLigs[($p + $n)] = $tmp;
- }
- }
- for ($p = count($this->OTLdata) - 1; $p >= 0; $p--) {
- if (isset($this->assocMarks[$p])) {
- if ($this->assocMarks[$p]['ligPos'] >= ($pos + $n)) {
- $this->assocMarks[$p]['ligPos'] += $n;
- }
- if ($p >= ($pos + $n)) {
- $tmp = $this->assocMarks[$p];
- unset($this->assocMarks[$p]);
- $this->assocMarks[($p + $n)] = $tmp;
- }
- }
- }
- } else if ($n < 1) {
- $nrem = -$n;
-
- for ($p = ($pos + 1); $p < count($this->OTLdata); $p++) {
- if (isset($this->assocLigs[$p])) {
- $tmp = $this->assocLigs[$p];
- unset($this->assocLigs[$p]);
- $this->assocLigs[($p - $nrem)] = $tmp;
- }
- }
- for ($p = 0; $p < count($this->OTLdata); $p++) {
- if (isset($this->assocMarks[$p])) {
- if ($this->assocMarks[$p]['ligPos'] >= ($pos)) {
- $this->assocMarks[$p]['ligPos'] -= $nrem;
- }
- if ($p > $pos) {
- $tmp = $this->assocMarks[$p];
- unset($this->assocMarks[$p]);
- $this->assocMarks[($p - $nrem)] = $tmp;
- }
- }
- }
- }
- }
- function GSUBsubstitute($pos, $substitute, $Type, $GlyphPos = NULL)
- {
-
-
- if ($Type == 1 || $Type == 3) {
- $this->OTLdata[$pos]['uni'] = $substitute;
- $this->OTLdata[$pos]['hex'] = $this->unicode_hex($substitute);
- return 1;
- }
-
- else if ($Type == 2) {
- for ($i = 0; $i < count($substitute); $i++) {
- $uni = $substitute[$i];
- $newOTLdata[$i] = array();
- $newOTLdata[$i]['uni'] = $uni;
- $newOTLdata[$i]['hex'] = $this->unicode_hex($uni);
-
-
-
- $bt = $this->OTLdata[$pos]['bidi_type'];
-
- if (strpos($this->GlyphClassMarks, $newOTLdata[$i]['hex']) !== false) {
- $gp = 'M';
- } else if ($uni == 32) {
- $gp = 'S';
- } else {
- $gp = 'C';
- }
-
- $newOTLdata[$i]['bidi_type'] = $bt;
- $newOTLdata[$i]['group'] = $gp;
-
- $newOTLdata[$i]['general_category'] = $this->OTLdata[$pos]['general_category'];
- if ($this->shaper == 'I' || $this->shaper == 'K' || $this->shaper == 'S') {
- $newOTLdata[$i]['indic_category'] = $this->OTLdata[$pos]['indic_category'];
- $newOTLdata[$i]['indic_position'] = $this->OTLdata[$pos]['indic_position'];
- } else if ($this->shaper == 'M') {
- $newOTLdata[$i]['myanmar_category'] = $this->OTLdata[$pos]['myanmar_category'];
- $newOTLdata[$i]['myanmar_position'] = $this->OTLdata[$pos]['myanmar_position'];
- }
- if (isset($this->OTLdata[$pos]['mask'])) {
- $newOTLdata[$i]['mask'] = $this->OTLdata[$pos]['mask'];
- }
- if (isset($this->OTLdata[$pos]['syllable'])) {
- $newOTLdata[$i]['syllable'] = $this->OTLdata[$pos]['syllable'];
- }
- }
- if ($this->shaper == 'K' || $this->shaper == 'T' || $this->shaper == 'L') {
- if ($this->OTLdata[$pos]['wordend']) {
- $newOTLdata[count($substitute) - 1]['wordend'] = true;
- }
- }
- array_splice($this->OTLdata, $pos, 1, $newOTLdata);
-
-
- $nadd = count($substitute) - 1;
- $this->_updateLigatureMarks($pos, $nadd);
- return count($substitute);
- }
-
- else if ($Type == 4) {
-
- $firstGlyph = $this->OTLdata[$pos]['hex'];
-
- $contains_marks = false;
- $contains_nonmarks = false;
- if (isset($this->OTLdata[$pos]['syllable'])) {
- $current_syllable = $this->OTLdata[$pos]['syllable'];
- } else {
- $current_syllable = 0;
- }
- for ($i = 0; $i < count($GlyphPos); $i++) {
-
- $unistr = $this->OTLdata[$GlyphPos[$i]]['hex'];
- if ($this->restrictToSyllable && isset($this->OTLdata[$GlyphPos[$i]]['syllable']) && $this->OTLdata[$GlyphPos[$i]]['syllable'] != $current_syllable) {
- return 0;
- }
- if (strpos($this->GlyphClassMarks, $unistr) !== false) {
- $contains_marks = true;
- } else {
- $contains_nonmarks = true;
- }
- }
- if ($contains_marks && !$contains_nonmarks) {
-
- $firstMarkAssoc = '';
- if (isset($this->assocMarks[$pos])) {
- $firstMarkAssoc = $this->assocMarks[$pos];
- }
-
- for ($i = 1; $i < count($GlyphPos); $i++) {
-
-
-
- $nextMarkAssoc = '';
- if (isset($this->assocMarks[$GlyphPos[$i]])) {
- $nextMarkAssoc = $this->assocMarks[$GlyphPos[$i]];
- }
-
-
-
-
-
- if ($firstMarkAssoc != $nextMarkAssoc) {
-
-
-
-
-
-
-
- if (!is_array($nextMarkAssoc) || $nextMarkAssoc['ligPos'] != $pos) {
- unset($this->assocMarks[$GlyphPos[$i]]);
- }
- }
- }
-
-
- $lastPos = $GlyphPos[(count($GlyphPos) - 1)];
- } else {
-
-
- $currComp = 0;
- for ($i = 0; $i < count($GlyphPos); $i++) {
- if ($i > 0 && isset($this->assocLigs[$GlyphPos[$i]])) {
- $nc = $this->assocLigs[$GlyphPos[$i]];
- } else {
- $nc = 1;
- }
-
-
- $ic = 1;
- while ((($i == count($GlyphPos) - 1) || (isset($GlyphPos[$i + 1]) && ($GlyphPos[$i] + $ic) < $GlyphPos[$i + 1])) && isset($this->OTLdata[($GlyphPos[$i] + $ic)]) && strpos($this->GlyphClassMarks, $this->OTLdata[($GlyphPos[$i] + $ic)]['hex']) !== false) {
- $newComp = $currComp;
- if (isset($this->assocMarks[$GlyphPos[$i] + $ic])) {
-
-
- $newComp += $this->assocMarks[($GlyphPos[$i] + $ic)]['compID'];
- }
- $this->assocMarks[($GlyphPos[$i] + $ic)] = array('compID' => $newComp, 'ligPos' => $pos);
- $ic++;
- }
- $currComp += $nc;
- }
- $lastPos = $GlyphPos[(count($GlyphPos) - 1)] + $ic - 1;
- $this->assocLigs[$pos] = $currComp;
- }
-
- $newOTLdata[0] = array();
-
-
-
- $bt = $this->OTLdata[$pos]['bidi_type'];
-
- if (strpos($this->GlyphClassMarks, $this->unicode_hex($substitute)) !== false) {
- $gp = 'M';
- } else if ($substitute == 32) {
- $gp = 'S';
- } else {
- $gp = 'C';
- }
-
- $newOTLdata[0]['general_category'] = $this->OTLdata[$pos]['general_category'];
- $newOTLdata[0]['bidi_type'] = $bt;
- $newOTLdata[0]['group'] = $gp;
-
-
-
- $ka = 0;
- if (isset($this->OTLdata[$GlyphPos[(count($GlyphPos) - 1)]]['GPOSinfo']['kashida'])) {
- $ka = $this->OTLdata[$GlyphPos[(count($GlyphPos) - 1)]]['GPOSinfo']['kashida'];
- }
- if ($ka == 1 && isset($this->OTLdata[$pos]['form']) && $this->OTLdata[$pos]['form'] == 3) {
- $newOTLdata[0]['GPOSinfo']['kashida'] = $ka;
- }
- $newOTLdata[0]['uni'] = $substitute;
- $newOTLdata[0]['hex'] = $this->unicode_hex($substitute);
- if ($this->shaper == 'I' || $this->shaper == 'K' || $this->shaper == 'S') {
- $newOTLdata[0]['indic_category'] = $this->OTLdata[$pos]['indic_category'];
- $newOTLdata[0]['indic_position'] = $this->OTLdata[$pos]['indic_position'];
- } else if ($this->shaper == 'M') {
- $newOTLdata[0]['myanmar_category'] = $this->OTLdata[$pos]['myanmar_category'];
- $newOTLdata[0]['myanmar_position'] = $this->OTLdata[$pos]['myanmar_position'];
- }
- if (isset($this->OTLdata[$pos]['mask'])) {
- $newOTLdata[0]['mask'] = $this->OTLdata[$pos]['mask'];
- }
- if (isset($this->OTLdata[$pos]['syllable'])) {
- $newOTLdata[0]['syllable'] = $this->OTLdata[$pos]['syllable'];
- }
- $newOTLdata[0]['is_ligature'] = true;
- array_splice($this->OTLdata, $pos, 1, $newOTLdata);
-
-
- for ($i = count($GlyphPos) - 1; $i > 0; $i--) {
- $gpos = $GlyphPos[$i];
- array_splice($this->OTLdata, $gpos, 1);
- unset($this->assocLigs[$gpos]);
- unset($this->assocMarks[$gpos]);
- }
-
-
-
-
-
- for ($p = ($GlyphPos[0] + 1); $p < (count($this->OTLdata) + count($GlyphPos) - 1); $p++) {
- $nrem = 0;
- for ($i = 0; $i < count($GlyphPos); $i++) {
- if ($i > 0 && $p > $GlyphPos[$i]) {
- $nrem++;
- }
- }
- if (isset($this->assocLigs[$p])) {
- $tmp = $this->assocLigs[$p];
- unset($this->assocLigs[$p]);
- $this->assocLigs[($p - $nrem)] = $tmp;
- }
- if (isset($this->assocMarks[$p])) {
- $tmp = $this->assocMarks[$p];
- unset($this->assocMarks[$p]);
- if ($tmp['ligPos'] > $GlyphPos[0]) {
- $tmp['ligPos'] -= $nrem;
- }
- $this->assocMarks[($p - $nrem)] = $tmp;
- }
- }
- return 1;
- } else {
- return 0;
- }
- }
- function arabic_initialise()
- {
-
-
-
- $this->arabLeftJoining = array(
- 0x0620 => 1, 0x0626 => 1, 0x0628 => 1, 0x062A => 1, 0x062B => 1, 0x062C => 1, 0x062D => 1, 0x062E => 1,
- 0x0633 => 1, 0x0634 => 1, 0x0635 => 1, 0x0636 => 1, 0x0637 => 1, 0x0638 => 1, 0x0639 => 1, 0x063A => 1,
- 0x063B => 1, 0x063C => 1, 0x063D => 1, 0x063E => 1, 0x063F => 1, 0x0640 => 1, 0x0641 => 1, 0x0642 => 1,
- 0x0643 => 1, 0x0644 => 1, 0x0645 => 1, 0x0646 => 1, 0x0647 => 1, 0x0649 => 1, 0x064A => 1, 0x066E => 1,
- 0x066F => 1, 0x0678 => 1, 0x0679 => 1, 0x067A => 1, 0x067B => 1, 0x067C => 1, 0x067D => 1, 0x067E => 1,
- 0x067F => 1, 0x0680 => 1, 0x0681 => 1, 0x0682 => 1, 0x0683 => 1, 0x0684 => 1, 0x0685 => 1, 0x0686 => 1,
- 0x0687 => 1, 0x069A => 1, 0x069B => 1, 0x069C => 1, 0x069D => 1, 0x069E => 1, 0x069F => 1, 0x06A0 => 1,
- 0x06A1 => 1, 0x06A2 => 1, 0x06A3 => 1, 0x06A4 => 1, 0x06A5 => 1, 0x06A6 => 1, 0x06A7 => 1, 0x06A8 => 1,
- 0x06A9 => 1, 0x06AA => 1, 0x06AB => 1, 0x06AC => 1, 0x06AD => 1, 0x06AE => 1, 0x06AF => 1, 0x06B0 => 1,
- 0x06B1 => 1, 0x06B2 => 1, 0x06B3 => 1, 0x06B4 => 1, 0x06B5 => 1, 0x06B6 => 1, 0x06B7 => 1, 0x06B8 => 1,
- 0x06B9 => 1, 0x06BA => 1, 0x06BB => 1, 0x06BC => 1, 0x06BD => 1, 0x06BE => 1, 0x06BF => 1, 0x06C1 => 1,
- 0x06C2 => 1, 0x06CC => 1, 0x06CE => 1, 0x06D0 => 1, 0x06D1 => 1, 0x06FA => 1, 0x06FB => 1, 0x06FC => 1,
- 0x06FF => 1,
-
- 0x0750 => 1, 0x0751 => 1, 0x0752 => 1, 0x0753 => 1, 0x0754 => 1, 0x0755 => 1, 0x0756 => 1, 0x0757 => 1,
- 0x0758 => 1, 0x075C => 1, 0x075D => 1, 0x075E => 1, 0x075F => 1, 0x0760 => 1, 0x0761 => 1, 0x0762 => 1,
- 0x0763 => 1, 0x0764 => 1, 0x0765 => 1, 0x0766 => 1, 0x0767 => 1, 0x0768 => 1, 0x0769 => 1, 0x076A => 1,
- 0x076D => 1, 0x076E => 1, 0x076F => 1, 0x0770 => 1, 0x0772 => 1, 0x0775 => 1, 0x0776 => 1, 0x0777 => 1,
- 0x077A => 1, 0x077B => 1, 0x077C => 1, 0x077D => 1, 0x077E => 1, 0x077F => 1,
-
- 0x08A0 => 1, 0x08A2 => 1, 0x08A3 => 1, 0x08A4 => 1, 0x08A5 => 1, 0x08A6 => 1, 0x08A7 => 1, 0x08A8 => 1,
- 0x08A9 => 1,
-
- 0x0712 => 1, 0x0713 => 1, 0x0714 => 1, 0x071A => 1, 0x071B => 1, 0x071C => 1, 0x071D => 1, 0x071F => 1,
- 0x0720 => 1, 0x0721 => 1, 0x0722 => 1, 0x0723 => 1, 0x0724 => 1, 0x0725 => 1, 0x0726 => 1, 0x0727 => 1,
- 0x0729 => 1, 0x072B => 1, 0x072D => 1, 0x072E => 1, 0x074E => 1, 0x074F => 1,
-
- 0x07CA => 1, 0x07CB => 1, 0x07CC => 1, 0x07CD => 1, 0x07CE => 1, 0x07CF => 1, 0x07D0 => 1, 0x07D1 => 1,
- 0x07D2 => 1, 0x07D3 => 1, 0x07D4 => 1, 0x07D5 => 1, 0x07D6 => 1, 0x07D7 => 1, 0x07D8 => 1, 0x07D9 => 1,
- 0x07DA => 1, 0x07DB => 1, 0x07DC => 1, 0x07DD => 1, 0x07DE => 1, 0x07DF => 1, 0x07E0 => 1, 0x07E1 => 1,
- 0x07E2 => 1, 0x07E3 => 1, 0x07E4 => 1, 0x07E5 => 1, 0x07E6 => 1, 0x07E7 => 1, 0x07E8 => 1, 0x07E9 => 1,
- 0x07EA => 1, 0x07FA => 1,
-
- 0x0841 => 1, 0x0842 => 1, 0x0843 => 1, 0x0844 => 1, 0x0845 => 1, 0x0847 => 1, 0x0848 => 1, 0x084A => 1,
- 0x084B => 1, 0x084C => 1, 0x084D => 1, 0x084E => 1, 0x0850 => 1, 0x0851 => 1, 0x0852 => 1, 0x0853 => 1,
- 0x0855 => 1,
-
- 0x0200D => 1);
-
- $this->arabRightJoining = array(
- 0x0620 => 1, 0x0622 => 1, 0x0623 => 1, 0x0624 => 1, 0x0625 => 1, 0x0626 => 1, 0x0627 => 1, 0x0628 => 1,
- 0x0629 => 1, 0x062A => 1, 0x062B => 1, 0x062C => 1, 0x062D => 1, 0x062E => 1, 0x062F => 1, 0x0630 => 1,
- 0x0631 => 1, 0x0632 => 1, 0x0633 => 1, 0x0634 => 1, 0x0635 => 1, 0x0636 => 1, 0x0637 => 1, 0x0638 => 1,
- 0x0639 => 1, 0x063A => 1, 0x063B => 1, 0x063C => 1, 0x063D => 1, 0x063E => 1, 0x063F => 1, 0x0640 => 1,
- 0x0641 => 1, 0x0642 => 1, 0x0643 => 1, 0x0644 => 1, 0x0645 => 1, 0x0646 => 1, 0x0647 => 1, 0x0648 => 1,
- 0x0649 => 1, 0x064A => 1, 0x066E => 1, 0x066F => 1, 0x0671 => 1, 0x0672 => 1, 0x0673 => 1, 0x0675 => 1,
- 0x0676 => 1, 0x0677 => 1, 0x0678 => 1, 0x0679 => 1, 0x067A => 1, 0x067B => 1, 0x067C => 1, 0x067D => 1,
- 0x067E => 1, 0x067F => 1, 0x0680 => 1, 0x0681 => 1, 0x0682 => 1, 0x0683 => 1, 0x0684 => 1, 0x0685 => 1,
- 0x0686 => 1, 0x0687 => 1, 0x0688 => 1, 0x0689 => 1, 0x068A => 1, 0x068B => 1, 0x068C => 1, 0x068D => 1,
- 0x068E => 1, 0x068F => 1, 0x0690 => 1, 0x0691 => 1, 0x0692 => 1, 0x0693 => 1, 0x0694 => 1, 0x0695 => 1,
- 0x0696 => 1, 0x0697 => 1, 0x0698 => 1, 0x0699 => 1, 0x069A => 1, 0x069B => 1, 0x069C => 1, 0x069D => 1,
- 0x069E => 1, 0x069F => 1, 0x06A0 => 1, 0x06A1 => 1, 0x06A2 => 1, 0x06A3 => 1, 0x06A4 => 1, 0x06A5 => 1,
- 0x06A6 => 1, 0x06A7 => 1, 0x06A8 => 1, 0x06A9 => 1, 0x06AA => 1, 0x06AB => 1, 0x06AC => 1, 0x06AD => 1,
- 0x06AE => 1, 0x06AF => 1, 0x06B0 => 1, 0x06B1 => 1, 0x06B2 => 1, 0x06B3 => 1, 0x06B4 => 1, 0x06B5 => 1,
- 0x06B6 => 1, 0x06B7 => 1, 0x06B8 => 1, 0x06B9 => 1, 0x06BA => 1, 0x06BB => 1, 0x06BC => 1, 0x06BD => 1,
- 0x06BE => 1, 0x06BF => 1, 0x06C0 => 1, 0x06C1 => 1, 0x06C2 => 1, 0x06C3 => 1, 0x06C4 => 1, 0x06C5 => 1,
- 0x06C6 => 1, 0x06C7 => 1, 0x06C8 => 1, 0x06C9 => 1, 0x06CA => 1, 0x06CB => 1, 0x06CC => 1, 0x06CD => 1,
- 0x06CE => 1, 0x06CF => 1, 0x06D0 => 1, 0x06D1 => 1, 0x06D2 => 1, 0x06D3 => 1, 0x06D5 => 1, 0x06EE => 1,
- 0x06EF => 1, 0x06FA => 1, 0x06FB => 1, 0x06FC => 1, 0x06FF => 1,
-
- 0x0750 => 1, 0x0751 => 1, 0x0752 => 1, 0x0753 => 1, 0x0754 => 1, 0x0755 => 1, 0x0756 => 1, 0x0757 => 1,
- 0x0758 => 1, 0x0759 => 1, 0x075A => 1, 0x075B => 1, 0x075C => 1, 0x075D => 1, 0x075E => 1, 0x075F => 1,
- 0x0760 => 1, 0x0761 => 1, 0x0762 => 1, 0x0763 => 1, 0x0764 => 1, 0x0765 => 1, 0x0766 => 1, 0x0767 => 1,
- 0x0768 => 1, 0x0769 => 1, 0x076A => 1, 0x076B => 1, 0x076C => 1, 0x076D => 1, 0x076E => 1, 0x076F => 1,
- 0x0770 => 1, 0x0771 => 1, 0x0772 => 1, 0x0773 => 1, 0x0774 => 1, 0x0775 => 1, 0x0776 => 1, 0x0777 => 1,
- 0x0778 => 1, 0x0779 => 1, 0x077A => 1, 0x077B => 1, 0x077C => 1, 0x077D => 1, 0x077E => 1, 0x077F => 1,
-
- 0x08A0 => 1, 0x08A2 => 1, 0x08A3 => 1, 0x08A4 => 1, 0x08A5 => 1, 0x08A6 => 1, 0x08A7 => 1, 0x08A8 => 1,
- 0x08A9 => 1, 0x08AA => 1, 0x08AB => 1, 0x08AC => 1,
-
- 0x0710 => 1, 0x0712 => 1, 0x0713 => 1, 0x0714 => 1, 0x0715 => 1, 0x0716 => 1, 0x0717 => 1, 0x0718 => 1,
- 0x0719 => 1, 0x071A => 1, 0x071B => 1, 0x071C => 1, 0x071D => 1, 0x071E => 1, 0x071F => 1, 0x0720 => 1,
- 0x0721 => 1, 0x0722 => 1, 0x0723 => 1, 0x0724 => 1, 0x0725 => 1, 0x0726 => 1, 0x0727 => 1, 0x0728 => 1,
- 0x0729 => 1, 0x072A => 1, 0x072B => 1, 0x072C => 1, 0x072D => 1, 0x072E => 1, 0x072F => 1, 0x074D => 1,
- 0x074E => 1, 0x074F,
-
- 0x07CA => 1, 0x07CB => 1, 0x07CC => 1, 0x07CD => 1, 0x07CE => 1, 0x07CF => 1, 0x07D0 => 1, 0x07D1 => 1,
- 0x07D2 => 1, 0x07D3 => 1, 0x07D4 => 1, 0x07D5 => 1, 0x07D6 => 1, 0x07D7 => 1, 0x07D8 => 1, 0x07D9 => 1,
- 0x07DA => 1, 0x07DB => 1, 0x07DC => 1, 0x07DD => 1, 0x07DE => 1, 0x07DF => 1, 0x07E0 => 1, 0x07E1 => 1,
- 0x07E2 => 1, 0x07E3 => 1, 0x07E4 => 1, 0x07E5 => 1, 0x07E6 => 1, 0x07E7 => 1, 0x07E8 => 1, 0x07E9 => 1,
- 0x07EA => 1, 0x07FA => 1,
-
- 0x0841 => 1, 0x0842 => 1, 0x0843 => 1, 0x0844 => 1, 0x0845 => 1, 0x0847 => 1, 0x0848 => 1, 0x084A => 1,
- 0x084B => 1, 0x084C => 1, 0x084D => 1, 0x084E => 1, 0x0850 => 1, 0x0851 => 1, 0x0852 => 1, 0x0853 => 1,
- 0x0855 => 1,
- 0x0840 => 1, 0x0846 => 1, 0x0849 => 1, 0x084F => 1, 0x0854 => 1,
-
- 0x0200D => 1);
-
- $this->arabTransparent = array(
- 0x0610 => 1, 0x0611 => 1, 0x0612 => 1, 0x0613 => 1, 0x0614 => 1, 0x0615 => 1, 0x0616 => 1, 0x0617 => 1,
- 0x0618 => 1, 0x0619 => 1, 0x061A => 1, 0x064B => 1, 0x064C => 1, 0x064D => 1, 0x064E => 1, 0x064F => 1,
- 0x0650 => 1, 0x0651 => 1, 0x0652 => 1, 0x0653 => 1, 0x0654 => 1, 0x0655 => 1, 0x0656 => 1, 0x0657 => 1,
- 0x0658 => 1, 0x0659 => 1, 0x065A => 1, 0x065B => 1, 0x065C => 1, 0x065D => 1, 0x065E => 1, 0x065F => 1,
- 0x0670 => 1, 0x06D6 => 1, 0x06D7 => 1, 0x06D8 => 1, 0x06D9 => 1, 0x06DA => 1, 0x06DB => 1, 0x06DC => 1,
- 0x06DF => 1, 0x06E0 => 1, 0x06E1 => 1, 0x06E2 => 1, 0x06E3 => 1, 0x06E4 => 1, 0x06E7 => 1, 0x06E8 => 1,
- 0x06EA => 1, 0x06EB => 1, 0x06EC => 1, 0x06ED => 1,
-
- 0x08E4 => 1, 0x08E5 => 1, 0x08E6 => 1, 0x08E7 => 1, 0x08E8 => 1, 0x08E9 => 1, 0x08EA => 1, 0x08EB => 1,
- 0x08EC => 1, 0x08ED => 1, 0x08EE => 1, 0x08EF => 1, 0x08F0 => 1, 0x08F1 => 1, 0x08F2 => 1, 0x08F3 => 1,
- 0x08F4 => 1, 0x08F5 => 1, 0x08F6 => 1, 0x08F7 => 1, 0x08F8 => 1, 0x08F9 => 1, 0x08FA => 1, 0x08FB => 1,
- 0x08FC => 1, 0x08FD => 1, 0x08FE => 1,
-
- 0xFC5E => 1, 0xFC5F => 1, 0xFC60 => 1, 0xFC61 => 1, 0xFC62 => 1,
-
- 0x070F => 1, 0x0711 => 1, 0x0730 => 1, 0x0731 => 1, 0x0732 => 1, 0x0733 => 1, 0x0734 => 1, 0x0735 => 1,
- 0x0736 => 1, 0x0737 => 1, 0x0738 => 1, 0x0739 => 1, 0x073A => 1, 0x073B => 1, 0x073C => 1, 0x073D => 1,
- 0x073E => 1, 0x073F => 1, 0x0740 => 1, 0x0741 => 1, 0x0742 => 1, 0x0743 => 1, 0x0744 => 1, 0x0745 => 1,
- 0x0746 => 1, 0x0747 => 1, 0x0748 => 1, 0x0749 => 1, 0x074A => 1,
-
- 0x07EB => 1, 0x07EC => 1, 0x07ED => 1, 0x07EE => 1, 0x07EF => 1, 0x07F0 => 1, 0x07F1 => 1, 0x07F2 => 1,
- 0x07F3 => 1,
-
- 0x0859 => 1, 0x085A => 1, 0x085B => 1,
- );
- }
- function arabic_shaper($usetags, $scriptTag)
- {
- $chars = array();
- for ($i = 0; $i < count($this->OTLdata); $i++) {
- $chars[] = $this->OTLdata[$i]['hex'];
- }
- $crntChar = null;
- $prevChar = null;
- $nextChar = null;
- $output = array();
- $max = count($chars);
- for ($i = $max - 1; $i >= 0; $i--) {
- $crntChar = $chars[$i];
- if ($i > 0) {
- $prevChar = hexdec($chars[$i - 1]);
- } else {
- $prevChar = NULL;
- }
- if ($prevChar && isset($this->arabTransparentJoin[$prevChar]) && isset($chars[$i - 2])) {
- $prevChar = hexdec($chars[$i - 2]);
- if ($prevChar && isset($this->arabTransparentJoin[$prevChar]) && isset($chars[$i - 3])) {
- $prevChar = hexdec($chars[$i - 3]);
- if ($prevChar && isset($this->arabTransparentJoin[$prevChar]) && isset($chars[$i - 4])) {
- $prevChar = hexdec($chars[$i - 4]);
- }
- }
- }
- if ($crntChar && isset($this->arabTransparentJoin[hexdec($crntChar)])) {
-
- if (isset($chars[$i + 1]) && $chars[$i + 1] && isset($this->arabRightJoining[hexdec($chars[$i + 1])]) && $prevChar && isset($this->arabLeftJoining[$prevChar])) {
- $output[] = $this->get_arab_glyphs($crntChar, 1, $chars, $i, $scriptTag, $usetags);
- } else {
- $output[] = $this->get_arab_glyphs($crntChar, 0, $chars, $i, $scriptTag, $usetags);
- }
- continue;
- }
- if (hexdec($crntChar) < 128) {
- $output[] = array($crntChar, 0);
- $nextChar = $crntChar;
- continue;
- }
-
- $form = 0;
- if ($prevChar && isset($this->arabLeftJoining[$prevChar])) {
- $form++;
- }
- if ($nextChar && isset($this->arabRightJoining[hexdec($nextChar)])) {
- $form += 2;
- }
- $output[] = $this->get_arab_glyphs($crntChar, $form, $chars, $i, $scriptTag, $usetags);
- $nextChar = $crntChar;
- }
- $ra = array_reverse($output);
- for ($i = 0; $i < count($this->OTLdata); $i++) {
- $this->OTLdata[$i]['uni'] = hexdec($ra[$i][0]);
- $this->OTLdata[$i]['hex'] = $ra[$i][0];
- $this->OTLdata[$i]['form'] = $ra[$i][1];
- }
- }
- function get_arab_glyphs($char, $type, &$chars, $i, $scriptTag, $usetags)
- {
-
- if (($type === 0 && strpos($usetags, 'isol') === false) || ($type === 1 && strpos($usetags, 'fina') === false) || ($type === 2 && strpos($usetags, 'init') === false) || ($type === 3 && strpos($usetags, 'medi') === false)) {
- return array($char, 0);
- }
-
- $retk = -1;
-
- if ($scriptTag == 'syrc' && $char == '00710') {
-
-
- $n = $i - 1;
-
-
- if (isset($chars[$n]) && isset($this->arabLeftJoining[hexdec($chars[$n])])) {
-
- if (isset($chars[$i + 1]) && preg_match('/[\x{0700}-\x{0745}]/u', code2utf(hexdec($chars[$n]))) && preg_match('/[\x{0700}-\x{0745}]/u', code2utf(hexdec($chars[$i + 1]))) && isset($this->arabGlyphs[$char][4])) {
- $retk = 4;
- }
-
- else if (!isset($chars[$i + 1]) || !preg_match('/[\x{0700}-\x{0745}]/u', code2utf(hexdec($chars[$i + 1])))) {
-
- if (strpos('0715|0716|072A', $chars[$n]) !== false && isset($this->arabGlyphs[$char][6])) {
- $retk = 6;
- }
-
- else if (isset($this->arabGlyphs[$char][5])) {
- $retk = 5;
- }
- }
- }
- if ($retk != -1) {
- return array($this->arabGlyphs[$char][$retk], $retk);
- } else {
- return array($char, 0);
- }
- }
- if (($type > 0 || $type === 0) && isset($this->arabGlyphs[$char][$type])) {
- $retk = $type;
- } else if ($type == 3 && isset($this->arabGlyphs[$char][1])) {
- $retk = 1;
- } else if ($type == 2 && isset($this->arabGlyphs[$char][0])) {
- $retk = 0;
- }
- if ($retk != -1) {
- $match = true;
-
- if (isset($this->arabGlyphs[$char]['prel'][$retk]) && $this->arabGlyphs[$char]['prel'][$retk]) {
- $ig = 1;
- foreach ($this->arabGlyphs[$char]['prel'][$retk] AS $k => $v) {
- if (!isset($chars[$i - $ig - $k])) {
- $match = false;
- } else if (strpos($v, $chars[$i - $ig - $k]) === false) {
- while (strpos($this->arabGlyphs[$char]['ignore'][$retk], $chars[$i - $ig - $k]) !== false) {
- $ig++;
- }
- if (!isset($chars[$i - $ig - $k])) {
- $match = false;
- } else if (strpos($v, $chars[$i - $ig - $k]) === false) {
- $match = false;
- }
- }
- }
- }
- if (isset($this->arabGlyphs[$char]['postl'][$retk]) && $this->arabGlyphs[$char]['postl'][$retk]) {
- $ig = 1;
- foreach ($this->arabGlyphs[$char]['postl'][$retk] AS $k => $v) {
- if (!isset($chars[$i + $ig + $k])) {
- $match = false;
- } else if (strpos($v, $chars[$i + $ig + $k]) === false) {
- while (strpos($this->arabGlyphs[$char]['ignore'][$retk], $chars[$i + $ig + $k]) !== false) {
- $ig++;
- }
- if (!isset($chars[$i + $ig + $k])) {
- $match = false;
- } else if (strpos($v, $chars[$i + $ig + $k]) === false) {
- $match = false;
- }
- }
- }
- }
- if ($match) {
- return array($this->arabGlyphs[$char][$retk], $retk);
- } else {
- return array($char, 0);
- }
- } else {
- return array($char, 0);
- }
- }
- function TibetanlineBreaking()
- {
- for ($ptr = 0; $ptr < count($this->OTLdata); $ptr++) {
-
- if (isset($this->OTLdata[$ptr]['uni']) && ($this->OTLdata[$ptr]['uni'] == 0x0F0B || $this->OTLdata[$ptr]['uni'] == 0x0F0D)) {
- if (isset($this->OTLdata[$ptr + 1]['uni']) && ($this->OTLdata[$ptr + 1]['uni'] == 0x0F0D || $this->OTLdata[$ptr + 1]['uni'] == 0xF0E)) {
- continue;
- }
-
- $this->OTLdata[$ptr]['wordend'] = true;
- }
- }
- }
- function SEAlineBreaking()
- {
-
- if (!isset($this->lbdicts[$this->shaper]) && file_exists(_MPDF_PATH . 'includes/linebrdict' . $this->shaper . '.dat')) {
- $this->lbdicts[$this->shaper] = file_get_contents(_MPDF_PATH . 'includes/linebrdict' . $this->shaper . '.dat');
- }
- $dict = &$this->lbdicts[$this->shaper];
-
-
-
-
-
-
- $rollover = array();
- $ptr = 0;
- while ($ptr < count($this->OTLdata) - 3) {
- if (count($rollover)) {
- $matches = $rollover;
- $rollover = array();
- } else {
- $matches = $this->checkwordmatch($dict, $ptr);
- }
- if (count($matches) == 1) {
- $matchpos = $matches[0];
-
- if (isset($this->OTLdata[$matchpos + 1]['uni']) && ($this->OTLdata[$matchpos + 1]['uni'] == 0x0E2F || $this->OTLdata[$matchpos + 1]['uni'] == 0x0E46 || $this->OTLdata[$matchpos + 1]['uni'] == 0x0EC6)) {
- $matchpos++;
- }
-
- $this->OTLdata[$matchpos]['wordend'] = true;
- $ptr = $matchpos + 1;
- } else if (empty($matches)) {
- $ptr++;
-
- while (isset($this->OTLdata[$ptr]['uni']) && ($this->OTLdata[$ptr]['uni'] >> 8) == 0) {
- $ptr++;
- }
- } else {
- $secondmatch = false;
- for ($m = count($matches) - 1; $m >= 0; $m--) {
-
- $firstmatch = $matches[$m];
- $matches2 = $this->checkwordmatch($dict, $firstmatch + 1);
- if (count($matches2)) {
-
- $this->OTLdata[$firstmatch]['wordend'] = true;
- $ptr = $firstmatch + 1;
- $rollover = $matches2;
- $secondmatch = true;
- break;
- }
- }
- if (!$secondmatch) {
-
- $this->OTLdata[$matches[count($matches) - 1]]['wordend'] = true;
- $ptr = $matches[count($matches) - 1] + 1;
-
- while (isset($this->OTLdata[$ptr]['uni']) && ($this->OTLdata[$ptr]['uni'] >> 8) == 0) {
- $ptr++;
- }
- }
- }
- }
- }
- function checkwordmatch(&$dict, $ptr)
- {
-
- $dictptr = 0;
- $ok = true;
- $matches = array();
- while ($ok) {
- $x = ord($dict{$dictptr});
- $c = $this->OTLdata[$ptr]['uni'] & 0xFF;
- if ($x == _DICT_INTERMEDIATE_MATCH) {
-
- if (isset($this->OTLdata[$ptr]['uni']) && strpos($this->GlyphClassMarks, $this->OTLdata[$ptr]['hex']) === false) {
- $matches[] = $ptr - 1;
- }
- $dictptr++;
- } else if ($x == _DICT_FINAL_MATCH) {
-
- if (isset($this->OTLdata[$ptr]['uni']) && strpos($this->GlyphClassMarks, $this->OTLdata[$ptr]['hex']) === false) {
- $matches[] = $ptr - 1;
- }
- return $matches;
- } else if ($x == _DICT_NODE_TYPE_LINEAR) {
- $dictptr++;
- $m = ord($dict{$dictptr});
- if ($c == $m) {
- $ptr++;
- if ($ptr > count($this->OTLdata) - 1) {
- $next = ord($dict{$dictptr + 1});
- if ($next == _DICT_INTERMEDIATE_MATCH || $next == _DICT_FINAL_MATCH) {
-
- if (isset($this->OTLdata[$ptr]['uni']) && strpos($this->GlyphClassMarks, $this->OTLdata[$ptr]['hex']) === false) {
- $matches[] = $ptr - 1;
- }
- }
- return $matches;
- }
- $dictptr++;
- continue;
- } else {
- return $matches;
- }
- } else if ($x == _DICT_NODE_TYPE_SPLIT) {
- $dictptr++;
- $d = ord($dict{$dictptr});
- if ($c < $d) {
- $dictptr += 5;
- } else {
- $dictptr++;
-
- $offset = (ord($dict{$dictptr}) * 16777216) + (ord($dict{$dictptr + 1}) << 16) + (ord($dict{$dictptr + 2}) << 8) + ord($dict{$dictptr + 3});
- $dictptr = $offset;
- }
- } else {
- $ok = false;
- }
- }
- return $matches;
- }
- function _applyGPOSrules($LookupList, $is_old_spec = false)
- {
- foreach ($LookupList AS $lu => $tag) {
- $Type = $this->GPOSLookups[$lu]['Type'];
- $Flag = $this->GPOSLookups[$lu]['Flag'];
- $MarkFilteringSet = '';
- if (isset($this->GPOSLookups[$lu]['MarkFilteringSet']))
- $MarkFilteringSet = $this->GPOSLookups[$lu]['MarkFilteringSet'];
- $ptr = 0;
-
- while ($ptr < (count($this->OTLdata))) {
- $currGlyph = $this->OTLdata[$ptr]['hex'];
- $currGID = $this->OTLdata[$ptr]['uni'];
- $shift = 1;
- foreach ($this->GPOSLookups[$lu]['Subtables'] AS $c => $subtable_offset) {
-
- if (isset($this->LuCoverage[$lu][$c][$currGID])) {
-
- if (isset($this->OTLdata[$ptr]['bidi_type'])) {
- $shift = $this->_applyGPOSsubtable($lu, $c, $ptr, $currGlyph, $currGID, ($subtable_offset - $this->GPOS_offset + $this->GSUB_length), $Type, $Flag, $MarkFilteringSet, $this->LuCoverage[$lu][$c], $tag, 0, $is_old_spec);
- if ($shift) {
- break;
- }
- }
- }
- }
- if ($shift == 0) {
- $shift = 1;
- }
- $ptr += $shift;
- }
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
- function _applyGPOSvaluerecord($basepos, $Value)
- {
-
-
- if (strpos($this->GlyphClassMarks, $this->OTLdata[$basepos]['hex']) !== false) {
- $cw = round($this->mpdf->_getCharWidth($this->mpdf->CurrentFont['cw'], $this->OTLdata[$basepos]['uni']) * $this->mpdf->CurrentFont['unitsPerEm'] / 1000);
- } else {
- $cw = 0;
- }
- $apos = $this->_getXAdvancePos($basepos);
- if (isset($Value['XAdvance']) && ($Value['XAdvance'] - $cw) != 0) {
-
-
- if ($Value['XAdvance'] < 0) {
- $cw = 0;
- }
-
-
- if (isset($this->OTLdata[$apos]['GPOSinfo']['XAdvanceL'])) {
- $this->OTLdata[$apos]['GPOSinfo']['XAdvanceL'] += $Value['XAdvance'] - $cw;
- } else {
- $this->OTLdata[$apos]['GPOSinfo']['XAdvanceL'] = $Value['XAdvance'] - $cw;
- }
- if (isset($this->OTLdata[$basepos]['GPOSinfo']['XAdvanceR'])) {
- $this->OTLdata[$basepos]['GPOSinfo']['XAdvanceR'] += $Value['XAdvance'] - $cw;
- } else {
- $this->OTLdata[$basepos]['GPOSinfo']['XAdvanceR'] = $Value['XAdvance'] - $cw;
- }
- }
-
- for ($a = $basepos; $a <= $apos; $a++) {
- if (isset($Value['XPlacement'])) {
- if (isset($this->OTLdata[$a]['GPOSinfo']['XPlacement'])) {
- $this->OTLdata[$a]['GPOSinfo']['XPlacement'] += $Value['XPlacement'];
- } else {
- $this->OTLdata[$a]['GPOSinfo']['XPlacement'] = $Value['XPlacement'];
- }
- }
- if (isset($Value['YPlacement'])) {
- if (isset($this->OTLdata[$a]['GPOSinfo']['YPlacement'])) {
- $this->OTLdata[$a]['GPOSinfo']['YPlacement'] += $Value['YPlacement'];
- } else {
- $this->OTLdata[$a]['GPOSinfo']['YPlacement'] = $Value['YPlacement'];
- }
- }
- }
- }
- function _getXAdvancePos($pos)
- {
-
-
- if (strpos($this->GlyphClassMarks, $this->OTLdata[$pos]['hex']) !== false) {
- return $pos;
- }
- while (isset($this->OTLdata[$pos + 1]['hex']) && strpos($this->GlyphClassMarks, $this->OTLdata[$pos + 1]['hex']) !== false) {
- $pos++;
- }
- return $pos;
- }
- function _applyGPOSsubtable($lookupID, $subtable, $ptr, $currGlyph, $currGID, $subtable_offset, $Type, $Flag, $MarkFilteringSet, $LuCoverage, $tag, $level = 0, $is_old_spec)
- {
- if (($Flag & 0x0001) == 1) {
- $dir = 'RTL';
- }
- else {
- $dir = 'LTR';
- }
- $ignore = $this->_getGCOMignoreString($Flag, $MarkFilteringSet);
-
- $this->seek($subtable_offset);
- $PosFormat = $this->read_ushort();
-
-
-
- if ($Type == 1) {
-
-
-
- if ($PosFormat == 1) {
- $Coverage = $subtable_offset + $this->read_ushort();
- $ValueFormat = $this->read_ushort();
- $Value = $this->_getValueRecord($ValueFormat);
- }
-
-
-
- else if ($PosFormat == 2) {
- $Coverage = $subtable_offset + $this->read_ushort();
- $ValueFormat = $this->read_ushort();
- $ValueCount = $this->read_ushort();
- $GlyphPos = $LuCoverage[$currGID];
- $this->skip($GlyphPos * 2 * $this->count_bits($ValueFormat));
- $Value = $this->_getValueRecord($ValueFormat);
- }
- $this->_applyGPOSvaluerecord($ptr, $Value);
- if ($this->debugOTL) {
- $this->_dumpproc('GPOS', $lookupID, $subtable, $Type, $PosFormat, $ptr, $currGlyph, $level);
- }
- return 1;
- }
-
-
-
- else if ($Type == 2) {
- $Coverage = $subtable_offset + $this->read_ushort();
- $ValueFormat1 = $this->read_ushort();
- $ValueFormat2 = $this->read_ushort();
- $sizeOfPair = ( 2 * $this->count_bits($ValueFormat1) ) + ( 2 * $this->count_bits($ValueFormat2) );
-
-
-
- if ($PosFormat == 1) {
- $PairSetCount = $this->read_ushort();
- $PairSetOffset = array();
- for ($p = 0; $p < $PairSetCount; $p++) {
- $PairSetOffset[] = $subtable_offset + $this->read_ushort();
- }
- for ($p = 0; $p < $PairSetCount; $p++) {
- if (isset($LuCoverage[$currGID]) && $LuCoverage[$currGID] == $p) {
- $this->seek($PairSetOffset[$p]);
-
- $PairValueCount = $this->read_ushort();
- for ($pv = 0; $pv < $PairValueCount; $pv++) {
-
- $gid = $this->read_ushort();
- $SecondGlyph = $this->glyphToChar($gid);
- $FirstGlyph = $this->OTLdata[$ptr]['uni'];
- $checkpos = $ptr;
- $checkpos++;
- while (isset($this->OTLdata[$checkpos]) && strpos($ignore, $this->OTLdata[$checkpos]['hex']) !== false) {
- $checkpos++;
- }
- if (isset($this->OTLdata[$checkpos]) && $this->OTLdata[$checkpos]['uni'] == $SecondGlyph) {
- $matchedpos = $checkpos;
- } else {
- $matchedpos = false;
- }
- if ($matchedpos !== false) {
- $Value1 = $this->_getValueRecord($ValueFormat1);
- $Value2 = $this->_getValueRecord($ValueFormat2);
- if ($ValueFormat1) {
- $this->_applyGPOSvaluerecord($ptr, $Value1);
- }
- if ($ValueFormat2) {
- $this->_applyGPOSvaluerecord($matchedpos, $Value2);
- if ($this->debugOTL) {
- $this->_dumpproc('GPOS', $lookupID, $subtable, $Type, $PosFormat, $ptr, $currGlyph, $level);
- }
- return $matchedpos - $ptr + 1;
- }
- if ($this->debugOTL) {
- $this->_dumpproc('GPOS', $lookupID, $subtable, $Type, $PosFormat, $ptr, $currGlyph, $level);
- }
- return $matchedpos - $ptr;
- } else {
- $this->skip($sizeOfPair);
- }
- }
- }
- }
- return 0;
- }
-
-
-
- else if ($PosFormat == 2) {
- $ClassDef1 = $subtable_offset + $this->read_ushort();
- $ClassDef2 = $subtable_offset + $this->read_ushort();
- $Class1Count = $this->read_ushort();
- $Class2Count = $this->read_ushort();
- $sizeOfValueRecords = $Class1Count * $Class2Count * $sizeOfPair;
-
-
-
- $Class1 = $this->_getClassDefinitionTable($ClassDef1);
- $Class2 = $this->_getClassDefinitionTable($ClassDef2);
- $FirstGlyph = $this->OTLdata[$ptr]['uni'];
- $checkpos = $ptr;
- $checkpos++;
- while (isset($this->OTLdata[$checkpos]) && strpos($ignore, $this->OTLdata[$checkpos]['hex']) !== false) {
- $checkpos++;
- }
- if (isset($this->OTLdata[$checkpos])) {
- $matchedpos = $checkpos;
- } else {
- return 0;
- }
- $SecondGlyph = $this->OTLdata[$matchedpos]['uni'];
- for ($i = 0; $i < $Class1Count; $i++) {
- if (isset($Class1[$i]) && count($Class1[$i])) {
- $FirstClassPos = array_search($FirstGlyph, $Class1[$i]);
- if ($FirstClassPos === false) {
- continue;
- } else {
- for ($j = 0; $j < $Class2Count; $j++) {
- if (isset($Class2[$j]) && count($Class2[$j])) {
- $SecondClassPos = array_search($SecondGlyph, $Class2[$j]);
- if ($SecondClassPos === false) {
- continue;
- }
-
- $offs = ($i * $Class2Count * $sizeOfPair) + ($j * $sizeOfPair);
- $this->seek($subtable_offset + 16 + $offs);
- $Value1 = $this->_getValueRecord($ValueFormat1);
- $Value2 = $this->_getValueRecord($ValueFormat2);
- if ($ValueFormat1) {
- $this->_applyGPOSvaluerecord($ptr, $Value1);
- }
- if ($ValueFormat2) {
- $this->_applyGPOSvaluerecord($matchedpos, $Value2);
- if ($this->debugOTL) {
- $this->_dumpproc('GPOS', $lookupID, $subtable, $Type, $PosFormat, $ptr, $currGlyph, $level);
- }
- return $matchedpos - $ptr + 1;
- }
- if ($this->debugOTL) {
- $this->_dumpproc('GPOS', $lookupID, $subtable, $Type, $PosFormat, $ptr, $currGlyph, $level);
- }
- return $matchedpos - $ptr;
- }
- }
- }
- }
- }
- return 0;
- }
- }
-
-
-
- else if ($Type == 3) {
- $this->skip(4);
-
- $pdfWidth = $this->mpdf->_getCharWidth($this->mpdf->CurrentFont['cw'], hexdec($currGlyph));
- $CPos = $LuCoverage[$currGID];
- $this->skip($CPos * 4);
- $EntryAnchor = $this->read_ushort();
- $ExitAnchor = $this->read_ushort();
- if ($EntryAnchor != 0) {
- $EntryAnchor += $subtable_offset;
- list($x, $y) = $this->_getAnchorTable($EntryAnchor);
- if ($dir == 'RTL') {
- if (round($pdfWidth) == round($x * 1000 / $this->mpdf->CurrentFont['unitsPerEm'])) {
- $x = 0;
- } else {
- $x = $x - ($pdfWidth * $this->mpdf->CurrentFont['unitsPerEm'] / 1000);
- }
- }
- $this->Entry[$ptr] = array('X' => $x, 'Y' => $y, 'dir' => $dir);
- }
- if ($ExitAnchor != 0) {
- $ExitAnchor += $subtable_offset;
- list($x, $y) = $this->_getAnchorTable($ExitAnchor);
- if ($dir == 'LTR') {
- if (round($pdfWidth) == round($x * 1000 / $this->mpdf->CurrentFont['unitsPerEm'])) {
- $x = 0;
- } else {
- $x = $x - ($pdfWidth * $this->mpdf->CurrentFont['unitsPerEm'] / 1000);
- }
- }
- $this->Exit[$ptr] = array('X' => $x, 'Y' => $y, 'dir' => $dir);
- }
- if ($this->debugOTL) {
- $this->_dumpproc('GPOS', $lookupID, $subtable, $Type, $PosFormat, $ptr, $currGlyph, $level);
- }
- return 1;
- }
-
-
-
- else if ($Type == 4) {
- $MarkCoverage = $subtable_offset + $this->read_ushort();
-
- $BaseCoverage = $subtable_offset + $this->read_ushort();
- $ClassCount = $this->read_ushort();
- $MarkArray = $subtable_offset + $this->read_ushort();
- $BaseArray = $subtable_offset + $this->read_ushort();
- $this->seek($BaseCoverage);
- $BaseGlyphs = implode('|', $this->_getCoverage());
- $checkpos = $ptr;
- $checkpos--;
-
-
-
-
-
-
-
- if ($this->shaper == 'I' && $is_old_spec && strpos($this->GlyphClassMarks, $this->OTLdata[$ptr]['hex']) === false) {
- return;
- }
-
- while (isset($this->OTLdata[$checkpos]) && strpos($this->GlyphClassMarks, $this->OTLdata[$checkpos]['hex']) !== false) {
- $checkpos--;
- }
- if (isset($this->OTLdata[$checkpos]) && strpos($BaseGlyphs, $this->OTLdata[$checkpos]['hex']) !== false) {
- $matchedpos = $checkpos;
- } else {
- $matchedpos = false;
- }
- if ($matchedpos !== false) {
-
- $MarkPos = $LuCoverage[$currGID];
- $MarkRecord = $this->_getMarkRecord($MarkArray, $MarkPos);
-
-
- $this->seek($BaseArray);
- $BaseCount = $this->read_ushort();
- $BasePos = strpos($BaseGlyphs, $this->OTLdata[$matchedpos]['hex']) / 6;
-
- $nSkip = (2 * $BasePos * $ClassCount );
- $this->skip($nSkip);
-
- $nSkip = 2 * $MarkRecord['Class'];
- $this->skip($nSkip);
- $BaseRecordOffset = $BaseArray + $this->read_ushort();
- list($x, $y) = $this->_getAnchorTable($BaseRecordOffset);
- $BaseRecord = array('AnchorX' => $x, 'AnchorY' => $y);
-
- $BaseWidth = $this->mpdf->_getCharWidth($this->mpdf->CurrentFont['cw'], $this->OTLdata[$matchedpos]['uni']) * $this->mpdf->CurrentFont['unitsPerEm'] / 1000;
- $this->OTLdata[$ptr]['GPOSinfo']['BaseWidth'] = $BaseWidth;
-
- if (($ptr - $matchedpos) > 1) {
- for ($i = $matchedpos + 1; $i < $ptr; $i++) {
- $BaseWidthExtra = $this->mpdf->_getCharWidth($this->mpdf->CurrentFont['cw'], $this->OTLdata[$i]['uni']) * $this->mpdf->CurrentFont['unitsPerEm'] / 1000;
- $this->OTLdata[$ptr]['GPOSinfo']['BaseWidth'] += $BaseWidthExtra;
- }
- }
-
- $prevXPlacement = (isset($this->OTLdata[$matchedpos]['GPOSinfo']['XPlacement']) ? $this->OTLdata[$matchedpos]['GPOSinfo']['XPlacement'] : 0);
- $prevYPlacement = (isset($this->OTLdata[$matchedpos]['GPOSinfo']['YPlacement']) ? $this->OTLdata[$matchedpos]['GPOSinfo']['YPlacement'] : 0);
- $this->OTLdata[$ptr]['GPOSinfo']['XPlacement'] = $prevXPlacement + $BaseRecord['AnchorX'] - $MarkRecord['AnchorX'];
- $this->OTLdata[$ptr]['GPOSinfo']['YPlacement'] = $prevYPlacement + $BaseRecord['AnchorY'] - $MarkRecord['AnchorY'];
- if ($this->debugOTL) {
- $this->_dumpproc('GPOS', $lookupID, $subtable, $Type, $PosFormat, $ptr, $currGlyph, $level);
- }
- return 1;
- }
- return 0;
- }
-
-
-
- else if ($Type == 5) {
- $MarkCoverage = $subtable_offset + $this->read_ushort();
-
- $LigatureCoverage = $subtable_offset + $this->read_ushort();
- $ClassCount = $this->read_ushort();
- $MarkArray = $subtable_offset + $this->read_ushort();
- $LigatureArray = $subtable_offset + $this->read_ushort();
- $this->seek($LigatureCoverage);
- $LigatureGlyphs = implode('|', $this->_getCoverage());
- $checkpos = $ptr;
- $checkpos--;
-
- while (isset($this->OTLdata[$checkpos]) && strpos($this->GlyphClassMarks, $this->OTLdata[$checkpos]['hex']) !== false) {
- $checkpos--;
- }
- if (isset($this->OTLdata[$checkpos]) && strpos($LigatureGlyphs, $this->OTLdata[$checkpos]['hex']) !== false) {
- $matchedpos = $checkpos;
- } else {
- $matchedpos = false;
- }
- if ($matchedpos !== false) {
-
- $MarkPos = $LuCoverage[$currGID];
- $MarkRecord = $this->_getMarkRecord($MarkArray, $MarkPos);
-
-
- $this->seek($LigatureArray);
- $LigatureCount = $this->read_ushort();
- $LigaturePos = strpos($LigatureGlyphs, $this->OTLdata[$matchedpos]['hex']) / 6;
-
- $nSkip = (2 * $LigaturePos);
- $this->skip($nSkip);
- $LigatureAttachOffset = $LigatureArray + $this->read_ushort();
- $this->seek($LigatureAttachOffset);
- $ComponentCount = $this->read_ushort();
- $offsets = array();
- for ($comp = 0; $comp < $ComponentCount; $comp++) {
-
- for ($class = 0; $class < $ClassCount; $class++) {
- $offsets[$comp][$class] = $this->read_ushort();
- }
- }
-
- if (isset($this->assocLigs[$matchedpos]) && isset($this->assocMarks[$ptr]['ligPos']) && $this->assocMarks[$ptr]['ligPos'] == $matchedpos) {
- $component = $this->assocMarks[$ptr]['compID'];
- } else {
- $component = $ComponentCount - 1;
- }
- $offset = $offsets[$component][$MarkRecord['Class']];
- if ($offset != 0) {
- $LigatureRecordOffset = $offset + $LigatureAttachOffset;
- list($x, $y) = $this->_getAnchorTable($LigatureRecordOffset);
- $LigatureRecord = array('AnchorX' => $x, 'AnchorY' => $y);
-
- $LigatureWidth = $this->mpdf->_getCharWidth($this->mpdf->CurrentFont['cw'], $this->OTLdata[$matchedpos]['uni']) * $this->mpdf->CurrentFont['unitsPerEm'] / 1000;
- $this->OTLdata[$ptr]['GPOSinfo']['BaseWidth'] = $LigatureWidth;
-
- if (($ptr - $matchedpos) > 1) {
- for ($i = $matchedpos + 1; $i < $ptr; $i++) {
- $LigatureWidthExtra = $this->mpdf->_getCharWidth($this->mpdf->CurrentFont['cw'], $this->OTLdata[$i]['uni']) * $this->mpdf->CurrentFont['unitsPerEm'] / 1000;
- $this->OTLdata[$ptr]['GPOSinfo']['BaseWidth'] += $LigatureWidthExtra;
- }
- }
-
- if (isset($this->OTLdata[$matchedpos]['GPOSinfo']['XPlacement']))
- $prevXPlacement = $this->OTLdata[$matchedpos]['GPOSinfo']['XPlacement'];
- else {
- $prevXPlacement = 0;
- }
- if (isset($this->OTLdata[$matchedpos]['GPOSinfo']['YPlacement'])) {
- $prevYPlacement = $this->OTLdata[$matchedpos]['GPOSinfo']['YPlacement'];
- } else {
- $prevYPlacement = 0;
- }
- $this->OTLdata[$ptr]['GPOSinfo']['XPlacement'] = $prevXPlacement + $LigatureRecord['AnchorX'] - $MarkRecord['AnchorX'];
- $this->OTLdata[$ptr]['GPOSinfo']['YPlacement'] = $prevYPlacement + $LigatureRecord['AnchorY'] - $MarkRecord['AnchorY'];
- if ($this->debugOTL) {
- $this->_dumpproc('GPOS', $lookupID, $subtable, $Type, $PosFormat, $ptr, $currGlyph, $level);
- }
- return 1;
- }
- }
- return 0;
- }
-
-
-
- else if ($Type == 6) {
- $Mark1Coverage = $subtable_offset + $this->read_ushort();
-
- $Mark2Coverage = $subtable_offset + $this->read_ushort();
- $ClassCount = $this->read_ushort();
- $Mark1Array = $subtable_offset + $this->read_ushort();
- $Mark2Array = $subtable_offset + $this->read_ushort();
- $this->seek($Mark2Coverage);
- $Mark2Glyphs = implode('|', $this->_getCoverage());
- $checkpos = $ptr;
- $checkpos--;
- while (isset($this->OTLdata[$checkpos]) && strpos($ignore, $this->OTLdata[$checkpos]['hex']) !== false) {
- $checkpos--;
- }
- if (isset($this->OTLdata[$checkpos]) && strpos($Mark2Glyphs, $this->OTLdata[$checkpos]['hex']) !== false) {
- $matchedpos = $checkpos;
- } else {
- $matchedpos = false;
- }
- if ($matchedpos !== false) {
-
- $Mark1Pos = $LuCoverage[$currGID];
- $Mark1Record = $this->_getMarkRecord($Mark1Array, $Mark1Pos);
-
-
- $this->seek($Mark2Array);
- $Mark2Count = $this->read_ushort();
- $Mark2Pos = strpos($Mark2Glyphs, $this->OTLdata[$matchedpos]['hex']) / 6;
-
- $nSkip = (2 * $Mark2Pos * $ClassCount );
- $this->skip($nSkip);
-
- $nSkip = 2 * $Mark1Record['Class'];
- $this->skip($nSkip);
- $Mark2RecordOffset = $Mark2Array + $this->read_ushort();
- list($x, $y) = $this->_getAnchorTable($Mark2RecordOffset);
- $Mark2Record = array('AnchorX' => $x, 'AnchorY' => $y);
-
- $Mark2Width = $this->mpdf->_getCharWidth($this->mpdf->CurrentFont['cw'], $this->OTLdata[$matchedpos]['uni']) * $this->mpdf->CurrentFont['unitsPerEm'] / 1000;
-
-
-
- $prevLig = -1;
- $thisLig = -1;
- $prevComp = -1;
- $thisComp = -1;
- if (isset($this->assocMarks[$matchedpos])) {
- $prevLig = $this->assocMarks[$matchedpos]['ligPos'];
- $prevComp = $this->assocMarks[$matchedpos]['compID'];
- }
- if (isset($this->assocMarks[$ptr])) {
- $thisLig = $this->assocMarks[$ptr]['ligPos'];
- $thisComp = $this->assocMarks[$ptr]['compID'];
- }
-
-
- if (!defined("OMIT_OTL_FIX_1") || OMIT_OTL_FIX_1 != 1) {
-
- if (isset($this->assocMarks[$matchedpos]) && ($prevLig != $thisLig || $prevComp != $thisComp )) {
- return 0;
- }
- } else {
-
- if ($prevLig != $thisLig || $prevComp != $thisComp) {
- return 0;
- }
- }
- if (!defined("OMIT_OTL_FIX_2") || OMIT_OTL_FIX_2 != 1) {
-
- if (!isset($this->OTLdata[$matchedpos]['GPOSinfo']['BaseWidth']) || !$this->OTLdata[$matchedpos]['GPOSinfo']['BaseWidth']) {
- $this->OTLdata[$ptr]['GPOSinfo']['BaseWidth'] = $Mark2Width;
- }
- }
-
- if (isset($this->OTLdata[$matchedpos]['GPOSinfo']['BaseWidth']) && $this->OTLdata[$matchedpos]['GPOSinfo']['BaseWidth']) {
- $this->OTLdata[$ptr]['GPOSinfo']['BaseWidth'] = $this->OTLdata[$matchedpos]['GPOSinfo']['BaseWidth'];
- }
-
- $prevXPlacement = (isset($this->OTLdata[$matchedpos]['GPOSinfo']['XPlacement']) ? $this->OTLdata[$matchedpos]['GPOSinfo']['XPlacement'] : 0);
- $prevYPlacement = (isset($this->OTLdata[$matchedpos]['GPOSinfo']['YPlacement']) ? $this->OTLdata[$matchedpos]['GPOSinfo']['YPlacement'] : 0);
- $this->OTLdata[$ptr]['GPOSinfo']['XPlacement'] = $prevXPlacement + $Mark2Record['AnchorX'] - $Mark1Record['AnchorX'];
- $this->OTLdata[$ptr]['GPOSinfo']['YPlacement'] = $prevYPlacement + $Mark2Record['AnchorY'] - $Mark1Record['AnchorY'];
- if ($this->debugOTL) {
- $this->_dumpproc('GPOS', $lookupID, $subtable, $Type, $PosFormat, $ptr, $currGlyph, $level);
- }
- return 1;
- }
- return 0;
- }
-
-
-
- else if ($Type == 7) {
-
-
-
- if ($PosFormat == 1) {
- throw new MpdfException("GPOS Lookup Type " . $Type . " Format " . $PosFormat . " not TESTED YET.");
- }
-
-
-
- else if ($PosFormat == 2) {
- $CoverageTableOffset = $subtable_offset + $this->read_ushort();
- $InputClassDefOffset = $subtable_offset + $this->read_ushort();
- $PosClassSetCnt = $this->read_ushort();
- $PosClassSetOffset = array();
- for ($b = 0; $b < $PosClassSetCnt; $b++) {
- $offset = $this->read_ushort();
- if ($offset == 0x0000) {
- $PosClassSetOffset[] = $offset;
- } else {
- $PosClassSetOffset[] = $subtable_offset + $offset;
- }
- }
- $InputClasses = $this->_getClasses($InputClassDefOffset);
- for ($s = 0; $s < $PosClassSetCnt; $s++) {
-
- if ($PosClassSetOffset[$s] > 0 && isset($InputClasses[$s][$currGID])) {
- $this->seek($PosClassSetOffset[$s]);
- $PosClassRuleCnt = $this->read_ushort();
- $PosClassRule = array();
- for ($b = 0; $b < $PosClassRuleCnt; $b++) {
- $PosClassRule[$b] = $PosClassSetOffset[$s] + $this->read_ushort();
- }
- for ($b = 0; $b < $PosClassRuleCnt; $b++) {
- $this->seek($PosClassRule[$b]);
- $InputGlyphCount = $this->read_ushort();
- $PosCount = $this->read_ushort();
- $Input = array();
- for ($r = 1; $r < $InputGlyphCount; $r++) {
- $Input[$r] = $this->read_ushort();
- }
- $inputClass = $s;
- $inputGlyphs = array();
- $inputGlyphs[0] = $InputClasses[$inputClass];
- if ($InputGlyphCount > 1) {
-
- for ($gcl = 1; $gcl < $InputGlyphCount; $gcl++) {
- $classindex = $Input[$gcl];
- if (isset($InputClasses[$classindex])) {
- $inputGlyphs[$gcl] = $InputClasses[$classindex];
- } else {
- $inputGlyphs[$gcl] = '';
- }
- }
- }
-
- $class0excl = array();
- for ($gc = 1; $gc <= count($InputClasses); $gc++) {
- if (is_array($InputClasses[$gc]))
- $class0excl = $class0excl + $InputClasses[$gc];
- }
- $backtrackGlyphs = array();
- $lookaheadGlyphs = array();
- $matched = $this->checkContextMatchMultipleUni($inputGlyphs, $backtrackGlyphs, $lookaheadGlyphs, $ignore, $ptr, $class0excl);
- if ($matched) {
- for ($p = 0; $p < $PosCount; $p++) {
- $SequenceIndex[$p] = $this->read_ushort();
- $LookupListIndex[$p] = $this->read_ushort();
- }
- for ($p = 0; $p < $PosCount; $p++) {
-
- if ($SequenceIndex[$p] >= $InputGlyphCount) {
- continue;
- }
- $lu = $LookupListIndex[$p];
- $luType = $this->GPOSLookups[$lu]['Type'];
- $luFlag = $this->GPOSLookups[$lu]['Flag'];
- $luMarkFilteringSet = $this->GPOSLookups[$lu]['MarkFilteringSet'];
- $luptr = $matched[$SequenceIndex[$p]];
- $lucurrGlyph = $this->OTLdata[$luptr]['hex'];
- $lucurrGID = $this->OTLdata[$luptr]['uni'];
- foreach ($this->GPOSLookups[$lu]['Subtables'] AS $luc => $lusubtable_offset) {
- $shift = $this->_applyGPOSsubtable($lu, $luc, $luptr, $lucurrGlyph, $lucurrGID, ($lusubtable_offset - $this->GPOS_offset + $this->GSUB_length), $luType, $luFlag, $luMarkFilteringSet, $this->LuCoverage[$lu][$luc], $tag, 1, $is_old_spec);
- if ($this->debugOTL && $shift) {
- $this->_dumpproc('GPOS', $lookupID, $subtable, $Type, $PosFormat, $ptr, $currGlyph, $level);
- }
- if ($shift) {
- break;
- }
- }
- }
- if (!defined("OMIT_OTL_FIX_3") || OMIT_OTL_FIX_3 != 1) {
- return $shift;
- }
- else
- return $InputGlyphCount;
- }
- }
- }
- }
- return 0;
- }
-
-
-
- else if ($PosFormat == 3) {
- throw new MpdfException("GPOS Lookup Type " . $Type . " Format " . $PosFormat . " not TESTED YET.");
- } else {
- throw new MpdfException("GPOS Lookup Type " . $Type . ", Format " . $PosFormat . " not supported.");
- }
- }
-
-
-
- else if ($Type == 8) {
-
-
-
- if ($PosFormat == 1) {
- throw new MpdfException("GPOS Lookup Type " . $Type . " Format " . $PosFormat . " not TESTED YET.");
- return 0;
- }
-
-
-
- else if ($PosFormat == 2) {
- $CoverageTableOffset = $subtable_offset + $this->read_ushort();
- $BacktrackClassDefOffset = $subtable_offset + $this->read_ushort();
- $InputClassDefOffset = $subtable_offset + $this->read_ushort();
- $LookaheadClassDefOffset = $subtable_offset + $this->read_ushort();
- $ChainPosClassSetCnt = $this->read_ushort();
- $ChainPosClassSetOffset = array();
- for ($b = 0; $b < $ChainPosClassSetCnt; $b++) {
- $offset = $this->read_ushort();
- if ($offset == 0x0000) {
- $ChainPosClassSetOffset[] = $offset;
- } else {
- $ChainPosClassSetOffset[] = $subtable_offset + $offset;
- }
- }
- $BacktrackClasses = $this->_getClasses($BacktrackClassDefOffset);
- $InputClasses = $this->_getClasses($InputClassDefOffset);
- $LookaheadClasses = $this->_getClasses($LookaheadClassDefOffset);
- for ($s = 0; $s < $ChainPosClassSetCnt; $s++) {
-
- if ($ChainPosClassSetOffset[$s] > 0 && isset($InputClasses[$s][$currGID])) {
- $this->seek($ChainPosClassSetOffset[$s]);
- $ChainPosClassRuleCnt = $this->read_ushort();
- $ChainPosClassRule = array();
- for ($b = 0; $b < $ChainPosClassRuleCnt; $b++) {
- $ChainPosClassRule[$b] = $ChainPosClassSetOffset[$s] + $this->read_ushort();
- }
- for ($b = 0; $b < $ChainPosClassRuleCnt; $b++) {
- $this->seek($ChainPosClassRule[$b]);
- $BacktrackGlyphCount = $this->read_ushort();
- $Backtrack = array();
- for ($r = 0; $r < $BacktrackGlyphCount; $r++) {
- $Backtrack[$r] = $this->read_ushort();
- }
- $InputGlyphCount = $this->read_ushort();
- $Input = array();
- for ($r = 1; $r < $InputGlyphCount; $r++) {
- $Input[$r] = $this->read_ushort();
- }
- $LookaheadGlyphCount = $this->read_ushort();
- $Lookahead = array();
- for ($r = 0; $r < $LookaheadGlyphCount; $r++) {
- $Lookahead[$r] = $this->read_ushort();
- }
- $inputClass = $s;
- $inputGlyphs = array();
- $inputGlyphs[0] = $InputClasses[$inputClass];
- if ($InputGlyphCount > 1) {
-
- for ($gcl = 1; $gcl < $InputGlyphCount; $gcl++) {
- $classindex = $Input[$gcl];
- if (isset($InputClasses[$classindex])) {
- $inputGlyphs[$gcl] = $InputClasses[$classindex];
- } else {
- $inputGlyphs[$gcl] = '';
- }
- }
- }
-
- $class0excl = array();
- for ($gc = 1; $gc <= count($InputClasses); $gc++) {
- if (isset($InputClasses[$gc]) && is_array($InputClasses[$gc]))
- $class0excl = $class0excl + $InputClasses[$gc];
- }
- if ($BacktrackGlyphCount) {
- $backtrackGlyphs = array();
- for ($gcl = 0; $gcl < $BacktrackGlyphCount; $gcl++) {
- $classindex = $Backtrack[$gcl];
- if (isset($BacktrackClasses[$classindex])) {
- $backtrackGlyphs[$gcl] = $BacktrackClasses[$classindex];
- } else {
- $backtrackGlyphs[$gcl] = '';
- }
- }
- } else {
- $backtrackGlyphs = array();
- }
-
- $bclass0excl = array();
- for ($gc = 1; $gc <= count($BacktrackClasses); $gc++) {
- if (isset($BacktrackClasses[$gc]) && is_array($BacktrackClasses[$gc]))
- $bclass0excl = $bclass0excl + $BacktrackClasses[$gc];
- }
- if ($LookaheadGlyphCount) {
- $lookaheadGlyphs = array();
- for ($gcl = 0; $gcl < $LookaheadGlyphCount; $gcl++) {
- $classindex = $Lookahead[$gcl];
- if (isset($LookaheadClasses[$classindex])) {
- $lookaheadGlyphs[$gcl] = $LookaheadClasses[$classindex];
- } else {
- $lookaheadGlyphs[$gcl] = '';
- }
- }
- } else {
- $lookaheadGlyphs = array();
- }
-
- $lclass0excl = array();
- for ($gc = 1; $gc <= count($LookaheadClasses); $gc++) {
- if (isset($LookaheadClasses[$gc]) && is_array($LookaheadClasses[$gc]))
- $lclass0excl = $lclass0excl + $LookaheadClasses[$gc];
- }
- $matched = $this->checkContextMatchMultipleUni($inputGlyphs, $backtrackGlyphs, $lookaheadGlyphs, $ignore, $ptr, $class0excl, $bclass0excl, $lclass0excl);
- if ($matched) {
- $PosCount = $this->read_ushort();
- $SequenceIndex = array();
- $LookupListIndex = array();
- for ($p = 0; $p < $PosCount; $p++) {
- $SequenceIndex[$p] = $this->read_ushort();
- $LookupListIndex[$p] = $this->read_ushort();
- }
- for ($p = 0; $p < $PosCount; $p++) {
-
- if ($SequenceIndex[$p] >= $InputGlyphCount) {
- continue;
- }
- $lu = $LookupListIndex[$p];
- $luType = $this->GPOSLookups[$lu]['Type'];
- $luFlag = $this->GPOSLookups[$lu]['Flag'];
- $luMarkFilteringSet = $this->GPOSLookups[$lu]['MarkFilteringSet'];
- $luptr = $matched[$SequenceIndex[$p]];
- $lucurrGlyph = $this->OTLdata[$luptr]['hex'];
- $lucurrGID = $this->OTLdata[$luptr]['uni'];
- foreach ($this->GPOSLookups[$lu]['Subtables'] AS $luc => $lusubtable_offset) {
- $shift = $this->_applyGPOSsubtable($lu, $luc, $luptr, $lucurrGlyph, $lucurrGID, ($lusubtable_offset - $this->GPOS_offset + $this->GSUB_length), $luType, $luFlag, $luMarkFilteringSet, $this->LuCoverage[$lu][$luc], $tag, 1, $is_old_spec);
- if ($this->debugOTL && $shift) {
- $this->_dumpproc('GPOS', $lookupID, $subtable, $Type, $PosFormat, $ptr, $currGlyph, $level);
- }
- if ($shift) {
- break;
- }
- }
- }
- if (!defined("OMIT_OTL_FIX_3") || OMIT_OTL_FIX_3 != 1) {
- return $shift;
- }
- else
- return $InputGlyphCount;
- }
- }
- }
- }
- return 0;
- }
-
-
-
- else if ($PosFormat == 3) {
- $BacktrackGlyphCount = $this->read_ushort();
- for ($b = 0; $b < $BacktrackGlyphCount; $b++) {
- $CoverageBacktrackOffset[] = $subtable_offset + $this->read_ushort();
- }
- $InputGlyphCount = $this->read_ushort();
- for ($b = 0; $b < $InputGlyphCount; $b++) {
- $CoverageInputOffset[] = $subtable_offset + $this->read_ushort();
- }
- $LookaheadGlyphCount = $this->read_ushort();
- for ($b = 0; $b < $LookaheadGlyphCount; $b++) {
- $CoverageLookaheadOffset[] = $subtable_offset + $this->read_ushort();
- }
- $PosCount = $this->read_ushort();
- $save_pos = $this->_pos;
- $CoverageBacktrackGlyphs = array();
- for ($b = 0; $b < $BacktrackGlyphCount; $b++) {
- $this->seek($CoverageBacktrackOffset[$b]);
- $glyphs = $this->_getCoverage();
- $CoverageBacktrackGlyphs[$b] = implode("|", $glyphs);
- }
- $CoverageInputGlyphs = array();
- for ($b = 0; $b < $InputGlyphCount; $b++) {
- $this->seek($CoverageInputOffset[$b]);
- $glyphs = $this->_getCoverage();
- $CoverageInputGlyphs[$b] = implode("|", $glyphs);
- }
- $CoverageLookaheadGlyphs = array();
- for ($b = 0; $b < $LookaheadGlyphCount; $b++) {
- $this->seek($CoverageLookaheadOffset[$b]);
- $glyphs = $this->_getCoverage();
- $CoverageLookaheadGlyphs[$b] = implode("|", $glyphs);
- }
- $matched = $this->checkContextMatchMultiple($CoverageInputGlyphs, $CoverageBacktrackGlyphs, $CoverageLookaheadGlyphs, $ignore, $ptr);
- if ($matched) {
- $this->seek($save_pos);
- for ($p = 0; $p < $PosCount; $p++) {
-
- $PosLookupRecord[$p]['SequenceIndex'] = $this->read_ushort();
- $PosLookupRecord[$p]['LookupListIndex'] = $this->read_ushort();
- }
- for ($p = 0; $p < $PosCount; $p++) {
-
- if ($PosLookupRecord[$p]['SequenceIndex'] >= $InputGlyphCount) {
- continue;
- }
- $lu = $PosLookupRecord[$p]['LookupListIndex'];
- $luType = $this->GPOSLookups[$lu]['Type'];
- $luFlag = $this->GPOSLookups[$lu]['Flag'];
- if (isset($this->GPOSLookups[$lu]['MarkFilteringSet'])) {
- $luMarkFilteringSet = $this->GPOSLookups[$lu]['MarkFilteringSet'];
- } else {
- $luMarkFilteringSet = '';
- }
- $luptr = $matched[$PosLookupRecord[$p]['SequenceIndex']];
- $lucurrGlyph = $this->OTLdata[$luptr]['hex'];
- $lucurrGID = $this->OTLdata[$luptr]['uni'];
- foreach ($this->GPOSLookups[$lu]['Subtables'] AS $luc => $lusubtable_offset) {
- $shift = $this->_applyGPOSsubtable($lu, $luc, $luptr, $lucurrGlyph, $lucurrGID, ($lusubtable_offset - $this->GPOS_offset + $this->GSUB_length), $luType, $luFlag, $luMarkFilteringSet, $this->LuCoverage[$lu][$luc], $tag, 1, $is_old_spec);
- if ($this->debugOTL && $shift) {
- $this->_dumpproc('GPOS', $lookupID, $subtable, $Type, $PosFormat, $ptr, $currGlyph, $level);
- }
- if ($shift) {
- break;
- }
- }
- }
- }
- } else {
- throw new MpdfException("GPOS Lookup Type " . $Type . ", Format " . $PosFormat . " not supported.");
- }
- } else {
- throw new MpdfException("GPOS Lookup Type " . $Type . " not supported.");
- }
- }
-
-
-
-
-
- function checkContextMatch($Input, $Backtrack, $Lookahead, $ignore, $ptr)
- {
-
-
-
- $current_syllable = (isset($this->OTLdata[$ptr]['syllable']) ? $this->OTLdata[$ptr]['syllable'] : 0);
-
- $checkpos = $ptr;
- for ($i = 0; $i < count($Backtrack); $i++) {
- $checkpos--;
- while (isset($this->OTLdata[$checkpos]) && strpos($ignore, $this->OTLdata[$checkpos]['hex']) !== false) {
- $checkpos--;
- }
-
- if ($this->restrictToSyllable && isset($this->OTLdata[$checkpos]['syllable']) && $this->OTLdata[$checkpos]['syllable'] != $current_syllable) {
- return false;
- } else if (!isset($this->OTLdata[$checkpos]) || $this->OTLdata[$checkpos]['uni'] != $Backtrack[$i]) {
- return false;
- }
- }
-
- $matched = array(0 => $ptr);
- $checkpos = $ptr;
- for ($i = 1; $i < count($Input); $i++) {
- $checkpos++;
- while (isset($this->OTLdata[$checkpos]) && strpos($ignore, $this->OTLdata[$checkpos]['hex']) !== false) {
- $checkpos++;
- }
-
- if ($this->restrictToSyllable && isset($this->OTLdata[$checkpos]['syllable']) && $this->OTLdata[$checkpos]['syllable'] != $current_syllable) {
- return false;
- } else if (isset($this->OTLdata[$checkpos]) && $this->OTLdata[$checkpos]['uni'] == $Input[$i]) {
- $matched[] = $checkpos;
- } else {
- return false;
- }
- }
-
- for ($i = 0; $i < count($Lookahead); $i++) {
- $checkpos++;
- while (isset($this->OTLdata[$checkpos]) && strpos($ignore, $this->OTLdata[$checkpos]['hex']) !== false) {
- $checkpos++;
- }
-
- if ($this->restrictToSyllable && isset($this->OTLdata[$checkpos]['syllable']) && $this->OTLdata[$checkpos]['syllable'] != $current_syllable) {
- return false;
- } else if (!isset($this->OTLdata[$checkpos]) || $this->OTLdata[$checkpos]['uni'] != $Lookahead[$i]) {
- return false;
- }
- }
- return $matched;
- }
- function checkContextMatchMultiple($Input, $Backtrack, $Lookahead, $ignore, $ptr, $class0excl = '', $bclass0excl = '', $lclass0excl = '')
- {
-
-
-
-
-
- $current_syllable = (isset($this->OTLdata[$ptr]['syllable']) ? $this->OTLdata[$ptr]['syllable'] : 0);
-
- $checkpos = $ptr;
- for ($i = 0; $i < count($Backtrack); $i++) {
- $checkpos--;
- while (isset($this->OTLdata[$checkpos]) && strpos($ignore, $this->OTLdata[$checkpos]['hex']) !== false) {
- $checkpos--;
- }
-
- if ($this->restrictToSyllable && isset($this->OTLdata[$checkpos]['syllable']) && $this->OTLdata[$checkpos]['syllable'] != $current_syllable) {
- return false;
- }
-
- else if (!$Backtrack[$i] && isset($this->OTLdata[$checkpos]) && strpos($bclass0excl, $this->OTLdata[$checkpos]['hex']) !== false) {
- return false;
- } else if (!isset($this->OTLdata[$checkpos]) || strpos($Backtrack[$i], $this->OTLdata[$checkpos]['hex']) === false) {
- return false;
- }
- }
-
- $matched = array(0 => $ptr);
- $checkpos = $ptr;
- for ($i = 1; $i < count($Input); $i++) {
- $checkpos++;
- while (isset($this->OTLdata[$checkpos]) && strpos($ignore, $this->OTLdata[$checkpos]['hex']) !== false) {
- $checkpos++;
- }
-
- if ($this->restrictToSyllable && isset($this->OTLdata[$checkpos]['syllable']) && $this->OTLdata[$checkpos]['syllable'] != $current_syllable) {
- return false;
- }
-
- else if (!$Input[$i] && isset($this->OTLdata[$checkpos]) && strpos($class0excl, $this->OTLdata[$checkpos]['hex']) === false) {
- $matched[] = $checkpos;
- } else if (isset($this->OTLdata[$checkpos]) && strpos($Input[$i], $this->OTLdata[$checkpos]['hex']) !== false) {
- $matched[] = $checkpos;
- } else {
- return false;
- }
- }
-
- for ($i = 0; $i < count($Lookahead); $i++) {
- $checkpos++;
- while (isset($this->OTLdata[$checkpos]) && strpos($ignore, $this->OTLdata[$checkpos]['hex']) !== false) {
- $checkpos++;
- }
-
- if ($this->restrictToSyllable && isset($this->OTLdata[$checkpos]['syllable']) && $this->OTLdata[$checkpos]['syllable'] != $current_syllable) {
- return false;
- }
-
- else if (!$Lookahead[$i] && isset($this->OTLdata[$checkpos]) && strpos($lclass0excl, $this->OTLdata[$checkpos]['hex']) !== false) {
- return false;
- } else if (!isset($this->OTLdata[$checkpos]) || strpos($Lookahead[$i], $this->OTLdata[$checkpos]['hex']) === false) {
- return false;
- }
- }
- return $matched;
- }
- function checkContextMatchMultipleUni($Input, $Backtrack, $Lookahead, $ignore, $ptr, $class0excl = array(), $bclass0excl = array(), $lclass0excl = array())
- {
-
-
-
-
-
- $current_syllable = (isset($this->OTLdata[$ptr]['syllable']) ? $this->OTLdata[$ptr]['syllable'] : 0);
-
- $checkpos = $ptr;
- for ($i = 0; $i < count($Backtrack); $i++) {
- $checkpos--;
- while (isset($this->OTLdata[$checkpos]) && strpos($ignore, $this->OTLdata[$checkpos]['hex']) !== false) {
- $checkpos--;
- }
-
- if ($this->restrictToSyllable && isset($this->OTLdata[$checkpos]['syllable']) && $this->OTLdata[$checkpos]['syllable'] != $current_syllable) {
- return false;
- }
-
- else if (!$Backtrack[$i] && isset($this->OTLdata[$checkpos]) && isset($bclass0excl[$this->OTLdata[$checkpos]['uni']])) {
- return false;
- } else if (!isset($this->OTLdata[$checkpos]) || !isset($Backtrack[$i][$this->OTLdata[$checkpos]['uni']])) {
- return false;
- }
- }
-
- $matched = array(0 => $ptr);
- $checkpos = $ptr;
- for ($i = 1; $i < count($Input); $i++) {
- $checkpos++;
- while (isset($this->OTLdata[$checkpos]) && strpos($ignore, $this->OTLdata[$checkpos]['hex']) !== false) {
- $checkpos++;
- }
-
- if ($this->restrictToSyllable && isset($this->OTLdata[$checkpos]['syllable']) && $this->OTLdata[$checkpos]['syllable'] != $current_syllable) {
- return false;
- }
-
- else if (!$Input[$i] && isset($this->OTLdata[$checkpos]) && !isset($class0excl[$this->OTLdata[$checkpos]['uni']])) {
- $matched[] = $checkpos;
- } else if (isset($this->OTLdata[$checkpos]) && isset($Input[$i][$this->OTLdata[$checkpos]['uni']])) {
- $matched[] = $checkpos;
- } else {
- return false;
- }
- }
-
- for ($i = 0; $i < count($Lookahead); $i++) {
- $checkpos++;
- while (isset($this->OTLdata[$checkpos]) && strpos($ignore, $this->OTLdata[$checkpos]['hex']) !== false) {
- $checkpos++;
- }
-
- if ($this->restrictToSyllable && isset($this->OTLdata[$checkpos]['syllable']) && $this->OTLdata[$checkpos]['syllable'] != $current_syllable) {
- return false;
- }
-
- else if (!$Lookahead[$i] && isset($this->OTLdata[$checkpos]) && isset($lclass0excl[$this->OTLdata[$checkpos]['uni']])) {
- return false;
- } else if (!isset($this->OTLdata[$checkpos]) || !isset($Lookahead[$i][$this->OTLdata[$checkpos]['uni']])) {
- return false;
- }
- }
- return $matched;
- }
- function _getClassDefinitionTable($offset)
- {
- if (isset($this->LuDataCache[$this->fontkey][$offset])) {
- $GlyphByClass = $this->LuDataCache[$this->fontkey][$offset];
- } else {
- $this->seek($offset);
- $ClassFormat = $this->read_ushort();
- $GlyphClass = array();
-
- if ($ClassFormat == 1) {
- $StartGlyph = $this->read_ushort();
- $GlyphCount = $this->read_ushort();
- for ($i = 0; $i < $GlyphCount; $i++) {
- $GlyphClass[$i]['startGlyphID'] = $StartGlyph + $i;
- $GlyphClass[$i]['endGlyphID'] = $StartGlyph + $i;
- $GlyphClass[$i]['class'] = $this->read_ushort();
- for ($g = $GlyphClass[$i]['startGlyphID']; $g <= $GlyphClass[$i]['endGlyphID']; $g++) {
- $GlyphByClass[$GlyphClass[$i]['class']][] = $this->glyphToChar($g);
- }
- }
- } else if ($ClassFormat == 2) {
- $tableCount = $this->read_ushort();
- for ($i = 0; $i < $tableCount; $i++) {
- $GlyphClass[$i]['startGlyphID'] = $this->read_ushort();
- $GlyphClass[$i]['endGlyphID'] = $this->read_ushort();
- $GlyphClass[$i]['class'] = $this->read_ushort();
- for ($g = $GlyphClass[$i]['startGlyphID']; $g <= $GlyphClass[$i]['endGlyphID']; $g++) {
- $GlyphByClass[$GlyphClass[$i]['class']][] = $this->glyphToChar($g);
- }
- }
- }
- ksort($GlyphByClass);
- $this->LuDataCache[$this->fontkey][$offset] = $GlyphByClass;
- }
- return $GlyphByClass;
- }
- function count_bits($n)
- {
- for ($c = 0; $n; $c++) {
- $n &= $n - 1;
- }
- return $c;
- }
- function _getValueRecord($ValueFormat)
- {
-
- $vra = array();
-
- if (($ValueFormat & 0x0001) == 0x0001) {
- $vra['XPlacement'] = $this->read_short();
- }
-
- if (($ValueFormat & 0x0002) == 0x0002) {
- $vra['YPlacement'] = $this->read_short();
- }
-
- if (($ValueFormat & 0x0004) == 0x0004) {
- $vra['XAdvance'] = $this->read_short();
- }
-
- if (($ValueFormat & 0x0008) == 0x0008) {
- $this->read_short();
- }
-
- if (($ValueFormat & 0x0010) == 0x0010) {
- $this->read_ushort();
- }
-
- if (($ValueFormat & 0x0020) == 0x0020) {
- $this->read_ushort();
- }
-
- if (($ValueFormat & 0x0040) == 0x0040) {
- $this->read_ushort();
- }
-
- if (($ValueFormat & 0x0080) == 0x0080) {
- $this->read_ushort();
- }
- return $vra;
- }
- function _getAnchorTable($offset = 0)
- {
- if ($offset) {
- $this->seek($offset);
- }
- $AnchorFormat = $this->read_ushort();
- $XCoordinate = $this->read_short();
- $YCoordinate = $this->read_short();
-
- return array($XCoordinate, $YCoordinate);
- }
- function _getMarkRecord($offset, $MarkPos)
- {
- $this->seek($offset);
- $MarkCount = $this->read_ushort();
- $this->skip($MarkPos * 4);
- $Class = $this->read_ushort();
- $MarkAnchor = $offset + $this->read_ushort();
- list($x, $y) = $this->_getAnchorTable($MarkAnchor);
- $MarkRecord = array('Class' => $Class, 'AnchorX' => $x, 'AnchorY' => $y);
- return $MarkRecord;
- }
- function _getGCOMignoreString($flag, $MarkFilteringSet)
- {
-
-
-
- $str = "";
- $ignoreflag = 0;
-
- if ($flag & 0xFF00) {
-
-
- $MarkAttachmentType = $flag >> 8;
- $ignoreflag = $flag;
- $str = $this->MarkAttachmentType[$MarkAttachmentType];
- }
-
- if ($flag & 0x0010) {
- throw new MpdfException("This font [" . $this->fontkey . "] contains MarkGlyphSets - Not tested yet");
-
- if ($MarkFilteringSet == '')
- throw new MpdfException("This font [" . $this->fontkey . "] contains MarkGlyphSets - but MarkFilteringSet not set");
- $str = $this->MarkGlyphSets[$MarkFilteringSet];
- }
-
-
- if (($flag & 0x0008) == 0x0008 && ($flag & 0xFF00) == 0) {
- $ignoreflag = 8;
- $str = $this->GlyphClassMarks;
- }
-
- if (($flag & 0x0004) == 0x0004) {
- $ignoreflag += 4;
- if ($str) {
- $str .= "|";
- }
- $str .= $this->GlyphClassLigatures;
- }
-
- if (($flag & 0x0002) == 0x0002) {
- $ignoreflag += 2;
- if ($str) {
- $str .= "|";
- }
- $str .= $this->GlyphClassBases;
- }
- if ($str) {
- return "((?:(?:" . $str . "))*)";
- } else
- return "()";
- }
- function _checkGCOMignore($flag, $glyph, $MarkFilteringSet)
- {
- $ignore = false;
-
- if (($flag & 0x0008 && ($flag & 0xFF00) == 0) && strpos($this->GlyphClassMarks, $glyph)) {
- $ignore = true;
- }
- if (($flag & 0x0004) && strpos($this->GlyphClassLigatures, $glyph)) {
- $ignore = true;
- }
- if (($flag & 0x0002) && strpos($this->GlyphClassBases, $glyph)) {
- $ignore = true;
- }
-
- if ($flag & 0xFF00) {
-
-
- if (strpos($this->MarkAttachmentType[($flag >> 8)], $glyph)) {
- $ignore = true;
- }
- }
-
- if (($flag & 0x0010) && strpos($this->MarkGlyphSets[$MarkFilteringSet], $glyph)) {
- $ignore = true;
- }
- return $ignore;
- }
-
- function _bidiSort($ta, $str = '', $dir, &$chunkOTLdata, $useGPOS)
- {
- $pel = 0;
- $maxlevel = 0;
- $numchars = count($chunkOTLdata['char_data']);
-
- if ($dir == 'rtl') {
- $pel = 1;
- } else {
- $pel = 0;
- }
-
-
- $cel = $pel;
-
- $dos = -1;
- $remember = array();
-
- $chardata = Array();
-
-
- for ($i = 0; $i < $numchars; ++$i) {
- if ($chunkOTLdata['char_data'][$i]['uni'] == 8235) {
-
-
-
- $next_level = $cel + ($cel % 2) + 1;
- if ($next_level < 62) {
- $remember[] = array('num' => 8235, 'cel' => $cel, 'dos' => $dos);
- $cel = $next_level;
- $dos = -1;
- }
- } else if ($chunkOTLdata['char_data'][$i]['uni'] == 8234) {
-
-
-
- $next_level = $cel + 2 - ($cel % 2);
- if ($next_level < 62) {
- $remember[] = array('num' => 8234, 'cel' => $cel, 'dos' => $dos);
- $cel = $next_level;
- $dos = -1;
- }
- } else if ($chunkOTLdata['char_data'][$i]['uni'] == 8238) {
-
-
-
- $next_level = $cel + ($cel % 2) + 1;
- if ($next_level < 62) {
- $remember[] = array('num' => 8238, 'cel' => $cel, 'dos' => $dos);
- $cel = $next_level;
- $dos = UCDN::BIDI_CLASS_R;
- }
- } else if ($chunkOTLdata['char_data'][$i]['uni'] == 8237) {
-
-
-
- $next_level = $cel + 2 - ($cel % 2);
- if ($next_level < 62) {
- $remember[] = array('num' => 8237, 'cel' => $cel, 'dos' => $dos);
- $cel = $next_level;
- $dos = UCDN::BIDI_CLASS_L;
- }
- } else if ($chunkOTLdata['char_data'][$i]['uni'] == 8236) {
-
- if (count($remember)) {
- $last = count($remember) - 1;
- if (($remember[$last]['num'] == 8235) || ($remember[$last]['num'] == 8234) || ($remember[$last]['num'] == 8238) ||
- ($remember[$last]['num'] == 8237)) {
- $match = array_pop($remember);
- $cel = $match['cel'];
- $dos = $match['dos'];
- }
- }
- } else if ($chunkOTLdata['char_data'][$i]['uni'] == 10) {
-
- $cel = $pel;
- $dos = -1;
- $remember = array();
- } else {
-
-
-
- if ($dos != -1) {
- $chardir = $dos;
- } else {
- $chardir = $chunkOTLdata['char_data'][$i]['bidi_class'];
- }
-
- if (isset($chunkOTLdata['GPOSinfo'][$i])) {
- $gpos = $chunkOTLdata['GPOSinfo'][$i];
- } else
- $gpos = '';
- $chardata[] = array('char' => $chunkOTLdata['char_data'][$i]['uni'], 'level' => $cel, 'type' => $chardir, 'group' => $chunkOTLdata['group']{$i}, 'GPOSinfo' => $gpos);
- }
- }
- $numchars = count($chardata);
-
-
-
-
-
-
-
-
- $prelevel = $pel;
- $postlevel = $pel;
- $cel = $prelevel;
- for ($i = 0; $i < $numchars; ++$i) {
- $level = $chardata[$i]['level'];
- if ($i == 0) {
- $left = $prelevel;
- } else {
- $left = $chardata[$i - 1]['level'];
- }
- if ($i == ($numchars - 1)) {
- $right = $postlevel;
- } else {
- $right = $chardata[$i + 1]['level'];
- }
- $chardata[$i]['sor'] = max($left, $level) % 2 ? UCDN::BIDI_CLASS_R : UCDN::BIDI_CLASS_L;
- $chardata[$i]['eor'] = max($right, $level) % 2 ? UCDN::BIDI_CLASS_R : UCDN::BIDI_CLASS_L;
- }
-
-
-
-
- for ($i = 0; $i < $numchars; ++$i) {
- if ($chardata[$i]['type'] == UCDN::BIDI_CLASS_NSM) {
- if ($i == 0 || $chardata[$i]['level'] != $chardata[$i - 1]['level']) {
- $chardata[$i]['type'] = $chardata[$i]['sor'];
- } else {
- $chardata[$i]['type'] = $chardata[($i - 1)]['type'];
- }
- }
- }
-
- $prevlevel = -1;
- $levcount = 0;
- for ($i = 0; $i < $numchars; ++$i) {
- if ($chardata[$i]['type'] == UCDN::BIDI_CLASS_EN) {
- $found = false;
- for ($j = $levcount; $j >= 0; $j--) {
- if ($chardata[$j]['type'] == UCDN::BIDI_CLASS_AL) {
- $chardata[$i]['type'] = UCDN::BIDI_CLASS_AN;
- $found = true;
- break;
- } else if (($chardata[$j]['type'] == UCDN::BIDI_CLASS_L) || ($chardata[$j]['type'] == UCDN::BIDI_CLASS_R)) {
- $found = true;
- break;
- }
- }
- }
- if ($chardata[$i]['level'] != $prevlevel) {
- $levcount = 0;
- } else {
- ++$levcount;
- }
- $prevlevel = $chardata[$i]['level'];
- }
-
- for ($i = 0; $i < $numchars; ++$i) {
- if ($chardata[$i]['type'] == UCDN::BIDI_CLASS_AL) {
- $chardata[$i]['type'] = UCDN::BIDI_CLASS_R;
- }
- }
-
- for ($i = 1; $i < $numchars; ++$i) {
- if (($i + 1) < $numchars && $chardata[($i)]['level'] == $chardata[($i + 1)]['level'] && $chardata[($i)]['level'] == $chardata[($i - 1)]['level']) {
- if ($chardata[$i]['type'] == UCDN::BIDI_CLASS_ES && $chardata[($i - 1)]['type'] == UCDN::BIDI_CLASS_EN && $chardata[($i + 1)]['type'] == UCDN::BIDI_CLASS_EN) {
- $chardata[$i]['type'] = UCDN::BIDI_CLASS_EN;
- } else if ($chardata[$i]['type'] == UCDN::BIDI_CLASS_CS && $chardata[($i - 1)]['type'] == UCDN::BIDI_CLASS_EN && $chardata[($i + 1)]['type'] == UCDN::BIDI_CLASS_EN) {
- $chardata[$i]['type'] = UCDN::BIDI_CLASS_EN;
- } else if ($chardata[$i]['type'] == UCDN::BIDI_CLASS_CS && $chardata[($i - 1)]['type'] == UCDN::BIDI_CLASS_AN && $chardata[($i + 1)]['type'] == UCDN::BIDI_CLASS_AN) {
- $chardata[$i]['type'] = UCDN::BIDI_CLASS_AN;
- }
- }
- }
-
- for ($i = 0; $i < $numchars; ++$i) {
- if ($chardata[$i]['type'] == UCDN::BIDI_CLASS_ET) {
- if ($i > 0 && $chardata[($i - 1)]['type'] == UCDN::BIDI_CLASS_EN && $chardata[($i)]['level'] == $chardata[($i - 1)]['level']) {
- $chardata[$i]['type'] = UCDN::BIDI_CLASS_EN;
- } else {
- $j = $i + 1;
- while ($j < $numchars && $chardata[$j]['level'] == $chardata[$i]['level']) {
- if ($chardata[$j]['type'] == UCDN::BIDI_CLASS_EN) {
- $chardata[$i]['type'] = UCDN::BIDI_CLASS_EN;
- break;
- } else if ($chardata[$j]['type'] != UCDN::BIDI_CLASS_ET) {
- break;
- }
- ++$j;
- }
- }
- }
- }
-
- for ($i = 0; $i < $numchars; ++$i) {
- if (($chardata[$i]['type'] == UCDN::BIDI_CLASS_ET) || ($chardata[$i]['type'] == UCDN::BIDI_CLASS_ES) || ($chardata[$i]['type'] == UCDN::BIDI_CLASS_CS)) {
- $chardata[$i]['type'] = UCDN::BIDI_CLASS_ON;
- }
- }
-
- for ($i = 0; $i < $numchars; ++$i) {
- if ($chardata[$i]['type'] == UCDN::BIDI_CLASS_EN) {
- if ($i == 0) {
- if ($chardata[$i]['sor'] == UCDN::BIDI_CLASS_L)
- $chardata[$i]['type'] = $chardata[$i]['sor'];
- }
- else {
- for ($j = $i - 1; $j >= 0; $j--) {
- if ($chardata[$j]['level'] != $chardata[$i]['level']) {
- if ($chardata[$j + 1]['sor'] == UCDN::BIDI_CLASS_L)
- $chardata[$i]['type'] = $chardata[$j + 1]['sor'];
- break;
- }
- else if ($chardata[$j]['type'] == UCDN::BIDI_CLASS_L) {
- $chardata[$i]['type'] = UCDN::BIDI_CLASS_L;
- break;
- } else if ($chardata[$j]['type'] == UCDN::BIDI_CLASS_R) {
- break;
- }
- }
- }
- }
- }
-
- for ($i = 0; $i < $numchars; ++$i) {
- if ($chardata[$i]['type'] == UCDN::BIDI_CLASS_ON || $chardata[$i]['type'] == UCDN::BIDI_CLASS_WS) {
- $left = -1;
-
- if ($i == 0) {
- $left = $chardata[($i)]['sor'];
- } else if ($chardata[($i - 1)]['level'] != $chardata[($i)]['level']) {
- $left = $chardata[($i)]['sor'];
- } else if ($chardata[($i - 1)]['type'] == UCDN::BIDI_CLASS_L) {
- $left = UCDN::BIDI_CLASS_L;
- } else if ($chardata[($i - 1)]['type'] == UCDN::BIDI_CLASS_R || $chardata[($i - 1)]['type'] == UCDN::BIDI_CLASS_EN || $chardata[($i - 1)]['type'] == UCDN::BIDI_CLASS_AN) {
- $left = UCDN::BIDI_CLASS_R;
- }
-
- $right = -1;
- $j = $i;
-
- while (($chardata[$j]['type'] == UCDN::BIDI_CLASS_ON || $chardata[$j]['type'] == UCDN::BIDI_CLASS_WS) && $j <= ($numchars - 1)) {
- if ($j == ($numchars - 1)) {
- $right = $chardata[($j)]['eor'];
- break;
- } else if ($chardata[($j + 1)]['level'] != $chardata[($j)]['level']) {
- $right = $chardata[($j)]['eor'];
- break;
- } else if ($chardata[($j + 1)]['type'] == UCDN::BIDI_CLASS_L) {
- $right = UCDN::BIDI_CLASS_L;
- break;
- } else if ($chardata[($j + 1)]['type'] == UCDN::BIDI_CLASS_R || $chardata[($j + 1)]['type'] == UCDN::BIDI_CLASS_EN || $chardata[($j + 1)]['type'] == UCDN::BIDI_CLASS_AN) {
- $right = UCDN::BIDI_CLASS_R;
- break;
- }
- $j++;
- }
- if ($left > -1 && $left == $right) {
- $chardata[$i]['orig_type'] = $chardata[$i]['type'];
- $chardata[$i]['type'] = $left;
- }
- }
- }
-
- for ($i = 0; $i < $numchars; ++$i) {
- if ($chardata[$i]['type'] == UCDN::BIDI_CLASS_ON || $chardata[$i]['type'] == UCDN::BIDI_CLASS_WS) {
- $chardata[$i]['type'] = ($chardata[$i]['level'] % 2) ? UCDN::BIDI_CLASS_R : UCDN::BIDI_CLASS_L;
- $chardata[$i]['orig_type'] = $chardata[$i]['type'];
- }
- }
-
-
- for ($i = 0; $i < $numchars; ++$i) {
- $odd = $chardata[$i]['level'] % 2;
- if ($odd) {
- if (($chardata[$i]['type'] == UCDN::BIDI_CLASS_L) || ($chardata[$i]['type'] == UCDN::BIDI_CLASS_AN) || ($chardata[$i]['type'] == UCDN::BIDI_CLASS_EN)) {
- $chardata[$i]['level'] += 1;
- }
- } else {
- if ($chardata[$i]['type'] == UCDN::BIDI_CLASS_R) {
- $chardata[$i]['level'] += 1;
- } else if (($chardata[$i]['type'] == UCDN::BIDI_CLASS_AN) || ($chardata[$i]['type'] == UCDN::BIDI_CLASS_EN)) {
- $chardata[$i]['level'] += 2;
- }
- }
- $maxlevel = max($chardata[$i]['level'], $maxlevel);
- }
-
-
-
-
-
-
-
- for ($i = ($numchars - 1); $i > 0; $i--) {
- if ($chardata[$i]['type'] == UCDN::BIDI_CLASS_WS || (isset($chardata[$i]['orig_type']) && $chardata[$i]['orig_type'] == UCDN::BIDI_CLASS_WS)) {
- $chardata[$i]['level'] = $pel;
- } else {
- break;
- }
- }
-
- for ($j = $maxlevel; $j > 0; $j--) {
- $ordarray = array();
- $revarr = array();
- $onlevel = false;
- for ($i = 0; $i < $numchars; ++$i) {
- if ($chardata[$i]['level'] >= $j) {
- $onlevel = true;
-
- if (isset(UCDN::$mirror_pairs[$chardata[$i]['char']]) && $chardata[$i]['type'] == UCDN::BIDI_CLASS_R) {
- $chardata[$i]['char'] = UCDN::$mirror_pairs[$chardata[$i]['char']];
- }
- $revarr[] = $chardata[$i];
- } else {
- if ($onlevel) {
- $revarr = array_reverse($revarr);
- $ordarray = array_merge($ordarray, $revarr);
- $revarr = Array();
- $onlevel = false;
- }
- $ordarray[] = $chardata[$i];
- }
- }
- if ($onlevel) {
- $revarr = array_reverse($revarr);
- $ordarray = array_merge($ordarray, $revarr);
- }
- $chardata = $ordarray;
- }
- $group = '';
- $e = '';
- $GPOS = array();
- $cctr = 0;
- $rtl_content = 0x0;
- foreach ($chardata as $cd) {
- $e.=code2utf($cd['char']);
- $group .= $cd['group'];
- if ($useGPOS && is_array($cd['GPOSinfo'])) {
- $GPOS[$cctr] = $cd['GPOSinfo'];
- $GPOS[$cctr]['wDir'] = ($cd['level'] % 2) ? 'RTL' : 'LTR';
- }
- if ($cd['type'] == UCDN::BIDI_CLASS_L) {
- $rtl_content |= 1;
- } else if ($cd['type'] == UCDN::BIDI_CLASS_R) {
- $rtl_content |= 2;
- }
- $cctr++;
- }
- $chunkOTLdata['group'] = $group;
- if ($useGPOS) {
- $chunkOTLdata['GPOSinfo'] = $GPOS;
- }
- return array($e, $rtl_content);
- }
- function _bidiPrepare(&$para, $dir)
- {
-
- $pel = 0;
- if ($dir == 'rtl') {
- $pel = 1;
- }
-
-
- $cel = $pel;
-
- $dos = -1;
- $remember = array();
- $controlchars = false;
- $strongrtl = false;
- $diid = 0;
- $dictr = 0;
-
-
- $numchunks = count($para);
- for ($nc = 0; $nc < $numchunks; $nc++) {
- $chunkOTLdata = & $para[$nc][18];
- $numchars = count($chunkOTLdata['char_data']);
- for ($i = 0; $i < $numchars; ++$i) {
- if ($chunkOTLdata['char_data'][$i]['uni'] == 8235) {
-
-
-
- $next_level = $cel + ($cel % 2) + 1;
- if ($next_level < 62) {
- $remember[] = array('num' => 8235, 'cel' => $cel, 'dos' => $dos);
- $cel = $next_level;
- $dos = -1;
- $controlchars = true;
- }
- } else if ($chunkOTLdata['char_data'][$i]['uni'] == 8234) {
-
-
-
- $next_level = $cel + 2 - ($cel % 2);
- if ($next_level < 62) {
- $remember[] = array('num' => 8234, 'cel' => $cel, 'dos' => $dos);
- $cel = $next_level;
- $dos = -1;
- $controlchars = true;
- }
- } else if ($chunkOTLdata['char_data'][$i]['uni'] == 8238) {
-
-
-
- $next_level = $cel + ($cel % 2) + 1;
- if ($next_level < 62) {
- $remember[] = array('num' => 8238, 'cel' => $cel, 'dos' => $dos);
- $cel = $next_level;
- $dos = UCDN::BIDI_CLASS_R;
- $controlchars = true;
- }
- } else if ($chunkOTLdata['char_data'][$i]['uni'] == 8237) {
-
-
-
- $next_level = $cel + 2 - ($cel % 2);
- if ($next_level < 62) {
- $remember[] = array('num' => 8237, 'cel' => $cel, 'dos' => $dos);
- $cel = $next_level;
- $dos = UCDN::BIDI_CLASS_L;
- $controlchars = true;
- }
- } else if ($chunkOTLdata['char_data'][$i]['uni'] == 8236) {
-
- if (count($remember)) {
- $last = count($remember) - 1;
- if (($remember[$last]['num'] == 8235) || ($remember[$last]['num'] == 8234) || ($remember[$last]['num'] == 8238) ||
- ($remember[$last]['num'] == 8237)) {
- $match = array_pop($remember);
- $cel = $match['cel'];
- $dos = $match['dos'];
- }
- }
- } else if ($chunkOTLdata['char_data'][$i]['uni'] == 8294 || $chunkOTLdata['char_data'][$i]['uni'] == 8295 ||
- $chunkOTLdata['char_data'][$i]['uni'] == 8296) {
-
-
-
-
- if ($dos != -1) {
- $chardir = $dos;
- } else {
- $chardir = $chunkOTLdata['char_data'][$i]['bidi_class'];
- }
- $chunkOTLdata['char_data'][$i]['level'] = $cel;
- $chunkOTLdata['char_data'][$i]['type'] = $chardir;
- $chunkOTLdata['char_data'][$i]['diid'] = $diid;
- $fsi = '';
-
- if ($chunkOTLdata['char_data'][$i]['uni'] == 8296) {
- $lvl = 0;
- $nc2 = $nc;
- $i2 = $i;
- while (!($nc2 == ($numchunks - 1) && $i2 == ((count($para[$nc2][18]['char_data'])) - 1))) {
- $i2++;
- if ($i2 >= count($para[$nc2][18]['char_data'])) {
- $nc2++;
- $i2 = 0;
- }
- if ($lvl > 0) {
- continue;
- }
- if ($para[$nc2][18]['char_data'][$i2]['uni'] == 8294 || $para[$nc2][18]['char_data'][$i2]['uni'] == 8295 || $para[$nc2][18]['char_data'][$i2]['uni'] == 8296) {
- $lvl++;
- continue;
- }
- if ($para[$nc2][18]['char_data'][$i2]['uni'] == 8297) {
- $lvl--;
- if ($lvl < 0) {
- break;
- }
- }
- if ($para[$nc2][18]['char_data'][$i2]['bidi_class'] === UCDN::BIDI_CLASS_L || $para[$nc2][18]['char_data'][$i2]['bidi_class'] == UCDN::BIDI_CLASS_AL || $para[$nc2][18]['char_data'][$i2]['bidi_class'] === UCDN::BIDI_CLASS_R) {
- $fsi = $para[$nc2][18]['char_data'][$i2]['bidi_class'];
- break;
- }
- }
-
- if (!$fsi && $fsi !== 0) {
- if ($pel == 1) {
- $fsi = UCDN::BIDI_CLASS_R;
- } else {
- $fsi = UCDN::BIDI_CLASS_L;
- }
- }
- }
- if ($chunkOTLdata['char_data'][$i]['uni'] == 8294 || $fsi === UCDN::BIDI_CLASS_L) {
-
- $next_level = $cel + 2 - ($cel % 2);
- } else if ($chunkOTLdata['char_data'][$i]['uni'] == 8295 || $fsi == UCDN::BIDI_CLASS_R || $fsi == UCDN::BIDI_CLASS_AL) {
-
- $next_level = $cel + ($cel % 2) + 1;
- }
-
-
- $remember[] = array('num' => $chunkOTLdata['char_data'][$i]['uni'], 'cel' => $cel, 'dos' => $dos, 'diid' => $diid);
- $cel = $next_level;
- $dos = -1;
- $diid = ++$dictr;
- $controlchars = true;
- } else if ($chunkOTLdata['char_data'][$i]['uni'] == 8297) {
-
-
- while (count($remember)) {
- $last = count($remember) - 1;
- if (($remember[$last]['num'] == 8294) || ($remember[$last]['num'] == 8295) || ($remember[$last]['num'] == 8296)) {
- $match = array_pop($remember);
- $cel = $match['cel'];
- $dos = $match['dos'];
- $diid = $match['diid'];
- break;
- }
-
- else if (($remember[$last]['num'] == 8235) || ($remember[$last]['num'] == 8234) || ($remember[$last]['num'] == 8238) ||
- ($remember[$last]['num'] == 8237)) {
- $match = array_pop($remember);
- }
- }
-
-
- if ($dos != -1) {
- $chardir = $dos;
- } else {
- $chardir = $chunkOTLdata['char_data'][$i]['bidi_class'];
- }
- $chunkOTLdata['char_data'][$i]['level'] = $cel;
- $chunkOTLdata['char_data'][$i]['type'] = $chardir;
- $chunkOTLdata['char_data'][$i]['diid'] = $diid;
- $controlchars = true;
- } else if ($chunkOTLdata['char_data'][$i]['uni'] == 10) {
-
- $cel = $pel;
- $dos = -1;
- $remember = array();
- } else {
-
-
-
- if ($dos != -1) {
- $chardir = $dos;
- } else {
- $chardir = $chunkOTLdata['char_data'][$i]['bidi_class'];
- if ($chardir == UCDN::BIDI_CLASS_R || $chardir == UCDN::BIDI_CLASS_AL) {
- $strongrtl = true;
- }
- }
- $chunkOTLdata['char_data'][$i]['level'] = $cel;
- $chunkOTLdata['char_data'][$i]['type'] = $chardir;
- $chunkOTLdata['char_data'][$i]['diid'] = $diid;
- }
- }
-
-
-
- if ($controlchars) {
- $this->removeChar($para[$nc][0], $para[$nc][18], "\xe2\x80\xaa");
- $this->removeChar($para[$nc][0], $para[$nc][18], "\xe2\x80\xab");
- $this->removeChar($para[$nc][0], $para[$nc][18], "\xe2\x80\xac");
- $this->removeChar($para[$nc][0], $para[$nc][18], "\xe2\x80\xad");
- $this->removeChar($para[$nc][0], $para[$nc][18], "\xe2\x80\xae");
- preg_replace("/\x{202a}-\x{202e}/u", '', $para[$nc][0]);
- }
- }
-
- $numchunks = count($para);
- for ($nc = ($numchunks - 1); $nc >= 0; $nc--) {
- if (count($para[$nc][18]['char_data']) == 0) {
- array_splice($para, $nc, 1);
- }
- }
- if ($dir != 'rtl' && !$strongrtl && !$controlchars) {
- return;
- }
- $numchunks = count($para);
-
-
-
-
- for ($ir = 0; $ir <= $dictr; $ir++) {
- $prelevel = $pel;
- $postlevel = $pel;
- $firstchar = true;
- for ($nc = 0; $nc < $numchunks; $nc++) {
- $chardata = & $para[$nc][18]['char_data'];
- $numchars = count($chardata);
- for ($i = 0; $i < $numchars; ++$i) {
- if (!isset($chardata[$i]['diid']) || $chardata[$i]['diid'] != $ir) {
- continue;
- }
- $right = $postlevel;
- $nc2 = $nc;
- $i2 = $i;
- while (!($nc2 == ($numchunks - 1) && $i2 == ((count($para[$nc2][18]['char_data'])) - 1))) {
- $i2++;
- if ($i2 >= count($para[$nc2][18]['char_data'])) {
- $nc2++;
- $i2 = 0;
- }
- if (isset($para[$nc2][18]['char_data'][$i2]['diid']) && $para[$nc2][18]['char_data'][$i2]['diid'] == $ir) {
- $right = $para[$nc2][18]['char_data'][$i2]['level'];
- break;
- }
- }
- $level = $chardata[$i]['level'];
- if ($firstchar || $level != $prelevel) {
- $chardata[$i]['sor'] = max($prelevel, $level) % 2 ? UCDN::BIDI_CLASS_R : UCDN::BIDI_CLASS_L;
- }
- if (($nc == ($numchunks - 1) && $i == ($numchars - 1)) || $level != $right) {
- $chardata[$i]['eor'] = max($right, $level) % 2 ? UCDN::BIDI_CLASS_R : UCDN::BIDI_CLASS_L;
- }
- $prelevel = $level;
- $firstchar = false;
- }
- }
- }
-
-
-
-
- for ($ir = 0; $ir <= $dictr; $ir++) {
- $prevtype = 0;
- for ($nc = 0; $nc < $numchunks; $nc++) {
- $chardata = & $para[$nc][18]['char_data'];
- $numchars = count($chardata);
- for ($i = 0; $i < $numchars; ++$i) {
- if (!isset($chardata[$i]['diid']) || $chardata[$i]['diid'] != $ir) {
- continue;
- }
- if ($chardata[$i]['type'] == UCDN::BIDI_CLASS_NSM) {
- if (isset($chardata[$i]['sor'])) {
- $chardata[$i]['type'] = $chardata[$i]['sor'];
- } else {
- $chardata[$i]['type'] = $prevtype;
- }
- }
- $prevtype = $chardata[$i]['type'];
- }
- }
- }
-
- for ($ir = 0; $ir <= $dictr; $ir++) {
- $laststrongtype = -1;
- for ($nc = 0; $nc < $numchunks; $nc++) {
- $chardata = & $para[$nc][18]['char_data'];
- $numchars = count($chardata);
- for ($i = 0; $i < $numchars; ++$i) {
- if (!isset($chardata[$i]['diid']) || $chardata[$i]['diid'] != $ir) {
- continue;
- }
- if (isset($chardata[$i]['sor'])) {
- $laststrongtype = $chardata[$i]['sor'];
- }
- if ($chardata[$i]['type'] == UCDN::BIDI_CLASS_EN && $laststrongtype == UCDN::BIDI_CLASS_AL) {
- $chardata[$i]['type'] = UCDN::BIDI_CLASS_AN;
- }
- if ($chardata[$i]['type'] == UCDN::BIDI_CLASS_L || $chardata[$i]['type'] == UCDN::BIDI_CLASS_R || $chardata[$i]['type'] == UCDN::BIDI_CLASS_AL) {
- $laststrongtype = $chardata[$i]['type'];
- }
- }
- }
- }
-
- for ($nc = 0; $nc < $numchunks; $nc++) {
- $chardata = & $para[$nc][18]['char_data'];
- $numchars = count($chardata);
- for ($i = 0; $i < $numchars; ++$i) {
- if (isset($chardata[$i]['type']) && $chardata[$i]['type'] == UCDN::BIDI_CLASS_AL) {
- $chardata[$i]['type'] = UCDN::BIDI_CLASS_R;
- }
- }
- }
-
- for ($ir = 0; $ir <= $dictr; $ir++) {
- $prevtype = -1;
- $nexttype = -1;
- for ($nc = 0; $nc < $numchunks; $nc++) {
- $chardata = & $para[$nc][18]['char_data'];
- $numchars = count($chardata);
- for ($i = 0; $i < $numchars; ++$i) {
- if (!isset($chardata[$i]['diid']) || $chardata[$i]['diid'] != $ir) {
- continue;
- }
-
- $nexttype = -1;
- $nc2 = $nc;
- $i2 = $i;
- while (!($nc2 == ($numchunks - 1) && $i2 == ((count($para[$nc2][18]['char_data'])) - 1))) {
- $i2++;
- if ($i2 >= count($para[$nc2][18]['char_data'])) {
- $nc2++;
- $i2 = 0;
- }
- if (isset($para[$nc2][18]['char_data'][$i2]['diid']) && $para[$nc2][18]['char_data'][$i2]['diid'] == $ir) {
- $nexttype = $para[$nc2][18]['char_data'][$i2]['type'];
- break;
- }
- }
- if (!isset($chardata[$i]['sor']) && !isset($chardata[$i]['eor'])) {
- if ($chardata[$i]['type'] == UCDN::BIDI_CLASS_ES && $prevtype == UCDN::BIDI_CLASS_EN && $nexttype == UCDN::BIDI_CLASS_EN) {
- $chardata[$i]['type'] = UCDN::BIDI_CLASS_EN;
- } else if ($chardata[$i]['type'] == UCDN::BIDI_CLASS_CS && $prevtype == UCDN::BIDI_CLASS_EN && $nexttype == UCDN::BIDI_CLASS_EN) {
- $chardata[$i]['type'] = UCDN::BIDI_CLASS_EN;
- } else if ($chardata[$i]['type'] == UCDN::BIDI_CLASS_CS && $prevtype == UCDN::BIDI_CLASS_AN && $nexttype == UCDN::BIDI_CLASS_AN) {
- $chardata[$i]['type'] = UCDN::BIDI_CLASS_AN;
- }
- }
- $prevtype = $chardata[$i]['type'];
- }
- }
- }
-
- for ($ir = 0; $ir <= $dictr; $ir++) {
- $prevtype = -1;
- $nexttype = -1;
- for ($nc = 0; $nc < $numchunks; $nc++) {
- $chardata = & $para[$nc][18]['char_data'];
- $numchars = count($chardata);
- for ($i = 0; $i < $numchars; ++$i) {
- if (!isset($chardata[$i]['diid']) || $chardata[$i]['diid'] != $ir) {
- continue;
- }
- if (isset($chardata[$i]['sor'])) {
- $prevtype = $chardata[$i]['sor'];
- }
- if ($chardata[$i]['type'] == UCDN::BIDI_CLASS_ET) {
- if ($prevtype == UCDN::BIDI_CLASS_EN) {
- $chardata[$i]['type'] = UCDN::BIDI_CLASS_EN;
- } else if (!isset($chardata[$i]['eor'])) {
- $nexttype = -1;
- $nc2 = $nc;
- $i2 = $i;
- while (!($nc2 == ($numchunks - 1) && $i2 == ((count($para[$nc2][18]['char_data'])) - 1))) {
- $i2++;
- if ($i2 >= count($para[$nc2][18]['char_data'])) {
- $nc2++;
- $i2 = 0;
- }
- if ($para[$nc2][18]['char_data'][$i2]['diid'] != $ir) {
- continue;
- }
- $nexttype = $para[$nc2][18]['char_data'][$i2]['type'];
- if (isset($para[$nc2][18]['char_data'][$i2]['sor'])) {
- break;
- }
- if ($nexttype == UCDN::BIDI_CLASS_EN) {
- $chardata[$i]['type'] = UCDN::BIDI_CLASS_EN;
- break;
- } else if ($nexttype != UCDN::BIDI_CLASS_ET) {
- break;
- }
- }
- }
- }
- $prevtype = $chardata[$i]['type'];
- }
- }
- }
-
- for ($nc = 0; $nc < $numchunks; $nc++) {
- $chardata = & $para[$nc][18]['char_data'];
- $numchars = count($chardata);
- for ($i = 0; $i < $numchars; ++$i) {
- if (isset($chardata[$i]['type']) && (($chardata[$i]['type'] == UCDN::BIDI_CLASS_ET) || ($chardata[$i]['type'] == UCDN::BIDI_CLASS_ES) || ($chardata[$i]['type'] == UCDN::BIDI_CLASS_CS))) {
- $chardata[$i]['type'] = UCDN::BIDI_CLASS_ON;
- }
- }
- }
-
- for ($ir = 0; $ir <= $dictr; $ir++) {
- $laststrongtype = -1;
- for ($nc = 0; $nc < $numchunks; $nc++) {
- $chardata = & $para[$nc][18]['char_data'];
- $numchars = count($chardata);
- for ($i = 0; $i < $numchars; ++$i) {
- if (!isset($chardata[$i]['diid']) || $chardata[$i]['diid'] != $ir) {
- continue;
- }
- if (isset($chardata[$i]['sor'])) {
- $laststrongtype = $chardata[$i]['sor'];
- }
- if (isset($chardata[$i]['type']) && $chardata[$i]['type'] == UCDN::BIDI_CLASS_EN && $laststrongtype == UCDN::BIDI_CLASS_L) {
- $chardata[$i]['type'] = UCDN::BIDI_CLASS_L;
- }
- if (isset($chardata[$i]['type']) && ($chardata[$i]['type'] == UCDN::BIDI_CLASS_L || $chardata[$i]['type'] == UCDN::BIDI_CLASS_R || $chardata[$i]['type'] == UCDN::BIDI_CLASS_AL)) {
- $laststrongtype = $chardata[$i]['type'];
- }
- }
- }
- }
-
- for ($ir = 0; $ir <= $dictr; $ir++) {
- $laststrongtype = -1;
- for ($nc = 0; $nc < $numchunks; $nc++) {
- $chardata = & $para[$nc][18]['char_data'];
- $numchars = count($chardata);
- for ($i = 0; $i < $numchars; ++$i) {
- if (!isset($chardata[$i]['diid']) || $chardata[$i]['diid'] != $ir) {
- continue;
- }
- if (isset($chardata[$i]['sor'])) {
- $laststrongtype = $chardata[$i]['sor'];
- }
- if ($chardata[$i]['type'] == UCDN::BIDI_CLASS_ON || $chardata[$i]['type'] == UCDN::BIDI_CLASS_WS) {
- $left = -1;
-
- if ($laststrongtype == UCDN::BIDI_CLASS_R || $laststrongtype == UCDN::BIDI_CLASS_EN || $laststrongtype == UCDN::BIDI_CLASS_AN) {
- $left = UCDN::BIDI_CLASS_R;
- } else if ($laststrongtype == UCDN::BIDI_CLASS_L) {
- $left = UCDN::BIDI_CLASS_L;
- }
-
- $right = -1;
-
- if (isset($chardata[$i]['eor'])) {
- $right = $chardata[$i]['eor'];
- } else {
- $nexttype = -1;
- $nc2 = $nc;
- $i2 = $i;
- while (!($nc2 == ($numchunks - 1) && $i2 == ((count($para[$nc2][18]['char_data'])) - 1))) {
- $i2++;
- if ($i2 >= count($para[$nc2][18]['char_data'])) {
- $nc2++;
- $i2 = 0;
- }
- if (!isset($para[$nc2][18]['char_data'][$i2]['diid']) || $para[$nc2][18]['char_data'][$i2]['diid'] != $ir) {
- continue;
- }
- $nexttype = $para[$nc2][18]['char_data'][$i2]['type'];
- if ($nexttype == UCDN::BIDI_CLASS_R || $nexttype == UCDN::BIDI_CLASS_EN || $nexttype == UCDN::BIDI_CLASS_AN) {
- $right = UCDN::BIDI_CLASS_R;
- break;
- } else if ($nexttype == UCDN::BIDI_CLASS_L) {
- $right = UCDN::BIDI_CLASS_L;
- break;
- } else if (isset($para[$nc2][18]['char_data'][$i2]['eor'])) {
- $right = $para[$nc2][18]['char_data'][$i2]['eor'];
- break;
- }
- }
- }
- if ($left > -1 && $left == $right) {
- $chardata[$i]['orig_type'] = $chardata[$i]['type'];
- $chardata[$i]['type'] = $left;
- }
- } else if ($chardata[$i]['type'] == UCDN::BIDI_CLASS_L || $chardata[$i]['type'] == UCDN::BIDI_CLASS_R || $chardata[$i]['type'] == UCDN::BIDI_CLASS_EN || $chardata[$i]['type'] == UCDN::BIDI_CLASS_AN) {
- $laststrongtype = $chardata[$i]['type'];
- }
- }
- }
- }
-
- for ($nc = 0; $nc < $numchunks; $nc++) {
- $chardata = & $para[$nc][18]['char_data'];
- $numchars = count($chardata);
- for ($i = 0; $i < $numchars; ++$i) {
- if (isset($chardata[$i]['type']) && ($chardata[$i]['type'] == UCDN::BIDI_CLASS_ON || $chardata[$i]['type'] == UCDN::BIDI_CLASS_WS)) {
- $chardata[$i]['orig_type'] = $chardata[$i]['type'];
- $chardata[$i]['type'] = ($chardata[$i]['level'] % 2) ? UCDN::BIDI_CLASS_R : UCDN::BIDI_CLASS_L;
- }
- }
- }
-
-
- for ($nc = 0; $nc < $numchunks; $nc++) {
- $chardata = & $para[$nc][18]['char_data'];
- $numchars = count($chardata);
- for ($i = 0; $i < $numchars; ++$i) {
- if (isset($chardata[$i]['level'])) {
- $odd = $chardata[$i]['level'] % 2;
- if ($odd) {
- if (($chardata[$i]['type'] == UCDN::BIDI_CLASS_L) || ($chardata[$i]['type'] == UCDN::BIDI_CLASS_AN) || ($chardata[$i]['type'] == UCDN::BIDI_CLASS_EN)) {
- $chardata[$i]['level'] += 1;
- }
- } else {
- if ($chardata[$i]['type'] == UCDN::BIDI_CLASS_R) {
- $chardata[$i]['level'] += 1;
- } else if (($chardata[$i]['type'] == UCDN::BIDI_CLASS_AN) || ($chardata[$i]['type'] == UCDN::BIDI_CLASS_EN)) {
- $chardata[$i]['level'] += 2;
- }
- }
- }
- }
- }
-
- $numchunks = count($para);
- if ($controlchars) {
- for ($nc = 0; $nc < $numchunks; $nc++) {
- $this->removeChar($para[$nc][0], $para[$nc][18], "\xe2\x81\xa6");
- $this->removeChar($para[$nc][0], $para[$nc][18], "\xe2\x81\xa7");
- $this->removeChar($para[$nc][0], $para[$nc][18], "\xe2\x81\xa8");
- $this->removeChar($para[$nc][0], $para[$nc][18], "\xe2\x81\xa9");
- preg_replace("/\x{2066}-\x{2069}/u", '', $para[$nc][0]);
- }
-
- for ($nc = ($numchunks - 1); $nc >= 0; $nc--) {
- if (count($para[$nc][18]['char_data']) == 0) {
- array_splice($para, $nc, 1);
- }
- }
- }
- }
- function _bidiReorder(&$chunkorder, &$content, &$cOTLdata, $blockdir)
- {
- $bidiData = array();
-
- $numchunks = count($content);
- $maxlevel = 0;
- for ($nc = 0; $nc < $numchunks; $nc++) {
- $numchars = count($cOTLdata[$nc]['char_data']);
- for ($i = 0; $i < $numchars; ++$i) {
- $carac = array();
- if (isset($cOTLdata[$nc]['GPOSinfo'][$i])) {
- $carac['GPOSinfo'] = $cOTLdata[$nc]['GPOSinfo'][$i];
- }
- $carac['uni'] = $cOTLdata[$nc]['char_data'][$i]['uni'];
- if (isset($cOTLdata[$nc]['char_data'][$i]['type']))
- $carac['type'] = $cOTLdata[$nc]['char_data'][$i]['type'];
- if (isset($cOTLdata[$nc]['char_data'][$i]['level']))
- $carac['level'] = $cOTLdata[$nc]['char_data'][$i]['level'];
- if (isset($cOTLdata[$nc]['char_data'][$i]['orig_type'])) {
- $carac['orig_type'] = $cOTLdata[$nc]['char_data'][$i]['orig_type'];
- }
- $carac['group'] = $cOTLdata[$nc]['group']{$i};
- $carac['chunkid'] = $chunkorder[$nc];
- $maxlevel = max((isset($carac['level']) ? $carac['level'] : 0), $maxlevel);
- $bidiData[] = $carac;
- }
- }
- if ($maxlevel == 0) {
- return;
- }
- $numchars = count($bidiData);
-
-
-
-
-
-
-
-
- if ($blockdir == 'rtl') {
- $pel = 1;
- } else {
- $pel = 0;
- }
- for ($i = ($numchars - 1); $i > 0; $i--) {
- if ($bidiData[$i]['type'] == UCDN::BIDI_CLASS_WS || (isset($bidiData[$i]['orig_type']) && $bidiData[$i]['orig_type'] == UCDN::BIDI_CLASS_WS)) {
- $bidiData[$i]['level'] = $pel;
- } else {
- break;
- }
- }
-
- for ($j = $maxlevel; $j > 0; $j--) {
- $ordarray = array();
- $revarr = array();
- $onlevel = false;
- for ($i = 0; $i < $numchars; ++$i) {
- if ($bidiData[$i]['level'] >= $j) {
- $onlevel = true;
-
- if (isset(UCDN::$mirror_pairs[$bidiData[$i]['uni']]) && $bidiData[$i]['type'] == UCDN::BIDI_CLASS_R) {
- $bidiData[$i]['uni'] = UCDN::$mirror_pairs[$bidiData[$i]['uni']];
- }
- $revarr[] = $bidiData[$i];
- } else {
- if ($onlevel) {
- $revarr = array_reverse($revarr);
- $ordarray = array_merge($ordarray, $revarr);
- $revarr = Array();
- $onlevel = false;
- }
- $ordarray[] = $bidiData[$i];
- }
- }
- if ($onlevel) {
- $revarr = array_reverse($revarr);
- $ordarray = array_merge($ordarray, $revarr);
- }
- $bidiData = $ordarray;
- }
- $content = array();
- $cOTLdata = array();
- $chunkorder = array();
- $nc = -1;
- $chunkid = -1;
- foreach ($bidiData as $carac) {
- if ($carac['chunkid'] != $chunkid) {
- $nc++;
- $chunkorder[$nc] = $carac['chunkid'];
- $cctr = 0;
- $content[$nc] = '';
- $cOTLdata[$nc]['group'] = '';
- }
- if ($carac['uni'] != 0xFFFC) {
- $content[$nc] .= code2utf($carac['uni']);
- $cOTLdata[$nc]['group'] .= $carac['group'];
- if (!empty($carac['GPOSinfo'])) {
- if (isset($carac['GPOSinfo'])) {
- $cOTLdata[$nc]['GPOSinfo'][$cctr] = $carac['GPOSinfo'];
- }
- $cOTLdata[$nc]['GPOSinfo'][$cctr]['wDir'] = ($carac['level'] % 2) ? 'RTL' : 'LTR';
- }
- }
- $chunkid = $carac['chunkid'];
- $cctr++;
- }
- }
- function splitOTLdata(&$cOTLdata, $OTLcutoffpos, $OTLrestartpos = '')
- {
- if (!$OTLrestartpos) {
- $OTLrestartpos = $OTLcutoffpos;
- }
- $newOTLdata = array('GPOSinfo' => array(), 'char_data' => array());
- $newOTLdata['group'] = substr($cOTLdata['group'], $OTLrestartpos);
- $cOTLdata['group'] = substr($cOTLdata['group'], 0, $OTLcutoffpos);
- if (isset($cOTLdata['GPOSinfo']) && $cOTLdata['GPOSinfo']) {
- foreach ($cOTLdata['GPOSinfo'] AS $k => $val) {
- if ($k >= $OTLrestartpos) {
- $newOTLdata['GPOSinfo'][($k - $OTLrestartpos)] = $val;
- }
- if ($k >= $OTLcutoffpos) {
- unset($cOTLdata['GPOSinfo'][$k]);
-
- }
- }
- }
- if (isset($cOTLdata['char_data'])) {
- $newOTLdata['char_data'] = array_slice($cOTLdata['char_data'], $OTLrestartpos);
- array_splice($cOTLdata['char_data'], $OTLcutoffpos);
- }
-
- if (isset($cOTLdata['GPOSinfo']))
- ksort($cOTLdata['GPOSinfo']);
- if (isset($newOTLdata['GPOSinfo']))
- ksort($newOTLdata['GPOSinfo']);
- return $newOTLdata;
- }
- function sliceOTLdata($OTLdata, $pos, $len)
- {
- $newOTLdata = array('GPOSinfo' => array(), 'char_data' => array());
- $newOTLdata['group'] = substr($OTLdata['group'], $pos, $len);
- if ($OTLdata['GPOSinfo']) {
- foreach ($OTLdata['GPOSinfo'] AS $k => $val) {
- if ($k >= $pos && $k < ($pos + $len)) {
- $newOTLdata['GPOSinfo'][($k - $pos)] = $val;
- }
- }
- }
- if (isset($OTLdata['char_data'])) {
- $newOTLdata['char_data'] = array_slice($OTLdata['char_data'], $pos, $len);
- }
-
- if ($newOTLdata['GPOSinfo'])
- ksort($newOTLdata['GPOSinfo']);
- return $newOTLdata;
- }
- function removeChar(&$txt, &$cOTLdata, $char)
- {
- while (mb_strpos($txt, $char, 0, $this->mpdf->mb_enc) !== false) {
- $pos = mb_strpos($txt, $char, 0, $this->mpdf->mb_enc);
- $newGPOSinfo = array();
- $cOTLdata['group'] = substr_replace($cOTLdata['group'], '', $pos, 1);
- if ($cOTLdata['GPOSinfo']) {
- foreach ($cOTLdata['GPOSinfo'] AS $k => $val) {
- if ($k > $pos) {
- $newGPOSinfo[($k - 1)] = $val;
- } else if ($k != $pos) {
- $newGPOSinfo[$k] = $val;
- }
- }
- $cOTLdata['GPOSinfo'] = $newGPOSinfo;
- }
- if (isset($cOTLdata['char_data'])) {
- array_splice($cOTLdata['char_data'], $pos, 1);
- }
- $txt = preg_replace("/" . $char . "/", '', $txt, 1);
- }
- }
- function replaceSpace(&$txt, &$cOTLdata)
- {
- $char = chr(194) . chr(160);
- while (mb_strpos($txt, $char, 0, $this->mpdf->mb_enc) !== false) {
- $pos = mb_strpos($txt, $char, 0, $this->mpdf->mb_enc);
- if ($cOTLdata['char_data'][$pos]['uni'] == 160) {
- $cOTLdata['char_data'][$pos]['uni'] = 32;
- }
- $txt = preg_replace("/" . $char . "/", ' ', $txt, 1);
- }
- }
- function trimOTLdata(&$cOTLdata, $Left = true, $Right = true)
- {
- $len = count($cOTLdata['char_data']);
- $nLeft = 0;
- $nRight = 0;
- for ($i = 0; $i < $len; $i++) {
- if ($cOTLdata['char_data'][$i]['uni'] == 32 || $cOTLdata['char_data'][$i]['uni'] == 12288) {
- $nLeft++;
- }
- else {
- break;
- }
- }
- for ($i = ($len - 1); $i >= 0; $i--) {
- if ($cOTLdata['char_data'][$i]['uni'] == 32 || $cOTLdata['char_data'][$i]['uni'] == 12288) {
- $nRight++;
- }
- else {
- break;
- }
- }
-
- if ($Right && $nRight) {
- $cOTLdata['group'] = substr($cOTLdata['group'], 0, strlen($cOTLdata['group']) - $nRight);
- if ($cOTLdata['GPOSinfo']) {
- foreach ($cOTLdata['GPOSinfo'] AS $k => $val) {
- if ($k >= $len - $nRight) {
- unset($cOTLdata['GPOSinfo'][$k]);
- }
- }
- }
- if (isset($cOTLdata['char_data'])) {
- for ($i = 0; $i < $nRight; $i++) {
- array_pop($cOTLdata['char_data']);
- }
- }
- }
-
- if ($Left && $nLeft) {
- $cOTLdata['group'] = substr($cOTLdata['group'], $nLeft);
- if ($cOTLdata['GPOSinfo']) {
- $newPOSinfo = array();
- foreach ($cOTLdata['GPOSinfo'] AS $k => $val) {
- if ($k >= $nLeft) {
- $newPOSinfo[$k - $nLeft] = $cOTLdata['GPOSinfo'][$k];
- }
- }
- $cOTLdata['GPOSinfo'] = $newPOSinfo;
- }
- if (isset($cOTLdata['char_data'])) {
- for ($i = 0; $i < $nLeft; $i++) {
- array_shift($cOTLdata['char_data']);
- }
- }
- }
- }
- function glyphToChar($gid)
- {
- return (ord($this->glyphIDtoUni[$gid * 3]) << 16) + (ord($this->glyphIDtoUni[$gid * 3 + 1]) << 8) + ord($this->glyphIDtoUni[$gid * 3 + 2]);
- }
- function unicode_hex($unicode_dec)
- {
- return (str_pad(strtoupper(dechex($unicode_dec)), 5, '0', STR_PAD_LEFT));
- }
- function seek($pos)
- {
- $this->_pos = $pos;
- }
- function skip($delta)
- {
- $this->_pos += $delta;
- }
- function read_short()
- {
- $a = (ord($this->ttfOTLdata[$this->_pos]) << 8) + ord($this->ttfOTLdata[$this->_pos + 1]);
- if ($a & (1 << 15)) {
- $a = ($a - (1 << 16));
- }
- $this->_pos += 2;
- return $a;
- }
- function read_ushort()
- {
- $a = (ord($this->ttfOTLdata[$this->_pos]) << 8) + ord($this->ttfOTLdata[$this->_pos + 1]);
- $this->_pos += 2;
- return $a;
- }
- function _getCoverageGID()
- {
-
-
-
- $offset = $this->_pos;
- if (isset($this->LuDataCache[$this->fontkey]['GID'][$offset])) {
- $g = $this->LuDataCache[$this->fontkey]['GID'][$offset];
- } else {
- $g = array();
- $CoverageFormat = $this->read_ushort();
- if ($CoverageFormat == 1) {
- $CoverageGlyphCount = $this->read_ushort();
- for ($gid = 0; $gid < $CoverageGlyphCount; $gid++) {
- $glyphID = $this->read_ushort();
- $g[] = $glyphID;
- }
- }
- if ($CoverageFormat == 2) {
- $RangeCount = $this->read_ushort();
- for ($r = 0; $r < $RangeCount; $r++) {
- $start = $this->read_ushort();
- $end = $this->read_ushort();
- $StartCoverageIndex = $this->read_ushort();
- for ($glyphID = $start; $glyphID <= $end; $glyphID++) {
- $g[] = $glyphID;
- }
- }
- }
- $this->LuDataCache[$this->fontkey]['GID'][$offset] = $g;
- }
- return $g;
- }
- function _getCoverage()
- {
- $offset = $this->_pos;
- if (isset($this->LuDataCache[$this->fontkey][$offset])) {
- $g = $this->LuDataCache[$this->fontkey][$offset];
- } else {
- $g = array();
- $CoverageFormat = $this->read_ushort();
- if ($CoverageFormat == 1) {
- $CoverageGlyphCount = $this->read_ushort();
- for ($gid = 0; $gid < $CoverageGlyphCount; $gid++) {
- $glyphID = $this->read_ushort();
- $g[] = $this->unicode_hex($this->glyphToChar($glyphID));
- }
- }
- if ($CoverageFormat == 2) {
- $RangeCount = $this->read_ushort();
- for ($r = 0; $r < $RangeCount; $r++) {
- $start = $this->read_ushort();
- $end = $this->read_ushort();
- $StartCoverageIndex = $this->read_ushort();
- for ($glyphID = $start; $glyphID <= $end; $glyphID++) {
- $g[] = $this->unicode_hex($this->glyphToChar($glyphID));
- }
- }
- }
- $this->LuDataCache[$this->fontkey][$offset] = $g;
- }
- return $g;
- }
- function _getClasses($offset)
- {
- if (isset($this->LuDataCache[$this->fontkey][$offset])) {
- $GlyphByClass = $this->LuDataCache[$this->fontkey][$offset];
- } else {
- $this->seek($offset);
- $ClassFormat = $this->read_ushort();
- $GlyphByClass = array();
- if ($ClassFormat == 1) {
- $StartGlyph = $this->read_ushort();
- $GlyphCount = $this->read_ushort();
- for ($i = 0; $i < $GlyphCount; $i++) {
- $startGlyphID = $StartGlyph + $i;
- $endGlyphID = $StartGlyph + $i;
- $class = $this->read_ushort();
-
-
-
- if ($class > 0) {
- for ($g = $startGlyphID; $g <= $endGlyphID; $g++) {
- if ($this->glyphToChar($g)) {
- $GlyphByClass[$class][$this->glyphToChar($g)] = 1;
- }
- }
- }
- }
- } else if ($ClassFormat == 2) {
- $tableCount = $this->read_ushort();
- for ($i = 0; $i < $tableCount; $i++) {
- $startGlyphID = $this->read_ushort();
- $endGlyphID = $this->read_ushort();
- $class = $this->read_ushort();
-
-
-
- if ($class > 0) {
- for ($g = $startGlyphID; $g <= $endGlyphID; $g++) {
- if ($this->glyphToChar($g)) {
- $GlyphByClass[$class][$this->glyphToChar($g)] = 1;
- }
- }
- }
- }
- }
- $this->LuDataCache[$this->fontkey][$offset] = $GlyphByClass;
- }
- return $GlyphByClass;
- }
- function _getOTLscriptTag($ScriptLang, $scripttag, $scriptblock, $shaper, $useOTL, $mode)
- {
-
-
-
-
- if ($scriptblock == UCDN::SCRIPT_LATIN) {
- if (!($useOTL & 0x01)) {
- return array('', false);
- }
- } else if ($scriptblock == UCDN::SCRIPT_CYRILLIC) {
- if (!($useOTL & 0x02)) {
- return array('', false);
- }
- } else if ($scriptblock == UCDN::SCRIPT_GREEK) {
- if (!($useOTL & 0x04)) {
- return array('', false);
- }
- } else if ($scriptblock >= UCDN::SCRIPT_HIRAGANA && $scriptblock <= UCDN::SCRIPT_YI) {
- if (!($useOTL & 0x08)) {
- return array('', false);
- }
- } else {
- if (!($useOTL & 0x80)) {
- return array('', false);
- }
- }
-
- if (isset($ScriptLang[$scripttag])) {
- return array($scripttag, false);
- }
-
- if ($shaper) {
- switch ($scripttag) {
- CASE 'bng2': if (isset($ScriptLang['beng']))
- return array('beng', true);
- CASE 'dev2': if (isset($ScriptLang['deva']))
- return array('deva', true);
- CASE 'gjr2': if (isset($ScriptLang['gujr']))
- return array('gujr', true);
- CASE 'gur2': if (isset($ScriptLang['guru']))
- return array('guru', true);
- CASE 'knd2': if (isset($ScriptLang['knda']))
- return array('knda', true);
- CASE 'mlm2': if (isset($ScriptLang['mlym']))
- return array('mlym', true);
- CASE 'ory2': if (isset($ScriptLang['orya']))
- return array('orya', true);
- CASE 'tml2': if (isset($ScriptLang['taml']))
- return array('taml', true);
- CASE 'tel2': if (isset($ScriptLang['telu']))
- return array('telu', true);
- CASE 'mym2': if (isset($ScriptLang['mymr']))
- return array('mymr', true);
- }
- }
-
- if (isset($ScriptLang['DFLT'])) {
- return array('DFLT', false);
- }
-
- if (isset($ScriptLang['dflt'])) {
- return array('dflt', false);
- }
-
- if (isset($ScriptLang['latn'])) {
- return array('latn', false);
- }
-
- return array('', false);
- }
- function _getOTLLangTag($ietf, $available)
- {
-
-
-
- if ($available == '') {
- return '';
- }
- $tags = preg_split('/-/', $ietf);
- $lang = '';
- $country = '';
- $script = '';
- $lang = strtolower($tags[0]);
- if (isset($tags[1]) && $tags[1]) {
- if (strlen($tags[1]) == 2) {
- $country = strtolower($tags[1]);
- }
- }
- if (isset($tags[2]) && $tags[2]) {
- $country = strtolower($tags[2]);
- }
- if ($lang != '' && isset(UCDN::$ot_languages[$lang])) {
- $langsys = UCDN::$ot_languages[$lang];
- } else if ($lang != '' && $country != '' && isset(UCDN::$ot_languages[$lang . '' . $country])) {
- $langsys = UCDN::$ot_languages[$lang . '' . $country];
- } else {
- $langsys = "DFLT";
- }
- if (strpos($available, $langsys) === false) {
- if (strpos($available, "DFLT") !== false) {
- return "DFLT";
- } else
- return '';
- }
- return $langsys;
- }
- function _dumpproc($GPOSSUB, $lookupID, $subtable, $Type, $Format, $ptr, $currGlyph, $level)
- {
- echo '<div style="padding-left: ' . ($level * 2) . 'em;">';
- echo $GPOSSUB . ' LookupID #' . $lookupID . ' Subtable#' . $subtable . ' Type: ' . $Type . ' Format: ' . $Format . '<br />';
- echo '<div style="font-family:monospace">';
- echo 'Glyph position: ' . $ptr . ' Current Glyph: ' . $currGlyph . '<br />';
- for ($i = 0; $i < count($this->OTLdata); $i++) {
- if ($i == $ptr) {
- echo '<b>';
- }
- echo $this->OTLdata[$i]['hex'] . ' ';
- if ($i == $ptr) {
- echo '</b>';
- }
- }
- echo '<br />';
- for ($i = 0; $i < count($this->OTLdata); $i++) {
- if ($i == $ptr) {
- echo '<b>';
- }
- echo str_pad($this->OTLdata[$i]['uni'], 5) . ' ';
- if ($i == $ptr) {
- echo '</b>';
- }
- }
- echo '<br />';
- if ($GPOSSUB == 'GPOS') {
- for ($i = 0; $i < count($this->OTLdata); $i++) {
- if (!empty($this->OTLdata[$i]['GPOSinfo'])) {
- echo $this->OTLdata[$i]['hex'] . ' &#x' . $this->OTLdata[$i]['hex'] . '; ';
- print_r($this->OTLdata[$i]['GPOSinfo']);
- echo ' ';
- }
- }
- }
- echo '</div>';
- echo '</div>';
- }
- }
|