TMP_Text.cs 417 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656
  1. #define TMP_PRESENT
  2. using UnityEngine;
  3. using UnityEngine.TextCore;
  4. using UnityEngine.UI;
  5. using UnityEngine.Events;
  6. using UnityEngine.EventSystems;
  7. using System;
  8. using System.Text;
  9. using System.Collections;
  10. using System.Collections.Generic;
  11. namespace TMPro
  12. {
  13. public interface ITextElement
  14. {
  15. Material sharedMaterial { get; }
  16. void Rebuild(CanvasUpdate update);
  17. int GetInstanceID();
  18. }
  19. public enum TextAlignmentOptions
  20. {
  21. TopLeft = HorizontalAlignmentOptions.Left | VerticalAlignmentOptions.Top,
  22. Top = HorizontalAlignmentOptions.Center | VerticalAlignmentOptions.Top,
  23. TopRight = HorizontalAlignmentOptions.Right | VerticalAlignmentOptions.Top,
  24. TopJustified = HorizontalAlignmentOptions.Justified | VerticalAlignmentOptions.Top,
  25. TopFlush = HorizontalAlignmentOptions.Flush | VerticalAlignmentOptions.Top,
  26. TopGeoAligned = HorizontalAlignmentOptions.Geometry | VerticalAlignmentOptions.Top,
  27. Left = HorizontalAlignmentOptions.Left | VerticalAlignmentOptions.Middle,
  28. Center = HorizontalAlignmentOptions.Center | VerticalAlignmentOptions.Middle,
  29. Right = HorizontalAlignmentOptions.Right | VerticalAlignmentOptions.Middle,
  30. Justified = HorizontalAlignmentOptions.Justified | VerticalAlignmentOptions.Middle,
  31. Flush = HorizontalAlignmentOptions.Flush | VerticalAlignmentOptions.Middle,
  32. CenterGeoAligned = HorizontalAlignmentOptions.Geometry | VerticalAlignmentOptions.Middle,
  33. BottomLeft = HorizontalAlignmentOptions.Left | VerticalAlignmentOptions.Bottom,
  34. Bottom = HorizontalAlignmentOptions.Center | VerticalAlignmentOptions.Bottom,
  35. BottomRight = HorizontalAlignmentOptions.Right | VerticalAlignmentOptions.Bottom,
  36. BottomJustified = HorizontalAlignmentOptions.Justified | VerticalAlignmentOptions.Bottom,
  37. BottomFlush = HorizontalAlignmentOptions.Flush | VerticalAlignmentOptions.Bottom,
  38. BottomGeoAligned = HorizontalAlignmentOptions.Geometry | VerticalAlignmentOptions.Bottom,
  39. BaselineLeft = HorizontalAlignmentOptions.Left | VerticalAlignmentOptions.Baseline,
  40. Baseline = HorizontalAlignmentOptions.Center | VerticalAlignmentOptions.Baseline,
  41. BaselineRight = HorizontalAlignmentOptions.Right | VerticalAlignmentOptions.Baseline,
  42. BaselineJustified = HorizontalAlignmentOptions.Justified | VerticalAlignmentOptions.Baseline,
  43. BaselineFlush = HorizontalAlignmentOptions.Flush | VerticalAlignmentOptions.Baseline,
  44. BaselineGeoAligned = HorizontalAlignmentOptions.Geometry | VerticalAlignmentOptions.Baseline,
  45. MidlineLeft = HorizontalAlignmentOptions.Left | VerticalAlignmentOptions.Geometry,
  46. Midline = HorizontalAlignmentOptions.Center | VerticalAlignmentOptions.Geometry,
  47. MidlineRight = HorizontalAlignmentOptions.Right | VerticalAlignmentOptions.Geometry,
  48. MidlineJustified = HorizontalAlignmentOptions.Justified | VerticalAlignmentOptions.Geometry,
  49. MidlineFlush = HorizontalAlignmentOptions.Flush | VerticalAlignmentOptions.Geometry,
  50. MidlineGeoAligned = HorizontalAlignmentOptions.Geometry | VerticalAlignmentOptions.Geometry,
  51. CaplineLeft = HorizontalAlignmentOptions.Left | VerticalAlignmentOptions.Capline,
  52. Capline = HorizontalAlignmentOptions.Center | VerticalAlignmentOptions.Capline,
  53. CaplineRight = HorizontalAlignmentOptions.Right | VerticalAlignmentOptions.Capline,
  54. CaplineJustified = HorizontalAlignmentOptions.Justified | VerticalAlignmentOptions.Capline,
  55. CaplineFlush = HorizontalAlignmentOptions.Flush | VerticalAlignmentOptions.Capline,
  56. CaplineGeoAligned = HorizontalAlignmentOptions.Geometry | VerticalAlignmentOptions.Capline,
  57. Converted = 0xFFFF
  58. };
  59. /// <summary>
  60. /// Horizontal text alignment options.
  61. /// </summary>
  62. public enum HorizontalAlignmentOptions
  63. {
  64. Left = 0x1, Center = 0x2, Right = 0x4, Justified = 0x8, Flush = 0x10, Geometry = 0x20
  65. }
  66. /// <summary>
  67. /// Vertical text alignment options.
  68. /// </summary>
  69. public enum VerticalAlignmentOptions
  70. {
  71. Top = 0x100, Middle = 0x200, Bottom = 0x400, Baseline = 0x800, Geometry = 0x1000, Capline = 0x2000,
  72. }
  73. /// <summary>
  74. /// Flags controlling what vertex data gets pushed to the mesh.
  75. /// </summary>
  76. public enum TextRenderFlags
  77. {
  78. DontRender = 0x0,
  79. Render = 0xFF
  80. };
  81. public enum TMP_TextElementType { Character, Sprite };
  82. public enum MaskingTypes { MaskOff = 0, MaskHard = 1, MaskSoft = 2 }; //, MaskTex = 4 };
  83. public enum TextOverflowModes { Overflow = 0, Ellipsis = 1, Masking = 2, Truncate = 3, ScrollRect = 4, Page = 5, Linked = 6 };
  84. public enum MaskingOffsetMode { Percentage = 0, Pixel = 1 };
  85. public enum TextureMappingOptions { Character = 0, Line = 1, Paragraph = 2, MatchAspect = 3 };
  86. [Flags]
  87. public enum FontStyles { Normal = 0x0, Bold = 0x1, Italic = 0x2, Underline = 0x4, LowerCase = 0x8, UpperCase = 0x10, SmallCaps = 0x20, Strikethrough = 0x40, Superscript = 0x80, Subscript = 0x100, Highlight = 0x200 };
  88. public enum FontWeight { Thin = 100, ExtraLight = 200, Light = 300, Regular = 400, Medium = 500, SemiBold = 600, Bold = 700, Heavy = 800, Black = 900 };
  89. /// <summary>
  90. /// Base class which contains common properties and functions shared between the TextMeshPro and TextMeshProUGUI component.
  91. /// </summary>
  92. public abstract class TMP_Text : MaskableGraphic
  93. {
  94. /// <summary>
  95. /// A string containing the text to be displayed.
  96. /// </summary>
  97. public virtual string text
  98. {
  99. get { return m_text; }
  100. set
  101. {
  102. if (m_text != null && value != null && m_text.Length == value.Length && m_text == value)
  103. return;
  104. m_text = value;
  105. m_inputSource = TextInputSources.String;
  106. m_havePropertiesChanged = true;
  107. m_isInputParsingRequired = true;
  108. SetVerticesDirty();
  109. SetLayoutDirty();
  110. }
  111. }
  112. [SerializeField]
  113. [TextArea(5, 10)]
  114. protected string m_text;
  115. /// <summary>
  116. /// The ITextPreprocessor component referenced by the text object (if any)
  117. /// </summary>
  118. public ITextPreprocessor textPreprocessor
  119. {
  120. get { return m_TextPreprocessor; }
  121. set { m_TextPreprocessor = value; }
  122. }
  123. [SerializeField]
  124. protected ITextPreprocessor m_TextPreprocessor;
  125. /// <summary>
  126. ///
  127. /// </summary>
  128. public bool isRightToLeftText
  129. {
  130. get { return m_isRightToLeft; }
  131. set { if (m_isRightToLeft == value) return; m_isRightToLeft = value; m_havePropertiesChanged = true; m_isInputParsingRequired = true; SetVerticesDirty(); SetLayoutDirty(); }
  132. }
  133. [SerializeField]
  134. protected bool m_isRightToLeft = false;
  135. /// <summary>
  136. /// The Font Asset to be assigned to this text object.
  137. /// </summary>
  138. public TMP_FontAsset font
  139. {
  140. get { return m_fontAsset; }
  141. set { if (m_fontAsset == value) return; m_fontAsset = value; LoadFontAsset(); m_havePropertiesChanged = true; m_isInputParsingRequired = true; SetVerticesDirty(); SetLayoutDirty(); }
  142. }
  143. [SerializeField]
  144. protected TMP_FontAsset m_fontAsset;
  145. protected TMP_FontAsset m_currentFontAsset;
  146. protected bool m_isSDFShader;
  147. /// <summary>
  148. /// The material to be assigned to this text object.
  149. /// </summary>
  150. public virtual Material fontSharedMaterial
  151. {
  152. get { return m_sharedMaterial; }
  153. set { if (m_sharedMaterial == value) return; SetSharedMaterial(value); m_havePropertiesChanged = true; m_isInputParsingRequired = true; SetVerticesDirty(); SetMaterialDirty(); }
  154. }
  155. [SerializeField]
  156. protected Material m_sharedMaterial;
  157. protected Material m_currentMaterial;
  158. protected MaterialReference[] m_materialReferences = new MaterialReference[32];
  159. protected Dictionary<int, int> m_materialReferenceIndexLookup = new Dictionary<int, int>();
  160. protected TMP_TextProcessingStack<MaterialReference> m_materialReferenceStack = new TMP_TextProcessingStack<MaterialReference>(new MaterialReference[16]);
  161. protected int m_currentMaterialIndex;
  162. /// <summary>
  163. /// An array containing the materials used by the text object.
  164. /// </summary>
  165. public virtual Material[] fontSharedMaterials
  166. {
  167. get { return GetSharedMaterials(); }
  168. set { SetSharedMaterials(value); m_havePropertiesChanged = true; m_isInputParsingRequired = true; SetVerticesDirty(); SetMaterialDirty(); }
  169. }
  170. [SerializeField]
  171. protected Material[] m_fontSharedMaterials;
  172. /// <summary>
  173. /// The material to be assigned to this text object. An instance of the material will be assigned to the object's renderer.
  174. /// </summary>
  175. public Material fontMaterial
  176. {
  177. // Return an Instance of the current material.
  178. get { return GetMaterial(m_sharedMaterial); }
  179. // Assign new font material
  180. set
  181. {
  182. if (m_sharedMaterial != null && m_sharedMaterial.GetInstanceID() == value.GetInstanceID()) return;
  183. m_sharedMaterial = value;
  184. m_padding = GetPaddingForMaterial();
  185. m_havePropertiesChanged = true;
  186. m_isInputParsingRequired = true;
  187. SetVerticesDirty();
  188. SetMaterialDirty();
  189. }
  190. }
  191. [SerializeField]
  192. protected Material m_fontMaterial;
  193. /// <summary>
  194. /// The materials to be assigned to this text object. An instance of the materials will be assigned.
  195. /// </summary>
  196. public virtual Material[] fontMaterials
  197. {
  198. get { return GetMaterials(m_fontSharedMaterials); }
  199. set { SetSharedMaterials(value); m_havePropertiesChanged = true; m_isInputParsingRequired = true; SetVerticesDirty(); SetMaterialDirty(); }
  200. }
  201. [SerializeField]
  202. protected Material[] m_fontMaterials;
  203. protected bool m_isMaterialDirty;
  204. /// <summary>
  205. /// This is the default vertex color assigned to each vertices. Color tags will override vertex colors unless the overrideColorTags is set.
  206. /// </summary>
  207. public override Color color
  208. {
  209. get { return m_fontColor; }
  210. set { if (m_fontColor == value) return; m_havePropertiesChanged = true; m_fontColor = value; SetVerticesDirty(); }
  211. }
  212. //[UnityEngine.Serialization.FormerlySerializedAs("m_fontColor")] // Required for backwards compatibility with pre-Unity 4.6 releases.
  213. [SerializeField]
  214. protected Color32 m_fontColor32 = Color.white;
  215. [SerializeField]
  216. protected Color m_fontColor = Color.white;
  217. protected static Color32 s_colorWhite = new Color32(255, 255, 255, 255);
  218. protected Color32 m_underlineColor = s_colorWhite;
  219. protected Color32 m_strikethroughColor = s_colorWhite;
  220. /// <summary>
  221. /// Sets the vertex color alpha value.
  222. /// </summary>
  223. public float alpha
  224. {
  225. get { return m_fontColor.a; }
  226. set { if (m_fontColor.a == value) return; m_fontColor.a = value; m_havePropertiesChanged = true; SetVerticesDirty(); }
  227. }
  228. /// <summary>
  229. /// Determines if Vertex Color Gradient should be used
  230. /// </summary>
  231. /// <value><c>true</c> if enable vertex gradient; otherwise, <c>false</c>.</value>
  232. public bool enableVertexGradient
  233. {
  234. get { return m_enableVertexGradient; }
  235. set { if (m_enableVertexGradient == value) return; m_havePropertiesChanged = true; m_enableVertexGradient = value; SetVerticesDirty(); }
  236. }
  237. [SerializeField]
  238. protected bool m_enableVertexGradient;
  239. [SerializeField]
  240. protected ColorMode m_colorMode = ColorMode.FourCornersGradient;
  241. /// <summary>
  242. /// Sets the vertex colors for each of the 4 vertices of the character quads.
  243. /// </summary>
  244. /// <value>The color gradient.</value>
  245. public VertexGradient colorGradient
  246. {
  247. get { return m_fontColorGradient; }
  248. set { m_havePropertiesChanged = true; m_fontColorGradient = value; SetVerticesDirty(); }
  249. }
  250. [SerializeField]
  251. protected VertexGradient m_fontColorGradient = new VertexGradient(Color.white);
  252. /// <summary>
  253. /// Set the vertex colors of the 4 vertices of each character quads.
  254. /// </summary>
  255. public TMP_ColorGradient colorGradientPreset
  256. {
  257. get { return m_fontColorGradientPreset; }
  258. set { m_havePropertiesChanged = true; m_fontColorGradientPreset = value; SetVerticesDirty(); }
  259. }
  260. [SerializeField]
  261. protected TMP_ColorGradient m_fontColorGradientPreset;
  262. /// <summary>
  263. /// Sprite Asset used by the text object.
  264. /// </summary>
  265. public TMP_SpriteAsset spriteAsset
  266. {
  267. get { return m_spriteAsset; }
  268. set { m_spriteAsset = value; m_havePropertiesChanged = true; m_isInputParsingRequired = true; SetVerticesDirty(); SetLayoutDirty(); }
  269. }
  270. [SerializeField]
  271. protected TMP_SpriteAsset m_spriteAsset;
  272. /// <summary>
  273. /// Determines whether or not the sprite color is multiplies by the vertex color of the text.
  274. /// </summary>
  275. public bool tintAllSprites
  276. {
  277. get { return m_tintAllSprites; }
  278. set { if (m_tintAllSprites == value) return; m_tintAllSprites = value; m_havePropertiesChanged = true; SetVerticesDirty(); }
  279. }
  280. [SerializeField]
  281. protected bool m_tintAllSprites;
  282. protected bool m_tintSprite;
  283. protected Color32 m_spriteColor;
  284. /// <summary>
  285. /// Style sheet used by the text object.
  286. /// </summary>
  287. public TMP_StyleSheet styleSheet
  288. {
  289. get { return m_StyleSheet; }
  290. set { m_StyleSheet = value; m_havePropertiesChanged = true; m_isInputParsingRequired = true; SetVerticesDirty(); SetLayoutDirty(); }
  291. }
  292. [SerializeField]
  293. protected TMP_StyleSheet m_StyleSheet;
  294. /// <summary>
  295. ///
  296. /// </summary>
  297. public TMP_Style textStyle
  298. {
  299. get
  300. {
  301. m_TextStyle = GetStyle(m_TextStyleHashCode);
  302. if (m_TextStyle == null)
  303. {
  304. m_TextStyle = TMP_Style.NormalStyle;
  305. m_TextStyleHashCode = m_TextStyle.hashCode;
  306. }
  307. return m_TextStyle;
  308. }
  309. set { m_TextStyle = value; m_TextStyleHashCode = m_TextStyle.hashCode; m_havePropertiesChanged = true; m_isInputParsingRequired = true; SetVerticesDirty(); SetLayoutDirty(); }
  310. }
  311. internal TMP_Style m_TextStyle;
  312. [SerializeField]
  313. protected int m_TextStyleHashCode;
  314. /// <summary>
  315. /// This overrides the color tags forcing the vertex colors to be the default font color.
  316. /// </summary>
  317. public bool overrideColorTags
  318. {
  319. get { return m_overrideHtmlColors; }
  320. set { if (m_overrideHtmlColors == value) return; m_havePropertiesChanged = true; m_overrideHtmlColors = value; SetVerticesDirty(); }
  321. }
  322. [SerializeField]
  323. protected bool m_overrideHtmlColors = false;
  324. /// <summary>
  325. /// Sets the color of the _FaceColor property of the assigned material. Changing face color will result in an instance of the material.
  326. /// </summary>
  327. public Color32 faceColor
  328. {
  329. get
  330. {
  331. if (m_sharedMaterial == null) return m_faceColor;
  332. m_faceColor = m_sharedMaterial.GetColor(ShaderUtilities.ID_FaceColor);
  333. return m_faceColor;
  334. }
  335. set { if (m_faceColor.Compare(value)) return; SetFaceColor(value); m_havePropertiesChanged = true; m_faceColor = value; SetVerticesDirty(); SetMaterialDirty(); }
  336. }
  337. [SerializeField]
  338. protected Color32 m_faceColor = Color.white;
  339. /// <summary>
  340. /// Sets the color of the _OutlineColor property of the assigned material. Changing outline color will result in an instance of the material.
  341. /// </summary>
  342. public Color32 outlineColor
  343. {
  344. get
  345. {
  346. if (m_sharedMaterial == null) return m_outlineColor;
  347. m_outlineColor = m_sharedMaterial.GetColor(ShaderUtilities.ID_OutlineColor);
  348. return m_outlineColor;
  349. }
  350. set { if (m_outlineColor.Compare(value)) return; SetOutlineColor(value); m_havePropertiesChanged = true; m_outlineColor = value; SetVerticesDirty(); }
  351. }
  352. //[SerializeField]
  353. protected Color32 m_outlineColor = Color.black;
  354. /// <summary>
  355. /// Sets the thickness of the outline of the font. Setting this value will result in an instance of the material.
  356. /// </summary>
  357. public float outlineWidth
  358. {
  359. get
  360. {
  361. if (m_sharedMaterial == null) return m_outlineWidth;
  362. m_outlineWidth = m_sharedMaterial.GetFloat(ShaderUtilities.ID_OutlineWidth);
  363. return m_outlineWidth;
  364. }
  365. set { if (m_outlineWidth == value) return; SetOutlineThickness(value); m_havePropertiesChanged = true; m_outlineWidth = value; SetVerticesDirty(); }
  366. }
  367. protected float m_outlineWidth = 0.0f;
  368. /// <summary>
  369. /// The point size of the font.
  370. /// </summary>
  371. public float fontSize
  372. {
  373. get { return m_fontSize; }
  374. set { if (m_fontSize == value) return; m_havePropertiesChanged = true; m_fontSize = value; if (!m_enableAutoSizing) m_fontSizeBase = m_fontSize; SetVerticesDirty(); SetLayoutDirty(); }
  375. }
  376. [SerializeField]
  377. protected float m_fontSize = 36; // Font Size
  378. protected float m_currentFontSize; // Temporary Font Size affected by tags
  379. [SerializeField] // TODO: Review if this should be serialized
  380. protected float m_fontSizeBase = 36;
  381. protected TMP_TextProcessingStack<float> m_sizeStack = new TMP_TextProcessingStack<float>(16);
  382. /// <summary>
  383. /// The scale of the current text.
  384. /// </summary>
  385. public float fontScale
  386. {
  387. get { return m_fontScale; }
  388. }
  389. /// <summary>
  390. /// Control the weight of the font if an alternative font asset is assigned for the given weight in the font asset editor.
  391. /// </summary>
  392. public FontWeight fontWeight
  393. {
  394. get { return m_fontWeight; }
  395. set { if (m_fontWeight == value) return; m_fontWeight = value; m_havePropertiesChanged = true; m_isInputParsingRequired = true; SetVerticesDirty(); SetLayoutDirty(); }
  396. }
  397. [SerializeField]
  398. protected FontWeight m_fontWeight = FontWeight.Regular;
  399. protected FontWeight m_FontWeightInternal = FontWeight.Regular;
  400. protected TMP_TextProcessingStack<FontWeight> m_FontWeightStack = new TMP_TextProcessingStack<FontWeight>(8);
  401. /// <summary>
  402. ///
  403. /// </summary>
  404. public float pixelsPerUnit
  405. {
  406. get
  407. {
  408. var localCanvas = canvas;
  409. if (!localCanvas)
  410. return 1;
  411. // For dynamic fonts, ensure we use one pixel per pixel on the screen.
  412. if (!font)
  413. return localCanvas.scaleFactor;
  414. // For non-dynamic fonts, calculate pixels per unit based on specified font size relative to font object's own font size.
  415. if (m_currentFontAsset == null || m_currentFontAsset.faceInfo.pointSize <= 0 || m_fontSize <= 0)
  416. return 1;
  417. return m_fontSize / m_currentFontAsset.faceInfo.pointSize;
  418. }
  419. }
  420. /// <summary>
  421. /// Enable text auto-sizing
  422. /// </summary>
  423. public bool enableAutoSizing
  424. {
  425. get { return m_enableAutoSizing; }
  426. set { if (m_enableAutoSizing == value) return; m_enableAutoSizing = value; SetVerticesDirty(); SetLayoutDirty(); }
  427. }
  428. [SerializeField]
  429. protected bool m_enableAutoSizing;
  430. protected float m_maxFontSize; // Used in conjunction with auto-sizing
  431. protected float m_minFontSize; // Used in conjunction with auto-sizing
  432. protected int m_AutoSizeIterationCount;
  433. protected int m_AutoSizeMaxIterationCount = 100;
  434. protected bool m_IsAutoSizePointSizeSet;
  435. /// <summary>
  436. /// Minimum point size of the font when text auto-sizing is enabled.
  437. /// </summary>
  438. public float fontSizeMin
  439. {
  440. get { return m_fontSizeMin; }
  441. set { if (m_fontSizeMin == value) return; m_fontSizeMin = value; SetVerticesDirty(); SetLayoutDirty(); }
  442. }
  443. [SerializeField]
  444. protected float m_fontSizeMin = 0; // Text Auto Sizing Min Font Size.
  445. /// <summary>
  446. /// Maximum point size of the font when text auto-sizing is enabled.
  447. /// </summary>
  448. public float fontSizeMax
  449. {
  450. get { return m_fontSizeMax; }
  451. set { if (m_fontSizeMax == value) return; m_fontSizeMax = value; SetVerticesDirty(); SetLayoutDirty(); }
  452. }
  453. [SerializeField]
  454. protected float m_fontSizeMax = 0; // Text Auto Sizing Max Font Size.
  455. /// <summary>
  456. /// The style of the text
  457. /// </summary>
  458. public FontStyles fontStyle
  459. {
  460. get { return m_fontStyle; }
  461. set { if (m_fontStyle == value) return; m_fontStyle = value; m_havePropertiesChanged = true; m_isInputParsingRequired = true; SetVerticesDirty(); SetLayoutDirty(); }
  462. }
  463. [SerializeField]
  464. protected FontStyles m_fontStyle = FontStyles.Normal;
  465. protected FontStyles m_FontStyleInternal = FontStyles.Normal;
  466. protected TMP_FontStyleStack m_fontStyleStack;
  467. /// <summary>
  468. /// Property used in conjunction with padding calculation for the geometry.
  469. /// </summary>
  470. public bool isUsingBold { get { return m_isUsingBold; } }
  471. protected bool m_isUsingBold = false; // Used to ensure GetPadding & Ratios take into consideration bold characters.
  472. /// <summary>
  473. /// Horizontal alignment options
  474. /// </summary>
  475. public HorizontalAlignmentOptions horizontalAlignment
  476. {
  477. get { return m_HorizontalAlignment; }
  478. set
  479. {
  480. if (m_HorizontalAlignment == value)
  481. return;
  482. m_HorizontalAlignment = value;
  483. m_havePropertiesChanged = true;
  484. SetVerticesDirty();
  485. }
  486. }
  487. [SerializeField]
  488. protected HorizontalAlignmentOptions m_HorizontalAlignment = HorizontalAlignmentOptions.Left;
  489. /// <summary>
  490. /// Vertical alignment options
  491. /// </summary>
  492. public VerticalAlignmentOptions verticalAlignment
  493. {
  494. get { return m_VerticalAlignment; }
  495. set
  496. {
  497. if (m_VerticalAlignment == value)
  498. return;
  499. m_VerticalAlignment = value;
  500. m_havePropertiesChanged = true;
  501. SetVerticesDirty();
  502. }
  503. }
  504. [SerializeField]
  505. protected VerticalAlignmentOptions m_VerticalAlignment = VerticalAlignmentOptions.Top;
  506. /// <summary>
  507. /// Text alignment options
  508. /// </summary>
  509. public TextAlignmentOptions alignment
  510. {
  511. get { return (TextAlignmentOptions)((int)m_HorizontalAlignment | (int)m_VerticalAlignment); }
  512. set
  513. {
  514. HorizontalAlignmentOptions horizontalAlignment = (HorizontalAlignmentOptions)((int)value & 0xFF);
  515. VerticalAlignmentOptions verticalAlignment = (VerticalAlignmentOptions)((int)value & 0xFF00);
  516. if (m_HorizontalAlignment == horizontalAlignment && m_VerticalAlignment == verticalAlignment)
  517. return;
  518. m_HorizontalAlignment = horizontalAlignment;
  519. m_VerticalAlignment = verticalAlignment;
  520. m_havePropertiesChanged = true;
  521. SetVerticesDirty();
  522. }
  523. }
  524. [SerializeField]
  525. [UnityEngine.Serialization.FormerlySerializedAs("m_lineJustification")]
  526. protected TextAlignmentOptions m_textAlignment = TextAlignmentOptions.Converted;
  527. protected HorizontalAlignmentOptions m_lineJustification;
  528. protected TMP_TextProcessingStack<HorizontalAlignmentOptions> m_lineJustificationStack = new TMP_TextProcessingStack<HorizontalAlignmentOptions>(new HorizontalAlignmentOptions[16]);
  529. protected Vector3[] m_textContainerLocalCorners = new Vector3[4];
  530. /// <summary>
  531. /// Use the extents of the text geometry for alignment instead of font metrics.
  532. /// </summary>
  533. //public bool alignByGeometry
  534. //{
  535. // get { return m_alignByGeometry; }
  536. // set { if (m_alignByGeometry == value) return; m_havePropertiesChanged = true; m_alignByGeometry = value; SetVerticesDirty(); }
  537. //}
  538. //[SerializeField]
  539. //protected bool m_alignByGeometry;
  540. /// <summary>
  541. /// The amount of additional spacing between characters.
  542. /// </summary>
  543. public float characterSpacing
  544. {
  545. get { return m_characterSpacing; }
  546. set { if (m_characterSpacing == value) return; m_havePropertiesChanged = true; m_characterSpacing = value; SetVerticesDirty(); SetLayoutDirty(); }
  547. }
  548. [SerializeField]
  549. protected float m_characterSpacing = 0;
  550. protected float m_cSpacing = 0;
  551. protected float m_monoSpacing = 0;
  552. /// <summary>
  553. /// The amount of additional spacing between words.
  554. /// </summary>
  555. public float wordSpacing
  556. {
  557. get { return m_wordSpacing; }
  558. set { if (m_wordSpacing == value) return; m_havePropertiesChanged = true; m_wordSpacing = value; SetVerticesDirty(); SetLayoutDirty(); }
  559. }
  560. [SerializeField]
  561. protected float m_wordSpacing = 0;
  562. /// <summary>
  563. /// The amount of additional spacing to add between each lines of text.
  564. /// </summary>
  565. public float lineSpacing
  566. {
  567. get { return m_lineSpacing; }
  568. set { if (m_lineSpacing == value) return; m_havePropertiesChanged = true; m_lineSpacing = value; SetVerticesDirty(); SetLayoutDirty(); }
  569. }
  570. [SerializeField]
  571. protected float m_lineSpacing = 0;
  572. protected float m_lineSpacingDelta = 0; // Used with Text Auto Sizing feature
  573. protected float m_lineHeight = TMP_Math.FLOAT_UNSET; // Used with the <line-height=xx.x> tag.
  574. protected bool m_IsDrivenLineSpacing;
  575. /// <summary>
  576. /// The amount of potential line spacing adjustment before text auto sizing kicks in.
  577. /// </summary>
  578. public float lineSpacingAdjustment
  579. {
  580. get { return m_lineSpacingMax; }
  581. set { if (m_lineSpacingMax == value) return; m_havePropertiesChanged = true; m_lineSpacingMax = value; SetVerticesDirty(); SetLayoutDirty(); }
  582. }
  583. [SerializeField]
  584. protected float m_lineSpacingMax = 0; // Text Auto Sizing Max Line spacing reduction.
  585. //protected bool m_forceLineBreak;
  586. /// <summary>
  587. /// The amount of additional spacing to add between each lines of text.
  588. /// </summary>
  589. public float paragraphSpacing
  590. {
  591. get { return m_paragraphSpacing; }
  592. set { if (m_paragraphSpacing == value) return; m_havePropertiesChanged = true; m_paragraphSpacing = value; SetVerticesDirty(); SetLayoutDirty(); }
  593. }
  594. [SerializeField]
  595. protected float m_paragraphSpacing = 0;
  596. /// <summary>
  597. /// Percentage the width of characters can be adjusted before text auto-sizing begins to reduce the point size.
  598. /// </summary>
  599. public float characterWidthAdjustment
  600. {
  601. get { return m_charWidthMaxAdj; }
  602. set { if (m_charWidthMaxAdj == value) return; m_havePropertiesChanged = true; m_charWidthMaxAdj = value; SetVerticesDirty(); SetLayoutDirty(); }
  603. }
  604. [SerializeField]
  605. protected float m_charWidthMaxAdj = 0f; // Text Auto Sizing Max Character Width reduction.
  606. protected float m_charWidthAdjDelta = 0;
  607. /// <summary>
  608. /// Controls whether or not word wrapping is applied. When disabled, the text will be displayed on a single line.
  609. /// </summary>
  610. public bool enableWordWrapping
  611. {
  612. get { return m_enableWordWrapping; }
  613. set { if (m_enableWordWrapping == value) return; m_havePropertiesChanged = true; m_isInputParsingRequired = true; m_enableWordWrapping = value; SetVerticesDirty(); SetLayoutDirty(); }
  614. }
  615. [SerializeField]
  616. protected bool m_enableWordWrapping = false;
  617. protected bool m_isCharacterWrappingEnabled = false;
  618. protected bool m_isNonBreakingSpace = false;
  619. protected bool m_isIgnoringAlignment;
  620. /// <summary>
  621. /// Controls the blending between using character and word spacing to fill-in the space for justified text.
  622. /// </summary>
  623. public float wordWrappingRatios
  624. {
  625. get { return m_wordWrappingRatios; }
  626. set { if (m_wordWrappingRatios == value) return; m_wordWrappingRatios = value; m_havePropertiesChanged = true; SetVerticesDirty(); SetLayoutDirty(); }
  627. }
  628. [SerializeField]
  629. protected float m_wordWrappingRatios = 0.4f; // Controls word wrapping ratios between word or characters.
  630. /// <summary>
  631. ///
  632. /// </summary>
  633. //public bool enableAdaptiveJustification
  634. //{
  635. // get { return m_enableAdaptiveJustification; }
  636. // set { if (m_enableAdaptiveJustification == value) return; m_enableAdaptiveJustification = value; m_havePropertiesChanged = true; m_isCalculateSizeRequired = true; SetVerticesDirty(); SetLayoutDirty(); }
  637. //}
  638. //[SerializeField]
  639. //protected bool m_enableAdaptiveJustification;
  640. //protected float m_adaptiveJustificationThreshold = 10.0f;
  641. /// <summary>
  642. /// Controls the Text Overflow Mode
  643. /// </summary>
  644. public TextOverflowModes overflowMode
  645. {
  646. get { return m_overflowMode; }
  647. set { if (m_overflowMode == value) return; m_overflowMode = value; m_havePropertiesChanged = true; SetVerticesDirty(); SetLayoutDirty(); }
  648. }
  649. [SerializeField]
  650. protected TextOverflowModes m_overflowMode = TextOverflowModes.Overflow;
  651. /// <summary>
  652. /// Indicates if the text exceeds the vertical bounds of its text container.
  653. /// </summary>
  654. public bool isTextOverflowing
  655. {
  656. get { if (m_firstOverflowCharacterIndex != -1) return true; return false; }
  657. }
  658. /// <summary>
  659. /// The first character which exceeds the vertical bounds of its text container.
  660. /// </summary>
  661. public int firstOverflowCharacterIndex
  662. {
  663. get { return m_firstOverflowCharacterIndex; }
  664. }
  665. //[SerializeField]
  666. protected int m_firstOverflowCharacterIndex = -1;
  667. /// <summary>
  668. /// The linked text component used for flowing the text from one text component to another.
  669. /// </summary>
  670. public TMP_Text linkedTextComponent
  671. {
  672. get { return m_linkedTextComponent; }
  673. set
  674. {
  675. if (value == null)
  676. {
  677. // Release linked text components
  678. ReleaseLinkedTextComponent(m_linkedTextComponent);
  679. m_linkedTextComponent = value;
  680. }
  681. else if (IsSelfOrLinkedAncestor(value))
  682. {
  683. // We do nothing since new assigned is invalid
  684. return;
  685. }
  686. else
  687. {
  688. // Release linked text components
  689. ReleaseLinkedTextComponent(m_linkedTextComponent);
  690. m_linkedTextComponent = value;
  691. m_linkedTextComponent.parentLinkedComponent = this;
  692. }
  693. m_havePropertiesChanged = true;
  694. SetVerticesDirty();
  695. SetLayoutDirty();
  696. }
  697. }
  698. [SerializeField]
  699. protected TMP_Text m_linkedTextComponent;
  700. [SerializeField]
  701. internal TMP_Text parentLinkedComponent;
  702. /// <summary>
  703. /// Property indicating whether the text is Truncated or using Ellipsis.
  704. /// </summary>
  705. public bool isTextTruncated { get { return m_isTextTruncated; } }
  706. //[SerializeField]
  707. protected bool m_isTextTruncated;
  708. /// <summary>
  709. /// Determines if kerning is enabled or disabled.
  710. /// </summary>
  711. public bool enableKerning
  712. {
  713. get { return m_enableKerning; }
  714. set { if (m_enableKerning == value) return; m_havePropertiesChanged = true; m_enableKerning = value; SetVerticesDirty(); SetLayoutDirty(); }
  715. }
  716. [SerializeField]
  717. protected bool m_enableKerning;
  718. protected float m_GlyphHorizontalAdvanceAdjustment;
  719. /// <summary>
  720. /// Adds extra padding around each character. This may be necessary when the displayed text is very small to prevent clipping.
  721. /// </summary>
  722. public bool extraPadding
  723. {
  724. get { return m_enableExtraPadding; }
  725. set { if (m_enableExtraPadding == value) return; m_havePropertiesChanged = true; m_enableExtraPadding = value; UpdateMeshPadding(); SetVerticesDirty(); /* SetLayoutDirty();*/ }
  726. }
  727. [SerializeField]
  728. protected bool m_enableExtraPadding = false;
  729. [SerializeField]
  730. protected bool checkPaddingRequired;
  731. /// <summary>
  732. /// Enables or Disables Rich Text Tags
  733. /// </summary>
  734. public bool richText
  735. {
  736. get { return m_isRichText; }
  737. set { if (m_isRichText == value) return; m_isRichText = value; m_havePropertiesChanged = true; m_isInputParsingRequired = true; SetVerticesDirty(); SetLayoutDirty(); }
  738. }
  739. [SerializeField]
  740. protected bool m_isRichText = true; // Used to enable or disable Rich Text.
  741. /// <summary>
  742. /// Enables or Disables parsing of CTRL characters in input text.
  743. /// </summary>
  744. public bool parseCtrlCharacters
  745. {
  746. get { return m_parseCtrlCharacters; }
  747. set { if (m_parseCtrlCharacters == value) return; m_parseCtrlCharacters = value; m_havePropertiesChanged = true; m_isInputParsingRequired = true; SetVerticesDirty(); SetLayoutDirty(); }
  748. }
  749. [SerializeField]
  750. protected bool m_parseCtrlCharacters = true;
  751. /// <summary>
  752. /// Sets the RenderQueue along with Ztest to force the text to be drawn last and on top of scene elements.
  753. /// </summary>
  754. public bool isOverlay
  755. {
  756. get { return m_isOverlay; }
  757. set { if (m_isOverlay == value) return; m_isOverlay = value; SetShaderDepth(); m_havePropertiesChanged = true; SetVerticesDirty(); }
  758. }
  759. protected bool m_isOverlay = false;
  760. /// <summary>
  761. /// Sets Perspective Correction to Zero for Orthographic Camera mode & 0.875f for Perspective Camera mode.
  762. /// </summary>
  763. public bool isOrthographic
  764. {
  765. get { return m_isOrthographic; }
  766. set { if (m_isOrthographic == value) return; m_havePropertiesChanged = true; m_isOrthographic = value; SetVerticesDirty(); }
  767. }
  768. [SerializeField]
  769. protected bool m_isOrthographic = false;
  770. /// <summary>
  771. /// Sets the culling on the shaders. Note changing this value will result in an instance of the material.
  772. /// </summary>
  773. public bool enableCulling
  774. {
  775. get { return m_isCullingEnabled; }
  776. set { if (m_isCullingEnabled == value) return; m_isCullingEnabled = value; SetCulling(); m_havePropertiesChanged = true; }
  777. }
  778. [SerializeField]
  779. protected bool m_isCullingEnabled = false;
  780. //
  781. protected bool m_isMaskingEnabled;
  782. protected bool isMaskUpdateRequired;
  783. /// <summary>
  784. /// Forces objects that are not visible to get refreshed.
  785. /// </summary>
  786. public bool ignoreVisibility
  787. {
  788. get { return m_ignoreCulling; }
  789. set { if (m_ignoreCulling == value) return; m_havePropertiesChanged = true; m_ignoreCulling = value; }
  790. }
  791. //[SerializeField]
  792. protected bool m_ignoreCulling = true; // Not implemented yet.
  793. /// <summary>
  794. /// Controls how the face and outline textures will be applied to the text object.
  795. /// </summary>
  796. public TextureMappingOptions horizontalMapping
  797. {
  798. get { return m_horizontalMapping; }
  799. set { if (m_horizontalMapping == value) return; m_havePropertiesChanged = true; m_horizontalMapping = value; SetVerticesDirty(); }
  800. }
  801. [SerializeField]
  802. protected TextureMappingOptions m_horizontalMapping = TextureMappingOptions.Character;
  803. /// <summary>
  804. /// Controls how the face and outline textures will be applied to the text object.
  805. /// </summary>
  806. public TextureMappingOptions verticalMapping
  807. {
  808. get { return m_verticalMapping; }
  809. set { if (m_verticalMapping == value) return; m_havePropertiesChanged = true; m_verticalMapping = value; SetVerticesDirty(); }
  810. }
  811. [SerializeField]
  812. protected TextureMappingOptions m_verticalMapping = TextureMappingOptions.Character;
  813. /// <summary>
  814. /// Controls the UV Offset for the various texture mapping mode on the text object.
  815. /// </summary>
  816. //public Vector2 mappingUvOffset
  817. //{
  818. // get { return m_uvOffset; }
  819. // set { if (m_uvOffset == value) return; m_havePropertiesChanged = true; m_uvOffset = value; SetVerticesDirty(); }
  820. //}
  821. //[SerializeField]
  822. //protected Vector2 m_uvOffset = Vector2.zero; // Used to offset UV on Texturing
  823. /// <summary>
  824. /// Controls the horizontal offset of the UV of the texture mapping mode for each line of the text object.
  825. /// </summary>
  826. public float mappingUvLineOffset
  827. {
  828. get { return m_uvLineOffset; }
  829. set { if (m_uvLineOffset == value) return; m_havePropertiesChanged = true; m_uvLineOffset = value; SetVerticesDirty(); }
  830. }
  831. [SerializeField]
  832. protected float m_uvLineOffset = 0.0f; // Used for UV line offset per line
  833. /// <summary>
  834. /// Determines if the Mesh will be rendered.
  835. /// </summary>
  836. public TextRenderFlags renderMode
  837. {
  838. get { return m_renderMode; }
  839. set { if (m_renderMode == value) return; m_renderMode = value; m_havePropertiesChanged = true; }
  840. }
  841. protected TextRenderFlags m_renderMode = TextRenderFlags.Render;
  842. /// <summary>
  843. /// Determines the sorting order of the geometry of the text object.
  844. /// </summary>
  845. public VertexSortingOrder geometrySortingOrder
  846. {
  847. get { return m_geometrySortingOrder; }
  848. set { m_geometrySortingOrder = value; m_havePropertiesChanged = true; SetVerticesDirty(); }
  849. }
  850. [SerializeField]
  851. protected VertexSortingOrder m_geometrySortingOrder;
  852. /// <summary>
  853. /// Determines if a text object will be excluded from the InternalUpdate callback used to handle updates of SDF Scale when the scale of the text object or parent(s) changes.
  854. /// </summary>
  855. public bool isTextObjectScaleStatic
  856. {
  857. get { return m_IsTextObjectScaleStatic; }
  858. set
  859. {
  860. m_IsTextObjectScaleStatic = value;
  861. if (m_IsTextObjectScaleStatic)
  862. TMP_UpdateManager.UnRegisterTextObjectForUpdate(this);
  863. else
  864. TMP_UpdateManager.RegisterTextObjectForUpdate(this);
  865. }
  866. }
  867. [SerializeField]
  868. protected bool m_IsTextObjectScaleStatic;
  869. /// <summary>
  870. /// Determines if the data structures allocated to contain the geometry of the text object will be reduced in size if the number of characters required to display the text is reduced by more than 256 characters.
  871. /// This reduction has the benefit of reducing the amount of vertex data being submitted to the graphic device but results in GC when it occurs.
  872. /// </summary>
  873. public bool vertexBufferAutoSizeReduction
  874. {
  875. get { return m_VertexBufferAutoSizeReduction; }
  876. set { m_VertexBufferAutoSizeReduction = value; m_havePropertiesChanged = true; SetVerticesDirty(); }
  877. }
  878. [SerializeField]
  879. protected bool m_VertexBufferAutoSizeReduction = true;
  880. /// <summary>
  881. /// The first character which should be made visible in conjunction with the Text Overflow Linked mode.
  882. /// </summary>
  883. public int firstVisibleCharacter
  884. {
  885. get { return m_firstVisibleCharacter; }
  886. set { if (m_firstVisibleCharacter == value) return; m_havePropertiesChanged = true; m_firstVisibleCharacter = value; SetVerticesDirty(); }
  887. }
  888. //[SerializeField]
  889. protected int m_firstVisibleCharacter;
  890. /// <summary>
  891. /// Allows to control how many characters are visible from the input.
  892. /// </summary>
  893. public int maxVisibleCharacters
  894. {
  895. get { return m_maxVisibleCharacters; }
  896. set { if (m_maxVisibleCharacters == value) return; m_havePropertiesChanged = true; m_maxVisibleCharacters = value; SetVerticesDirty(); }
  897. }
  898. protected int m_maxVisibleCharacters = 99999;
  899. /// <summary>
  900. /// Allows to control how many words are visible from the input.
  901. /// </summary>
  902. public int maxVisibleWords
  903. {
  904. get { return m_maxVisibleWords; }
  905. set { if (m_maxVisibleWords == value) return; m_havePropertiesChanged = true; m_maxVisibleWords = value; SetVerticesDirty(); }
  906. }
  907. protected int m_maxVisibleWords = 99999;
  908. /// <summary>
  909. /// Allows control over how many lines of text are displayed.
  910. /// </summary>
  911. public int maxVisibleLines
  912. {
  913. get { return m_maxVisibleLines; }
  914. set { if (m_maxVisibleLines == value) return; m_havePropertiesChanged = true; m_isInputParsingRequired = true; m_maxVisibleLines = value; SetVerticesDirty(); }
  915. }
  916. protected int m_maxVisibleLines = 99999;
  917. /// <summary>
  918. /// Determines if the text's vertical alignment will be adjusted based on visible descender of the text.
  919. /// </summary>
  920. public bool useMaxVisibleDescender
  921. {
  922. get { return m_useMaxVisibleDescender; }
  923. set { if (m_useMaxVisibleDescender == value) return; m_havePropertiesChanged = true; m_isInputParsingRequired = true; m_useMaxVisibleDescender = value; SetVerticesDirty(); }
  924. }
  925. [SerializeField]
  926. protected bool m_useMaxVisibleDescender = true;
  927. /// <summary>
  928. /// Controls which page of text is shown
  929. /// </summary>
  930. public int pageToDisplay
  931. {
  932. get { return m_pageToDisplay; }
  933. set { if (m_pageToDisplay == value) return; m_havePropertiesChanged = true; m_pageToDisplay = value; SetVerticesDirty(); }
  934. }
  935. [SerializeField]
  936. protected int m_pageToDisplay = 1;
  937. protected bool m_isNewPage = false;
  938. /// <summary>
  939. /// The margins of the text object.
  940. /// </summary>
  941. public virtual Vector4 margin
  942. {
  943. get { return m_margin; }
  944. set { if (m_margin == value) return; m_margin = value; ComputeMarginSize(); m_havePropertiesChanged = true; SetVerticesDirty(); }
  945. }
  946. [SerializeField]
  947. protected Vector4 m_margin = new Vector4(0, 0, 0, 0);
  948. protected float m_marginLeft;
  949. protected float m_marginRight;
  950. protected float m_marginWidth; // Width of the RectTransform minus left and right margins.
  951. protected float m_marginHeight; // Height of the RectTransform minus top and bottom margins.
  952. protected float m_width = -1;
  953. /// <summary>
  954. /// Returns data about the text object which includes information about each character, word, line, link, etc.
  955. /// </summary>
  956. public TMP_TextInfo textInfo
  957. {
  958. get { return m_textInfo; }
  959. }
  960. //[SerializeField]
  961. protected TMP_TextInfo m_textInfo; // Class which holds information about the Text object such as characters, lines, mesh data as well as metrics.
  962. /// <summary>
  963. /// Property tracking if any of the text properties have changed. Flag is set before the text is regenerated.
  964. /// </summary>
  965. public bool havePropertiesChanged
  966. {
  967. get { return m_havePropertiesChanged; }
  968. set { if (m_havePropertiesChanged == value) return; m_havePropertiesChanged = value; m_isInputParsingRequired = true; SetAllDirty(); }
  969. }
  970. //[SerializeField]
  971. protected bool m_havePropertiesChanged; // Used to track when properties of the text object have changed.
  972. /// <summary>
  973. /// Property to handle legacy animation component.
  974. /// </summary>
  975. public bool isUsingLegacyAnimationComponent
  976. {
  977. get { return m_isUsingLegacyAnimationComponent; }
  978. set { m_isUsingLegacyAnimationComponent = value; }
  979. }
  980. [SerializeField]
  981. protected bool m_isUsingLegacyAnimationComponent;
  982. /// <summary>
  983. /// Returns are reference to the Transform
  984. /// </summary>
  985. public new Transform transform
  986. {
  987. get
  988. {
  989. if (m_transform == null)
  990. m_transform = GetComponent<Transform>();
  991. return m_transform;
  992. }
  993. }
  994. protected Transform m_transform;
  995. /// <summary>
  996. /// Returns are reference to the RectTransform
  997. /// </summary>
  998. public new RectTransform rectTransform
  999. {
  1000. get
  1001. {
  1002. if (m_rectTransform == null)
  1003. m_rectTransform = GetComponent<RectTransform>();
  1004. return m_rectTransform;
  1005. }
  1006. }
  1007. protected RectTransform m_rectTransform;
  1008. /// <summary>
  1009. /// Used to track potential changes in RectTransform size to allow us to ignore OnRectTransformDimensionsChange getting called due to rounding errors when using Stretch Anchors.
  1010. /// </summary>
  1011. protected Vector2 m_PreviousRectTransformSize;
  1012. /// <summary>
  1013. /// Used to track potential changes in pivot position to allow us to ignore OnRectTransformDimensionsChange getting called due to rounding errors when using Stretch Anchors.
  1014. /// </summary>
  1015. protected Vector2 m_PreviousPivotPosition;
  1016. /// <summary>
  1017. /// Enables control over setting the size of the text container to match the text object.
  1018. /// </summary>
  1019. public virtual bool autoSizeTextContainer
  1020. {
  1021. get;
  1022. set;
  1023. }
  1024. protected bool m_autoSizeTextContainer;
  1025. /// <summary>
  1026. /// The mesh used by the font asset and material assigned to the text object.
  1027. /// </summary>
  1028. public virtual Mesh mesh
  1029. {
  1030. get { return m_mesh; }
  1031. }
  1032. protected Mesh m_mesh;
  1033. /// <summary>
  1034. /// Determines if the geometry of the characters will be quads or volumetric (cubes).
  1035. /// </summary>
  1036. public bool isVolumetricText
  1037. {
  1038. get { return m_isVolumetricText; }
  1039. set { if (m_isVolumetricText == value) return; m_havePropertiesChanged = value; m_textInfo.ResetVertexLayout(value); m_isInputParsingRequired = true; SetVerticesDirty(); SetLayoutDirty(); }
  1040. }
  1041. [SerializeField]
  1042. protected bool m_isVolumetricText;
  1043. /// <summary>
  1044. /// Returns the bounds of the mesh of the text object in world space.
  1045. /// </summary>
  1046. public Bounds bounds
  1047. {
  1048. get
  1049. {
  1050. if (m_mesh == null) return new Bounds();
  1051. return GetCompoundBounds();
  1052. }
  1053. }
  1054. /// <summary>
  1055. /// Returns the bounds of the text of the text object.
  1056. /// </summary>
  1057. public Bounds textBounds
  1058. {
  1059. get
  1060. {
  1061. if (m_textInfo == null) return new Bounds();
  1062. return GetTextBounds();
  1063. }
  1064. }
  1065. // *** Unity Event Handling ***
  1066. /// <summary>
  1067. /// Event delegate to allow custom loading of TMP_FontAsset when using the <font="Font Asset Name"> tag.
  1068. /// </summary>
  1069. public static event Func<int, string, TMP_FontAsset> OnFontAssetRequest;
  1070. /// <summary>
  1071. /// Event delegate to allow custom loading of TMP_SpriteAsset when using the <sprite="Sprite Asset Name"> tag.
  1072. /// </summary>
  1073. public static event Func<int, string, TMP_SpriteAsset> OnSpriteAssetRequest;
  1074. /// <summary>
  1075. /// Event delegate to allow modifying the text geometry before it is uploaded to the mesh and rendered.
  1076. /// </summary>
  1077. public virtual event Action<TMP_TextInfo> OnPreRenderText = delegate { };
  1078. // *** SPECIAL COMPONENTS ***
  1079. /// <summary>
  1080. /// Component used to control wrapping of text following some arbitrary shape.
  1081. /// </summary>
  1082. //public MarginShaper marginShaper
  1083. //{
  1084. // get
  1085. // {
  1086. // if (m_marginShaper == null) m_marginShaper = GetComponent<MarginShaper>();
  1087. // return m_marginShaper;
  1088. // }
  1089. //}
  1090. //[SerializeField]
  1091. //protected MarginShaper m_marginShaper;
  1092. /// <summary>
  1093. /// Component used to control and animate sprites in the text object.
  1094. /// </summary>
  1095. protected TMP_SpriteAnimator spriteAnimator
  1096. {
  1097. get
  1098. {
  1099. if (m_spriteAnimator == null)
  1100. {
  1101. m_spriteAnimator = GetComponent<TMP_SpriteAnimator>();
  1102. if (m_spriteAnimator == null) m_spriteAnimator = gameObject.AddComponent<TMP_SpriteAnimator>();
  1103. }
  1104. return m_spriteAnimator;
  1105. }
  1106. }
  1107. //[SerializeField]
  1108. protected TMP_SpriteAnimator m_spriteAnimator;
  1109. /// <summary>
  1110. ///
  1111. /// </summary>
  1112. //public TMP_TextShaper textShaper
  1113. //{
  1114. // get
  1115. // {
  1116. // if (m_textShaper == null)
  1117. // m_textShaper = GetComponent<TMP_TextShaper>();
  1118. // return m_textShaper;
  1119. // }
  1120. //}
  1121. //[SerializeField]
  1122. //protected TMP_TextShaper m_textShaper;
  1123. // *** PROPERTIES RELATED TO UNITY LAYOUT SYSTEM ***
  1124. /// <summary>
  1125. ///
  1126. /// </summary>
  1127. public float flexibleHeight { get { return m_flexibleHeight; } }
  1128. protected float m_flexibleHeight = -1f;
  1129. /// <summary>
  1130. ///
  1131. /// </summary>
  1132. public float flexibleWidth { get { return m_flexibleWidth; } }
  1133. protected float m_flexibleWidth = -1f;
  1134. /// <summary>
  1135. ///
  1136. /// </summary>
  1137. public float minWidth { get { return m_minWidth; } }
  1138. protected float m_minWidth;
  1139. /// <summary>
  1140. ///
  1141. /// </summary>
  1142. public float minHeight { get { return m_minHeight; } }
  1143. protected float m_minHeight;
  1144. /// <summary>
  1145. ///
  1146. /// </summary>
  1147. public float maxWidth { get { return m_maxWidth; } }
  1148. protected float m_maxWidth;
  1149. /// <summary>
  1150. ///
  1151. /// </summary>
  1152. public float maxHeight { get { return m_maxHeight; } }
  1153. protected float m_maxHeight;
  1154. /// <summary>
  1155. ///
  1156. /// </summary>
  1157. protected LayoutElement layoutElement
  1158. {
  1159. get
  1160. {
  1161. if (m_LayoutElement == null)
  1162. {
  1163. m_LayoutElement = GetComponent<LayoutElement>();
  1164. }
  1165. return m_LayoutElement;
  1166. }
  1167. }
  1168. protected LayoutElement m_LayoutElement;
  1169. /// <summary>
  1170. /// Computed preferred width of the text object.
  1171. /// </summary>
  1172. public virtual float preferredWidth { get { m_preferredWidth = GetPreferredWidth(); return m_preferredWidth; } }
  1173. protected float m_preferredWidth;
  1174. protected float m_renderedWidth;
  1175. protected bool m_isPreferredWidthDirty;
  1176. /// <summary>
  1177. /// Computed preferred height of the text object.
  1178. /// </summary>
  1179. public virtual float preferredHeight { get { m_preferredHeight = GetPreferredHeight(); return m_preferredHeight; } }
  1180. protected float m_preferredHeight;
  1181. protected float m_renderedHeight;
  1182. protected bool m_isPreferredHeightDirty;
  1183. protected bool m_isCalculatingPreferredValues;
  1184. /// <summary>
  1185. /// Compute the rendered width of the text object.
  1186. /// </summary>
  1187. public virtual float renderedWidth { get { return GetRenderedWidth(); } }
  1188. /// <summary>
  1189. /// Compute the rendered height of the text object.
  1190. /// </summary>
  1191. public virtual float renderedHeight { get { return GetRenderedHeight(); } }
  1192. /// <summary>
  1193. ///
  1194. /// </summary>
  1195. public int layoutPriority { get { return m_layoutPriority; } }
  1196. protected int m_layoutPriority = 0;
  1197. protected bool m_isLayoutDirty;
  1198. protected bool m_isAwake;
  1199. internal bool m_isWaitingOnResourceLoad;
  1200. internal bool m_isInputParsingRequired = false; // Used to determine if the input text needs to be re-parsed.
  1201. //internal enum CharacterSubstitution
  1202. //{
  1203. // None = 0x00,
  1204. // AnyByEndOfLine = 0x03,
  1205. // SoftHyphenByHyphenMinus = 0xAD,
  1206. //}
  1207. protected struct CharacterSubstitution
  1208. {
  1209. public int index;
  1210. public uint unicode;
  1211. public CharacterSubstitution (int index, uint unicode)
  1212. {
  1213. this.index = index;
  1214. this.unicode = unicode;
  1215. }
  1216. }
  1217. // Protected Fields
  1218. internal enum TextInputSources { Text = 0, SetText = 1, SetCharArray = 2, String = 3 };
  1219. //[SerializeField]
  1220. internal TextInputSources m_inputSource;
  1221. protected float m_fontScale; // Scaling of the font based on Atlas true Font Size and Rendered Font Size.
  1222. protected float m_fontScaleMultiplier; // Used for handling of superscript and subscript.
  1223. protected char[] m_htmlTag = new char[128]; // Maximum length of rich text tag. This is preallocated to avoid GC.
  1224. protected RichTextTagAttribute[] m_xmlAttribute = new RichTextTagAttribute[8];
  1225. protected float[] m_attributeParameterValues = new float[16];
  1226. protected float tag_LineIndent = 0;
  1227. protected float tag_Indent = 0;
  1228. protected TMP_TextProcessingStack<float> m_indentStack = new TMP_TextProcessingStack<float>(new float[16]);
  1229. protected bool tag_NoParsing;
  1230. //protected TMP_LinkInfo tag_LinkInfo = new TMP_LinkInfo();
  1231. protected bool m_isParsingText;
  1232. protected Matrix4x4 m_FXMatrix;
  1233. protected bool m_isFXMatrixSet;
  1234. /// <summary>
  1235. /// Array containing the Unicode characters to be parsed.
  1236. /// </summary>
  1237. protected UnicodeChar[] m_InternalParsingBuffer = new UnicodeChar[8];
  1238. /// <summary>
  1239. /// The number of Unicode characters that have been parsed and contained in the m_InternalParsingBuffer
  1240. /// </summary>
  1241. protected int m_InternalParsingBufferSize;
  1242. protected struct UnicodeChar
  1243. {
  1244. public int unicode;
  1245. public int stringIndex;
  1246. public int length;
  1247. }
  1248. protected struct SpecialCharacter
  1249. {
  1250. public TMP_Character character;
  1251. public TMP_FontAsset fontAsset;
  1252. public Material material;
  1253. public int materialIndex;
  1254. public SpecialCharacter(TMP_Character character, int materialIndex)
  1255. {
  1256. this.character = character;
  1257. this.fontAsset = character.textAsset as TMP_FontAsset;
  1258. this.material = this.fontAsset != null ? this.fontAsset.material : null;
  1259. this.materialIndex = materialIndex;
  1260. }
  1261. }
  1262. private TMP_CharacterInfo[] m_internalCharacterInfo; // Used by functions to calculate preferred values.
  1263. protected char[] m_input_CharArray = new char[256]; // This array hold the characters from the SetText();
  1264. private int m_charArray_Length = 0;
  1265. protected int m_totalCharacterCount;
  1266. // Structures used to save the state of the text layout in conjunction with line breaking / word wrapping.
  1267. protected WordWrapState m_SavedWordWrapState = new WordWrapState();
  1268. protected WordWrapState m_SavedLineState = new WordWrapState();
  1269. protected WordWrapState m_SavedEllipsisState = new WordWrapState();
  1270. protected WordWrapState m_SavedLastValidState = new WordWrapState();
  1271. protected WordWrapState m_SavedSoftLineBreakState = new WordWrapState();
  1272. //internal Stack<WordWrapState> m_LineBreakCandiateStack = new Stack<WordWrapState>();
  1273. internal TMP_TextProcessingStack<WordWrapState> m_EllipsisInsertionCandidateStack = new TMP_TextProcessingStack<WordWrapState>(8, 8);
  1274. // Fields whose state is saved in conjunction with text parsing and word wrapping.
  1275. protected int m_characterCount;
  1276. //protected int m_visibleCharacterCount;
  1277. //protected int m_visibleSpriteCount;
  1278. protected int m_firstCharacterOfLine;
  1279. protected int m_firstVisibleCharacterOfLine;
  1280. protected int m_lastCharacterOfLine;
  1281. protected int m_lastVisibleCharacterOfLine;
  1282. protected int m_lineNumber;
  1283. protected int m_lineVisibleCharacterCount;
  1284. protected int m_pageNumber;
  1285. protected float m_PageAscender;
  1286. protected float m_maxTextAscender;
  1287. protected float m_maxCapHeight;
  1288. protected float m_ElementAscender;
  1289. protected float m_ElementDescender;
  1290. protected float m_maxLineAscender;
  1291. protected float m_maxLineDescender;
  1292. protected float m_startOfLineAscender;
  1293. protected float m_startOfLineDescender;
  1294. //protected float m_maxFontScale;
  1295. protected float m_lineOffset;
  1296. protected Extents m_meshExtents;
  1297. // Fields used for vertex colors
  1298. protected Color32 m_htmlColor = new Color(255, 255, 255, 128);
  1299. protected TMP_TextProcessingStack<Color32> m_colorStack = new TMP_TextProcessingStack<Color32>(new Color32[16]);
  1300. protected TMP_TextProcessingStack<Color32> m_underlineColorStack = new TMP_TextProcessingStack<Color32>(new Color32[16]);
  1301. protected TMP_TextProcessingStack<Color32> m_strikethroughColorStack = new TMP_TextProcessingStack<Color32>(new Color32[16]);
  1302. protected TMP_TextProcessingStack<HighlightState> m_HighlightStateStack = new TMP_TextProcessingStack<HighlightState>(new HighlightState[16]);
  1303. protected TMP_ColorGradient m_colorGradientPreset;
  1304. protected TMP_TextProcessingStack<TMP_ColorGradient> m_colorGradientStack = new TMP_TextProcessingStack<TMP_ColorGradient>(new TMP_ColorGradient[16]);
  1305. protected bool m_colorGradientPresetIsTinted;
  1306. protected float m_tabSpacing = 0;
  1307. protected float m_spacing = 0;
  1308. // STYLE TAGS
  1309. protected TMP_TextProcessingStack<int>[] m_TextStyleStacks = new TMP_TextProcessingStack<int>[8];
  1310. protected int m_TextStyleStackDepth = 0;
  1311. protected TMP_TextProcessingStack<int> m_ItalicAngleStack = new TMP_TextProcessingStack<int>(new int[16]);
  1312. protected int m_ItalicAngle;
  1313. protected TMP_TextProcessingStack<int> m_actionStack = new TMP_TextProcessingStack<int>(new int[16]);
  1314. protected float m_padding = 0;
  1315. protected float m_baselineOffset; // Used for superscript and subscript.
  1316. protected TMP_TextProcessingStack<float> m_baselineOffsetStack = new TMP_TextProcessingStack<float>(new float[16]);
  1317. protected float m_xAdvance; // Tracks x advancement from character to character.
  1318. protected TMP_TextElementType m_textElementType;
  1319. protected TMP_TextElement m_cached_TextElement; // Glyph / Character information is cached into this variable which is faster than having to fetch from the Dictionary multiple times.
  1320. protected SpecialCharacter m_Ellipsis;
  1321. protected SpecialCharacter m_Underline;
  1322. protected TMP_SpriteAsset m_defaultSpriteAsset;
  1323. protected TMP_SpriteAsset m_currentSpriteAsset;
  1324. protected int m_spriteCount = 0;
  1325. protected int m_spriteIndex;
  1326. protected int m_spriteAnimationID;
  1327. //protected TMP_XmlTagStack<int> m_spriteAnimationStack = new TMP_XmlTagStack<int>(new int[16]);
  1328. /// <summary>
  1329. /// Method which derived classes need to override to load Font Assets.
  1330. /// </summary>
  1331. protected virtual void LoadFontAsset() { }
  1332. /// <summary>
  1333. /// Function called internally when a new shared material is assigned via the fontSharedMaterial property.
  1334. /// </summary>
  1335. /// <param name="mat"></param>
  1336. protected virtual void SetSharedMaterial(Material mat) { }
  1337. /// <summary>
  1338. /// Function called internally when a new material is assigned via the fontMaterial property.
  1339. /// </summary>
  1340. protected virtual Material GetMaterial(Material mat) { return null; }
  1341. /// <summary>
  1342. /// Function called internally when assigning a new base material.
  1343. /// </summary>
  1344. /// <param name="mat"></param>
  1345. protected virtual void SetFontBaseMaterial(Material mat) { }
  1346. /// <summary>
  1347. /// Method which returns an array containing the materials used by the text object.
  1348. /// </summary>
  1349. /// <returns></returns>
  1350. protected virtual Material[] GetSharedMaterials() { return null; }
  1351. /// <summary>
  1352. ///
  1353. /// </summary>
  1354. protected virtual void SetSharedMaterials(Material[] materials) { }
  1355. /// <summary>
  1356. /// Method returning instances of the materials used by the text object.
  1357. /// </summary>
  1358. /// <returns></returns>
  1359. protected virtual Material[] GetMaterials(Material[] mats) { return null; }
  1360. /// <summary>
  1361. /// Method to set the materials of the text and sub text objects.
  1362. /// </summary>
  1363. /// <param name="mats"></param>
  1364. //protected virtual void SetMaterials (Material[] mats) { }
  1365. /// <summary>
  1366. /// Function used to create an instance of the material
  1367. /// </summary>
  1368. /// <param name="source"></param>
  1369. /// <returns></returns>
  1370. protected virtual Material CreateMaterialInstance(Material source)
  1371. {
  1372. Material mat = new Material(source);
  1373. mat.shaderKeywords = source.shaderKeywords;
  1374. mat.name += " (Instance)";
  1375. return mat;
  1376. }
  1377. protected void SetVertexColorGradient(TMP_ColorGradient gradient)
  1378. {
  1379. if (gradient == null) return;
  1380. m_fontColorGradient.bottomLeft = gradient.bottomLeft;
  1381. m_fontColorGradient.bottomRight = gradient.bottomRight;
  1382. m_fontColorGradient.topLeft = gradient.topLeft;
  1383. m_fontColorGradient.topRight = gradient.topRight;
  1384. SetVerticesDirty();
  1385. }
  1386. /// <summary>
  1387. /// Function to control the sorting of the geometry of the text object.
  1388. /// </summary>
  1389. protected void SetTextSortingOrder(VertexSortingOrder order)
  1390. {
  1391. }
  1392. /// <summary>
  1393. /// Function to sort the geometry of the text object in accordance to the provided order.
  1394. /// </summary>
  1395. /// <param name="order"></param>
  1396. protected void SetTextSortingOrder(int[] order)
  1397. {
  1398. }
  1399. /// <summary>
  1400. /// Function called internally to set the face color of the material. This will results in an instance of the material.
  1401. /// </summary>
  1402. /// <param name="color"></param>
  1403. protected virtual void SetFaceColor(Color32 color) { }
  1404. /// <summary>
  1405. /// Function called internally to set the outline color of the material. This will results in an instance of the material.
  1406. /// </summary>
  1407. /// <param name="color"></param>
  1408. protected virtual void SetOutlineColor(Color32 color) { }
  1409. /// <summary>
  1410. /// Function called internally to set the outline thickness property of the material. This will results in an instance of the material.
  1411. /// </summary>
  1412. /// <param name="thickness"></param>
  1413. protected virtual void SetOutlineThickness(float thickness) { }
  1414. /// <summary>
  1415. /// Set the Render Queue and ZTest mode on the current material
  1416. /// </summary>
  1417. protected virtual void SetShaderDepth() { }
  1418. /// <summary>
  1419. /// Set the culling mode on the material.
  1420. /// </summary>
  1421. protected virtual void SetCulling() { }
  1422. /// <summary>
  1423. ///
  1424. /// </summary>
  1425. internal virtual void UpdateCulling() {}
  1426. /// <summary>
  1427. /// Get the padding value for the currently assigned material
  1428. /// </summary>
  1429. /// <returns></returns>
  1430. protected virtual float GetPaddingForMaterial()
  1431. {
  1432. ShaderUtilities.GetShaderPropertyIDs();
  1433. if (m_sharedMaterial == null) return 0;
  1434. m_padding = ShaderUtilities.GetPadding(m_sharedMaterial, m_enableExtraPadding, m_isUsingBold);
  1435. m_isMaskingEnabled = ShaderUtilities.IsMaskingEnabled(m_sharedMaterial);
  1436. m_isSDFShader = m_sharedMaterial.HasProperty(ShaderUtilities.ID_WeightNormal);
  1437. return m_padding;
  1438. }
  1439. /// <summary>
  1440. /// Get the padding value for the given material
  1441. /// </summary>
  1442. /// <returns></returns>
  1443. protected virtual float GetPaddingForMaterial(Material mat)
  1444. {
  1445. if (mat == null)
  1446. return 0;
  1447. m_padding = ShaderUtilities.GetPadding(mat, m_enableExtraPadding, m_isUsingBold);
  1448. m_isMaskingEnabled = ShaderUtilities.IsMaskingEnabled(m_sharedMaterial);
  1449. m_isSDFShader = mat.HasProperty(ShaderUtilities.ID_WeightNormal);
  1450. return m_padding;
  1451. }
  1452. /// <summary>
  1453. /// Method to return the local corners of the Text Container or RectTransform.
  1454. /// </summary>
  1455. /// <returns></returns>
  1456. protected virtual Vector3[] GetTextContainerLocalCorners() { return null; }
  1457. // PUBLIC FUNCTIONS
  1458. protected bool m_ignoreActiveState;
  1459. /// <summary>
  1460. /// Function to force regeneration of the text object before its normal process time. This is useful when changes to the text object properties need to be applied immediately.
  1461. /// </summary>
  1462. /// <param name="ignoreActiveState">Ignore Active State of text objects. Inactive objects are ignored by default.</param>
  1463. /// <param name="forceTextReparsing">Force re-parsing of the text.</param>
  1464. public virtual void ForceMeshUpdate(bool ignoreActiveState = false, bool forceTextReparsing = false) { }
  1465. /// <summary>
  1466. /// Method used for resetting vertex layout when switching to and from Volumetric Text mode.
  1467. /// </summary>
  1468. /// <param name="updateMesh"></param>
  1469. //protected virtual void ResetVertexLayout() { }
  1470. /// <summary>
  1471. /// Internal function used by the Text Input Field to populate TMP_TextInfo data.
  1472. /// </summary>
  1473. internal void SetTextInternal(string text)
  1474. {
  1475. m_text = text;
  1476. m_renderMode = TextRenderFlags.DontRender;
  1477. m_isInputParsingRequired = true;
  1478. ForceMeshUpdate();
  1479. m_renderMode = TextRenderFlags.Render;
  1480. }
  1481. /// <summary>
  1482. /// Function to force the regeneration of the text object.
  1483. /// </summary>
  1484. /// <param name="flags"> Flags to control which portions of the geometry gets uploaded.</param>
  1485. //public virtual void ForceMeshUpdate(TMP_VertexDataUpdateFlags flags) { }
  1486. /// <summary>
  1487. /// Function to update the geometry of the main and sub text objects.
  1488. /// </summary>
  1489. /// <param name="mesh"></param>
  1490. /// <param name="index"></param>
  1491. public virtual void UpdateGeometry(Mesh mesh, int index) { }
  1492. /// <summary>
  1493. /// Function to push the updated vertex data into the mesh and renderer.
  1494. /// </summary>
  1495. public virtual void UpdateVertexData(TMP_VertexDataUpdateFlags flags) { }
  1496. /// <summary>
  1497. /// Function to push the updated vertex data into the mesh and renderer.
  1498. /// </summary>
  1499. public virtual void UpdateVertexData() { }
  1500. /// <summary>
  1501. /// Function to push a new set of vertices to the mesh.
  1502. /// </summary>
  1503. /// <param name="vertices"></param>
  1504. public virtual void SetVertices(Vector3[] vertices) { }
  1505. /// <summary>
  1506. /// Function to be used to force recomputing of character padding when Shader / Material properties have been changed via script.
  1507. /// </summary>
  1508. public virtual void UpdateMeshPadding() { }
  1509. /// <summary>
  1510. ///
  1511. /// </summary>
  1512. //public virtual new void UpdateGeometry() { }
  1513. /// <summary>
  1514. /// Tweens the CanvasRenderer color associated with this Graphic.
  1515. /// </summary>
  1516. /// <param name="targetColor">Target color.</param>
  1517. /// <param name="duration">Tween duration.</param>
  1518. /// <param name="ignoreTimeScale">Should ignore Time.scale?</param>
  1519. /// <param name="useAlpha">Should also Tween the alpha channel?</param>
  1520. public override void CrossFadeColor(Color targetColor, float duration, bool ignoreTimeScale, bool useAlpha)
  1521. {
  1522. base.CrossFadeColor(targetColor, duration, ignoreTimeScale, useAlpha);
  1523. InternalCrossFadeColor(targetColor, duration, ignoreTimeScale, useAlpha);
  1524. }
  1525. /// <summary>
  1526. /// Tweens the alpha of the CanvasRenderer color associated with this Graphic.
  1527. /// </summary>
  1528. /// <param name="alpha">Target alpha.</param>
  1529. /// <param name="duration">Duration of the tween in seconds.</param>
  1530. /// <param name="ignoreTimeScale">Should ignore Time.scale?</param>
  1531. public override void CrossFadeAlpha(float alpha, float duration, bool ignoreTimeScale)
  1532. {
  1533. base.CrossFadeAlpha(alpha, duration, ignoreTimeScale);
  1534. InternalCrossFadeAlpha(alpha, duration, ignoreTimeScale);
  1535. }
  1536. /// <summary>
  1537. ///
  1538. /// </summary>
  1539. /// <param name="targetColor"></param>
  1540. /// <param name="duration"></param>
  1541. /// <param name="ignoreTimeScale"></param>
  1542. /// <param name="useAlpha"></param>
  1543. /// <param name="useRGB"></param>
  1544. protected virtual void InternalCrossFadeColor(Color targetColor, float duration, bool ignoreTimeScale, bool useAlpha) { }
  1545. /// <summary>
  1546. ///
  1547. /// </summary>
  1548. /// <param name="alpha"></param>
  1549. /// <param name="duration"></param>
  1550. /// <param name="ignoreTimeScale"></param>
  1551. protected virtual void InternalCrossFadeAlpha(float alpha, float duration, bool ignoreTimeScale) { }
  1552. /// <summary>
  1553. /// Method to parse the input text based on its source
  1554. /// </summary>
  1555. protected void ParseInputText()
  1556. {
  1557. //Debug.Log("Re-parsing Text.");
  1558. ////Profiler.BeginSample("ParseInputText()");
  1559. m_isInputParsingRequired = false;
  1560. switch (m_inputSource)
  1561. {
  1562. case TextInputSources.String:
  1563. case TextInputSources.Text:
  1564. if (m_TextPreprocessor != null)
  1565. m_InternalParsingBufferSize = StringToInternalParsingBuffer(m_TextPreprocessor.PreprocessText(m_text), ref m_InternalParsingBuffer);
  1566. else
  1567. m_InternalParsingBufferSize = StringToInternalParsingBuffer(m_text, ref m_InternalParsingBuffer);
  1568. break;
  1569. case TextInputSources.SetText:
  1570. m_InternalParsingBufferSize = CharArrayToInternalParsingBuffer(m_input_CharArray, ref m_InternalParsingBuffer);
  1571. break;
  1572. case TextInputSources.SetCharArray:
  1573. break;
  1574. }
  1575. SetArraySizes(m_InternalParsingBuffer);
  1576. ////Profiler.EndSample();
  1577. }
  1578. /// <summary>
  1579. ///
  1580. /// </summary>
  1581. /// <param name="text"></param>
  1582. public void SetText(string text, bool syncTextInputBox = true)
  1583. {
  1584. this.text = text;
  1585. }
  1586. /// <summary>
  1587. /// <para>Formatted string containing a pattern and a value representing the text to be rendered.</para>
  1588. /// <para>Ex. TMP_Text.SetText("A = {0}, B = {1:00}, C = {2:000.0}", 10.75f, 10.75f, 10.75f);</para>
  1589. /// <para>Results "A = 10.75, B = 11, C = 010.8."</para>
  1590. /// </summary>
  1591. /// <param name="text">String containing the pattern.</param>
  1592. /// <param name="arg0">First float value.</param>
  1593. public void SetText(string text, float arg0)
  1594. {
  1595. SetText(text, arg0, 0, 0, 0, 0, 0, 0, 0);
  1596. }
  1597. /// <summary>
  1598. /// <para>Formatted string containing a pattern and a value representing the text to be rendered.</para>
  1599. /// <para>Ex. TMP_Text.SetText("A = {0}, B = {1:00}, C = {2:000.0}", 10.75f, 10.75f, 10.75f);</para>
  1600. /// <para>Results "A = 10.75, B = 11, C = 010.8."</para>
  1601. /// </summary>
  1602. /// <param name="text">String containing the pattern.</param>
  1603. /// <param name="arg0">First float value.</param>
  1604. /// <param name="arg1">Second float value.</param>
  1605. public void SetText(string text, float arg0, float arg1)
  1606. {
  1607. SetText(text, arg0, arg1, 0, 0, 0, 0, 0, 0);
  1608. }
  1609. /// <summary>
  1610. /// <para>Formatted string containing a pattern and a value representing the text to be rendered.</para>
  1611. /// <para>Ex. TMP_Text.SetText("A = {0}, B = {1:00}, C = {2:000.0}", 10.75f, 10.75f, 10.75f);</para>
  1612. /// <para>Results "A = 10.75, B = 11, C = 010.8."</para>
  1613. /// </summary>
  1614. /// <param name="text">String containing the pattern.</param>
  1615. /// <param name="arg0">First float value.</param>
  1616. /// <param name="arg1">Second float value.</param>
  1617. /// <param name="arg2">Third float value.</param>
  1618. public void SetText(string text, float arg0, float arg1, float arg2)
  1619. {
  1620. SetText(text, arg0, arg1, arg2, 0, 0, 0, 0, 0);
  1621. }
  1622. /// <summary>
  1623. /// <para>Formatted string containing a pattern and a value representing the text to be rendered.</para>
  1624. /// <para>Ex. TMP_Text.SetText("A = {0}, B = {1:00}, C = {2:000.0}", 10.75f, 10.75f, 10.75f);</para>
  1625. /// <para>Results "A = 10.75, B = 11, C = 010.8."</para>
  1626. /// </summary>
  1627. /// <param name="text">String containing the pattern.</param>
  1628. /// <param name="arg0">First float value.</param>
  1629. /// <param name="arg1">Second float value.</param>
  1630. /// <param name="arg2">Third float value.</param>
  1631. /// <param name="arg3">Forth float value.</param>
  1632. public void SetText(string text, float arg0, float arg1, float arg2, float arg3)
  1633. {
  1634. SetText(text, arg0, arg1, arg2, arg3, 0, 0, 0, 0);
  1635. }
  1636. /// <summary>
  1637. /// <para>Formatted string containing a pattern and a value representing the text to be rendered.</para>
  1638. /// <para>Ex. TMP_Text.SetText("A = {0}, B = {1:00}, C = {2:000.0}", 10.75f, 10.75f, 10.75f);</para>
  1639. /// <para>Results "A = 10.75, B = 11, C = 010.8."</para>
  1640. /// </summary>
  1641. /// <param name="text">String containing the pattern.</param>
  1642. /// <param name="arg0">First float value.</param>
  1643. /// <param name="arg1">Second float value.</param>
  1644. /// <param name="arg2">Third float value.</param>
  1645. /// <param name="arg3">Forth float value.</param>
  1646. /// <param name="arg4">Fifth float value.</param>
  1647. public void SetText(string text, float arg0, float arg1, float arg2, float arg3, float arg4)
  1648. {
  1649. SetText(text, arg0, arg1, arg2, arg3, arg4, 0, 0, 0);
  1650. }
  1651. /// <summary>
  1652. /// <para>Formatted string containing a pattern and a value representing the text to be rendered.</para>
  1653. /// <para>Ex. TMP_Text.SetText("A = {0}, B = {1:00}, C = {2:000.0}", 10.75f, 10.75f, 10.75f);</para>
  1654. /// <para>Results "A = 10.75, B = 11, C = 010.8."</para>
  1655. /// </summary>
  1656. /// <param name="text">String containing the pattern.</param>
  1657. /// <param name="arg0">First float value.</param>
  1658. /// <param name="arg1">Second float value.</param>
  1659. /// <param name="arg2">Third float value.</param>
  1660. /// <param name="arg3">Forth float value.</param>
  1661. /// <param name="arg4">Fifth float value.</param>
  1662. /// <param name="arg5">Sixth float value.</param>
  1663. public void SetText(string text, float arg0, float arg1, float arg2, float arg3, float arg4, float arg5)
  1664. {
  1665. SetText(text, arg0, arg1, arg2, arg3, arg4, arg5, 0, 0);
  1666. }
  1667. /// <summary>
  1668. /// <para>Formatted string containing a pattern and a value representing the text to be rendered.</para>
  1669. /// <para>Ex. TMP_Text.SetText("A = {0}, B = {1:00}, C = {2:000.0}", 10.75f, 10.75f, 10.75f);</para>
  1670. /// <para>Results "A = 10.75, B = 11, C = 010.8."</para>
  1671. /// </summary>
  1672. /// <param name="text">String containing the pattern.</param>
  1673. /// <param name="arg0">First float value.</param>
  1674. /// <param name="arg1">Second float value.</param>
  1675. /// <param name="arg2">Third float value.</param>
  1676. /// <param name="arg3">Forth float value.</param>
  1677. /// <param name="arg4">Fifth float value.</param>
  1678. /// <param name="arg5">Sixth float value.</param>
  1679. /// <param name="arg6">Seventh float value.</param>
  1680. public void SetText(string text, float arg0, float arg1, float arg2, float arg3, float arg4, float arg5, float arg6)
  1681. {
  1682. SetText(text, arg0, arg1, arg2, arg3, arg4, arg5, arg6, 0);
  1683. }
  1684. /// <summary>
  1685. /// <para>Formatted string containing a pattern and a value representing the text to be rendered.</para>
  1686. /// <para>Ex. TMP_Text.SetText("A = {0}, B = {1:00}, C = {2:000.0}", 10.75f, 10.75f, 10.75f);</para>
  1687. /// <para>Results "A = 10.75, B = 11, C = 010.8."</para>
  1688. /// </summary>
  1689. /// <param name="text">String containing the pattern.</param>
  1690. /// <param name="arg0">First float value.</param>
  1691. /// <param name="arg1">Second float value.</param>
  1692. /// <param name="arg2">Third float value.</param>
  1693. /// <param name="arg3">Forth float value.</param>
  1694. /// <param name="arg4">Fifth float value.</param>
  1695. /// <param name="arg5">Sixth float value.</param>
  1696. /// <param name="arg6">Seventh float value.</param>
  1697. /// <param name="arg7">Eighth float value.</param>
  1698. public void SetText(string text, float arg0, float arg1, float arg2, float arg3, float arg4, float arg5, float arg6, float arg7)
  1699. {
  1700. int argIndex = 0;
  1701. int padding = 0;
  1702. int decimalPrecision = 0;
  1703. int readFlag = 0;
  1704. int readIndex = 0;
  1705. int writeIndex = 0;
  1706. for (; readIndex < text.Length; readIndex++)
  1707. {
  1708. char c = text[readIndex];
  1709. if (c == '{')
  1710. {
  1711. readFlag = 1;
  1712. continue;
  1713. }
  1714. if (c == '}')
  1715. {
  1716. // Add arg(index) to array
  1717. switch (argIndex)
  1718. {
  1719. case 0:
  1720. AddFloatToCharArray(arg0, padding, decimalPrecision, ref writeIndex);
  1721. break;
  1722. case 1:
  1723. AddFloatToCharArray(arg1, padding, decimalPrecision, ref writeIndex);
  1724. break;
  1725. case 2:
  1726. AddFloatToCharArray(arg2, padding, decimalPrecision, ref writeIndex);
  1727. break;
  1728. case 3:
  1729. AddFloatToCharArray(arg3, padding, decimalPrecision, ref writeIndex);
  1730. break;
  1731. case 4:
  1732. AddFloatToCharArray(arg4, padding, decimalPrecision, ref writeIndex);
  1733. break;
  1734. case 5:
  1735. AddFloatToCharArray(arg5, padding, decimalPrecision, ref writeIndex);
  1736. break;
  1737. case 6:
  1738. AddFloatToCharArray(arg6, padding, decimalPrecision, ref writeIndex);
  1739. break;
  1740. case 7:
  1741. AddFloatToCharArray(arg7, padding, decimalPrecision, ref writeIndex);
  1742. break;
  1743. }
  1744. argIndex = 0;
  1745. readFlag = 0;
  1746. padding = 0;
  1747. decimalPrecision = 0;
  1748. continue;
  1749. }
  1750. // Read Argument index
  1751. if (readFlag == 1)
  1752. {
  1753. if (c >= '0' && c <= '8')
  1754. {
  1755. argIndex = c - 48;
  1756. readFlag = 2;
  1757. continue;
  1758. }
  1759. }
  1760. // Read formatting for integral part of the value
  1761. if (readFlag == 2)
  1762. {
  1763. // Skip ':' separator
  1764. if (c == ':')
  1765. continue;
  1766. // Done reading integral formatting and value
  1767. if (c == '.')
  1768. {
  1769. readFlag = 3;
  1770. continue;
  1771. }
  1772. if (c == '#')
  1773. {
  1774. // do something
  1775. continue;
  1776. }
  1777. if (c == '0')
  1778. {
  1779. padding += 1;
  1780. continue;
  1781. }
  1782. if (c == ',')
  1783. {
  1784. // Use commas in the integral value
  1785. continue;
  1786. }
  1787. // Legacy mode
  1788. if (c >= '1' && c <= '9')
  1789. {
  1790. decimalPrecision = c - 48;
  1791. continue;
  1792. }
  1793. }
  1794. // Read Decimal Precision value
  1795. if (readFlag == 3)
  1796. {
  1797. if (c == '0')
  1798. {
  1799. decimalPrecision += 1;
  1800. continue;
  1801. }
  1802. }
  1803. // Write value
  1804. m_input_CharArray[writeIndex] = c;
  1805. writeIndex += 1;
  1806. }
  1807. m_input_CharArray[writeIndex] = (char)0;
  1808. m_charArray_Length = writeIndex; // Set the length to where this '0' termination is.
  1809. #if UNITY_EDITOR
  1810. // Create new string to be displayed in the Input Text Box of the Editor Panel.
  1811. m_text = new string(m_input_CharArray, 0, writeIndex - 1);
  1812. #endif
  1813. m_inputSource = TextInputSources.SetText;
  1814. m_isInputParsingRequired = true;
  1815. m_havePropertiesChanged = true;
  1816. SetVerticesDirty();
  1817. SetLayoutDirty();
  1818. }
  1819. /// <summary>
  1820. /// Set the text using a StringBuilder.
  1821. /// </summary>
  1822. /// <description>
  1823. /// Using a StringBuilder instead of concatenating strings prevents memory pollution with temporary objects.
  1824. /// </description>
  1825. /// <param name="text">StringBuilder with text to display.</param>
  1826. public void SetText(StringBuilder text)
  1827. {
  1828. m_inputSource = TextInputSources.SetCharArray;
  1829. #if UNITY_EDITOR
  1830. // Set the text in the Text Input Box in the Unity Editor only.
  1831. m_text = text.ToString();
  1832. #endif
  1833. m_InternalParsingBufferSize = StringBuilderToInternalParsingBuffer(text, ref m_InternalParsingBuffer);
  1834. m_isInputParsingRequired = true;
  1835. m_havePropertiesChanged = true;
  1836. SetVerticesDirty();
  1837. SetLayoutDirty();
  1838. }
  1839. /// <summary>
  1840. /// Set the text using a char array.
  1841. /// </summary>
  1842. /// <param name="text"></param>
  1843. public void SetText(char[] text)
  1844. {
  1845. SetCharArray(text);
  1846. }
  1847. /// <summary>
  1848. /// Set the text using a char array with specified starting character and length.
  1849. /// </summary>
  1850. /// <param name="text">Source char array that contains the Unicode characters</param>
  1851. /// <param name="start">The starting character index in the array.</param>
  1852. /// <param name="length">The number of characters to be set.</param>
  1853. public void SetText(char[] text, int start, int length)
  1854. {
  1855. SetCharArray(text, start, length);
  1856. }
  1857. /// <summary>
  1858. /// Character array containing the text to be displayed.
  1859. /// </summary>
  1860. /// <param name="sourceText"></param>
  1861. public void SetCharArray(char[] sourceText)
  1862. {
  1863. int characterCount = sourceText == null ? 0 : sourceText.Length;
  1864. #if UNITY_EDITOR
  1865. // Create new string to be displayed in the Input Text Box of the Editor Panel.
  1866. if (characterCount == 0)
  1867. m_text = string.Empty;
  1868. else
  1869. m_text = new string(sourceText);
  1870. #endif
  1871. // Early exit if string is null or empty
  1872. if (characterCount == 0)
  1873. {
  1874. m_InternalParsingBuffer[0].unicode = 0;
  1875. m_InternalParsingBufferSize = 0;
  1876. return;
  1877. }
  1878. // Make sure parsing buffer is large enough to handle the required text.
  1879. if (m_InternalParsingBuffer.Length < characterCount)
  1880. ResizeInternalArray(ref m_InternalParsingBuffer, characterCount);
  1881. // Clear Style stacks.
  1882. for (int i = 0; i < m_TextStyleStacks.Length; i++)
  1883. m_TextStyleStacks[i].SetDefault(0);
  1884. m_TextStyleStackDepth = 0;
  1885. int writeIndex = 0;
  1886. // Insert Opening Style
  1887. if (textStyle.hashCode != (int)TagHashCode.NORMAL)
  1888. InsertOpeningStyleTag(m_TextStyle, 0, ref m_InternalParsingBuffer, ref writeIndex);
  1889. for (int i = 0; sourceText != null && i < sourceText.Length; i++)
  1890. {
  1891. if (sourceText[i] == 92 && i < sourceText.Length - 1)
  1892. {
  1893. switch ((int)sourceText[i + 1])
  1894. {
  1895. case 110: // \n LineFeed
  1896. if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer);
  1897. m_InternalParsingBuffer[writeIndex].unicode = 10;
  1898. i += 1;
  1899. writeIndex += 1;
  1900. continue;
  1901. case 114: // \r LineFeed
  1902. if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer);
  1903. m_InternalParsingBuffer[writeIndex].unicode = 13;
  1904. i += 1;
  1905. writeIndex += 1;
  1906. continue;
  1907. case 116: // \t Tab
  1908. if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer);
  1909. m_InternalParsingBuffer[writeIndex].unicode = 9;
  1910. i += 1;
  1911. writeIndex += 1;
  1912. continue;
  1913. case 118: // \v Vertical tab used as soft line break
  1914. if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer);
  1915. m_InternalParsingBuffer[writeIndex].unicode = 11;
  1916. i += 1;
  1917. writeIndex += 1;
  1918. continue;
  1919. }
  1920. }
  1921. // Handle inline replacement of <stlye> and <br> tags.
  1922. if (sourceText[i] == 60)
  1923. {
  1924. if (IsTagName(ref sourceText, "<BR>", i))
  1925. {
  1926. if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer);
  1927. m_InternalParsingBuffer[writeIndex].unicode = 10;
  1928. writeIndex += 1;
  1929. i += 3;
  1930. continue;
  1931. }
  1932. else if (IsTagName(ref sourceText, "<NBSP>", i))
  1933. {
  1934. if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer);
  1935. m_InternalParsingBuffer[writeIndex].unicode = 160;
  1936. writeIndex += 1;
  1937. i += 5;
  1938. continue;
  1939. }
  1940. else if (IsTagName(ref sourceText, "<ZWSP>", i))
  1941. {
  1942. if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer);
  1943. m_InternalParsingBuffer[writeIndex].unicode = 0x200B;
  1944. writeIndex += 1;
  1945. i += 5;
  1946. continue;
  1947. }
  1948. else if (IsTagName(ref sourceText, "<STYLE=", i))
  1949. {
  1950. int srcOffset;
  1951. if (ReplaceOpeningStyleTag(ref sourceText, i, out srcOffset, ref m_InternalParsingBuffer, ref writeIndex))
  1952. {
  1953. i = srcOffset;
  1954. continue;
  1955. }
  1956. }
  1957. else if (IsTagName(ref sourceText, "</STYLE>", i))
  1958. {
  1959. ReplaceClosingStyleTag(ref sourceText, i, ref m_InternalParsingBuffer, ref writeIndex);
  1960. // Strip </style> even if style is invalid.
  1961. i += 7;
  1962. continue;
  1963. }
  1964. }
  1965. if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer);
  1966. m_InternalParsingBuffer[writeIndex].unicode = sourceText[i];
  1967. writeIndex += 1;
  1968. }
  1969. m_TextStyleStackDepth = 0;
  1970. // Insert Closing Style
  1971. if (textStyle.hashCode != (int)TagHashCode.NORMAL)
  1972. InsertClosingStyleTag(ref m_InternalParsingBuffer, ref writeIndex);
  1973. if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer);
  1974. m_InternalParsingBuffer[writeIndex].unicode = 0;
  1975. m_InternalParsingBufferSize = writeIndex;
  1976. m_inputSource = TextInputSources.SetCharArray;
  1977. m_isInputParsingRequired = true;
  1978. m_havePropertiesChanged = true;
  1979. SetVerticesDirty();
  1980. SetLayoutDirty();
  1981. }
  1982. /// <summary>
  1983. /// Character array containing the text to be displayed.
  1984. /// </summary>
  1985. /// <param name="sourceText"></param>
  1986. public void SetCharArray(char[] sourceText, int start, int length)
  1987. {
  1988. int characterCount = 0;
  1989. // Range check
  1990. if (sourceText != null)
  1991. {
  1992. start = Mathf.Clamp(start, 0, sourceText.Length);
  1993. length = Mathf.Clamp(length, 0, start + length < sourceText.Length ? length : sourceText.Length - start);
  1994. characterCount = length;
  1995. }
  1996. #if UNITY_EDITOR
  1997. // Create new string to be displayed in the Input Text Box of the Editor Panel.
  1998. if (characterCount == 0)
  1999. m_text = string.Empty;
  2000. else
  2001. m_text = new string(sourceText, start, length);
  2002. #endif
  2003. // Early exit if string is null or empty
  2004. if (characterCount == 0)
  2005. {
  2006. m_InternalParsingBuffer[0].unicode = 0;
  2007. m_InternalParsingBufferSize = 0;
  2008. return;
  2009. }
  2010. // Make sure parsing buffer is large enough to handle the required text.
  2011. if (m_InternalParsingBuffer.Length < characterCount)
  2012. ResizeInternalArray(ref m_InternalParsingBuffer, characterCount);
  2013. // Clear Style stacks.
  2014. for (int j = 0; j < m_TextStyleStacks.Length; j++)
  2015. m_TextStyleStacks[j].SetDefault(0);
  2016. m_TextStyleStackDepth = 0;
  2017. int writeIndex = 0;
  2018. // Insert Opening Style
  2019. if (textStyle.hashCode != (int)TagHashCode.NORMAL)
  2020. InsertOpeningStyleTag(m_TextStyle, 0, ref m_InternalParsingBuffer, ref writeIndex);
  2021. int i = start;
  2022. int end = start + length;
  2023. for (; i < end; i++)
  2024. {
  2025. if (sourceText[i] == 92 && i < length - 1)
  2026. {
  2027. switch ((int)sourceText[i + 1])
  2028. {
  2029. case 110: // \n LineFeed
  2030. if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer);
  2031. m_InternalParsingBuffer[writeIndex].unicode = 10;
  2032. i += 1;
  2033. writeIndex += 1;
  2034. continue;
  2035. case 114: // \r Carriage Return
  2036. if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer);
  2037. m_InternalParsingBuffer[writeIndex].unicode = 13;
  2038. i += 1;
  2039. writeIndex += 1;
  2040. continue;
  2041. case 116: // \t Tab
  2042. if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer);
  2043. m_InternalParsingBuffer[writeIndex].unicode = 9;
  2044. i += 1;
  2045. writeIndex += 1;
  2046. continue;
  2047. case 118: // \v Vertical tab used as soft line break
  2048. if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer);
  2049. m_InternalParsingBuffer[writeIndex].unicode = 11;
  2050. i += 1;
  2051. writeIndex += 1;
  2052. continue;
  2053. }
  2054. }
  2055. // Handle inline replacement of <stlye> and <br> tags.
  2056. if (sourceText[i] == 60)
  2057. {
  2058. if (IsTagName(ref sourceText, "<BR>", i))
  2059. {
  2060. if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer);
  2061. m_InternalParsingBuffer[writeIndex].unicode = 10;
  2062. writeIndex += 1;
  2063. i += 3;
  2064. continue;
  2065. }
  2066. else if (IsTagName(ref sourceText, "<NBSP>", i))
  2067. {
  2068. if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer);
  2069. m_InternalParsingBuffer[writeIndex].unicode = 160;
  2070. writeIndex += 1;
  2071. i += 5;
  2072. continue;
  2073. }
  2074. else if (IsTagName(ref sourceText, "<ZWSP>", i))
  2075. {
  2076. if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer);
  2077. m_InternalParsingBuffer[writeIndex].unicode = 0x200B;
  2078. writeIndex += 1;
  2079. i += 5;
  2080. continue;
  2081. }
  2082. else if (IsTagName(ref sourceText, "<STYLE=", i))
  2083. {
  2084. int srcOffset;
  2085. if (ReplaceOpeningStyleTag(ref sourceText, i, out srcOffset, ref m_InternalParsingBuffer, ref writeIndex))
  2086. {
  2087. i = srcOffset;
  2088. continue;
  2089. }
  2090. }
  2091. else if (IsTagName(ref sourceText, "</STYLE>", i))
  2092. {
  2093. ReplaceClosingStyleTag(ref sourceText, i, ref m_InternalParsingBuffer, ref writeIndex);
  2094. // Strip </style> even if style is invalid.
  2095. i += 7;
  2096. continue;
  2097. }
  2098. }
  2099. if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer);
  2100. m_InternalParsingBuffer[writeIndex].unicode = sourceText[i];
  2101. writeIndex += 1;
  2102. }
  2103. m_TextStyleStackDepth = 0;
  2104. // Insert Closing Style
  2105. if (textStyle.hashCode != (int)TagHashCode.NORMAL)
  2106. InsertClosingStyleTag(ref m_InternalParsingBuffer, ref writeIndex);
  2107. if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer);
  2108. m_InternalParsingBuffer[writeIndex].unicode = 0;
  2109. m_inputSource = TextInputSources.SetCharArray;
  2110. m_havePropertiesChanged = true;
  2111. m_isInputParsingRequired = true;
  2112. SetVerticesDirty();
  2113. SetLayoutDirty();
  2114. }
  2115. /// <summary>
  2116. /// Character array containing the text to be displayed.
  2117. /// </summary>
  2118. /// <param name="sourceText"></param>
  2119. public void SetCharArray(int[] sourceText, int start, int length)
  2120. {
  2121. // Initialize internal character buffer if necessary
  2122. if (m_InternalParsingBuffer == null) m_InternalParsingBuffer = new UnicodeChar[8];
  2123. #if UNITY_EDITOR
  2124. // Create new string to be displayed in the Input Text Box of the Editor Panel.
  2125. if (sourceText == null || sourceText.Length == 0 || length == 0)
  2126. {
  2127. m_text = string.Empty;
  2128. start = 0;
  2129. length = 0;
  2130. }
  2131. else
  2132. {
  2133. m_text = sourceText.IntToString(start, length);
  2134. }
  2135. #endif
  2136. // Clear Style stacks.
  2137. for (int j = 0; j < m_TextStyleStacks.Length; j++)
  2138. m_TextStyleStacks[j].SetDefault(0);
  2139. m_TextStyleStackDepth = 0;
  2140. int writeIndex = 0;
  2141. // Insert Opening Style
  2142. if (textStyle.hashCode != (int)TagHashCode.NORMAL)
  2143. InsertOpeningStyleTag(m_TextStyle, 0, ref m_InternalParsingBuffer, ref writeIndex);
  2144. int end = start + length;
  2145. for (int i = start; i < end && i < sourceText.Length; i++)
  2146. {
  2147. if (sourceText[i] == 92 && i < length - 1)
  2148. {
  2149. switch ((int)sourceText[i + 1])
  2150. {
  2151. case 110: // \n LineFeed
  2152. if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer);
  2153. m_InternalParsingBuffer[writeIndex].unicode = 10;
  2154. i += 1;
  2155. writeIndex += 1;
  2156. continue;
  2157. case 114: // \r LineFeed
  2158. if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer);
  2159. m_InternalParsingBuffer[writeIndex].unicode = 13;
  2160. i += 1;
  2161. writeIndex += 1;
  2162. continue;
  2163. case 116: // \t Tab
  2164. if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer);
  2165. m_InternalParsingBuffer[writeIndex].unicode = 9;
  2166. i += 1;
  2167. writeIndex += 1;
  2168. continue;
  2169. case 118: // \v Vertical tab used as soft line break
  2170. if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer);
  2171. m_InternalParsingBuffer[writeIndex].unicode = 11;
  2172. i += 1;
  2173. writeIndex += 1;
  2174. continue;
  2175. }
  2176. }
  2177. // Handle inline replacement of <stlye> and <br> tags.
  2178. if (sourceText[i] == 60)
  2179. {
  2180. if (IsTagName(ref sourceText, "<BR>", i))
  2181. {
  2182. if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer);
  2183. m_InternalParsingBuffer[writeIndex].unicode = 10;
  2184. writeIndex += 1;
  2185. i += 3;
  2186. continue;
  2187. }
  2188. else if (IsTagName(ref sourceText, "<NBSP>", i))
  2189. {
  2190. if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer);
  2191. m_InternalParsingBuffer[writeIndex].unicode = 160;
  2192. writeIndex += 1;
  2193. i += 5;
  2194. continue;
  2195. }
  2196. else if (IsTagName(ref sourceText, "<ZWSP>", i))
  2197. {
  2198. if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer);
  2199. m_InternalParsingBuffer[writeIndex].unicode = 0x200B;
  2200. writeIndex += 1;
  2201. i += 5;
  2202. continue;
  2203. }
  2204. else if (IsTagName(ref sourceText, "<STYLE=", i))
  2205. {
  2206. int srcOffset;
  2207. if (ReplaceOpeningStyleTag(ref sourceText, i, out srcOffset, ref m_InternalParsingBuffer, ref writeIndex))
  2208. {
  2209. i = srcOffset;
  2210. continue;
  2211. }
  2212. }
  2213. else if (IsTagName(ref sourceText, "</STYLE>", i))
  2214. {
  2215. ReplaceClosingStyleTag(ref sourceText, i, ref m_InternalParsingBuffer, ref writeIndex);
  2216. // Strip </style> even if style is invalid.
  2217. i += 7;
  2218. continue;
  2219. }
  2220. }
  2221. if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer);
  2222. m_InternalParsingBuffer[writeIndex].unicode = sourceText[i];
  2223. writeIndex += 1;
  2224. }
  2225. m_TextStyleStackDepth = 0;
  2226. // Insert Closing Style
  2227. if (textStyle.hashCode != (int)TagHashCode.NORMAL)
  2228. InsertClosingStyleTag(ref m_InternalParsingBuffer, ref writeIndex);
  2229. if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer);
  2230. m_InternalParsingBuffer[writeIndex].unicode = 0;
  2231. m_inputSource = TextInputSources.SetCharArray;
  2232. m_havePropertiesChanged = true;
  2233. m_isInputParsingRequired = true;
  2234. SetVerticesDirty();
  2235. SetLayoutDirty();
  2236. }
  2237. /// <summary>
  2238. /// Copies Content of formatted SetText() to charBuffer.
  2239. /// </summary>
  2240. /// <param name="sourceText"></param>
  2241. /// <param name="internalParsingArray"></param>
  2242. protected int CharArrayToInternalParsingBuffer(char[] sourceText, ref UnicodeChar[] internalParsingArray)
  2243. {
  2244. int characterCount = sourceText == null ? 0 : sourceText.Length;
  2245. #if UNITY_EDITOR
  2246. // Create new string to be displayed in the Input Text Box of the Editor Panel.
  2247. // This results in allocations in the Unity Editor only
  2248. if (characterCount == 0)
  2249. m_text = string.Empty;
  2250. else
  2251. m_text = new string(sourceText);
  2252. #endif
  2253. // Early exit if string is null or empty
  2254. if (characterCount == 0)
  2255. {
  2256. if (internalParsingArray != null)
  2257. internalParsingArray[0].unicode = 0;
  2258. return 0;
  2259. }
  2260. // Make sure parsing buffer is large enough to handle the required text.
  2261. if (internalParsingArray == null)
  2262. internalParsingArray = new UnicodeChar[characterCount];
  2263. else if (internalParsingArray.Length < characterCount)
  2264. ResizeInternalArray(ref internalParsingArray, characterCount);
  2265. // Clear Style stacks.
  2266. for (int j = 0; j < m_TextStyleStacks.Length; j++)
  2267. m_TextStyleStacks[j].SetDefault(0);
  2268. m_TextStyleStackDepth = 0;
  2269. int writeIndex = 0;
  2270. // Insert Opening Style
  2271. if (textStyle.hashCode != (int)TagHashCode.NORMAL)
  2272. InsertOpeningStyleTag(m_TextStyle, 0, ref internalParsingArray, ref writeIndex);
  2273. for (int i = 0; i < m_charArray_Length; i++)
  2274. {
  2275. // Handle UTF-32 in the input text (string).
  2276. if (char.IsHighSurrogate(sourceText[i]) && char.IsLowSurrogate(sourceText[i + 1]))
  2277. {
  2278. if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray);
  2279. internalParsingArray[writeIndex].unicode = char.ConvertToUtf32(sourceText[i], sourceText[i + 1]);
  2280. i += 1;
  2281. writeIndex += 1;
  2282. continue;
  2283. }
  2284. // Handle inline replacement of <stlye> and <br> tags.
  2285. if (sourceText[i] == 60)
  2286. {
  2287. if (IsTagName(ref sourceText, "<BR>", i))
  2288. {
  2289. if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray);
  2290. internalParsingArray[writeIndex].unicode = 10;
  2291. writeIndex += 1;
  2292. i += 3;
  2293. continue;
  2294. }
  2295. else if (IsTagName(ref sourceText, "<NBSP>", i))
  2296. {
  2297. if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray);
  2298. internalParsingArray[writeIndex].unicode = 160;
  2299. writeIndex += 1;
  2300. i += 5;
  2301. continue;
  2302. }
  2303. else if (IsTagName(ref sourceText, "<ZWSP>", i))
  2304. {
  2305. if (writeIndex == m_InternalParsingBuffer.Length) ResizeInternalArray(ref m_InternalParsingBuffer);
  2306. m_InternalParsingBuffer[writeIndex].unicode = 0x200B;
  2307. writeIndex += 1;
  2308. i += 5;
  2309. continue;
  2310. }
  2311. else if (IsTagName(ref sourceText, "<STYLE=", i))
  2312. {
  2313. int srcOffset;
  2314. if (ReplaceOpeningStyleTag(ref sourceText, i, out srcOffset, ref internalParsingArray, ref writeIndex))
  2315. {
  2316. i = srcOffset;
  2317. continue;
  2318. }
  2319. }
  2320. else if (IsTagName(ref sourceText, "</STYLE>", i))
  2321. {
  2322. ReplaceClosingStyleTag(ref sourceText, i, ref internalParsingArray, ref writeIndex);
  2323. // Strip </style> even if style is invalid.
  2324. i += 7;
  2325. continue;
  2326. }
  2327. }
  2328. if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray);
  2329. internalParsingArray[writeIndex].unicode = sourceText[i];
  2330. writeIndex += 1;
  2331. }
  2332. m_TextStyleStackDepth = 0;
  2333. // Insert Closing Style
  2334. if (textStyle.hashCode != (int)TagHashCode.NORMAL)
  2335. InsertClosingStyleTag(ref internalParsingArray, ref writeIndex);
  2336. if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray);
  2337. internalParsingArray[writeIndex].unicode = 0;
  2338. return writeIndex;
  2339. }
  2340. /// <summary>
  2341. /// Method to store the content of a string into an integer array.
  2342. /// </summary>
  2343. /// <param name="sourceText"></param>
  2344. /// <param name="internalParsingArray"></param>
  2345. protected int StringToInternalParsingBuffer(string sourceText, ref UnicodeChar[] internalParsingArray)
  2346. {
  2347. int characterCount = sourceText == null ? 0 : sourceText.Length;
  2348. // Early exit if string is null or empty
  2349. if (characterCount == 0)
  2350. {
  2351. if (internalParsingArray != null)
  2352. internalParsingArray[0].unicode = 0;
  2353. return 0;
  2354. }
  2355. // Allocate internal buffers that are large enough to handle the required text.
  2356. if (internalParsingArray == null)
  2357. internalParsingArray = new UnicodeChar[characterCount];
  2358. else if (internalParsingArray.Length < characterCount)
  2359. ResizeInternalArray(ref internalParsingArray, characterCount);
  2360. // Clear Style stacks.
  2361. for (int j = 0; j < m_TextStyleStacks.Length; j++)
  2362. m_TextStyleStacks[j].SetDefault(0);
  2363. m_TextStyleStackDepth = 0;
  2364. int writeIndex = 0;
  2365. // Insert Opening Style
  2366. if (textStyle.hashCode != (int)TagHashCode.NORMAL)
  2367. InsertOpeningStyleTag(m_TextStyle, 0, ref internalParsingArray, ref writeIndex);
  2368. for (int i = 0; i < sourceText.Length; i++)
  2369. {
  2370. if (m_inputSource == TextInputSources.Text && sourceText[i] == 92 && sourceText.Length > i + 1)
  2371. {
  2372. switch ((int)sourceText[i + 1])
  2373. {
  2374. case 85: // \U00000000 for UTF-32 Unicode
  2375. if (sourceText.Length > i + 9)
  2376. {
  2377. if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray);
  2378. internalParsingArray[writeIndex].unicode = GetUTF32(sourceText, i + 2);
  2379. internalParsingArray[writeIndex].stringIndex = i;
  2380. internalParsingArray[writeIndex].length = 10;
  2381. i += 9;
  2382. writeIndex += 1;
  2383. continue;
  2384. }
  2385. break;
  2386. case 92: // \ escape
  2387. if (!m_parseCtrlCharacters) break;
  2388. if (sourceText.Length <= i + 2) break;
  2389. if (writeIndex + 2 > internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray);
  2390. internalParsingArray[writeIndex].unicode = sourceText[i + 1];
  2391. internalParsingArray[writeIndex + 1].unicode = sourceText[i + 2];
  2392. i += 2;
  2393. writeIndex += 2;
  2394. continue;
  2395. case 110: // \n LineFeed
  2396. if (!m_parseCtrlCharacters) break;
  2397. if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray);
  2398. internalParsingArray[writeIndex].unicode = 10;
  2399. internalParsingArray[writeIndex].stringIndex = i;
  2400. internalParsingArray[writeIndex].length = 1;
  2401. i += 1;
  2402. writeIndex += 1;
  2403. continue;
  2404. case 114: // \r
  2405. if (!m_parseCtrlCharacters) break;
  2406. if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray);
  2407. internalParsingArray[writeIndex].unicode = 13;
  2408. internalParsingArray[writeIndex].stringIndex = i;
  2409. internalParsingArray[writeIndex].length = 1;
  2410. i += 1;
  2411. writeIndex += 1;
  2412. continue;
  2413. case 116: // \t Tab
  2414. if (!m_parseCtrlCharacters) break;
  2415. if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray);
  2416. internalParsingArray[writeIndex].unicode = 9;
  2417. internalParsingArray[writeIndex].stringIndex = i;
  2418. internalParsingArray[writeIndex].length = 1;
  2419. i += 1;
  2420. writeIndex += 1;
  2421. continue;
  2422. case 117: // \u0000 for UTF-16 Unicode
  2423. if (sourceText.Length > i + 5)
  2424. {
  2425. if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray);
  2426. internalParsingArray[writeIndex].unicode = GetUTF16(sourceText, i + 2);
  2427. internalParsingArray[writeIndex].stringIndex = i;
  2428. internalParsingArray[writeIndex].length = 6;
  2429. i += 5;
  2430. writeIndex += 1;
  2431. continue;
  2432. }
  2433. break;
  2434. case 118: // \v Vertical tab used as soft line break
  2435. if (!m_parseCtrlCharacters) break;
  2436. if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray);
  2437. internalParsingArray[writeIndex].unicode = 11;
  2438. internalParsingArray[writeIndex].stringIndex = i;
  2439. internalParsingArray[writeIndex].length = 1;
  2440. i += 1;
  2441. writeIndex += 1;
  2442. continue;
  2443. }
  2444. }
  2445. // Handle UTF-32 in the input text (string). // Not sure this is needed //
  2446. if (char.IsHighSurrogate(sourceText[i]) && char.IsLowSurrogate(sourceText[i + 1]))
  2447. {
  2448. if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray);
  2449. internalParsingArray[writeIndex].unicode = char.ConvertToUtf32(sourceText[i], sourceText[i + 1]);
  2450. internalParsingArray[writeIndex].stringIndex = i;
  2451. internalParsingArray[writeIndex].length = 2;
  2452. i += 1;
  2453. writeIndex += 1;
  2454. continue;
  2455. }
  2456. //// Handle inline replacement of <stlye> and <br> tags.
  2457. if (sourceText[i] == 60 && m_isRichText)
  2458. {
  2459. if (IsTagName(ref sourceText, "<BR>", i))
  2460. {
  2461. if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray);
  2462. internalParsingArray[writeIndex].unicode = 10;
  2463. internalParsingArray[writeIndex].stringIndex = i;
  2464. internalParsingArray[writeIndex].length = 1;
  2465. writeIndex += 1;
  2466. i += 3;
  2467. continue;
  2468. }
  2469. else if (IsTagName(ref sourceText, "<NBSP>", i))
  2470. {
  2471. if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray);
  2472. internalParsingArray[writeIndex].unicode = 160;
  2473. internalParsingArray[writeIndex].stringIndex = i;
  2474. internalParsingArray[writeIndex].length = 1;
  2475. writeIndex += 1;
  2476. i += 5;
  2477. continue;
  2478. }
  2479. else if (IsTagName(ref sourceText, "<ZWSP>", i))
  2480. {
  2481. if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray);
  2482. internalParsingArray[writeIndex].unicode = 0x200B;
  2483. internalParsingArray[writeIndex].stringIndex = i;
  2484. internalParsingArray[writeIndex].length = 1;
  2485. writeIndex += 1;
  2486. i += 5;
  2487. continue;
  2488. }
  2489. else if (IsTagName(ref sourceText, "<STYLE=", i))
  2490. {
  2491. int srcOffset;
  2492. if (ReplaceOpeningStyleTag(ref sourceText, i, out srcOffset, ref internalParsingArray, ref writeIndex))
  2493. {
  2494. i = srcOffset;
  2495. continue;
  2496. }
  2497. }
  2498. else if (IsTagName(ref sourceText, "</STYLE>", i))
  2499. {
  2500. ReplaceClosingStyleTag(ref sourceText, i, ref internalParsingArray, ref writeIndex);
  2501. i += 7;
  2502. continue;
  2503. }
  2504. }
  2505. if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray);
  2506. internalParsingArray[writeIndex].unicode = sourceText[i];
  2507. internalParsingArray[writeIndex].stringIndex = writeIndex;
  2508. internalParsingArray[writeIndex].length = 1;
  2509. writeIndex += 1;
  2510. }
  2511. m_TextStyleStackDepth = 0;
  2512. // Insert Closing Style
  2513. if (textStyle.hashCode != (int)TagHashCode.NORMAL)
  2514. InsertClosingStyleTag(ref internalParsingArray, ref writeIndex);
  2515. if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray);
  2516. internalParsingArray[writeIndex].unicode = 0;
  2517. return writeIndex;
  2518. }
  2519. /// <summary>
  2520. /// Copy contents of StringBuilder into int array.
  2521. /// </summary>
  2522. /// <param name="sourceText">Text to copy.</param>
  2523. /// <param name="internalParsingArray">Array to store contents.</param>
  2524. protected int StringBuilderToInternalParsingBuffer(StringBuilder sourceText, ref UnicodeChar[] internalParsingArray)
  2525. {
  2526. int characterCount = sourceText == null ? 0 : sourceText.Length;
  2527. #if UNITY_EDITOR
  2528. // Create new string to be displayed in the Input Text Box of the Editor Panel.
  2529. // This results in allocations in the Unity Editor only
  2530. if (characterCount == 0)
  2531. m_text = string.Empty;
  2532. else
  2533. m_text = sourceText.ToString();
  2534. #endif
  2535. // Early exit if string is null or empty
  2536. if (characterCount == 0)
  2537. {
  2538. if (internalParsingArray != null)
  2539. internalParsingArray[0].unicode = 0;
  2540. return 0;
  2541. }
  2542. // Make sure parsing buffer is large enough to handle the required text.
  2543. if (internalParsingArray == null)
  2544. internalParsingArray = new UnicodeChar[characterCount];
  2545. else if (internalParsingArray.Length < characterCount)
  2546. ResizeInternalArray(ref internalParsingArray, characterCount);
  2547. // Clear Style stacks.
  2548. for (int j = 0; j < m_TextStyleStacks.Length; j++)
  2549. m_TextStyleStacks[j].SetDefault(0);
  2550. m_TextStyleStackDepth = 0;
  2551. int writeIndex = 0;
  2552. // Insert Opening Style
  2553. if (textStyle.hashCode != (int)TagHashCode.NORMAL)
  2554. InsertOpeningStyleTag(m_TextStyle, 0, ref internalParsingArray, ref writeIndex);
  2555. for (int i = 0; i < sourceText.Length; i++)
  2556. {
  2557. if (m_parseCtrlCharacters && sourceText[i] == 92 && sourceText.Length > i + 1)
  2558. {
  2559. switch ((int)sourceText[i + 1])
  2560. {
  2561. case 85: // \U00000000 for UTF-32 Unicode
  2562. if (sourceText.Length > i + 9)
  2563. {
  2564. if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray);
  2565. internalParsingArray[writeIndex].unicode = GetUTF32(sourceText, i + 2);
  2566. i += 9;
  2567. writeIndex += 1;
  2568. continue;
  2569. }
  2570. break;
  2571. case 92: // \ escape
  2572. if (sourceText.Length <= i + 2) break;
  2573. if (writeIndex + 2 > internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray);
  2574. internalParsingArray[writeIndex].unicode = sourceText[i + 1];
  2575. internalParsingArray[writeIndex + 1].unicode = sourceText[i + 2];
  2576. i += 2;
  2577. writeIndex += 2;
  2578. continue;
  2579. case 110: // \n LineFeed
  2580. if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray);
  2581. internalParsingArray[writeIndex].unicode = 10;
  2582. i += 1;
  2583. writeIndex += 1;
  2584. continue;
  2585. case 114: // \r
  2586. if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray);
  2587. internalParsingArray[writeIndex].unicode = 13;
  2588. i += 1;
  2589. writeIndex += 1;
  2590. continue;
  2591. case 116: // \t Tab
  2592. if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray);
  2593. internalParsingArray[writeIndex].unicode = 9;
  2594. i += 1;
  2595. writeIndex += 1;
  2596. continue;
  2597. case 117: // \u0000 for UTF-16 Unicode
  2598. if (sourceText.Length > i + 5)
  2599. {
  2600. if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray);
  2601. internalParsingArray[writeIndex].unicode = GetUTF16(sourceText, i + 2);
  2602. i += 5;
  2603. writeIndex += 1;
  2604. continue;
  2605. }
  2606. break;
  2607. case 118: // \v Vertical tab used as soft line break
  2608. if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray);
  2609. internalParsingArray[writeIndex].unicode = 11;
  2610. i += 1;
  2611. writeIndex += 1;
  2612. continue;
  2613. }
  2614. }
  2615. // Handle UTF-32 in the input text (string).
  2616. if (char.IsHighSurrogate(sourceText[i]) && char.IsLowSurrogate(sourceText[i + 1]))
  2617. {
  2618. if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray);
  2619. internalParsingArray[writeIndex].unicode = char.ConvertToUtf32(sourceText[i], sourceText[i + 1]);
  2620. i += 1;
  2621. writeIndex += 1;
  2622. continue;
  2623. }
  2624. // Handle inline replacement of <stlye> and <br> tags.
  2625. if (sourceText[i] == 60)
  2626. {
  2627. if (IsTagName(ref sourceText, "<BR>", i))
  2628. {
  2629. if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray);
  2630. internalParsingArray[writeIndex].unicode = 10;
  2631. writeIndex += 1;
  2632. i += 3;
  2633. continue;
  2634. }
  2635. else if (IsTagName(ref sourceText, "<NBSP>", i))
  2636. {
  2637. if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray);
  2638. internalParsingArray[writeIndex].unicode = 160;
  2639. writeIndex += 1;
  2640. i += 5;
  2641. continue;
  2642. }
  2643. else if (IsTagName(ref sourceText, "<ZWSP>", i))
  2644. {
  2645. if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray);
  2646. internalParsingArray[writeIndex].unicode = 0x200B;
  2647. writeIndex += 1;
  2648. i += 5;
  2649. continue;
  2650. }
  2651. else if (IsTagName(ref sourceText, "<STYLE=", i))
  2652. {
  2653. int srcOffset;
  2654. if (ReplaceOpeningStyleTag(ref sourceText, i, out srcOffset, ref internalParsingArray, ref writeIndex))
  2655. {
  2656. i = srcOffset;
  2657. continue;
  2658. }
  2659. }
  2660. else if (IsTagName(ref sourceText, "</STYLE>", i))
  2661. {
  2662. ReplaceClosingStyleTag(ref sourceText, i, ref internalParsingArray, ref writeIndex);
  2663. // Strip </style> even if style is invalid.
  2664. i += 7;
  2665. continue;
  2666. }
  2667. }
  2668. if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray);
  2669. internalParsingArray[writeIndex].unicode = sourceText[i];
  2670. writeIndex += 1;
  2671. }
  2672. m_TextStyleStackDepth = 0;
  2673. // Insert Closing Style
  2674. if (textStyle.hashCode != (int)TagHashCode.NORMAL)
  2675. InsertClosingStyleTag(ref internalParsingArray, ref writeIndex);
  2676. if (writeIndex == internalParsingArray.Length) ResizeInternalArray(ref internalParsingArray);
  2677. internalParsingArray[writeIndex].unicode = 0;
  2678. return writeIndex;
  2679. }
  2680. /// <summary>
  2681. /// Method to handle inline replacement of style tag by opening style definition.
  2682. /// </summary>
  2683. /// <param name="sourceText"></param>
  2684. /// <param name="srcIndex"></param>
  2685. /// <param name="srcOffset"></param>
  2686. /// <param name="charBuffer"></param>
  2687. /// <param name="writeIndex"></param>
  2688. /// <returns></returns>
  2689. bool ReplaceOpeningStyleTag(ref string sourceText, int srcIndex, out int srcOffset, ref UnicodeChar[] charBuffer, ref int writeIndex)
  2690. {
  2691. // Validate <style> tag.
  2692. int hashCode = GetTagHashCode(ref sourceText, srcIndex + 7, out srcOffset);
  2693. TMP_Style style = GetStyle(hashCode);
  2694. // Return if we don't have a valid style.
  2695. if (style == null || srcOffset == 0) return false;
  2696. // Increase style depth
  2697. m_TextStyleStackDepth += 1;
  2698. // Push style hashcode onto stack
  2699. m_TextStyleStacks[m_TextStyleStackDepth].Push(style.hashCode);
  2700. int styleLength = style.styleOpeningTagArray.Length;
  2701. // Replace <style> tag with opening definition
  2702. int[] tagDefinition = style.styleOpeningTagArray;
  2703. for (int i = 0; i < styleLength; i++)
  2704. {
  2705. int c = tagDefinition[i];
  2706. if (c == '\\' && i + 1 < styleLength)
  2707. {
  2708. switch (tagDefinition[i + 1])
  2709. {
  2710. case '\\':
  2711. i += 1;
  2712. break;
  2713. case 'n':
  2714. c = 10;
  2715. i += 1;
  2716. break;
  2717. case 'r':
  2718. break;
  2719. case 't':
  2720. break;
  2721. case 'u':
  2722. // UTF16 format is "\uFF00" or u + 2 hex pairs.
  2723. if (i + 5 < styleLength)
  2724. {
  2725. c = GetUTF16(tagDefinition, i + 2);
  2726. i += 5;
  2727. }
  2728. break;
  2729. case 'U':
  2730. // UTF32 format is "\UFF00FF00" or U + 4 hex pairs.
  2731. if (i + 9 < styleLength)
  2732. {
  2733. c = GetUTF32(tagDefinition, i + 2);
  2734. i += 9;
  2735. }
  2736. break;
  2737. }
  2738. }
  2739. if (c == 60)
  2740. {
  2741. if (IsTagName(ref tagDefinition, "<BR>", i))
  2742. {
  2743. if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
  2744. charBuffer[writeIndex].unicode = 10;
  2745. writeIndex += 1;
  2746. i += 3;
  2747. continue;
  2748. }
  2749. else if (IsTagName(ref tagDefinition, "<NBSP>", i))
  2750. {
  2751. if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
  2752. charBuffer[writeIndex].unicode = 160;
  2753. writeIndex += 1;
  2754. i += 5;
  2755. continue;
  2756. }
  2757. else if (IsTagName(ref tagDefinition, "<ZWSP>", i))
  2758. {
  2759. if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
  2760. charBuffer[writeIndex].unicode = 0x200B;
  2761. writeIndex += 1;
  2762. i += 5;
  2763. continue;
  2764. }
  2765. else if (IsTagName(ref tagDefinition, "<STYLE=", i))
  2766. {
  2767. int offset;
  2768. if (ReplaceOpeningStyleTag(ref tagDefinition, i, out offset, ref charBuffer, ref writeIndex))
  2769. {
  2770. i = offset;
  2771. continue;
  2772. }
  2773. }
  2774. else if (IsTagName(ref tagDefinition, "</STYLE>", i))
  2775. {
  2776. ReplaceClosingStyleTag(ref tagDefinition, i, ref charBuffer, ref writeIndex);
  2777. // Strip </style> even if style is invalid.
  2778. i += 7;
  2779. continue;
  2780. }
  2781. }
  2782. if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
  2783. charBuffer[writeIndex].unicode = c;
  2784. writeIndex += 1;
  2785. }
  2786. m_TextStyleStackDepth -= 1;
  2787. return true;
  2788. }
  2789. /// <summary>
  2790. /// Method to handle inline replacement of style tag by opening style definition.
  2791. /// </summary>
  2792. /// <param name="sourceText"></param>
  2793. /// <param name="srcIndex"></param>
  2794. /// <param name="srcOffset"></param>
  2795. /// <param name="charBuffer"></param>
  2796. /// <param name="writeIndex"></param>
  2797. /// <returns></returns>
  2798. bool ReplaceOpeningStyleTag(ref int[] sourceText, int srcIndex, out int srcOffset, ref UnicodeChar[] charBuffer, ref int writeIndex)
  2799. {
  2800. // Validate <style> tag.
  2801. int hashCode = GetTagHashCode(ref sourceText, srcIndex + 7, out srcOffset);
  2802. TMP_Style style = GetStyle(hashCode);
  2803. // Return if we don't have a valid style.
  2804. if (style == null || srcOffset == 0) return false;
  2805. // Increase style depth
  2806. m_TextStyleStackDepth += 1;
  2807. // Push style hashcode onto stack
  2808. m_TextStyleStacks[m_TextStyleStackDepth].Push(style.hashCode);
  2809. int styleLength = style.styleOpeningTagArray.Length;
  2810. // Replace <style> tag with opening definition
  2811. int[] tagDefinition = style.styleOpeningTagArray;
  2812. for (int i = 0; i < styleLength; i++)
  2813. {
  2814. int c = tagDefinition[i];
  2815. if (c == '\\' && i + 1 < styleLength)
  2816. {
  2817. switch (tagDefinition[i + 1])
  2818. {
  2819. case '\\':
  2820. i += 1;
  2821. break;
  2822. case 'n':
  2823. c = 10;
  2824. i += 1;
  2825. break;
  2826. case 'r':
  2827. break;
  2828. case 't':
  2829. break;
  2830. case 'u':
  2831. // UTF16 format is "\uFF00" or u + 2 hex pairs.
  2832. if (i + 5 < styleLength)
  2833. {
  2834. c = GetUTF16(tagDefinition, i + 2);
  2835. i += 5;
  2836. }
  2837. break;
  2838. case 'U':
  2839. // UTF32 format is "\UFF00FF00" or U + 4 hex pairs.
  2840. if (i + 9 < styleLength)
  2841. {
  2842. c = GetUTF32(tagDefinition, i + 2);
  2843. i += 9;
  2844. }
  2845. break;
  2846. }
  2847. }
  2848. if (c == 60)
  2849. {
  2850. if (IsTagName(ref tagDefinition, "<BR>", i))
  2851. {
  2852. if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
  2853. charBuffer[writeIndex].unicode = 10;
  2854. writeIndex += 1;
  2855. i += 3;
  2856. continue;
  2857. }
  2858. else if (IsTagName(ref tagDefinition, "<NBSP>", i))
  2859. {
  2860. if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
  2861. charBuffer[writeIndex].unicode = 160;
  2862. writeIndex += 1;
  2863. i += 5;
  2864. continue;
  2865. }
  2866. else if (IsTagName(ref tagDefinition, "<ZWSP>", i))
  2867. {
  2868. if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
  2869. charBuffer[writeIndex].unicode = 0x200B;
  2870. writeIndex += 1;
  2871. i += 5;
  2872. continue;
  2873. }
  2874. else if (IsTagName(ref tagDefinition, "<STYLE=", i))
  2875. {
  2876. int offset;
  2877. if (ReplaceOpeningStyleTag(ref tagDefinition, i, out offset, ref charBuffer, ref writeIndex))
  2878. {
  2879. i = offset;
  2880. continue;
  2881. }
  2882. }
  2883. else if (IsTagName(ref tagDefinition, "</STYLE>", i))
  2884. {
  2885. ReplaceClosingStyleTag(ref tagDefinition, i, ref charBuffer, ref writeIndex);
  2886. // Strip </style> even if style is invalid.
  2887. i += 7;
  2888. continue;
  2889. }
  2890. }
  2891. if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
  2892. charBuffer[writeIndex].unicode = c;
  2893. writeIndex += 1;
  2894. }
  2895. m_TextStyleStackDepth -= 1;
  2896. return true;
  2897. }
  2898. /// <summary>
  2899. /// Method to handle inline replacement of style tag by opening style definition.
  2900. /// </summary>
  2901. /// <param name="sourceText"></param>
  2902. /// <param name="srcIndex"></param>
  2903. /// <param name="srcOffset"></param>
  2904. /// <param name="charBuffer"></param>
  2905. /// <param name="writeIndex"></param>
  2906. /// <returns></returns>
  2907. bool ReplaceOpeningStyleTag(ref char[] sourceText, int srcIndex, out int srcOffset, ref UnicodeChar[] charBuffer, ref int writeIndex)
  2908. {
  2909. // Validate <style> tag.
  2910. int hashCode = GetTagHashCode(ref sourceText, srcIndex + 7, out srcOffset);
  2911. TMP_Style style = GetStyle(hashCode);
  2912. // Return if we don't have a valid style.
  2913. if (style == null || srcOffset == 0) return false;
  2914. // Increase style depth
  2915. m_TextStyleStackDepth += 1;
  2916. // Push style hashcode onto stack
  2917. m_TextStyleStacks[m_TextStyleStackDepth].Push(style.hashCode);
  2918. int styleLength = style.styleOpeningTagArray.Length;
  2919. // Replace <style> tag with opening definition
  2920. int[] tagDefinition = style.styleOpeningTagArray;
  2921. for (int i = 0; i < styleLength; i++)
  2922. {
  2923. int c = tagDefinition[i];
  2924. if (c == '\\' && i + 1 < styleLength)
  2925. {
  2926. switch (tagDefinition[i + 1])
  2927. {
  2928. case '\\':
  2929. i += 1;
  2930. break;
  2931. case 'n':
  2932. c = 10;
  2933. i += 1;
  2934. break;
  2935. case 'r':
  2936. break;
  2937. case 't':
  2938. break;
  2939. case 'u':
  2940. // UTF16 format is "\uFF00" or u + 2 hex pairs.
  2941. if (i + 5 < styleLength)
  2942. {
  2943. c = GetUTF16(tagDefinition, i + 2);
  2944. i += 5;
  2945. }
  2946. break;
  2947. case 'U':
  2948. // UTF32 format is "\UFF00FF00" or U + 4 hex pairs.
  2949. if (i + 9 < styleLength)
  2950. {
  2951. c = GetUTF32(tagDefinition, i + 2);
  2952. i += 9;
  2953. }
  2954. break;
  2955. }
  2956. }
  2957. if (c == 60)
  2958. {
  2959. if (IsTagName(ref tagDefinition, "<BR>", i))
  2960. {
  2961. if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
  2962. charBuffer[writeIndex].unicode = 10;
  2963. writeIndex += 1;
  2964. i += 3;
  2965. continue;
  2966. }
  2967. else if (IsTagName(ref tagDefinition, "<NBSP>", i))
  2968. {
  2969. if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
  2970. charBuffer[writeIndex].unicode = 160;
  2971. writeIndex += 1;
  2972. i += 5;
  2973. continue;
  2974. }
  2975. else if (IsTagName(ref tagDefinition, "<ZWSP>", i))
  2976. {
  2977. if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
  2978. charBuffer[writeIndex].unicode = 0x200B;
  2979. writeIndex += 1;
  2980. i += 5;
  2981. continue;
  2982. }
  2983. else if (IsTagName(ref tagDefinition, "<STYLE=", i))
  2984. {
  2985. int offset;
  2986. if (ReplaceOpeningStyleTag(ref tagDefinition, i, out offset, ref charBuffer, ref writeIndex))
  2987. {
  2988. i = offset;
  2989. continue;
  2990. }
  2991. }
  2992. else if (IsTagName(ref tagDefinition, "</STYLE>", i))
  2993. {
  2994. ReplaceClosingStyleTag(ref tagDefinition, i, ref charBuffer, ref writeIndex);
  2995. // Strip </style> even if style is invalid.
  2996. i += 7;
  2997. continue;
  2998. }
  2999. }
  3000. if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
  3001. charBuffer[writeIndex].unicode = c;
  3002. writeIndex += 1;
  3003. }
  3004. m_TextStyleStackDepth -= 1;
  3005. return true;
  3006. }
  3007. /// <summary>
  3008. /// Method to handle inline replacement of style tag by opening style definition.
  3009. /// </summary>
  3010. /// <param name="sourceText"></param>
  3011. /// <param name="srcIndex"></param>
  3012. /// <param name="srcOffset"></param>
  3013. /// <param name="charBuffer"></param>
  3014. /// <param name="writeIndex"></param>
  3015. /// <returns></returns>
  3016. bool ReplaceOpeningStyleTag(ref StringBuilder sourceText, int srcIndex, out int srcOffset, ref UnicodeChar[] charBuffer, ref int writeIndex)
  3017. {
  3018. // Validate <style> tag.
  3019. int hashCode = GetTagHashCode(ref sourceText, srcIndex + 7, out srcOffset);
  3020. TMP_Style style = GetStyle(hashCode);
  3021. // Return if we don't have a valid style.
  3022. if (style == null || srcOffset == 0) return false;
  3023. // Increase style depth
  3024. m_TextStyleStackDepth += 1;
  3025. // Push style hashcode onto stack
  3026. m_TextStyleStacks[m_TextStyleStackDepth].Push(style.hashCode);
  3027. int styleLength = style.styleOpeningTagArray.Length;
  3028. // Replace <style> tag with opening definition
  3029. int[] tagDefinition = style.styleOpeningTagArray;
  3030. for (int i = 0; i < styleLength; i++)
  3031. {
  3032. int c = tagDefinition[i];
  3033. if (c == '\\' && i + 1 < styleLength)
  3034. {
  3035. switch (tagDefinition[i + 1])
  3036. {
  3037. case '\\':
  3038. i += 1;
  3039. break;
  3040. case 'n':
  3041. c = 10;
  3042. i += 1;
  3043. break;
  3044. case 'r':
  3045. break;
  3046. case 't':
  3047. break;
  3048. case 'u':
  3049. // UTF16 format is "\uFF00" or u + 2 hex pairs.
  3050. if (i + 5 < styleLength)
  3051. {
  3052. c = GetUTF16(tagDefinition, i + 2);
  3053. i += 5;
  3054. }
  3055. break;
  3056. case 'U':
  3057. // UTF32 format is "\UFF00FF00" or U + 4 hex pairs.
  3058. if (i + 9 < styleLength)
  3059. {
  3060. c = GetUTF32(tagDefinition, i + 2);
  3061. i += 9;
  3062. }
  3063. break;
  3064. }
  3065. }
  3066. if (c == 60)
  3067. {
  3068. if (IsTagName(ref tagDefinition, "<BR>", i))
  3069. {
  3070. if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
  3071. charBuffer[writeIndex].unicode = 10;
  3072. writeIndex += 1;
  3073. i += 3;
  3074. continue;
  3075. }
  3076. else if (IsTagName(ref tagDefinition, "<NBSP>", i))
  3077. {
  3078. if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
  3079. charBuffer[writeIndex].unicode = 160;
  3080. writeIndex += 1;
  3081. i += 5;
  3082. continue;
  3083. }
  3084. else if (IsTagName(ref tagDefinition, "<ZWSP>", i))
  3085. {
  3086. if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
  3087. charBuffer[writeIndex].unicode = 0x200B;
  3088. writeIndex += 1;
  3089. i += 5;
  3090. continue;
  3091. }
  3092. else if (IsTagName(ref tagDefinition, "<STYLE=", i))
  3093. {
  3094. int offset;
  3095. if (ReplaceOpeningStyleTag(ref tagDefinition, i, out offset, ref charBuffer, ref writeIndex))
  3096. {
  3097. i = offset;
  3098. continue;
  3099. }
  3100. }
  3101. else if (IsTagName(ref tagDefinition, "</STYLE>", i))
  3102. {
  3103. ReplaceClosingStyleTag(ref tagDefinition, i, ref charBuffer, ref writeIndex);
  3104. // Strip </style> even if style is invalid.
  3105. i += 7;
  3106. continue;
  3107. }
  3108. }
  3109. if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
  3110. charBuffer[writeIndex].unicode = c;
  3111. writeIndex += 1;
  3112. }
  3113. return true;
  3114. }
  3115. /// <summary>
  3116. /// Method to handle inline replacement of style tag by closing style definition.
  3117. /// </summary>
  3118. /// <param name="sourceText"></param>
  3119. /// <param name="srcIndex"></param>
  3120. /// <param name="charBuffer"></param>
  3121. /// <param name="writeIndex"></param>
  3122. /// <returns></returns>
  3123. bool ReplaceClosingStyleTag(ref string sourceText, int srcIndex, ref UnicodeChar[] charBuffer, ref int writeIndex)
  3124. {
  3125. // Get style from the Style Stack
  3126. int hashCode = m_TextStyleStacks[m_TextStyleStackDepth + 1].Pop();
  3127. TMP_Style style = GetStyle(hashCode);
  3128. // Return if we don't have a valid style.
  3129. if (style == null) return false;
  3130. // Increase style depth
  3131. m_TextStyleStackDepth += 1;
  3132. int styleLength = style.styleClosingTagArray.Length;
  3133. // Replace <style> tag with opening definition
  3134. int[] tagDefinition = style.styleClosingTagArray;
  3135. for (int i = 0; i < styleLength; i++)
  3136. {
  3137. int c = tagDefinition[i];
  3138. if (c == '\\' && i + 1 < styleLength)
  3139. {
  3140. switch (tagDefinition[i + 1])
  3141. {
  3142. case '\\':
  3143. i += 1;
  3144. break;
  3145. case 'n':
  3146. c = 10;
  3147. i += 1;
  3148. break;
  3149. case 'r':
  3150. break;
  3151. case 't':
  3152. break;
  3153. case 'u':
  3154. // UTF16 format is "\uFF00" or u + 2 hex pairs.
  3155. if (i + 5 < styleLength)
  3156. {
  3157. c = GetUTF16(tagDefinition, i + 2);
  3158. i += 5;
  3159. }
  3160. break;
  3161. case 'U':
  3162. // UTF32 format is "\UFF00FF00" or U + 4 hex pairs.
  3163. if (i + 9 < styleLength)
  3164. {
  3165. c = GetUTF32(tagDefinition, i + 2);
  3166. i += 9;
  3167. }
  3168. break;
  3169. }
  3170. }
  3171. if (c == 60)
  3172. {
  3173. if (IsTagName(ref tagDefinition, "<BR>", i))
  3174. {
  3175. if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
  3176. charBuffer[writeIndex].unicode = 10;
  3177. writeIndex += 1;
  3178. i += 3;
  3179. continue;
  3180. }
  3181. else if (IsTagName(ref tagDefinition, "<NBSP>", i))
  3182. {
  3183. if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
  3184. charBuffer[writeIndex].unicode = 160;
  3185. writeIndex += 1;
  3186. i += 5;
  3187. continue;
  3188. }
  3189. else if (IsTagName(ref tagDefinition, "<ZWSP>", i))
  3190. {
  3191. if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
  3192. charBuffer[writeIndex].unicode = 0x200B;
  3193. writeIndex += 1;
  3194. i += 5;
  3195. continue;
  3196. }
  3197. else if (IsTagName(ref tagDefinition, "<STYLE=", i))
  3198. {
  3199. int offset;
  3200. if (ReplaceOpeningStyleTag(ref tagDefinition, i, out offset, ref charBuffer, ref writeIndex))
  3201. {
  3202. i = offset;
  3203. continue;
  3204. }
  3205. }
  3206. else if (IsTagName(ref tagDefinition, "</STYLE>", i))
  3207. {
  3208. ReplaceClosingStyleTag(ref tagDefinition, i, ref charBuffer, ref writeIndex);
  3209. i += 7;
  3210. continue;
  3211. }
  3212. }
  3213. if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
  3214. charBuffer[writeIndex].unicode = c;
  3215. writeIndex += 1;
  3216. }
  3217. m_TextStyleStackDepth -= 1;
  3218. return true;
  3219. }
  3220. /// <summary>
  3221. /// Method to handle inline replacement of style tag by closing style definition.
  3222. /// </summary>
  3223. /// <param name="sourceText"></param>
  3224. /// <param name="srcIndex"></param>
  3225. /// <param name="charBuffer"></param>
  3226. /// <param name="writeIndex"></param>
  3227. /// <returns></returns>
  3228. bool ReplaceClosingStyleTag(ref int[] sourceText, int srcIndex, ref UnicodeChar[] charBuffer, ref int writeIndex)
  3229. {
  3230. // Get style from the Style Stack
  3231. int hashCode = m_TextStyleStacks[m_TextStyleStackDepth + 1].Pop();
  3232. TMP_Style style = GetStyle(hashCode);
  3233. // Return if we don't have a valid style.
  3234. if (style == null) return false;
  3235. // Increase style depth
  3236. m_TextStyleStackDepth += 1;
  3237. int styleLength = style.styleClosingTagArray.Length;
  3238. // Replace <style> tag with opening definition
  3239. int[] tagDefinition = style.styleClosingTagArray;
  3240. for (int i = 0; i < styleLength; i++)
  3241. {
  3242. int c = tagDefinition[i];
  3243. if (c == '\\' && i + 1 < styleLength)
  3244. {
  3245. switch (tagDefinition[i + 1])
  3246. {
  3247. case '\\':
  3248. i += 1;
  3249. break;
  3250. case 'n':
  3251. c = 10;
  3252. i += 1;
  3253. break;
  3254. case 'r':
  3255. break;
  3256. case 't':
  3257. break;
  3258. case 'u':
  3259. // UTF16 format is "\uFF00" or u + 2 hex pairs.
  3260. if (i + 5 < styleLength)
  3261. {
  3262. c = GetUTF16(tagDefinition, i + 2);
  3263. i += 5;
  3264. }
  3265. break;
  3266. case 'U':
  3267. // UTF32 format is "\UFF00FF00" or U + 4 hex pairs.
  3268. if (i + 9 < styleLength)
  3269. {
  3270. c = GetUTF32(tagDefinition, i + 2);
  3271. i += 9;
  3272. }
  3273. break;
  3274. }
  3275. }
  3276. if (c == 60)
  3277. {
  3278. if (IsTagName(ref tagDefinition, "<BR>", i))
  3279. {
  3280. if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
  3281. charBuffer[writeIndex].unicode = 10;
  3282. writeIndex += 1;
  3283. i += 3;
  3284. continue;
  3285. }
  3286. else if (IsTagName(ref tagDefinition, "<NBSP>", i))
  3287. {
  3288. if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
  3289. charBuffer[writeIndex].unicode = 160;
  3290. writeIndex += 1;
  3291. i += 5;
  3292. continue;
  3293. }
  3294. else if (IsTagName(ref tagDefinition, "<ZWSP>", i))
  3295. {
  3296. if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
  3297. charBuffer[writeIndex].unicode = 0x200B;
  3298. writeIndex += 1;
  3299. i += 5;
  3300. continue;
  3301. }
  3302. else if (IsTagName(ref tagDefinition, "<STYLE=", i))
  3303. {
  3304. int offset; ;
  3305. if (ReplaceOpeningStyleTag(ref tagDefinition, i, out offset, ref charBuffer, ref writeIndex))
  3306. {
  3307. i = offset;
  3308. continue;
  3309. }
  3310. }
  3311. else if (IsTagName(ref tagDefinition, "</STYLE>", i))
  3312. {
  3313. ReplaceClosingStyleTag(ref tagDefinition, i, ref charBuffer, ref writeIndex);
  3314. // Strip </style> even if style is invalid.
  3315. i += 7;
  3316. continue;
  3317. }
  3318. }
  3319. if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
  3320. charBuffer[writeIndex].unicode = c;
  3321. writeIndex += 1;
  3322. }
  3323. m_TextStyleStackDepth -= 1;
  3324. return true;
  3325. }
  3326. /// <summary>
  3327. /// Method to handle inline replacement of style tag by closing style definition.
  3328. /// </summary>
  3329. /// <param name="sourceText"></param>
  3330. /// <param name="srcIndex"></param>
  3331. /// <param name="charBuffer"></param>
  3332. /// <param name="writeIndex"></param>
  3333. /// <returns></returns>
  3334. bool ReplaceClosingStyleTag(ref char[] sourceText, int srcIndex, ref UnicodeChar[] charBuffer, ref int writeIndex)
  3335. {
  3336. // Get style from the Style Stack
  3337. int hashCode = m_TextStyleStacks[m_TextStyleStackDepth + 1].Pop();
  3338. TMP_Style style = GetStyle(hashCode);
  3339. // Return if we don't have a valid style.
  3340. if (style == null) return false;
  3341. // Increase style depth
  3342. m_TextStyleStackDepth += 1;
  3343. int styleLength = style.styleClosingTagArray.Length;
  3344. // Replace <style> tag with opening definition
  3345. int[] tagDefinition = style.styleClosingTagArray;
  3346. for (int i = 0; i < styleLength; i++)
  3347. {
  3348. int c = tagDefinition[i];
  3349. if (c == '\\' && i + 1 < styleLength)
  3350. {
  3351. switch (tagDefinition[i + 1])
  3352. {
  3353. case '\\':
  3354. i += 1;
  3355. break;
  3356. case 'n':
  3357. c = 10;
  3358. i += 1;
  3359. break;
  3360. case 'r':
  3361. break;
  3362. case 't':
  3363. break;
  3364. case 'u':
  3365. // UTF16 format is "\uFF00" or u + 2 hex pairs.
  3366. if (i + 5 < styleLength)
  3367. {
  3368. c = GetUTF16(tagDefinition, i + 2);
  3369. i += 5;
  3370. }
  3371. break;
  3372. case 'U':
  3373. // UTF32 format is "\UFF00FF00" or U + 4 hex pairs.
  3374. if (i + 9 < styleLength)
  3375. {
  3376. c = GetUTF32(tagDefinition, i + 2);
  3377. i += 9;
  3378. }
  3379. break;
  3380. }
  3381. }
  3382. if (c == 60)
  3383. {
  3384. if (IsTagName(ref tagDefinition, "<BR>", i))
  3385. {
  3386. if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
  3387. charBuffer[writeIndex].unicode = 10;
  3388. writeIndex += 1;
  3389. i += 3;
  3390. continue;
  3391. }
  3392. else if (IsTagName(ref tagDefinition, "<NBSP>", i))
  3393. {
  3394. if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
  3395. charBuffer[writeIndex].unicode = 160;
  3396. writeIndex += 1;
  3397. i += 5;
  3398. continue;
  3399. }
  3400. else if (IsTagName(ref tagDefinition, "<ZWSP>", i))
  3401. {
  3402. if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
  3403. charBuffer[writeIndex].unicode = 0x200B;
  3404. writeIndex += 1;
  3405. i += 5;
  3406. continue;
  3407. }
  3408. else if (IsTagName(ref tagDefinition, "<STYLE=", i))
  3409. {
  3410. int offset;
  3411. if (ReplaceOpeningStyleTag(ref tagDefinition, i, out offset, ref charBuffer, ref writeIndex))
  3412. {
  3413. i = offset;
  3414. continue;
  3415. }
  3416. }
  3417. else if (IsTagName(ref tagDefinition, "</STYLE>", i))
  3418. {
  3419. ReplaceClosingStyleTag(ref tagDefinition, i, ref charBuffer, ref writeIndex);
  3420. // Strip </style> even if style is invalid.
  3421. i += 7;
  3422. continue;
  3423. }
  3424. }
  3425. if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
  3426. charBuffer[writeIndex].unicode = c;
  3427. writeIndex += 1;
  3428. }
  3429. m_TextStyleStackDepth -= 1;
  3430. return true;
  3431. }
  3432. /// <summary>
  3433. /// Method to handle inline replacement of style tag by closing style definition.
  3434. /// </summary>
  3435. /// <param name="sourceText"></param>
  3436. /// <param name="srcIndex"></param>
  3437. /// <param name="charBuffer"></param>
  3438. /// <param name="writeIndex"></param>
  3439. /// <returns></returns>
  3440. bool ReplaceClosingStyleTag(ref StringBuilder sourceText, int srcIndex, ref UnicodeChar[] charBuffer, ref int writeIndex)
  3441. {
  3442. // Get style from the Style Stack
  3443. int hashCode = m_TextStyleStacks[m_TextStyleStackDepth + 1].Pop();
  3444. TMP_Style style = GetStyle(hashCode);
  3445. // Return if we don't have a valid style.
  3446. if (style == null) return false;
  3447. // Increase style depth
  3448. m_TextStyleStackDepth += 1;
  3449. int styleLength = style.styleClosingTagArray.Length;
  3450. // Replace <style> tag with opening definition
  3451. int[] tagDefinition = style.styleClosingTagArray;
  3452. for (int i = 0; i < styleLength; i++)
  3453. {
  3454. int c = tagDefinition[i];
  3455. if (c == '\\' && i + 1 < styleLength)
  3456. {
  3457. switch (tagDefinition[i + 1])
  3458. {
  3459. case '\\':
  3460. i += 1;
  3461. break;
  3462. case 'n':
  3463. c = 10;
  3464. i += 1;
  3465. break;
  3466. case 'r':
  3467. break;
  3468. case 't':
  3469. break;
  3470. case 'u':
  3471. // UTF16 format is "\uFF00" or u + 2 hex pairs.
  3472. if (i + 5 < styleLength)
  3473. {
  3474. c = GetUTF16(tagDefinition, i + 2);
  3475. i += 5;
  3476. }
  3477. break;
  3478. case 'U':
  3479. // UTF32 format is "\UFF00FF00" or U + 4 hex pairs.
  3480. if (i + 9 < styleLength)
  3481. {
  3482. c = GetUTF32(tagDefinition, i + 2);
  3483. i += 9;
  3484. }
  3485. break;
  3486. }
  3487. }
  3488. if (c == 60)
  3489. {
  3490. if (IsTagName(ref tagDefinition, "<BR>", i))
  3491. {
  3492. if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
  3493. charBuffer[writeIndex].unicode = 10;
  3494. writeIndex += 1;
  3495. i += 3;
  3496. continue;
  3497. }
  3498. else if (IsTagName(ref tagDefinition, "<NBSP>", i))
  3499. {
  3500. if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
  3501. charBuffer[writeIndex].unicode = 160;
  3502. writeIndex += 1;
  3503. i += 5;
  3504. continue;
  3505. }
  3506. else if (IsTagName(ref tagDefinition, "<ZWSP>", i))
  3507. {
  3508. if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
  3509. charBuffer[writeIndex].unicode = 0x200B;
  3510. writeIndex += 1;
  3511. i += 5;
  3512. continue;
  3513. }
  3514. else if (IsTagName(ref tagDefinition, "<STYLE=", i))
  3515. {
  3516. int offset;
  3517. if (ReplaceOpeningStyleTag(ref tagDefinition, i, out offset, ref charBuffer, ref writeIndex))
  3518. {
  3519. i = offset;
  3520. continue;
  3521. }
  3522. }
  3523. else if (IsTagName(ref tagDefinition, "</STYLE>", i))
  3524. {
  3525. ReplaceClosingStyleTag(ref tagDefinition, i, ref charBuffer, ref writeIndex);
  3526. // Strip </style> even if style is invalid.
  3527. i += 7;
  3528. continue;
  3529. }
  3530. }
  3531. if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
  3532. charBuffer[writeIndex].unicode = c;
  3533. writeIndex += 1;
  3534. }
  3535. m_TextStyleStackDepth -= 1;
  3536. return true;
  3537. }
  3538. /// <summary>
  3539. ///
  3540. /// </summary>
  3541. /// <param name="hashCode"></param>
  3542. /// <returns></returns>
  3543. TMP_Style GetStyle(int hashCode)
  3544. {
  3545. TMP_Style style = null;
  3546. // Get Style from Style Sheet potentially assigned to text object.
  3547. if (m_StyleSheet != null)
  3548. {
  3549. style = m_StyleSheet.GetStyle(hashCode);
  3550. if (style != null)
  3551. return style;
  3552. }
  3553. if (TMP_Settings.defaultStyleSheet != null)
  3554. style = TMP_Settings.defaultStyleSheet.GetStyle(hashCode);
  3555. return style;
  3556. }
  3557. bool InsertOpeningStyleTag(TMP_Style style, int srcIndex, ref UnicodeChar[] charBuffer, ref int writeIndex)
  3558. {
  3559. // Return if we don't have a valid style.
  3560. if (style == null) return false;
  3561. m_TextStyleStacks[0].Push(style.hashCode);
  3562. int styleLength = style.styleOpeningTagArray.Length;
  3563. // Replace <style> tag with opening definition
  3564. int[] tagDefinition = style.styleOpeningTagArray;
  3565. for (int i = 0; i < styleLength; i++)
  3566. {
  3567. int c = tagDefinition[i];
  3568. if (c == '\\' && i + 1 < styleLength)
  3569. {
  3570. switch (tagDefinition[i + 1])
  3571. {
  3572. case '\\':
  3573. i += 1;
  3574. break;
  3575. case 'n':
  3576. c = 10;
  3577. i += 1;
  3578. break;
  3579. case 'r':
  3580. break;
  3581. case 't':
  3582. break;
  3583. case 'u':
  3584. // UTF16 format is "\uFF00" or u + 2 hex pairs.
  3585. if (i + 5 < styleLength)
  3586. {
  3587. c = GetUTF16(tagDefinition, i + 2);
  3588. i += 5;
  3589. }
  3590. break;
  3591. case 'U':
  3592. // UTF32 format is "\UFF00FF00" or U + 4 hex pairs.
  3593. if (i + 9 < styleLength)
  3594. {
  3595. c = GetUTF32(tagDefinition, i + 2);
  3596. i += 9;
  3597. }
  3598. break;
  3599. }
  3600. }
  3601. if (c == 60)
  3602. {
  3603. if (IsTagName(ref tagDefinition, "<BR>", i))
  3604. {
  3605. if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
  3606. charBuffer[writeIndex].unicode = 10;
  3607. writeIndex += 1;
  3608. i += 3;
  3609. continue;
  3610. }
  3611. else if (IsTagName(ref tagDefinition, "<NBSP>", i))
  3612. {
  3613. if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
  3614. charBuffer[writeIndex].unicode = 160;
  3615. writeIndex += 1;
  3616. i += 5;
  3617. continue;
  3618. }
  3619. else if (IsTagName(ref tagDefinition, "<ZWSP>", i))
  3620. {
  3621. if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
  3622. charBuffer[writeIndex].unicode = 0x200B;
  3623. writeIndex += 1;
  3624. i += 5;
  3625. continue;
  3626. }
  3627. else if (IsTagName(ref tagDefinition, "<STYLE=", i))
  3628. {
  3629. int offset;
  3630. if (ReplaceOpeningStyleTag(ref tagDefinition, i, out offset, ref charBuffer, ref writeIndex))
  3631. {
  3632. i = offset;
  3633. continue;
  3634. }
  3635. }
  3636. else if (IsTagName(ref tagDefinition, "</STYLE>", i))
  3637. {
  3638. ReplaceClosingStyleTag(ref tagDefinition, i, ref charBuffer, ref writeIndex);
  3639. // Strip </style> even if style is invalid.
  3640. i += 7;
  3641. continue;
  3642. }
  3643. }
  3644. if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
  3645. charBuffer[writeIndex].unicode = c;
  3646. writeIndex += 1;
  3647. }
  3648. m_TextStyleStackDepth = 0;
  3649. return true;
  3650. }
  3651. bool InsertClosingStyleTag(ref UnicodeChar[] charBuffer, ref int writeIndex)
  3652. {
  3653. // Get style from the Style Stack
  3654. int hashCode = m_TextStyleStacks[0].Pop();
  3655. TMP_Style style = GetStyle(hashCode);
  3656. int styleLength = style.styleClosingTagArray.Length;
  3657. // Replace <style> tag with opening definition
  3658. int[] tagDefinition = style.styleClosingTagArray;
  3659. for (int i = 0; i < styleLength; i++)
  3660. {
  3661. int c = tagDefinition[i];
  3662. if (c == '\\' && i + 1 < styleLength)
  3663. {
  3664. switch (tagDefinition[i + 1])
  3665. {
  3666. case '\\':
  3667. i += 1;
  3668. break;
  3669. case 'n':
  3670. c = 10;
  3671. i += 1;
  3672. break;
  3673. case 'r':
  3674. break;
  3675. case 't':
  3676. break;
  3677. case 'u':
  3678. // UTF16 format is "\uFF00" or u + 2 hex pairs.
  3679. if (i + 5 < styleLength)
  3680. {
  3681. c = GetUTF16(tagDefinition, i + 2);
  3682. i += 5;
  3683. }
  3684. break;
  3685. case 'U':
  3686. // UTF32 format is "\UFF00FF00" or U + 4 hex pairs.
  3687. if (i + 9 < styleLength)
  3688. {
  3689. c = GetUTF32(tagDefinition, i + 2);
  3690. i += 9;
  3691. }
  3692. break;
  3693. }
  3694. }
  3695. if (c == 60)
  3696. {
  3697. if (IsTagName(ref tagDefinition, "<BR>", i))
  3698. {
  3699. if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
  3700. charBuffer[writeIndex].unicode = 10;
  3701. writeIndex += 1;
  3702. i += 3;
  3703. continue;
  3704. }
  3705. else if (IsTagName(ref tagDefinition, "<NBSP>", i))
  3706. {
  3707. if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
  3708. charBuffer[writeIndex].unicode = 160;
  3709. writeIndex += 1;
  3710. i += 5;
  3711. continue;
  3712. }
  3713. else if (IsTagName(ref tagDefinition, "<ZWSP>", i))
  3714. {
  3715. if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
  3716. charBuffer[writeIndex].unicode = 0x200B;
  3717. writeIndex += 1;
  3718. i += 5;
  3719. continue;
  3720. }
  3721. else if (IsTagName(ref tagDefinition, "<STYLE=", i))
  3722. {
  3723. int offset;
  3724. if (ReplaceOpeningStyleTag(ref tagDefinition, i, out offset, ref charBuffer, ref writeIndex))
  3725. {
  3726. i = offset;
  3727. continue;
  3728. }
  3729. }
  3730. else if (IsTagName(ref tagDefinition, "</STYLE>", i))
  3731. {
  3732. ReplaceClosingStyleTag(ref tagDefinition, i, ref charBuffer, ref writeIndex);
  3733. // Strip </style> even if style is invalid.
  3734. i += 7;
  3735. continue;
  3736. }
  3737. }
  3738. if (writeIndex == charBuffer.Length) ResizeInternalArray(ref charBuffer);
  3739. charBuffer[writeIndex].unicode = c;
  3740. writeIndex += 1;
  3741. }
  3742. m_TextStyleStackDepth = 0;
  3743. return true;
  3744. }
  3745. /// <summary>
  3746. /// Method to check for a matching rich text tag.
  3747. /// </summary>
  3748. /// <param name="text"></param>
  3749. /// <param name="tag"></param>
  3750. /// <param name="index"></param>
  3751. /// <returns></returns>
  3752. bool IsTagName (ref string text, string tag, int index)
  3753. {
  3754. if (text.Length < index + tag.Length) return false;
  3755. for (int i = 0; i < tag.Length; i++)
  3756. {
  3757. if (TMP_TextUtilities.ToUpperFast(text[index + i]) != tag[i]) return false;
  3758. }
  3759. return true;
  3760. }
  3761. /// <summary>
  3762. /// Method to check for a matching rich text tag.
  3763. /// </summary>
  3764. /// <param name="text"></param>
  3765. /// <param name="tag"></param>
  3766. /// <param name="index"></param>
  3767. /// <returns></returns>
  3768. bool IsTagName(ref char[] text, string tag, int index)
  3769. {
  3770. if (text.Length < index + tag.Length) return false;
  3771. for (int i = 0; i < tag.Length; i++)
  3772. {
  3773. if (TMP_TextUtilities.ToUpperFast(text[index + i]) != tag[i]) return false;
  3774. }
  3775. return true;
  3776. }
  3777. /// <summary>
  3778. /// Method to check for a matching rich text tag.
  3779. /// </summary>
  3780. /// <param name="text"></param>
  3781. /// <param name="tag"></param>
  3782. /// <param name="index"></param>
  3783. /// <returns></returns>
  3784. bool IsTagName(ref int[] text, string tag, int index)
  3785. {
  3786. if (text.Length < index + tag.Length) return false;
  3787. for (int i = 0; i < tag.Length; i++)
  3788. {
  3789. if (TMP_TextUtilities.ToUpperFast((char)text[index + i]) != tag[i]) return false;
  3790. }
  3791. return true;
  3792. }
  3793. /// <summary>
  3794. /// Method to check for a matching rich text tag.
  3795. /// </summary>
  3796. /// <param name="text"></param>
  3797. /// <param name="tag"></param>
  3798. /// <param name="index"></param>
  3799. /// <returns></returns>
  3800. bool IsTagName(ref StringBuilder text, string tag, int index)
  3801. {
  3802. if (text.Length < index + tag.Length) return false;
  3803. for (int i = 0; i < tag.Length; i++)
  3804. {
  3805. if (TMP_TextUtilities.ToUpperFast(text[index + i]) != tag[i]) return false;
  3806. }
  3807. return true;
  3808. }
  3809. /// <summary>
  3810. /// Get Hashcode for a given tag.
  3811. /// </summary>
  3812. /// <param name="text"></param>
  3813. /// <param name="index"></param>
  3814. /// <param name="closeIndex"></param>
  3815. /// <returns></returns>
  3816. int GetTagHashCode(ref string text, int index, out int closeIndex)
  3817. {
  3818. int hashCode = 0;
  3819. closeIndex = 0;
  3820. for (int i = index; i < text.Length; i++)
  3821. {
  3822. // Skip quote '"' character
  3823. if (text[i] == 34) continue;
  3824. // Break at '>'
  3825. if (text[i] == 62) { closeIndex = i; break; }
  3826. hashCode = (hashCode << 5) + hashCode ^ TMP_TextParsingUtilities.ToUpperASCIIFast(text[i]);
  3827. }
  3828. return hashCode;
  3829. }
  3830. /// <summary>
  3831. /// Get Hashcode for a given tag.
  3832. /// </summary>
  3833. /// <param name="text"></param>
  3834. /// <param name="index"></param>
  3835. /// <param name="closeIndex"></param>
  3836. /// <returns></returns>
  3837. int GetTagHashCode(ref char[] text, int index, out int closeIndex)
  3838. {
  3839. int hashCode = 0;
  3840. closeIndex = 0;
  3841. for (int i = index; i < text.Length; i++)
  3842. {
  3843. // Skip quote '"' character
  3844. if (text[i] == 34) continue;
  3845. // Break at '>'
  3846. if (text[i] == 62) { closeIndex = i; break; }
  3847. hashCode = (hashCode << 5) + hashCode ^ TMP_TextParsingUtilities.ToUpperASCIIFast(text[i]);
  3848. }
  3849. return hashCode;
  3850. }
  3851. /// <summary>
  3852. /// Get Hashcode for a given tag.
  3853. /// </summary>
  3854. /// <param name="text"></param>
  3855. /// <param name="index"></param>
  3856. /// <param name="closeIndex"></param>
  3857. /// <returns></returns>
  3858. int GetTagHashCode(ref int[] text, int index, out int closeIndex)
  3859. {
  3860. int hashCode = 0;
  3861. closeIndex = 0;
  3862. for (int i = index; i < text.Length; i++)
  3863. {
  3864. // Skip quote '"' character
  3865. if (text[i] == 34) continue;
  3866. // Break at '>'
  3867. if (text[i] == 62) { closeIndex = i; break; }
  3868. hashCode = (hashCode << 5) + hashCode ^ TMP_TextParsingUtilities.ToUpperASCIIFast((char)text[i]);
  3869. }
  3870. return hashCode;
  3871. }
  3872. /// <summary>
  3873. /// Get Hashcode for a given tag.
  3874. /// </summary>
  3875. /// <param name="text"></param>
  3876. /// <param name="index"></param>
  3877. /// <param name="closeIndex"></param>
  3878. /// <returns></returns>
  3879. int GetTagHashCode(ref StringBuilder text, int index, out int closeIndex)
  3880. {
  3881. int hashCode = 0;
  3882. closeIndex = 0;
  3883. for (int i = index; i < text.Length; i++)
  3884. {
  3885. // Skip quote '"' character
  3886. if (text[i] == 34) continue;
  3887. // Break at '>'
  3888. if (text[i] == 62) { closeIndex = i; break; }
  3889. hashCode = (hashCode << 5) + hashCode ^ TMP_TextParsingUtilities.ToUpperASCIIFast(text[i]);
  3890. }
  3891. return hashCode;
  3892. }
  3893. /// <summary>
  3894. ///
  3895. /// </summary>
  3896. void ResizeInternalArray <T>(ref T[] array)
  3897. {
  3898. int size = Mathf.NextPowerOfTwo(array.Length + 1);
  3899. System.Array.Resize(ref array, size);
  3900. }
  3901. void ResizeInternalArray<T>(ref T[] array, int size)
  3902. {
  3903. size = Mathf.NextPowerOfTwo(size + 1);
  3904. System.Array.Resize(ref array, size);
  3905. }
  3906. private readonly decimal[] k_Power = { 5e-1m, 5e-2m, 5e-3m, 5e-4m, 5e-5m, 5e-6m, 5e-7m, 5e-8m, 5e-9m, 5e-10m }; // Used by FormatText to enable rounding and avoid using Mathf.Pow.
  3907. void AddFloatToCharArray(float value, int padding, int precision, ref int writeIndex)
  3908. {
  3909. if (value < 0)
  3910. {
  3911. m_input_CharArray[writeIndex] = '-';
  3912. writeIndex += 1;
  3913. value = -value;
  3914. }
  3915. // Using decimal type due to floating point precision impacting formatting
  3916. decimal valueD = (decimal)value;
  3917. // Round up value to the specified prevision otherwise set precision to max.
  3918. if (padding == 0 && precision == 0)
  3919. precision = 9;
  3920. else
  3921. valueD += k_Power[Mathf.Min(9, precision)];
  3922. long integer = (long)valueD;
  3923. AddIntegerToCharArray(integer, padding, ref writeIndex);
  3924. if (precision > 0)
  3925. {
  3926. valueD -= integer;
  3927. // Add decimal point and values only if remainder is not zero.
  3928. if (valueD != 0)
  3929. {
  3930. // Add decimal point
  3931. m_input_CharArray[writeIndex++] = '.';
  3932. for (int p = 0; p < precision; p++)
  3933. {
  3934. valueD *= 10;
  3935. long d = (long)valueD;
  3936. m_input_CharArray[writeIndex++] = (char)(d + 48);
  3937. valueD -= d;
  3938. if (valueD == 0)
  3939. p = precision;
  3940. }
  3941. }
  3942. }
  3943. }
  3944. /// <summary>
  3945. ///
  3946. /// </summary>
  3947. /// <param name="number"></param>
  3948. /// <param name="padding"></param>
  3949. /// <param name="writeIndex"></param>
  3950. void AddIntegerToCharArray(double number, int padding, ref int writeIndex)
  3951. {
  3952. int integralCount = 0;
  3953. int i = writeIndex;
  3954. do
  3955. {
  3956. m_input_CharArray[i++] = (char)(number % 10 + 48);
  3957. number /= 10;
  3958. integralCount += 1;
  3959. } while (number > 0.999d || integralCount < padding);
  3960. int lastIndex = i;
  3961. //// Reverse string
  3962. while (writeIndex + 1 < i)
  3963. {
  3964. i -= 1;
  3965. char t = m_input_CharArray[writeIndex];
  3966. m_input_CharArray[writeIndex] = m_input_CharArray[i];
  3967. m_input_CharArray[i] = t;
  3968. writeIndex += 1;
  3969. }
  3970. writeIndex = lastIndex;
  3971. }
  3972. /// <summary>
  3973. /// Method used to determine the number of visible characters and required buffer allocations.
  3974. /// </summary>
  3975. /// <param name="unicodeChars"></param>
  3976. /// <returns></returns>
  3977. protected virtual int SetArraySizes(UnicodeChar[] unicodeChars) { return 0; }
  3978. /// <summary>
  3979. /// Method which parses the text input, does the layout of the text as well as generating the geometry.
  3980. /// </summary>
  3981. protected virtual void GenerateTextMesh() { }
  3982. /// <summary>
  3983. /// Function to Calculate the Preferred Width and Height of the text object.
  3984. /// </summary>
  3985. /// <returns></returns>
  3986. public Vector2 GetPreferredValues()
  3987. {
  3988. if (m_isInputParsingRequired || m_isTextTruncated)
  3989. {
  3990. m_isCalculatingPreferredValues = true;
  3991. ParseInputText();
  3992. }
  3993. // CALCULATE PREFERRED WIDTH
  3994. float preferredWidth = GetPreferredWidth();
  3995. // CALCULATE PREFERRED HEIGHT
  3996. float preferredHeight = GetPreferredHeight();
  3997. return new Vector2(preferredWidth, preferredHeight);
  3998. }
  3999. /// <summary>
  4000. /// Function to Calculate the Preferred Width and Height of the text object given the provided width and height.
  4001. /// </summary>
  4002. /// <returns></returns>
  4003. public Vector2 GetPreferredValues(float width, float height)
  4004. {
  4005. if (m_isInputParsingRequired || m_isTextTruncated)
  4006. {
  4007. m_isCalculatingPreferredValues = true;
  4008. ParseInputText();
  4009. }
  4010. Vector2 margin = new Vector2(width, height);
  4011. // CALCULATE PREFERRED WIDTH
  4012. float preferredWidth = GetPreferredWidth(margin);
  4013. // CALCULATE PREFERRED HEIGHT
  4014. float preferredHeight = GetPreferredHeight(margin);
  4015. return new Vector2(preferredWidth, preferredHeight);
  4016. }
  4017. /// <summary>
  4018. /// Function to Calculate the Preferred Width and Height of the text object given a certain string.
  4019. /// </summary>
  4020. /// <param name="text"></param>
  4021. /// <returns></returns>
  4022. public Vector2 GetPreferredValues(string text)
  4023. {
  4024. m_isCalculatingPreferredValues = true;
  4025. StringToInternalParsingBuffer(text, ref m_InternalParsingBuffer);
  4026. SetArraySizes(m_InternalParsingBuffer);
  4027. Vector2 margin = k_LargePositiveVector2;
  4028. // CALCULATE PREFERRED WIDTH
  4029. float preferredWidth = GetPreferredWidth(margin);
  4030. // CALCULATE PREFERRED HEIGHT
  4031. float preferredHeight = GetPreferredHeight(margin);
  4032. return new Vector2(preferredWidth, preferredHeight);
  4033. }
  4034. /// <summary>
  4035. /// Function to Calculate the Preferred Width and Height of the text object given a certain string and size of text container.
  4036. /// </summary>
  4037. /// <param name="text"></param>
  4038. /// <returns></returns>
  4039. public Vector2 GetPreferredValues(string text, float width, float height)
  4040. {
  4041. m_isCalculatingPreferredValues = true;
  4042. StringToInternalParsingBuffer(text, ref m_InternalParsingBuffer);
  4043. SetArraySizes(m_InternalParsingBuffer);
  4044. Vector2 margin = new Vector2(width, height);
  4045. // CALCULATE PREFERRED WIDTH
  4046. float preferredWidth = GetPreferredWidth(margin);
  4047. // CALCULATE PREFERRED HEIGHT
  4048. float preferredHeight = GetPreferredHeight(margin);
  4049. return new Vector2(preferredWidth, preferredHeight);
  4050. }
  4051. /// <summary>
  4052. /// Method to calculate the preferred width of a text object.
  4053. /// </summary>
  4054. /// <returns></returns>
  4055. protected float GetPreferredWidth()
  4056. {
  4057. if (TMP_Settings.instance == null) return 0;
  4058. // Return cached preferred height if already computed
  4059. if (!m_isPreferredWidthDirty)
  4060. return m_preferredWidth;
  4061. float fontSize = m_enableAutoSizing ? m_fontSizeMax : m_fontSize;
  4062. // Reset auto sizing point size bounds
  4063. m_minFontSize = m_fontSizeMin;
  4064. m_maxFontSize = m_fontSizeMax;
  4065. m_charWidthAdjDelta = 0;
  4066. // Set Margins to Infinity
  4067. Vector2 margin = k_LargePositiveVector2;
  4068. if (m_isInputParsingRequired || m_isTextTruncated)
  4069. {
  4070. m_isCalculatingPreferredValues = true;
  4071. ParseInputText();
  4072. }
  4073. m_AutoSizeIterationCount = 0;
  4074. float preferredWidth = CalculatePreferredValues(ref fontSize, margin, false, false).x;
  4075. m_isPreferredWidthDirty = false;
  4076. //Debug.Log("GetPreferredWidth() called on Object ID: " + GetInstanceID() + " on frame: " + Time.frameCount + ". Returning width of " + preferredWidth);
  4077. return preferredWidth;
  4078. }
  4079. /// <summary>
  4080. /// Method to calculate the preferred width of a text object.
  4081. /// </summary>
  4082. /// <param name="margin"></param>
  4083. /// <returns></returns>
  4084. float GetPreferredWidth(Vector2 margin)
  4085. {
  4086. float fontSize = m_enableAutoSizing ? m_fontSizeMax : m_fontSize;
  4087. // Reset auto sizing point size bounds
  4088. m_minFontSize = m_fontSizeMin;
  4089. m_maxFontSize = m_fontSizeMax;
  4090. m_charWidthAdjDelta = 0;
  4091. m_AutoSizeIterationCount = 0;
  4092. float preferredWidth = CalculatePreferredValues(ref fontSize, margin, false, false).x;
  4093. //Debug.Log("GetPreferredWidth() Called. Returning width of " + preferredWidth);
  4094. return preferredWidth;
  4095. }
  4096. /// <summary>
  4097. /// Method to calculate the preferred height of a text object.
  4098. /// </summary>
  4099. /// <returns></returns>
  4100. protected float GetPreferredHeight()
  4101. {
  4102. if (TMP_Settings.instance == null) return 0;
  4103. // Return cached preferred height if already computed
  4104. if (!m_isPreferredHeightDirty)
  4105. return m_preferredHeight;
  4106. float fontSize = m_enableAutoSizing ? m_fontSizeMax : m_fontSize;
  4107. // Reset auto sizing point size bounds
  4108. m_minFontSize = m_fontSizeMin;
  4109. m_maxFontSize = m_fontSizeMax;
  4110. m_charWidthAdjDelta = 0;
  4111. Vector2 margin = new Vector2(m_marginWidth != 0 ? m_marginWidth : k_LargePositiveFloat, k_LargePositiveFloat);
  4112. if (m_isInputParsingRequired || m_isTextTruncated)
  4113. {
  4114. m_isCalculatingPreferredValues = true;
  4115. ParseInputText();
  4116. }
  4117. // Reset Text Auto Size iteration tracking.
  4118. m_IsAutoSizePointSizeSet = false;
  4119. m_AutoSizeIterationCount = 0;
  4120. // The CalculatePreferredValues function is potentially called repeatedly when text auto size is enabled.
  4121. // This is a revised implementation to remove the use of recursion which could potentially result in stack overflow issues.
  4122. float preferredHeight = 0;
  4123. while (m_IsAutoSizePointSizeSet == false)
  4124. {
  4125. preferredHeight = CalculatePreferredValues(ref fontSize, margin, m_enableAutoSizing, m_enableWordWrapping).y;
  4126. m_AutoSizeIterationCount += 1;
  4127. }
  4128. m_isPreferredHeightDirty = false;
  4129. //Debug.Log("GetPreferredHeight() called on Object ID: " + GetInstanceID() + " on frame: " + Time.frameCount +". Returning height of " + preferredHeight);
  4130. return preferredHeight;
  4131. }
  4132. /// <summary>
  4133. /// Method to calculate the preferred height of a text object.
  4134. /// </summary>
  4135. /// <param name="margin"></param>
  4136. /// <returns></returns>
  4137. float GetPreferredHeight(Vector2 margin)
  4138. {
  4139. float fontSize = m_enableAutoSizing ? m_fontSizeMax : m_fontSize;
  4140. // Reset auto sizing point size bounds
  4141. m_minFontSize = m_fontSizeMin;
  4142. m_maxFontSize = m_fontSizeMax;
  4143. m_charWidthAdjDelta = 0;
  4144. // Reset Text Auto Size iteration tracking.
  4145. m_IsAutoSizePointSizeSet = false;
  4146. m_AutoSizeIterationCount = 0;
  4147. // The CalculatePreferredValues function is potentially called repeatedly when text auto size is enabled.
  4148. // This is a revised implementation to remove the use of recursion which could potentially result in stack overflow issues.
  4149. float preferredHeight = 0;
  4150. while (m_IsAutoSizePointSizeSet == false)
  4151. {
  4152. preferredHeight = CalculatePreferredValues(ref fontSize, margin, m_enableAutoSizing, m_enableWordWrapping).y;
  4153. m_AutoSizeIterationCount += 1;
  4154. }
  4155. //Debug.Log("GetPreferredHeight() Called. Returning height of " + preferredHeight);
  4156. return preferredHeight;
  4157. }
  4158. /// <summary>
  4159. /// Method returning the rendered width and height of the text object.
  4160. /// </summary>
  4161. /// <returns></returns>
  4162. public Vector2 GetRenderedValues()
  4163. {
  4164. return GetTextBounds().size;
  4165. }
  4166. /// <summary>
  4167. ///
  4168. /// </summary>
  4169. /// <param name="onlyVisibleCharacters">Should returned value only factor in visible characters and exclude those greater than maxVisibleCharacters for instance.</param>
  4170. /// <returns></returns>
  4171. public Vector2 GetRenderedValues(bool onlyVisibleCharacters)
  4172. {
  4173. return GetTextBounds(onlyVisibleCharacters).size;
  4174. }
  4175. /// <summary>
  4176. /// Method returning the rendered width of the text object.
  4177. /// </summary>
  4178. /// <returns></returns>
  4179. float GetRenderedWidth()
  4180. {
  4181. return GetRenderedValues().x;
  4182. }
  4183. /// <summary>
  4184. /// Method returning the rendered width of the text object.
  4185. /// </summary>
  4186. /// <returns></returns>
  4187. protected float GetRenderedWidth(bool onlyVisibleCharacters)
  4188. {
  4189. return GetRenderedValues(onlyVisibleCharacters).x;
  4190. }
  4191. /// <summary>
  4192. /// Method returning the rendered height of the text object.
  4193. /// </summary>
  4194. /// <returns></returns>
  4195. float GetRenderedHeight()
  4196. {
  4197. return GetRenderedValues().y;
  4198. }
  4199. /// <summary>
  4200. /// Method returning the rendered height of the text object.
  4201. /// </summary>
  4202. /// <returns></returns>
  4203. protected float GetRenderedHeight(bool onlyVisibleCharacters)
  4204. {
  4205. return GetRenderedValues(onlyVisibleCharacters).y;
  4206. }
  4207. /// <summary>
  4208. /// Method to calculate the preferred width and height of the text object.
  4209. /// </summary>
  4210. /// <returns></returns>
  4211. protected virtual Vector2 CalculatePreferredValues(ref float fontSize, Vector2 marginSize, bool isTextAutoSizingEnabled, bool isWordWrappingEnabled)
  4212. {
  4213. //Debug.Log("*** CalculatePreferredValues() ***"); // ***** Frame: " + Time.frameCount);
  4214. ////Profiler.BeginSample("TMP Generate Text - Phase I");
  4215. // Early exit if no font asset was assigned. This should not be needed since LiberationSans SDF will be assigned by default.
  4216. if (m_fontAsset == null || m_fontAsset.characterLookupTable == null)
  4217. {
  4218. Debug.LogWarning("Can't Generate Mesh! No Font Asset has been assigned to Object ID: " + this.GetInstanceID());
  4219. m_IsAutoSizePointSizeSet = true;
  4220. return Vector2.zero;
  4221. }
  4222. // Early exit if we don't have any Text to generate.
  4223. if (m_InternalParsingBuffer == null || m_InternalParsingBuffer.Length == 0 || m_InternalParsingBuffer[0].unicode == (char)0)
  4224. {
  4225. m_IsAutoSizePointSizeSet = true;
  4226. return Vector2.zero;
  4227. }
  4228. m_currentFontAsset = m_fontAsset;
  4229. m_currentMaterial = m_sharedMaterial;
  4230. m_currentMaterialIndex = 0;
  4231. m_materialReferenceStack.SetDefault(new MaterialReference(0, m_currentFontAsset, null, m_currentMaterial, m_padding));
  4232. // Total character count is computed when the text is parsed.
  4233. int totalCharacterCount = m_totalCharacterCount; // m_VisibleCharacters.Count;
  4234. if (m_internalCharacterInfo == null || totalCharacterCount > m_internalCharacterInfo.Length)
  4235. m_internalCharacterInfo = new TMP_CharacterInfo[totalCharacterCount > 1024 ? totalCharacterCount + 256 : Mathf.NextPowerOfTwo(totalCharacterCount)];
  4236. // Calculate the scale of the font based on selected font size and sampling point size.
  4237. // baseScale is calculated using the font asset assigned to the text object.
  4238. float baseScale = m_fontScale = (fontSize / m_fontAsset.faceInfo.pointSize * m_fontAsset.faceInfo.scale * (m_isOrthographic ? 1 : 0.1f));
  4239. float currentElementScale = baseScale;
  4240. float currentEmScale = fontSize * 0.01f * (m_isOrthographic ? 1 : 0.1f);
  4241. m_fontScaleMultiplier = 1;
  4242. m_currentFontSize = fontSize;
  4243. m_sizeStack.SetDefault(m_currentFontSize);
  4244. float fontSizeDelta = 0;
  4245. m_FontStyleInternal = m_fontStyle; // Set the default style.
  4246. m_lineJustification = m_HorizontalAlignment; // m_textAlignment; // Sets the line justification mode to match editor alignment.
  4247. m_lineJustificationStack.SetDefault(m_lineJustification);
  4248. m_baselineOffset = 0; // Used by subscript characters.
  4249. m_baselineOffsetStack.Clear();
  4250. m_lineOffset = 0; // Amount of space between lines (font line spacing + m_linespacing).
  4251. m_lineHeight = TMP_Math.FLOAT_UNSET;
  4252. float lineGap = m_currentFontAsset.faceInfo.lineHeight - (m_currentFontAsset.faceInfo.ascentLine - m_currentFontAsset.faceInfo.descentLine);
  4253. m_cSpacing = 0; // Amount of space added between characters as a result of the use of the <cspace> tag.
  4254. m_monoSpacing = 0;
  4255. //float lineOffsetDelta = 0;
  4256. m_xAdvance = 0; // Used to track the position of each character.
  4257. float maxXAdvance = 0; // Used to determine Preferred Width.
  4258. tag_LineIndent = 0; // Used for indentation of text.
  4259. tag_Indent = 0;
  4260. m_indentStack.SetDefault(0);
  4261. tag_NoParsing = false;
  4262. //m_isIgnoringAlignment = false;
  4263. m_characterCount = 0; // Total characters in the char[]
  4264. // Tracking of line information
  4265. m_firstCharacterOfLine = 0;
  4266. m_maxLineAscender = k_LargeNegativeFloat;
  4267. m_maxLineDescender = k_LargePositiveFloat;
  4268. m_lineNumber = 0;
  4269. m_startOfLineAscender = 0;
  4270. m_IsDrivenLineSpacing = false;
  4271. float marginWidth = marginSize.x;
  4272. float marginHeight = marginSize.y;
  4273. m_marginLeft = 0;
  4274. m_marginRight = 0;
  4275. float lineMarginLeft = 0;
  4276. float lineMarginRight = 0;
  4277. m_width = -1;
  4278. float widthOfTextArea = marginWidth + 0.0001f - m_marginLeft - m_marginRight;
  4279. // Used by Unity's Auto Layout system.
  4280. float renderedWidth = 0;
  4281. float renderedHeight = 0;
  4282. float textWidth = 0;
  4283. m_isCalculatingPreferredValues = true;
  4284. // Tracking of the highest Ascender
  4285. m_maxCapHeight = 0;
  4286. m_maxTextAscender = 0;
  4287. m_ElementDescender = 0;
  4288. float maxVisibleDescender = 0;
  4289. bool isMaxVisibleDescenderSet = false;
  4290. // Initialize struct to track states of word wrapping
  4291. bool isFirstWordOfLine = true;
  4292. m_isNonBreakingSpace = false;
  4293. //bool isLastBreakingChar = false;
  4294. bool isLastCharacterCJK = false;
  4295. //int lastSoftLineBreak = 0;
  4296. CharacterSubstitution characterToSubstitute = new CharacterSubstitution(-1, 0);
  4297. bool isSoftHyphenIgnored = false;
  4298. WordWrapState internalWordWrapState = new WordWrapState();
  4299. WordWrapState internalLineState = new WordWrapState();
  4300. WordWrapState internalSoftLineBreak = new WordWrapState();
  4301. // Counter to prevent recursive lockup when computing preferred values.
  4302. m_AutoSizeIterationCount += 1;
  4303. // Parse through Character buffer to read HTML tags and begin creating mesh.
  4304. for (int i = 0; i < m_InternalParsingBuffer.Length && m_InternalParsingBuffer[i].unicode != 0; i++)
  4305. {
  4306. int charCode = m_InternalParsingBuffer[i].unicode;
  4307. // Parse Rich Text Tag
  4308. #region Parse Rich Text Tag
  4309. if (m_isRichText && charCode == 60) // '<'
  4310. {
  4311. m_isParsingText = true;
  4312. m_textElementType = TMP_TextElementType.Character;
  4313. int endTagIndex;
  4314. // Check if Tag is valid. If valid, skip to the end of the validated tag.
  4315. if (ValidateHtmlTag(m_InternalParsingBuffer, i + 1, out endTagIndex))
  4316. {
  4317. i = endTagIndex;
  4318. // Continue to next character or handle the sprite element
  4319. if (m_textElementType == TMP_TextElementType.Character)
  4320. continue;
  4321. }
  4322. }
  4323. else
  4324. {
  4325. m_textElementType = m_textInfo.characterInfo[m_characterCount].elementType;
  4326. m_currentMaterialIndex = m_textInfo.characterInfo[m_characterCount].materialReferenceIndex;
  4327. m_currentFontAsset = m_textInfo.characterInfo[m_characterCount].fontAsset;
  4328. }
  4329. #endregion End Parse Rich Text Tag
  4330. int prev_MaterialIndex = m_currentMaterialIndex;
  4331. bool isUsingAltTypeface = m_textInfo.characterInfo[m_characterCount].isUsingAlternateTypeface;
  4332. m_isParsingText = false;
  4333. // Handle potential character substitutions
  4334. #region Character Substitutions
  4335. bool isInjectingCharacter = false;
  4336. if (characterToSubstitute.index == m_characterCount)
  4337. {
  4338. charCode = (int)characterToSubstitute.unicode;
  4339. m_textElementType = TMP_TextElementType.Character;
  4340. isInjectingCharacter = true;
  4341. switch (charCode)
  4342. {
  4343. case 0x03:
  4344. m_internalCharacterInfo[m_characterCount].textElement = m_currentFontAsset.characterLookupTable[0x03];
  4345. m_isTextTruncated = true;
  4346. break;
  4347. case 0x2D:
  4348. //
  4349. break;
  4350. case 0x2026:
  4351. m_internalCharacterInfo[m_characterCount].textElement = m_Ellipsis.character; ;
  4352. m_internalCharacterInfo[m_characterCount].elementType = TMP_TextElementType.Character;
  4353. m_internalCharacterInfo[m_characterCount].fontAsset = m_Ellipsis.fontAsset;
  4354. m_internalCharacterInfo[m_characterCount].material = m_Ellipsis.material;
  4355. m_internalCharacterInfo[m_characterCount].materialReferenceIndex = m_Ellipsis.materialIndex;
  4356. // Indicates the source parsing data has been modified.
  4357. m_isTextTruncated = true;
  4358. // End Of Text
  4359. characterToSubstitute.index = m_characterCount + 1;
  4360. characterToSubstitute.unicode = 0x03;
  4361. break;
  4362. }
  4363. }
  4364. #endregion
  4365. // When using Linked text, mark character as ignored and skip to next character.
  4366. #region Linked Text
  4367. if (m_characterCount < m_firstVisibleCharacter && charCode != 0x03)
  4368. {
  4369. m_internalCharacterInfo[m_characterCount].isVisible = false;
  4370. m_internalCharacterInfo[m_characterCount].character = (char)0x200B;
  4371. m_internalCharacterInfo[m_characterCount].lineNumber = 0;
  4372. m_characterCount += 1;
  4373. continue;
  4374. }
  4375. #endregion
  4376. // Handle Font Styles like LowerCase, UpperCase and SmallCaps.
  4377. #region Handling of LowerCase, UpperCase and SmallCaps Font Styles
  4378. float smallCapsMultiplier = 1.0f;
  4379. if (m_textElementType == TMP_TextElementType.Character)
  4380. {
  4381. if (/*(m_fontStyle & FontStyles.UpperCase) == FontStyles.UpperCase ||*/ (m_FontStyleInternal & FontStyles.UpperCase) == FontStyles.UpperCase)
  4382. {
  4383. // If this character is lowercase, switch to uppercase.
  4384. if (char.IsLower((char)charCode))
  4385. charCode = char.ToUpper((char)charCode);
  4386. }
  4387. else if (/*(m_fontStyle & FontStyles.LowerCase) == FontStyles.LowerCase ||*/ (m_FontStyleInternal & FontStyles.LowerCase) == FontStyles.LowerCase)
  4388. {
  4389. // If this character is uppercase, switch to lowercase.
  4390. if (char.IsUpper((char)charCode))
  4391. charCode = char.ToLower((char)charCode);
  4392. }
  4393. else if (/*(m_fontStyle & FontStyles.SmallCaps) == FontStyles.SmallCaps ||*/ (m_FontStyleInternal & FontStyles.SmallCaps) == FontStyles.SmallCaps)
  4394. {
  4395. if (char.IsLower((char)charCode))
  4396. {
  4397. smallCapsMultiplier = 0.8f;
  4398. charCode = char.ToUpper((char)charCode);
  4399. }
  4400. }
  4401. }
  4402. #endregion
  4403. // Look up Character Data from Dictionary and cache it.
  4404. #region Look up Character Data
  4405. //float baselineOffset = 0;
  4406. float elementAscentLine = 0;
  4407. float elementDescentLine = 0;
  4408. if (m_textElementType == TMP_TextElementType.Sprite)
  4409. {
  4410. // If a sprite is used as a fallback then get a reference to it and set the color to white.
  4411. m_currentSpriteAsset = m_textInfo.characterInfo[m_characterCount].spriteAsset;
  4412. m_spriteIndex = m_textInfo.characterInfo[m_characterCount].spriteIndex;
  4413. TMP_SpriteCharacter sprite = m_currentSpriteAsset.spriteCharacterTable[m_spriteIndex];
  4414. if (sprite == null) continue;
  4415. // Sprites are assigned in the E000 Private Area + sprite Index
  4416. if (charCode == 60)
  4417. charCode = 57344 + m_spriteIndex;
  4418. // The sprite scale calculations are based on the font asset assigned to the text object.
  4419. if (m_currentSpriteAsset.faceInfo.pointSize > 0)
  4420. {
  4421. float spriteScale = (m_currentFontSize / m_currentSpriteAsset.faceInfo.pointSize * m_currentSpriteAsset.faceInfo.scale * (m_isOrthographic ? 1 : 0.1f));
  4422. currentElementScale = sprite.scale * sprite.glyph.scale * spriteScale;
  4423. elementAscentLine = m_currentSpriteAsset.faceInfo.ascentLine;
  4424. //baselineOffset = m_currentSpriteAsset.faceInfo.baseline * m_fontScale * m_fontScaleMultiplier * m_currentSpriteAsset.faceInfo.scale;
  4425. elementDescentLine = m_currentSpriteAsset.faceInfo.descentLine;
  4426. }
  4427. else
  4428. {
  4429. float spriteScale = (m_currentFontSize / m_currentFontAsset.faceInfo.pointSize * m_currentFontAsset.faceInfo.scale * (m_isOrthographic ? 1 : 0.1f));
  4430. currentElementScale = m_currentFontAsset.faceInfo.ascentLine / sprite.glyph.metrics.height * sprite.scale * sprite.glyph.scale * spriteScale;
  4431. float scaleDelta = spriteScale / currentElementScale;
  4432. elementAscentLine = m_currentFontAsset.faceInfo.ascentLine * scaleDelta;
  4433. //baselineOffset = m_currentFontAsset.faceInfo.baseline * m_fontScale * m_fontScaleMultiplier * m_currentFontAsset.faceInfo.scale;
  4434. elementDescentLine = m_currentFontAsset.faceInfo.descentLine * scaleDelta;
  4435. }
  4436. m_cached_TextElement = sprite;
  4437. m_internalCharacterInfo[m_characterCount].elementType = TMP_TextElementType.Sprite;
  4438. m_internalCharacterInfo[m_characterCount].scale = currentElementScale;
  4439. m_currentMaterialIndex = prev_MaterialIndex;
  4440. }
  4441. else if (m_textElementType == TMP_TextElementType.Character)
  4442. {
  4443. m_cached_TextElement = m_textInfo.characterInfo[m_characterCount].textElement;
  4444. if (m_cached_TextElement == null) continue;
  4445. m_currentMaterialIndex = m_textInfo.characterInfo[m_characterCount].materialReferenceIndex;
  4446. float adjustedScale;
  4447. if (isInjectingCharacter && m_InternalParsingBuffer[i].unicode == 0x0A && m_characterCount != m_firstCharacterOfLine)
  4448. adjustedScale = m_textInfo.characterInfo[m_characterCount - 1].pointSize * smallCapsMultiplier / m_currentFontAsset.m_FaceInfo.pointSize * m_currentFontAsset.m_FaceInfo.scale * (m_isOrthographic ? 1 : 0.1f);
  4449. else
  4450. adjustedScale = m_currentFontSize * smallCapsMultiplier / m_currentFontAsset.m_FaceInfo.pointSize * m_currentFontAsset.m_FaceInfo.scale * (m_isOrthographic ? 1 : 0.1f);
  4451. elementAscentLine = m_currentFontAsset.m_FaceInfo.ascentLine;
  4452. elementDescentLine = m_currentFontAsset.m_FaceInfo.descentLine;
  4453. currentElementScale = adjustedScale * m_fontScaleMultiplier * m_cached_TextElement.scale;
  4454. //baselineOffset = m_currentFontAsset.faceInfo.baseline * m_fontScale * m_fontScaleMultiplier * m_currentFontAsset.faceInfo.scale;
  4455. m_internalCharacterInfo[m_characterCount].elementType = TMP_TextElementType.Character;
  4456. }
  4457. #endregion
  4458. // Handle Soft Hyphen
  4459. #region Handle Soft Hyphen
  4460. float currentElementUnmodifiedScale = currentElementScale;
  4461. if (charCode == 0xAD || charCode == 0x03)
  4462. currentElementScale = 0;
  4463. #endregion
  4464. // Store some of the text object's information
  4465. m_internalCharacterInfo[m_characterCount].character = (char)charCode;
  4466. // Cache glyph metrics
  4467. GlyphMetrics currentGlyphMetrics = m_cached_TextElement.m_Glyph.metrics;
  4468. // Optimization to avoid calling this more than once per character.
  4469. bool isWhiteSpace = char.IsWhiteSpace((char)charCode);
  4470. // Handle Kerning if Enabled.
  4471. #region Handle Kerning
  4472. TMP_GlyphValueRecord glyphAdjustments = new TMP_GlyphValueRecord();
  4473. float characterSpacingAdjustment = m_characterSpacing;
  4474. m_GlyphHorizontalAdvanceAdjustment = 0;
  4475. if (m_enableKerning)
  4476. {
  4477. TMP_GlyphPairAdjustmentRecord adjustmentPair;
  4478. uint baseGlyphIndex = m_cached_TextElement.m_GlyphIndex;
  4479. if (m_characterCount < totalCharacterCount - 1)
  4480. {
  4481. uint nextGlyphIndex = m_textInfo.characterInfo[m_characterCount + 1].textElement.m_GlyphIndex;
  4482. uint key = nextGlyphIndex << 16 | baseGlyphIndex;
  4483. if (m_currentFontAsset.m_FontFeatureTable.m_GlyphPairAdjustmentRecordLookupDictionary.TryGetValue(key, out adjustmentPair))
  4484. {
  4485. glyphAdjustments = adjustmentPair.m_FirstAdjustmentRecord.m_GlyphValueRecord;
  4486. characterSpacingAdjustment = (adjustmentPair.m_FeatureLookupFlags & FontFeatureLookupFlags.IgnoreSpacingAdjustments) == FontFeatureLookupFlags.IgnoreSpacingAdjustments ? 0 : characterSpacingAdjustment;
  4487. }
  4488. }
  4489. if (m_characterCount >= 1)
  4490. {
  4491. uint previousGlyphIndex = m_textInfo.characterInfo[m_characterCount - 1].textElement.m_GlyphIndex;
  4492. uint key = baseGlyphIndex << 16 | previousGlyphIndex;
  4493. if (m_currentFontAsset.m_FontFeatureTable.m_GlyphPairAdjustmentRecordLookupDictionary.TryGetValue(key, out adjustmentPair))
  4494. {
  4495. glyphAdjustments += adjustmentPair.m_SecondAdjustmentRecord.m_GlyphValueRecord;
  4496. characterSpacingAdjustment = (adjustmentPair.m_FeatureLookupFlags & FontFeatureLookupFlags.IgnoreSpacingAdjustments) == FontFeatureLookupFlags.IgnoreSpacingAdjustments ? 0 : characterSpacingAdjustment;
  4497. }
  4498. }
  4499. m_GlyphHorizontalAdvanceAdjustment = glyphAdjustments.m_XAdvance;
  4500. }
  4501. #endregion
  4502. // Initial Implementation for RTL support.
  4503. #region Handle Right-to-Left
  4504. //if (m_isRightToLeft)
  4505. //{
  4506. // m_xAdvance -= ((m_cached_TextElement.xAdvance * bold_xAdvance_multiplier + m_characterSpacing + m_wordSpacing + m_currentFontAsset.normalSpacingOffset) * currentElementScale + m_cSpacing) * (1 - m_charWidthAdjDelta);
  4507. // if (char.IsWhiteSpace((char)charCode) || charCode == 0x200B)
  4508. // m_xAdvance -= m_wordSpacing * currentElementScale;
  4509. //}
  4510. #endregion
  4511. // Handle Mono Spacing
  4512. #region Handle Mono Spacing
  4513. float monoAdvance = 0;
  4514. if (m_monoSpacing != 0)
  4515. {
  4516. monoAdvance = (m_monoSpacing / 2 - (m_cached_TextElement.glyph.metrics.width / 2 + m_cached_TextElement.glyph.metrics.horizontalBearingX) * currentElementScale) * (1 - m_charWidthAdjDelta);
  4517. m_xAdvance += monoAdvance;
  4518. }
  4519. #endregion
  4520. // Set Padding based on selected font style
  4521. #region Handle Style Padding
  4522. float boldSpacingAdjustment = 0;
  4523. if (m_textElementType == TMP_TextElementType.Character && !isUsingAltTypeface && ((m_FontStyleInternal & FontStyles.Bold) == FontStyles.Bold)) // Checks for any combination of Bold Style.
  4524. boldSpacingAdjustment = m_currentFontAsset.boldSpacing;
  4525. #endregion Handle Style Padding
  4526. m_internalCharacterInfo[m_characterCount].baseLine = 0 - m_lineOffset + m_baselineOffset;
  4527. // Compute text metrics
  4528. #region Compute Ascender & Descender values
  4529. // Element Ascender in line space
  4530. float elementAscender = m_textElementType == TMP_TextElementType.Character
  4531. ? elementAscentLine * currentElementScale / smallCapsMultiplier + m_baselineOffset
  4532. : elementAscentLine * currentElementScale + m_baselineOffset;
  4533. // Element Descender in line space
  4534. float elementDescender = m_textElementType == TMP_TextElementType.Character
  4535. ? elementDescentLine * currentElementScale / smallCapsMultiplier + m_baselineOffset
  4536. : elementDescentLine * currentElementScale + m_baselineOffset;
  4537. float adjustedAscender = elementAscender;
  4538. float adjustedDescender = elementDescender;
  4539. bool isFirstCharacterOfLine = m_characterCount == m_firstCharacterOfLine;
  4540. // Max line ascender and descender in line space
  4541. if (isFirstCharacterOfLine || isWhiteSpace == false)
  4542. {
  4543. // Special handling for Superscript and Subscript where we use the unadjusted line ascender and descender
  4544. if (m_baselineOffset != 0)
  4545. {
  4546. adjustedAscender = Mathf.Max((elementAscender - m_baselineOffset) / m_fontScaleMultiplier, adjustedAscender);
  4547. adjustedDescender = Mathf.Min((elementDescender - m_baselineOffset) / m_fontScaleMultiplier, adjustedDescender);
  4548. }
  4549. m_maxLineAscender = Mathf.Max(adjustedAscender, m_maxLineAscender);
  4550. m_maxLineDescender = Mathf.Min(adjustedDescender, m_maxLineDescender);
  4551. }
  4552. // Element Ascender and Descender in object space
  4553. if (isFirstCharacterOfLine || isWhiteSpace == false)
  4554. {
  4555. m_internalCharacterInfo[m_characterCount].adjustedAscender = adjustedAscender;
  4556. m_internalCharacterInfo[m_characterCount].adjustedDescender = adjustedDescender;
  4557. m_ElementAscender = m_internalCharacterInfo[m_characterCount].ascender = elementAscender - m_lineOffset;
  4558. m_ElementDescender = m_internalCharacterInfo[m_characterCount].descender = elementDescender - m_lineOffset;
  4559. }
  4560. else
  4561. {
  4562. m_internalCharacterInfo[m_characterCount].adjustedAscender = m_maxLineAscender;
  4563. m_internalCharacterInfo[m_characterCount].adjustedDescender = m_maxLineDescender;
  4564. m_ElementAscender = m_internalCharacterInfo[m_characterCount].ascender = m_maxLineAscender - m_lineOffset;
  4565. m_ElementDescender = m_internalCharacterInfo[m_characterCount].descender = m_maxLineDescender - m_lineOffset;
  4566. }
  4567. // Max text object ascender and cap height
  4568. if (m_lineNumber == 0 || m_isNewPage)
  4569. {
  4570. if (isFirstCharacterOfLine || isWhiteSpace == false)
  4571. {
  4572. m_maxTextAscender = m_maxLineAscender;
  4573. m_maxCapHeight = Mathf.Max(m_maxCapHeight, m_currentFontAsset.m_FaceInfo.capLine * currentElementScale / smallCapsMultiplier);
  4574. }
  4575. }
  4576. // Page ascender
  4577. if (m_lineOffset == 0)
  4578. {
  4579. if (!isWhiteSpace || m_characterCount == m_firstCharacterOfLine)
  4580. m_PageAscender = m_PageAscender > elementAscender ? m_PageAscender : elementAscender;
  4581. }
  4582. #endregion
  4583. bool isJustifiedOrFlush = (m_lineJustification & HorizontalAlignmentOptions.Flush) == HorizontalAlignmentOptions.Flush || (m_lineJustification & HorizontalAlignmentOptions.Justified) == HorizontalAlignmentOptions.Justified;
  4584. // Setup Mesh for visible text elements. ie. not a SPACE / LINEFEED / CARRIAGE RETURN.
  4585. #region Handle Visible Characters
  4586. if (charCode == 9 || (isWhiteSpace == false && charCode != 0x200B && charCode != 0xAD && charCode != 0x03) || (charCode == 0xAD && isSoftHyphenIgnored == false) || m_textElementType == TMP_TextElementType.Sprite)
  4587. {
  4588. //float marginLeft = m_marginLeft;
  4589. //float marginRight = m_marginRight;
  4590. // Injected characters do not override margins
  4591. //if (isInjectingCharacter)
  4592. //{
  4593. // marginLeft = m_textInfo.lineInfo[m_lineNumber].marginLeft;
  4594. // marginRight = m_textInfo.lineInfo[m_lineNumber].marginRight;
  4595. //}
  4596. widthOfTextArea = m_width != -1 ? Mathf.Min(marginWidth + 0.0001f - m_marginLeft - m_marginRight, m_width) : marginWidth + 0.0001f - m_marginLeft - m_marginRight;
  4597. // Calculate the line breaking width of the text.
  4598. textWidth = Mathf.Abs(m_xAdvance) + currentGlyphMetrics.horizontalAdvance * (1 - m_charWidthAdjDelta) * (charCode == 0xAD ? currentElementUnmodifiedScale : currentElementScale);
  4599. int testedCharacterCount = m_characterCount;
  4600. // Handling of Horizontal Bounds
  4601. #region Current Line Horizontal Bounds Check
  4602. if (textWidth > widthOfTextArea * (isJustifiedOrFlush ? 1.05f : 1.0f))
  4603. {
  4604. // Handle Line Breaking (if still possible)
  4605. if (isWordWrappingEnabled && m_characterCount != m_firstCharacterOfLine) // && isFirstWord == false)
  4606. {
  4607. // Restore state to previous safe line breaking
  4608. i = RestoreWordWrappingState(ref internalWordWrapState);
  4609. // Replace Soft Hyphen by Hyphen Minus 0x2D
  4610. #region Handle Soft Hyphenation
  4611. if (m_internalCharacterInfo[m_characterCount - 1].character == 0xAD && isSoftHyphenIgnored == false && m_overflowMode == TextOverflowModes.Overflow)
  4612. {
  4613. characterToSubstitute.index = m_characterCount - 1;
  4614. characterToSubstitute.unicode = 0x2D;
  4615. i -= 1;
  4616. m_characterCount -= 1;
  4617. continue;
  4618. }
  4619. isSoftHyphenIgnored = false;
  4620. // Ignore Soft Hyphen to prevent it from wrapping
  4621. if (m_internalCharacterInfo[m_characterCount].character == 0xAD)
  4622. {
  4623. isSoftHyphenIgnored = true;
  4624. continue;
  4625. }
  4626. #endregion
  4627. // Adjust character spacing before breaking up word if auto size is enabled
  4628. #region Handle Text Auto Size (if word wrapping is no longer possible)
  4629. if (isTextAutoSizingEnabled && isFirstWordOfLine)
  4630. {
  4631. // Handle Character Width Adjustments
  4632. #region Character Width Adjustments
  4633. if (m_charWidthAdjDelta < m_charWidthMaxAdj / 100 && m_AutoSizeIterationCount < m_AutoSizeMaxIterationCount)
  4634. {
  4635. float adjustedTextWidth = textWidth;
  4636. // Determine full width of the text
  4637. if (m_charWidthAdjDelta > 0)
  4638. adjustedTextWidth /= 1f - m_charWidthAdjDelta;
  4639. float adjustmentDelta = textWidth - (widthOfTextArea - 0.0001f) * (isJustifiedOrFlush ? 1.05f : 1.0f);
  4640. m_charWidthAdjDelta += adjustmentDelta / adjustedTextWidth;
  4641. m_charWidthAdjDelta = Mathf.Min(m_charWidthAdjDelta, m_charWidthMaxAdj / 100);
  4642. //Debug.Log("[" + m_AutoSizeIterationCount + "] Reducing Character Width by " + (m_charWidthAdjDelta * 100) + "%");
  4643. return Vector2.zero;
  4644. }
  4645. #endregion
  4646. // Handle Text Auto-sizing resulting from text exceeding vertical bounds.
  4647. #region Text Auto-Sizing (Text greater than vertical bounds)
  4648. if (fontSize > m_fontSizeMin && m_AutoSizeIterationCount < m_AutoSizeMaxIterationCount)
  4649. {
  4650. m_maxFontSize = fontSize;
  4651. float sizeDelta = Mathf.Max((fontSize - m_minFontSize) / 2, 0.05f);
  4652. fontSize -= sizeDelta;
  4653. fontSize = Mathf.Max((int)(fontSize * 20 + 0.5f) / 20f, m_fontSizeMin);
  4654. //Debug.Log("[" + m_AutoSizeIterationCount + "] Reducing Point Size from [" + m_maxFontSize.ToString("f3") + "] to [" + m_fontSize.ToString("f3") + "] with delta of [" + sizeDelta.ToString("f3") + "].");
  4655. return Vector2.zero;
  4656. }
  4657. #endregion Text Auto-Sizing
  4658. }
  4659. #endregion
  4660. // Adjust line spacing if necessary
  4661. float baselineAdjustmentDelta = m_maxLineAscender - m_startOfLineAscender;
  4662. if (m_lineOffset > 0 && Math.Abs(baselineAdjustmentDelta) > 0.01f && m_IsDrivenLineSpacing == false && !m_isNewPage)
  4663. {
  4664. //AdjustLineOffset(m_firstCharacterOfLine, m_characterCount, baselineAdjustmentDelta);
  4665. m_ElementDescender -= baselineAdjustmentDelta;
  4666. m_lineOffset += baselineAdjustmentDelta;
  4667. }
  4668. // Calculate line ascender and make sure if last character is superscript or subscript that we check that as well.
  4669. float lineAscender = m_maxLineAscender - m_lineOffset;
  4670. float lineDescender = m_maxLineDescender - m_lineOffset;
  4671. // Update maxDescender and maxVisibleDescender
  4672. m_ElementDescender = m_ElementDescender < lineDescender ? m_ElementDescender : lineDescender;
  4673. if (!isMaxVisibleDescenderSet)
  4674. maxVisibleDescender = m_ElementDescender;
  4675. if (m_useMaxVisibleDescender && (m_characterCount >= m_maxVisibleCharacters || m_lineNumber >= m_maxVisibleLines))
  4676. isMaxVisibleDescenderSet = true;
  4677. // Store first character of the next line.
  4678. m_firstCharacterOfLine = m_characterCount;
  4679. m_lineVisibleCharacterCount = 0;
  4680. // Compute Preferred Width & Height
  4681. renderedWidth += m_xAdvance;
  4682. if (isWordWrappingEnabled)
  4683. renderedHeight = m_maxTextAscender - m_ElementDescender;
  4684. else
  4685. renderedHeight = Mathf.Max(renderedHeight, lineAscender - lineDescender);
  4686. // Store the state of the line before starting on the new line.
  4687. SaveWordWrappingState(ref internalLineState, i, m_characterCount - 1);
  4688. m_lineNumber += 1;
  4689. float ascender = m_internalCharacterInfo[m_characterCount].adjustedAscender;
  4690. // Compute potential new line offset in the event a line break is needed.
  4691. if (m_lineHeight == TMP_Math.FLOAT_UNSET)
  4692. {
  4693. m_lineOffset += 0 - m_maxLineDescender + ascender + (lineGap + m_lineSpacingDelta) * baseScale + m_lineSpacing * currentEmScale;
  4694. m_IsDrivenLineSpacing = false;
  4695. }
  4696. else
  4697. {
  4698. m_lineOffset += m_lineHeight + m_lineSpacing * currentEmScale;
  4699. m_IsDrivenLineSpacing = true;
  4700. }
  4701. m_maxLineAscender = k_LargeNegativeFloat;
  4702. m_maxLineDescender = k_LargePositiveFloat;
  4703. m_startOfLineAscender = ascender;
  4704. m_xAdvance = 0 + tag_Indent;
  4705. //isStartOfNewLine = true;
  4706. isFirstWordOfLine = true;
  4707. continue;
  4708. }
  4709. }
  4710. #endregion
  4711. lineMarginLeft = m_marginLeft;
  4712. lineMarginRight = m_marginRight;
  4713. }
  4714. #endregion Handle Visible Characters
  4715. // Check if Line Spacing of previous line needs to be adjusted.
  4716. #region Adjust Line Spacing
  4717. /*if (m_lineOffset > 0 && !TMP_Math.Approximately(m_maxLineAscender, m_startOfLineAscender) && m_IsDrivenLineSpacing == false && !m_isNewPage)
  4718. {
  4719. float offsetDelta = m_maxLineAscender - m_startOfLineAscender;
  4720. //AdjustLineOffset(m_firstCharacterOfLine, m_characterCount, offsetDelta);
  4721. m_ElementDescender -= offsetDelta;
  4722. m_lineOffset += offsetDelta;
  4723. m_startOfLineAscender += offsetDelta;
  4724. internalWordWrapState.lineOffset = m_lineOffset;
  4725. internalWordWrapState.startOfLineAscender = m_startOfLineAscender;
  4726. }*/
  4727. #endregion
  4728. // Handle xAdvance & Tabulation Stops. Tab stops at every 25% of Font Size.
  4729. #region XAdvance, Tabulation & Stops
  4730. if (charCode == 9)
  4731. {
  4732. float tabSize = m_currentFontAsset.faceInfo.tabWidth * m_currentFontAsset.tabSize * currentElementScale;
  4733. float tabs = Mathf.Ceil(m_xAdvance / tabSize) * tabSize;
  4734. m_xAdvance = tabs > m_xAdvance ? tabs : m_xAdvance + tabSize;
  4735. }
  4736. else if (m_monoSpacing != 0)
  4737. {
  4738. m_xAdvance += (m_monoSpacing - monoAdvance + ((m_currentFontAsset.normalSpacingOffset + characterSpacingAdjustment) * currentEmScale) + m_cSpacing) * (1 - m_charWidthAdjDelta);
  4739. if (isWhiteSpace || charCode == 0x200B)
  4740. m_xAdvance += m_wordSpacing * currentEmScale;
  4741. }
  4742. else
  4743. {
  4744. m_xAdvance += ((currentGlyphMetrics.horizontalAdvance + glyphAdjustments.xAdvance + boldSpacingAdjustment) * currentElementScale + (m_currentFontAsset.normalSpacingOffset + characterSpacingAdjustment) * currentEmScale + m_cSpacing) * (1 - m_charWidthAdjDelta);
  4745. if (isWhiteSpace || charCode == 0x200B)
  4746. m_xAdvance += m_wordSpacing * currentEmScale;
  4747. }
  4748. #endregion Tabulation & Stops
  4749. // Handle Carriage Return
  4750. #region Carriage Return
  4751. if (charCode == 13)
  4752. {
  4753. maxXAdvance = Mathf.Max(maxXAdvance, renderedWidth + m_xAdvance);
  4754. renderedWidth = 0;
  4755. m_xAdvance = 0 + tag_Indent;
  4756. }
  4757. #endregion Carriage Return
  4758. // Handle Line Spacing Adjustments + Word Wrapping & special case for last line.
  4759. #region Check for Line Feed and Last Character
  4760. if (charCode == 10 || charCode == 11 || charCode == 0x03 || charCode == 0x2028 || charCode == 0x2029 || m_characterCount == totalCharacterCount - 1)
  4761. {
  4762. // Check if Line Spacing of previous line needs to be adjusted.
  4763. float baselineAdjustmentDelta = m_maxLineAscender - m_startOfLineAscender;
  4764. if (m_lineOffset > 0 && Math.Abs(baselineAdjustmentDelta) > 0.01f && m_IsDrivenLineSpacing == false && !m_isNewPage)
  4765. {
  4766. m_ElementDescender -= baselineAdjustmentDelta;
  4767. m_lineOffset += baselineAdjustmentDelta;
  4768. }
  4769. m_isNewPage = false;
  4770. // Calculate lineAscender & make sure if last character is superscript or subscript that we check that as well.
  4771. //float lineAscender = m_maxLineAscender - m_lineOffset;
  4772. float lineDescender = m_maxLineDescender - m_lineOffset;
  4773. // Update maxDescender and maxVisibleDescender
  4774. m_ElementDescender = m_ElementDescender < lineDescender ? m_ElementDescender : lineDescender;
  4775. // Store PreferredWidth paying attention to linefeed and last character of text.
  4776. if (m_characterCount == totalCharacterCount - 1)
  4777. renderedWidth = Mathf.Max(maxXAdvance, renderedWidth + textWidth + lineMarginLeft + lineMarginRight);
  4778. else
  4779. {
  4780. maxXAdvance = Mathf.Max(maxXAdvance, renderedWidth + textWidth + lineMarginLeft + lineMarginRight);
  4781. renderedWidth = 0;
  4782. }
  4783. renderedHeight = m_maxTextAscender - m_ElementDescender;
  4784. // Add new line if not last lines or character.
  4785. if (charCode == 10 || charCode == 11 || charCode == 0x2D || charCode == 0x2028 || charCode == 0x2029)
  4786. {
  4787. // Store the state of the line before starting on the new line.
  4788. SaveWordWrappingState(ref internalLineState, i, m_characterCount);
  4789. // Store the state of the last Character before the new line.
  4790. SaveWordWrappingState(ref internalWordWrapState, i, m_characterCount);
  4791. m_lineNumber += 1;
  4792. m_firstCharacterOfLine = m_characterCount + 1;
  4793. float ascender = m_internalCharacterInfo[m_characterCount].adjustedAscender;
  4794. // Apply Line Spacing with special handling for VT char(11)
  4795. if (m_lineHeight == TMP_Math.FLOAT_UNSET)
  4796. {
  4797. float lineOffsetDelta = 0 - m_maxLineDescender + ascender + (lineGap + m_lineSpacingDelta) * baseScale + (m_lineSpacing + (charCode == 10 || charCode == 0x2029 ? m_paragraphSpacing : 0)) * currentEmScale;
  4798. m_lineOffset += lineOffsetDelta;
  4799. m_IsDrivenLineSpacing = false;
  4800. }
  4801. else
  4802. {
  4803. m_lineOffset += m_lineHeight + (m_lineSpacing + (charCode == 10 || charCode == 0x2029 ? m_paragraphSpacing : 0)) * currentEmScale;
  4804. m_IsDrivenLineSpacing = true;
  4805. }
  4806. m_maxLineAscender = k_LargeNegativeFloat;
  4807. m_maxLineDescender = k_LargePositiveFloat;
  4808. m_startOfLineAscender = ascender;
  4809. m_xAdvance = 0 + tag_LineIndent + tag_Indent;
  4810. m_characterCount += 1;
  4811. continue;
  4812. }
  4813. // If End of Text
  4814. if (charCode == 0x03)
  4815. i = m_InternalParsingBuffer.Length;
  4816. }
  4817. #endregion Check for Linefeed or Last Character
  4818. // Save State of Mesh Creation for handling of Word Wrapping
  4819. #region Save Word Wrapping State
  4820. if (isWordWrappingEnabled || m_overflowMode == TextOverflowModes.Truncate || m_overflowMode == TextOverflowModes.Ellipsis)
  4821. {
  4822. if ((isWhiteSpace || charCode == 0x200B || charCode == 0x2D || charCode == 0xAD) && !m_isNonBreakingSpace && charCode != 0xA0 && charCode != 0x2007 && charCode != 0x2011 && charCode != 0x202F && charCode != 0x2060)
  4823. {
  4824. // We store the state of numerous variables for the most recent Space, LineFeed or Carriage Return to enable them to be restored
  4825. // for Word Wrapping.
  4826. SaveWordWrappingState(ref internalWordWrapState, i, m_characterCount);
  4827. isFirstWordOfLine = false;
  4828. isLastCharacterCJK = false;
  4829. // Reset soft line breaking point since we now have a valid hard break point.
  4830. internalSoftLineBreak.previous_WordBreak = -1;
  4831. }
  4832. // Handling for East Asian languages
  4833. else if (m_isNonBreakingSpace == false &&
  4834. ((charCode > 0x1100 && charCode < 0x11ff || /* Hangul Jamo */
  4835. charCode > 0xA960 && charCode < 0xA97F || /* Hangul Jamo Extended-A */
  4836. charCode > 0xAC00 && charCode < 0xD7FF)&& /* Hangul Syllables */
  4837. TMP_Settings.useModernHangulLineBreakingRules == false ||
  4838. (charCode > 0x2E80 && charCode < 0x9FFF || /* CJK */
  4839. charCode > 0xF900 && charCode < 0xFAFF || /* CJK Compatibility Ideographs */
  4840. charCode > 0xFE30 && charCode < 0xFE4F || /* CJK Compatibility Forms */
  4841. charCode > 0xFF00 && charCode < 0xFFEF))) /* CJK Halfwidth */
  4842. {
  4843. bool isLeadingCharacter = TMP_Settings.linebreakingRules.leadingCharacters.ContainsKey(charCode);
  4844. bool isFollowingCharacter = m_characterCount < totalCharacterCount - 1 && TMP_Settings.linebreakingRules.followingCharacters.ContainsKey(m_internalCharacterInfo[m_characterCount + 1].character);
  4845. if (isFirstWordOfLine || isLeadingCharacter == false)
  4846. {
  4847. if (isFollowingCharacter == false)
  4848. {
  4849. SaveWordWrappingState(ref internalWordWrapState, i, m_characterCount);
  4850. isFirstWordOfLine = false;
  4851. }
  4852. if (isFirstWordOfLine)
  4853. {
  4854. // Special handling for non-breaking space and soft line breaks
  4855. if (isWhiteSpace)
  4856. SaveWordWrappingState(ref internalSoftLineBreak, i, m_characterCount);
  4857. SaveWordWrappingState(ref internalWordWrapState, i, m_characterCount);
  4858. }
  4859. }
  4860. isLastCharacterCJK = true;
  4861. }
  4862. else if (isLastCharacterCJK)
  4863. {
  4864. bool isLeadingCharacter = TMP_Settings.linebreakingRules.leadingCharacters.ContainsKey(charCode);
  4865. if (isLeadingCharacter == false)
  4866. SaveWordWrappingState(ref internalWordWrapState, i, m_characterCount);
  4867. isLastCharacterCJK = false;
  4868. }
  4869. else if (isFirstWordOfLine)
  4870. {
  4871. // Special handling for non-breaking space and soft line breaks
  4872. if (isWhiteSpace || (charCode == 0xAD && isSoftHyphenIgnored == false))
  4873. SaveWordWrappingState(ref internalSoftLineBreak, i, m_characterCount);
  4874. SaveWordWrappingState(ref internalWordWrapState, i, m_characterCount);
  4875. isLastCharacterCJK = false;
  4876. }
  4877. }
  4878. #endregion Save Word Wrapping State
  4879. m_characterCount += 1;
  4880. }
  4881. // Check Auto Sizing and increase font size to fill text container.
  4882. #region Check Auto-Sizing (Upper Font Size Bounds)
  4883. fontSizeDelta = m_maxFontSize - m_minFontSize;
  4884. if (isTextAutoSizingEnabled && fontSizeDelta > 0.051f && fontSize < m_fontSizeMax && m_AutoSizeIterationCount < m_AutoSizeMaxIterationCount)
  4885. {
  4886. // Reset character width adjustment delta
  4887. if (m_charWidthAdjDelta < m_charWidthMaxAdj / 100)
  4888. m_charWidthAdjDelta = 0;
  4889. m_minFontSize = fontSize;
  4890. float sizeDelta = Mathf.Max((m_maxFontSize - fontSize) / 2, 0.05f);
  4891. fontSize += sizeDelta;
  4892. fontSize = Mathf.Min((int)(fontSize * 20 + 0.5f) / 20f, m_fontSizeMax);
  4893. //Debug.Log("[" + m_AutoSizeIterationCount + "] Increasing Point Size from [" + m_minFontSize.ToString("f3") + "] to [" + m_fontSize.ToString("f3") + "] with delta of [" + sizeDelta.ToString("f3") + "].");
  4894. return Vector2.zero;
  4895. }
  4896. #endregion End Auto-sizing Check
  4897. m_IsAutoSizePointSizeSet = true;
  4898. m_isCalculatingPreferredValues = false;
  4899. // Adjust Preferred Width and Height to account for Margins.
  4900. renderedWidth += m_margin.x > 0 ? m_margin.x : 0;
  4901. renderedWidth += m_margin.z > 0 ? m_margin.z : 0;
  4902. renderedHeight += m_margin.y > 0 ? m_margin.y : 0;
  4903. renderedHeight += m_margin.w > 0 ? m_margin.w : 0;
  4904. // Round Preferred Values to nearest 5/100.
  4905. renderedWidth = (int)(renderedWidth * 100 + 1f) / 100f;
  4906. renderedHeight = (int)(renderedHeight * 100 + 1f) / 100f;
  4907. //Debug.Log("Preferred Values: (" + renderedWidth + ", " + renderedHeight + ") with Recursive count of " + m_recursiveCount);
  4908. ////Profiler.EndSample();
  4909. return new Vector2(renderedWidth, renderedHeight);
  4910. }
  4911. /// <summary>
  4912. /// Method returning the compound bounds of the text object and child sub objects.
  4913. /// </summary>
  4914. /// <returns></returns>
  4915. protected virtual Bounds GetCompoundBounds() { return new Bounds(); }
  4916. internal virtual Rect GetCanvasSpaceClippingRect() { return Rect.zero; }
  4917. /// <summary>
  4918. /// Method which returns the bounds of the text object;
  4919. /// </summary>
  4920. /// <returns></returns>
  4921. protected Bounds GetTextBounds()
  4922. {
  4923. if (m_textInfo == null || m_textInfo.characterCount > m_textInfo.characterInfo.Length) return new Bounds();
  4924. Extents extent = new Extents(k_LargePositiveVector2, k_LargeNegativeVector2);
  4925. for (int i = 0; i < m_textInfo.characterCount && i < m_textInfo.characterInfo.Length; i++)
  4926. {
  4927. if (!m_textInfo.characterInfo[i].isVisible) continue;
  4928. extent.min.x = Mathf.Min(extent.min.x, m_textInfo.characterInfo[i].bottomLeft.x);
  4929. extent.min.y = Mathf.Min(extent.min.y, m_textInfo.characterInfo[i].descender);
  4930. extent.max.x = Mathf.Max(extent.max.x, m_textInfo.characterInfo[i].xAdvance);
  4931. extent.max.y = Mathf.Max(extent.max.y, m_textInfo.characterInfo[i].ascender);
  4932. }
  4933. Vector2 size;
  4934. size.x = extent.max.x - extent.min.x;
  4935. size.y = extent.max.y - extent.min.y;
  4936. Vector3 center = (extent.min + extent.max) / 2;
  4937. return new Bounds(center, size);
  4938. }
  4939. /// <summary>
  4940. /// Method which returns the bounds of the text object;
  4941. /// </summary>
  4942. /// <param name="onlyVisibleCharacters"></param>
  4943. /// <returns></returns>
  4944. protected Bounds GetTextBounds(bool onlyVisibleCharacters)
  4945. {
  4946. if (m_textInfo == null) return new Bounds();
  4947. Extents extent = new Extents(k_LargePositiveVector2, k_LargeNegativeVector2);
  4948. for (int i = 0; i < m_textInfo.characterCount; i++)
  4949. {
  4950. if ((i > maxVisibleCharacters || m_textInfo.characterInfo[i].lineNumber > m_maxVisibleLines) && onlyVisibleCharacters) break;
  4951. if (onlyVisibleCharacters && !m_textInfo.characterInfo[i].isVisible) continue;
  4952. extent.min.x = Mathf.Min(extent.min.x, m_textInfo.characterInfo[i].origin);
  4953. extent.min.y = Mathf.Min(extent.min.y, m_textInfo.characterInfo[i].descender);
  4954. extent.max.x = Mathf.Max(extent.max.x, m_textInfo.characterInfo[i].xAdvance);
  4955. extent.max.y = Mathf.Max(extent.max.y, m_textInfo.characterInfo[i].ascender);
  4956. }
  4957. Vector2 size;
  4958. size.x = extent.max.x - extent.min.x;
  4959. size.y = extent.max.y - extent.min.y;
  4960. Vector2 center = (extent.min + extent.max) / 2;
  4961. return new Bounds(center, size);
  4962. }
  4963. /// <summary>
  4964. /// Method to adjust line spacing as a result of using different fonts or font point size.
  4965. /// </summary>
  4966. /// <param name="startIndex"></param>
  4967. /// <param name="endIndex"></param>
  4968. /// <param name="offset"></param>
  4969. // Function to offset vertices position to account for line spacing changes.
  4970. protected void AdjustLineOffset(int startIndex, int endIndex, float offset)
  4971. {
  4972. Vector3 vertexOffset = new Vector3(0, offset, 0);
  4973. for (int i = startIndex; i <= endIndex; i++)
  4974. {
  4975. m_textInfo.characterInfo[i].bottomLeft -= vertexOffset;
  4976. m_textInfo.characterInfo[i].topLeft -= vertexOffset;
  4977. m_textInfo.characterInfo[i].topRight -= vertexOffset;
  4978. m_textInfo.characterInfo[i].bottomRight -= vertexOffset;
  4979. m_textInfo.characterInfo[i].ascender -= vertexOffset.y;
  4980. m_textInfo.characterInfo[i].baseLine -= vertexOffset.y;
  4981. m_textInfo.characterInfo[i].descender -= vertexOffset.y;
  4982. if (m_textInfo.characterInfo[i].isVisible)
  4983. {
  4984. m_textInfo.characterInfo[i].vertex_BL.position -= vertexOffset;
  4985. m_textInfo.characterInfo[i].vertex_TL.position -= vertexOffset;
  4986. m_textInfo.characterInfo[i].vertex_TR.position -= vertexOffset;
  4987. m_textInfo.characterInfo[i].vertex_BR.position -= vertexOffset;
  4988. }
  4989. }
  4990. }
  4991. /// <summary>
  4992. /// Function to increase the size of the Line Extents Array.
  4993. /// </summary>
  4994. /// <param name="size"></param>
  4995. protected void ResizeLineExtents(int size)
  4996. {
  4997. size = size > 1024 ? size + 256 : Mathf.NextPowerOfTwo(size + 1);
  4998. TMP_LineInfo[] temp_lineInfo = new TMP_LineInfo[size];
  4999. for (int i = 0; i < size; i++)
  5000. {
  5001. if (i < m_textInfo.lineInfo.Length)
  5002. temp_lineInfo[i] = m_textInfo.lineInfo[i];
  5003. else
  5004. {
  5005. temp_lineInfo[i].lineExtents.min = k_LargePositiveVector2;
  5006. temp_lineInfo[i].lineExtents.max = k_LargeNegativeVector2;
  5007. temp_lineInfo[i].ascender = k_LargeNegativeFloat;
  5008. temp_lineInfo[i].descender = k_LargePositiveFloat;
  5009. }
  5010. }
  5011. m_textInfo.lineInfo = temp_lineInfo;
  5012. }
  5013. protected static Vector2 k_LargePositiveVector2 = new Vector2(TMP_Math.INT_MAX, TMP_Math.INT_MAX);
  5014. protected static Vector2 k_LargeNegativeVector2 = new Vector2(TMP_Math.INT_MIN, TMP_Math.INT_MIN);
  5015. protected static float k_LargePositiveFloat = TMP_Math.FLOAT_MAX;
  5016. protected static float k_LargeNegativeFloat = TMP_Math.FLOAT_MIN;
  5017. protected static int k_LargePositiveInt = TMP_Math.INT_MAX;
  5018. protected static int k_LargeNegativeInt = TMP_Math.INT_MIN;
  5019. /// <summary>
  5020. /// Function used to evaluate the length of a text string.
  5021. /// </summary>
  5022. /// <param name="text"></param>
  5023. /// <returns></returns>
  5024. public virtual TMP_TextInfo GetTextInfo(string text) { return null; }
  5025. /// <summary>
  5026. /// Function to force an update of the margin size.
  5027. /// </summary>
  5028. public virtual void ComputeMarginSize() { }
  5029. /// <summary>
  5030. /// Function used in conjunction with GetTextInfo to figure out Array allocations.
  5031. /// </summary>
  5032. /// <param name="chars"></param>
  5033. /// <returns></returns>
  5034. //protected int GetArraySizes(int[] chars)
  5035. //{
  5036. // //Debug.Log("Set Array Size called.");
  5037. // //int visibleCount = 0;
  5038. // //int totalCount = 0;
  5039. // int tagEnd = 0;
  5040. // m_totalCharacterCount = 0;
  5041. // m_isUsingBold = false;
  5042. // m_isParsingText = false;
  5043. // //m_VisibleCharacters.Clear();
  5044. // for (int i = 0; chars[i] != 0; i++)
  5045. // {
  5046. // int c = chars[i];
  5047. // if (m_isRichText && c == 60) // if Char '<'
  5048. // {
  5049. // // Check if Tag is Valid
  5050. // if (ValidateHtmlTag(chars, i + 1, out tagEnd))
  5051. // {
  5052. // i = tagEnd;
  5053. // //if ((m_style & FontStyles.Underline) == FontStyles.Underline) visibleCount += 3;
  5054. // if ((m_style & FontStyles.Bold) == FontStyles.Bold) m_isUsingBold = true;
  5055. // continue;
  5056. // }
  5057. // }
  5058. // //if (!char.IsWhiteSpace((char)c) && c != 0x200B)
  5059. // //{
  5060. // //visibleCount += 1;
  5061. // //}
  5062. // //m_VisibleCharacters.Add((char)c);
  5063. // m_totalCharacterCount += 1;
  5064. // }
  5065. // return m_totalCharacterCount;
  5066. //}
  5067. protected void InsertNewLine(int i, float baseScale, float currentElementScale, float currentEmScale, float glyphAdjustment, float boldSpacingAdjustment, float characterSpacingAdjustment, float width, float lineGap, ref bool isMaxVisibleDescenderSet, ref float maxVisibleDescender)
  5068. {
  5069. // Adjust line spacing if necessary
  5070. float baselineAdjustmentDelta = m_maxLineAscender - m_startOfLineAscender;
  5071. if (m_lineOffset > 0 && Math.Abs(baselineAdjustmentDelta) > 0.01f && m_IsDrivenLineSpacing == false && !m_isNewPage)
  5072. {
  5073. AdjustLineOffset(m_firstCharacterOfLine, m_characterCount, baselineAdjustmentDelta);
  5074. m_ElementDescender -= baselineAdjustmentDelta;
  5075. m_lineOffset += baselineAdjustmentDelta;
  5076. }
  5077. // Calculate lineAscender & make sure if last character is superscript or subscript that we check that as well.
  5078. float lineAscender = m_maxLineAscender - m_lineOffset;
  5079. float lineDescender = m_maxLineDescender - m_lineOffset;
  5080. // Update maxDescender and maxVisibleDescender
  5081. m_ElementDescender = m_ElementDescender < lineDescender ? m_ElementDescender : lineDescender;
  5082. if (!isMaxVisibleDescenderSet)
  5083. maxVisibleDescender = m_ElementDescender;
  5084. if (m_useMaxVisibleDescender && (m_characterCount >= m_maxVisibleCharacters || m_lineNumber >= m_maxVisibleLines))
  5085. isMaxVisibleDescenderSet = true;
  5086. // Track & Store lineInfo for the new line
  5087. m_textInfo.lineInfo[m_lineNumber].firstCharacterIndex = m_firstCharacterOfLine;
  5088. m_textInfo.lineInfo[m_lineNumber].firstVisibleCharacterIndex = m_firstVisibleCharacterOfLine = m_firstCharacterOfLine > m_firstVisibleCharacterOfLine ? m_firstCharacterOfLine : m_firstVisibleCharacterOfLine;
  5089. int lastCharacterIndex = m_textInfo.lineInfo[m_lineNumber].lastCharacterIndex = m_lastCharacterOfLine = m_characterCount - 1 > 0 ? m_characterCount - 1 : 0;
  5090. m_textInfo.lineInfo[m_lineNumber].lastVisibleCharacterIndex = m_lastVisibleCharacterOfLine = m_lastVisibleCharacterOfLine < m_firstVisibleCharacterOfLine ? m_firstVisibleCharacterOfLine : m_lastVisibleCharacterOfLine;
  5091. m_textInfo.lineInfo[m_lineNumber].characterCount = m_textInfo.lineInfo[m_lineNumber].lastCharacterIndex - m_textInfo.lineInfo[m_lineNumber].firstCharacterIndex + 1;
  5092. m_textInfo.lineInfo[m_lineNumber].visibleCharacterCount = m_lineVisibleCharacterCount;
  5093. m_textInfo.lineInfo[m_lineNumber].lineExtents.min = new Vector2(m_textInfo.characterInfo[m_firstVisibleCharacterOfLine].bottomLeft.x, lineDescender);
  5094. m_textInfo.lineInfo[m_lineNumber].lineExtents.max = new Vector2(m_textInfo.characterInfo[m_lastVisibleCharacterOfLine].topRight.x, lineAscender);
  5095. m_textInfo.lineInfo[m_lineNumber].length = m_textInfo.lineInfo[m_lineNumber].lineExtents.max.x;
  5096. m_textInfo.lineInfo[m_lineNumber].width = width;
  5097. float maxAdvanceOffset = ((glyphAdjustment + boldSpacingAdjustment) * currentElementScale + (m_currentFontAsset.normalSpacingOffset + characterSpacingAdjustment) * currentEmScale - m_cSpacing) * (1 - m_charWidthAdjDelta);
  5098. float adjustedHorizontalAdvance = m_textInfo.lineInfo[m_lineNumber].maxAdvance = m_textInfo.characterInfo[m_lastVisibleCharacterOfLine].xAdvance + (m_isRightToLeft ? maxAdvanceOffset : - maxAdvanceOffset);
  5099. m_textInfo.characterInfo[lastCharacterIndex].xAdvance = adjustedHorizontalAdvance;
  5100. m_textInfo.lineInfo[m_lineNumber].baseline = 0 - m_lineOffset;
  5101. m_textInfo.lineInfo[m_lineNumber].ascender = lineAscender;
  5102. m_textInfo.lineInfo[m_lineNumber].descender = lineDescender;
  5103. m_textInfo.lineInfo[m_lineNumber].lineHeight = lineAscender - lineDescender + lineGap * baseScale;
  5104. m_firstCharacterOfLine = m_characterCount; // Store first character of the next line.
  5105. m_lineVisibleCharacterCount = 0;
  5106. // Store the state of the line before starting on the new line.
  5107. SaveWordWrappingState(ref m_SavedLineState, i, m_characterCount - 1);
  5108. m_lineNumber += 1;
  5109. // Check to make sure Array is large enough to hold a new line.
  5110. if (m_lineNumber >= m_textInfo.lineInfo.Length)
  5111. ResizeLineExtents(m_lineNumber);
  5112. // Apply Line Spacing based on scale of the last character of the line.
  5113. if (m_lineHeight == TMP_Math.FLOAT_UNSET)
  5114. {
  5115. float ascender = m_textInfo.characterInfo[m_characterCount].adjustedAscender;
  5116. float lineOffsetDelta = 0 - m_maxLineDescender + ascender + (lineGap + m_lineSpacingDelta) * baseScale + m_lineSpacing * currentEmScale;
  5117. m_lineOffset += lineOffsetDelta;
  5118. m_startOfLineAscender = ascender;
  5119. }
  5120. else
  5121. {
  5122. m_lineOffset += m_lineHeight + m_lineSpacing * currentEmScale;
  5123. }
  5124. m_maxLineAscender = k_LargeNegativeFloat;
  5125. m_maxLineDescender = k_LargePositiveFloat;
  5126. m_xAdvance = 0 + tag_Indent;
  5127. }
  5128. /// <summary>
  5129. /// Save the State of various variables used in the mesh creation loop in conjunction with Word Wrapping
  5130. /// </summary>
  5131. /// <param name="state"></param>
  5132. /// <param name="index"></param>
  5133. /// <param name="count"></param>
  5134. protected void SaveWordWrappingState(ref WordWrapState state, int index, int count)
  5135. {
  5136. // Multi Font & Material support related
  5137. state.currentFontAsset = m_currentFontAsset;
  5138. state.currentSpriteAsset = m_currentSpriteAsset;
  5139. state.currentMaterial = m_currentMaterial;
  5140. state.currentMaterialIndex = m_currentMaterialIndex;
  5141. state.previous_WordBreak = index;
  5142. state.total_CharacterCount = count;
  5143. state.visible_CharacterCount = m_lineVisibleCharacterCount;
  5144. //state.visible_CharacterCount = m_visibleCharacterCount;
  5145. //state.visible_SpriteCount = m_visibleSpriteCount;
  5146. state.visible_LinkCount = m_textInfo.linkCount;
  5147. state.firstCharacterIndex = m_firstCharacterOfLine;
  5148. state.firstVisibleCharacterIndex = m_firstVisibleCharacterOfLine;
  5149. state.lastVisibleCharIndex = m_lastVisibleCharacterOfLine;
  5150. state.fontStyle = m_FontStyleInternal;
  5151. state.italicAngle = m_ItalicAngle;
  5152. state.fontScale = m_fontScale;
  5153. //state.maxFontScale = m_maxFontScale;
  5154. state.fontScaleMultiplier = m_fontScaleMultiplier;
  5155. state.currentFontSize = m_currentFontSize;
  5156. state.xAdvance = m_xAdvance;
  5157. state.maxCapHeight = m_maxCapHeight;
  5158. state.maxAscender = m_maxTextAscender;
  5159. state.maxDescender = m_ElementDescender;
  5160. state.startOfLineAscender = m_startOfLineAscender;
  5161. state.maxLineAscender = m_maxLineAscender;
  5162. state.maxLineDescender = m_maxLineDescender;
  5163. state.pageAscender = m_PageAscender;
  5164. state.preferredWidth = m_preferredWidth;
  5165. state.preferredHeight = m_preferredHeight;
  5166. state.meshExtents = m_meshExtents;
  5167. state.lineNumber = m_lineNumber;
  5168. state.lineOffset = m_lineOffset;
  5169. state.baselineOffset = m_baselineOffset;
  5170. state.isDrivenLineSpacing = m_IsDrivenLineSpacing;
  5171. state.glyphHorizontalAdvanceAdjustment = m_GlyphHorizontalAdvanceAdjustment;
  5172. state.cSpace = m_cSpacing;
  5173. state.mSpace = m_monoSpacing;
  5174. state.horizontalAlignment = m_lineJustification;
  5175. state.marginLeft = m_marginLeft;
  5176. state.marginRight = m_marginRight;
  5177. state.vertexColor = m_htmlColor;
  5178. state.underlineColor = m_underlineColor;
  5179. state.strikethroughColor = m_strikethroughColor;
  5180. state.isNonBreakingSpace = m_isNonBreakingSpace;
  5181. state.tagNoParsing = tag_NoParsing;
  5182. // XML Tag Stack
  5183. state.basicStyleStack = m_fontStyleStack;
  5184. state.italicAngleStack = m_ItalicAngleStack;
  5185. state.colorStack = m_colorStack;
  5186. state.underlineColorStack = m_underlineColorStack;
  5187. state.strikethroughColorStack = m_strikethroughColorStack;
  5188. state.highlightStateStack = m_HighlightStateStack;
  5189. state.colorGradientStack = m_colorGradientStack;
  5190. state.sizeStack = m_sizeStack;
  5191. state.indentStack = m_indentStack;
  5192. state.fontWeightStack = m_FontWeightStack;
  5193. //state.styleStack = m_styleStack;
  5194. state.baselineStack = m_baselineOffsetStack;
  5195. state.actionStack = m_actionStack;
  5196. state.materialReferenceStack = m_materialReferenceStack;
  5197. state.lineJustificationStack = m_lineJustificationStack;
  5198. //state.spriteAnimationStack = m_spriteAnimationStack;
  5199. state.spriteAnimationID = m_spriteAnimationID;
  5200. if (m_lineNumber < m_textInfo.lineInfo.Length)
  5201. state.lineInfo = m_textInfo.lineInfo[m_lineNumber];
  5202. }
  5203. /// <summary>
  5204. /// Restore the State of various variables used in the mesh creation loop.
  5205. /// </summary>
  5206. /// <param name="state"></param>
  5207. /// <returns></returns>
  5208. protected int RestoreWordWrappingState(ref WordWrapState state)
  5209. {
  5210. int index = state.previous_WordBreak;
  5211. // Multi Font & Material support related
  5212. m_currentFontAsset = state.currentFontAsset;
  5213. m_currentSpriteAsset = state.currentSpriteAsset;
  5214. m_currentMaterial = state.currentMaterial;
  5215. m_currentMaterialIndex = state.currentMaterialIndex;
  5216. m_characterCount = state.total_CharacterCount + 1;
  5217. m_lineVisibleCharacterCount = state.visible_CharacterCount;
  5218. //m_visibleCharacterCount = state.visible_CharacterCount;
  5219. //m_visibleSpriteCount = state.visible_SpriteCount;
  5220. m_textInfo.linkCount = state.visible_LinkCount;
  5221. m_firstCharacterOfLine = state.firstCharacterIndex;
  5222. m_firstVisibleCharacterOfLine = state.firstVisibleCharacterIndex;
  5223. m_lastVisibleCharacterOfLine = state.lastVisibleCharIndex;
  5224. m_FontStyleInternal = state.fontStyle;
  5225. m_ItalicAngle = state.italicAngle;
  5226. m_fontScale = state.fontScale;
  5227. m_fontScaleMultiplier = state.fontScaleMultiplier;
  5228. //m_maxFontScale = state.maxFontScale;
  5229. m_currentFontSize = state.currentFontSize;
  5230. m_xAdvance = state.xAdvance;
  5231. m_maxCapHeight = state.maxCapHeight;
  5232. m_maxTextAscender = state.maxAscender;
  5233. m_ElementDescender = state.maxDescender;
  5234. m_startOfLineAscender = state.startOfLineAscender;
  5235. m_maxLineAscender = state.maxLineAscender;
  5236. m_maxLineDescender = state.maxLineDescender;
  5237. m_PageAscender = state.pageAscender;
  5238. m_preferredWidth = state.preferredWidth;
  5239. m_preferredHeight = state.preferredHeight;
  5240. m_meshExtents = state.meshExtents;
  5241. m_lineNumber = state.lineNumber;
  5242. m_lineOffset = state.lineOffset;
  5243. m_baselineOffset = state.baselineOffset;
  5244. m_IsDrivenLineSpacing = state.isDrivenLineSpacing;
  5245. m_GlyphHorizontalAdvanceAdjustment = state.glyphHorizontalAdvanceAdjustment;
  5246. m_cSpacing = state.cSpace;
  5247. m_monoSpacing = state.mSpace;
  5248. m_lineJustification = state.horizontalAlignment;
  5249. m_marginLeft = state.marginLeft;
  5250. m_marginRight = state.marginRight;
  5251. m_htmlColor = state.vertexColor;
  5252. m_underlineColor = state.underlineColor;
  5253. m_strikethroughColor = state.strikethroughColor;
  5254. m_isNonBreakingSpace = state.isNonBreakingSpace;
  5255. tag_NoParsing = state.tagNoParsing;
  5256. // XML Tag Stack
  5257. m_fontStyleStack = state.basicStyleStack;
  5258. m_ItalicAngleStack = state.italicAngleStack;
  5259. m_colorStack = state.colorStack;
  5260. m_underlineColorStack = state.underlineColorStack;
  5261. m_strikethroughColorStack = state.strikethroughColorStack;
  5262. m_HighlightStateStack = state.highlightStateStack;
  5263. m_colorGradientStack = state.colorGradientStack;
  5264. m_sizeStack = state.sizeStack;
  5265. m_indentStack = state.indentStack;
  5266. m_FontWeightStack = state.fontWeightStack;
  5267. //m_styleStack = state.styleStack;
  5268. m_baselineOffsetStack = state.baselineStack;
  5269. m_actionStack = state.actionStack;
  5270. m_materialReferenceStack = state.materialReferenceStack;
  5271. m_lineJustificationStack = state.lineJustificationStack;
  5272. //m_spriteAnimationStack = state.spriteAnimationStack;
  5273. m_spriteAnimationID = state.spriteAnimationID;
  5274. if (m_lineNumber < m_textInfo.lineInfo.Length)
  5275. m_textInfo.lineInfo[m_lineNumber] = state.lineInfo;
  5276. return index;
  5277. }
  5278. /// <summary>
  5279. /// Store vertex information for each character.
  5280. /// </summary>
  5281. /// <param name="style_padding">Style_padding.</param>
  5282. /// <param name="vertexColor">Vertex color.</param>
  5283. protected virtual void SaveGlyphVertexInfo(float padding, float style_padding, Color32 vertexColor)
  5284. {
  5285. // Save the Vertex Position for the Character
  5286. #region Setup Mesh Vertices
  5287. m_textInfo.characterInfo[m_characterCount].vertex_BL.position = m_textInfo.characterInfo[m_characterCount].bottomLeft;
  5288. m_textInfo.characterInfo[m_characterCount].vertex_TL.position = m_textInfo.characterInfo[m_characterCount].topLeft;
  5289. m_textInfo.characterInfo[m_characterCount].vertex_TR.position = m_textInfo.characterInfo[m_characterCount].topRight;
  5290. m_textInfo.characterInfo[m_characterCount].vertex_BR.position = m_textInfo.characterInfo[m_characterCount].bottomRight;
  5291. #endregion
  5292. #region Setup Vertex Colors
  5293. // Alpha is the lower of the vertex color or tag color alpha used.
  5294. vertexColor.a = m_fontColor32.a < vertexColor.a ? m_fontColor32.a : vertexColor.a;
  5295. // Handle Vertex Colors & Vertex Color Gradient
  5296. if (!m_enableVertexGradient)
  5297. {
  5298. m_textInfo.characterInfo[m_characterCount].vertex_BL.color = vertexColor;
  5299. m_textInfo.characterInfo[m_characterCount].vertex_TL.color = vertexColor;
  5300. m_textInfo.characterInfo[m_characterCount].vertex_TR.color = vertexColor;
  5301. m_textInfo.characterInfo[m_characterCount].vertex_BR.color = vertexColor;
  5302. }
  5303. else
  5304. {
  5305. if (!m_overrideHtmlColors && m_colorStack.index > 1)
  5306. {
  5307. m_textInfo.characterInfo[m_characterCount].vertex_BL.color = vertexColor;
  5308. m_textInfo.characterInfo[m_characterCount].vertex_TL.color = vertexColor;
  5309. m_textInfo.characterInfo[m_characterCount].vertex_TR.color = vertexColor;
  5310. m_textInfo.characterInfo[m_characterCount].vertex_BR.color = vertexColor;
  5311. }
  5312. else // Handle Vertex Color Gradient
  5313. {
  5314. // Use Vertex Color Gradient Preset (if one is assigned)
  5315. if (m_fontColorGradientPreset != null)
  5316. {
  5317. m_textInfo.characterInfo[m_characterCount].vertex_BL.color = m_fontColorGradientPreset.bottomLeft * vertexColor;
  5318. m_textInfo.characterInfo[m_characterCount].vertex_TL.color = m_fontColorGradientPreset.topLeft * vertexColor;
  5319. m_textInfo.characterInfo[m_characterCount].vertex_TR.color = m_fontColorGradientPreset.topRight * vertexColor;
  5320. m_textInfo.characterInfo[m_characterCount].vertex_BR.color = m_fontColorGradientPreset.bottomRight * vertexColor;
  5321. }
  5322. else
  5323. {
  5324. m_textInfo.characterInfo[m_characterCount].vertex_BL.color = m_fontColorGradient.bottomLeft * vertexColor;
  5325. m_textInfo.characterInfo[m_characterCount].vertex_TL.color = m_fontColorGradient.topLeft * vertexColor;
  5326. m_textInfo.characterInfo[m_characterCount].vertex_TR.color = m_fontColorGradient.topRight * vertexColor;
  5327. m_textInfo.characterInfo[m_characterCount].vertex_BR.color = m_fontColorGradient.bottomRight * vertexColor;
  5328. }
  5329. }
  5330. }
  5331. if (m_colorGradientPreset != null)
  5332. {
  5333. if (m_colorGradientPresetIsTinted)
  5334. {
  5335. m_textInfo.characterInfo[m_characterCount].vertex_BL.color *= m_colorGradientPreset.bottomLeft;
  5336. m_textInfo.characterInfo[m_characterCount].vertex_TL.color *= m_colorGradientPreset.topLeft;
  5337. m_textInfo.characterInfo[m_characterCount].vertex_TR.color *= m_colorGradientPreset.topRight;
  5338. m_textInfo.characterInfo[m_characterCount].vertex_BR.color *= m_colorGradientPreset.bottomRight;
  5339. }
  5340. else
  5341. {
  5342. m_textInfo.characterInfo[m_characterCount].vertex_BL.color = m_colorGradientPreset.bottomLeft.MinAlpha(vertexColor);
  5343. m_textInfo.characterInfo[m_characterCount].vertex_TL.color = m_colorGradientPreset.topLeft.MinAlpha(vertexColor);
  5344. m_textInfo.characterInfo[m_characterCount].vertex_TR.color = m_colorGradientPreset.topRight.MinAlpha(vertexColor);
  5345. m_textInfo.characterInfo[m_characterCount].vertex_BR.color = m_colorGradientPreset.bottomRight.MinAlpha(vertexColor);
  5346. }
  5347. }
  5348. #endregion
  5349. // Apply style_padding only if this is a SDF Shader.
  5350. if (!m_isSDFShader)
  5351. style_padding = 0f;
  5352. // Setup UVs for the Character
  5353. #region Setup UVs
  5354. GlyphRect glyphRect = m_cached_TextElement.m_Glyph.glyphRect;
  5355. Vector2 uv0;
  5356. uv0.x = (glyphRect.x - padding - style_padding) / m_currentFontAsset.m_AtlasWidth;
  5357. uv0.y = (glyphRect.y - padding - style_padding) / m_currentFontAsset.m_AtlasHeight;
  5358. Vector2 uv1;
  5359. uv1.x = uv0.x;
  5360. uv1.y = (glyphRect.y + padding + style_padding + glyphRect.height) / m_currentFontAsset.m_AtlasHeight;
  5361. Vector2 uv2;
  5362. uv2.x = (glyphRect.x + padding + style_padding + glyphRect.width) / m_currentFontAsset.m_AtlasWidth;
  5363. uv2.y = uv1.y;
  5364. Vector2 uv3;
  5365. uv3.x = uv2.x;
  5366. uv3.y = uv0.y;
  5367. // Store UV Information
  5368. m_textInfo.characterInfo[m_characterCount].vertex_BL.uv = uv0;
  5369. m_textInfo.characterInfo[m_characterCount].vertex_TL.uv = uv1;
  5370. m_textInfo.characterInfo[m_characterCount].vertex_TR.uv = uv2;
  5371. m_textInfo.characterInfo[m_characterCount].vertex_BR.uv = uv3;
  5372. #endregion Setup UVs
  5373. // Normal
  5374. #region Setup Normals & Tangents
  5375. //Vector3 normal = new Vector3(0, 0, -1);
  5376. //m_textInfo.characterInfo[m_characterCount].vertex_BL.normal = normal;
  5377. //m_textInfo.characterInfo[m_characterCount].vertex_TL.normal = normal;
  5378. //m_textInfo.characterInfo[m_characterCount].vertex_TR.normal = normal;
  5379. //m_textInfo.characterInfo[m_characterCount].vertex_BR.normal = normal;
  5380. // Tangents
  5381. //Vector4 tangent = new Vector4(-1, 0, 0, 1);
  5382. //m_textInfo.characterInfo[m_characterCount].vertex_BL.tangent = tangent;
  5383. //m_textInfo.characterInfo[m_characterCount].vertex_TL.tangent = tangent;
  5384. //m_textInfo.characterInfo[m_characterCount].vertex_TR.tangent = tangent;
  5385. //m_textInfo.characterInfo[m_characterCount].vertex_BR.tangent = tangent;
  5386. #endregion end Normals & Tangents
  5387. }
  5388. /// <summary>
  5389. /// Store vertex information for each sprite.
  5390. /// </summary>
  5391. /// <param name="padding"></param>
  5392. /// <param name="style_padding"></param>
  5393. /// <param name="vertexColor"></param>
  5394. protected virtual void SaveSpriteVertexInfo(Color32 vertexColor)
  5395. {
  5396. // Save the Vertex Position for the Character
  5397. #region Setup Mesh Vertices
  5398. m_textInfo.characterInfo[m_characterCount].vertex_BL.position = m_textInfo.characterInfo[m_characterCount].bottomLeft;
  5399. m_textInfo.characterInfo[m_characterCount].vertex_TL.position = m_textInfo.characterInfo[m_characterCount].topLeft;
  5400. m_textInfo.characterInfo[m_characterCount].vertex_TR.position = m_textInfo.characterInfo[m_characterCount].topRight;
  5401. m_textInfo.characterInfo[m_characterCount].vertex_BR.position = m_textInfo.characterInfo[m_characterCount].bottomRight;
  5402. #endregion
  5403. // Vertex Color Alpha
  5404. if (m_tintAllSprites) m_tintSprite = true;
  5405. Color32 spriteColor = m_tintSprite ? m_spriteColor.Multiply(vertexColor) : m_spriteColor;
  5406. spriteColor.a = spriteColor.a < m_fontColor32.a ? spriteColor.a = spriteColor.a < vertexColor.a ? spriteColor.a : vertexColor.a : m_fontColor32.a;
  5407. Color32 c0 = spriteColor;
  5408. Color32 c1 = spriteColor;
  5409. Color32 c2 = spriteColor;
  5410. Color32 c3 = spriteColor;
  5411. if (m_enableVertexGradient)
  5412. {
  5413. if (m_fontColorGradientPreset != null)
  5414. {
  5415. c0 = m_tintSprite ? c0.Multiply(m_fontColorGradientPreset.bottomLeft) : c0;
  5416. c1 = m_tintSprite ? c1.Multiply(m_fontColorGradientPreset.topLeft) : c1;
  5417. c2 = m_tintSprite ? c2.Multiply(m_fontColorGradientPreset.topRight) : c2;
  5418. c3 = m_tintSprite ? c3.Multiply(m_fontColorGradientPreset.bottomRight) : c3;
  5419. }
  5420. else
  5421. {
  5422. c0 = m_tintSprite ? c0.Multiply(m_fontColorGradient.bottomLeft) : c0;
  5423. c1 = m_tintSprite ? c1.Multiply(m_fontColorGradient.topLeft) : c1;
  5424. c2 = m_tintSprite ? c2.Multiply(m_fontColorGradient.topRight) : c2;
  5425. c3 = m_tintSprite ? c3.Multiply(m_fontColorGradient.bottomRight) : c3;
  5426. }
  5427. }
  5428. if (m_colorGradientPreset != null)
  5429. {
  5430. c0 = m_tintSprite ? c0.Multiply(m_colorGradientPreset.bottomLeft) : c0;
  5431. c1 = m_tintSprite ? c1.Multiply(m_colorGradientPreset.topLeft) : c1;
  5432. c2 = m_tintSprite ? c2.Multiply(m_colorGradientPreset.topRight) : c2;
  5433. c3 = m_tintSprite ? c3.Multiply(m_colorGradientPreset.bottomRight) : c3;
  5434. }
  5435. m_textInfo.characterInfo[m_characterCount].vertex_BL.color = c0;
  5436. m_textInfo.characterInfo[m_characterCount].vertex_TL.color = c1;
  5437. m_textInfo.characterInfo[m_characterCount].vertex_TR.color = c2;
  5438. m_textInfo.characterInfo[m_characterCount].vertex_BR.color = c3;
  5439. // Setup UVs for the Character
  5440. #region Setup UVs
  5441. GlyphRect glyphRect = m_cached_TextElement.m_Glyph.glyphRect;
  5442. Vector2 uv0 = new Vector2((float)glyphRect.x / m_currentSpriteAsset.spriteSheet.width, (float)glyphRect.y / m_currentSpriteAsset.spriteSheet.height); // bottom left
  5443. Vector2 uv1 = new Vector2(uv0.x, (float)(glyphRect.y + glyphRect.height) / m_currentSpriteAsset.spriteSheet.height); // top left
  5444. Vector2 uv2 = new Vector2((float)(glyphRect.x + glyphRect.width) / m_currentSpriteAsset.spriteSheet.width, uv1.y); // top right
  5445. Vector2 uv3 = new Vector2(uv2.x, uv0.y); // bottom right
  5446. // Store UV Information
  5447. m_textInfo.characterInfo[m_characterCount].vertex_BL.uv = uv0;
  5448. m_textInfo.characterInfo[m_characterCount].vertex_TL.uv = uv1;
  5449. m_textInfo.characterInfo[m_characterCount].vertex_TR.uv = uv2;
  5450. m_textInfo.characterInfo[m_characterCount].vertex_BR.uv = uv3;
  5451. #endregion Setup UVs
  5452. // Normal
  5453. #region Setup Normals & Tangents
  5454. //Vector3 normal = new Vector3(0, 0, -1);
  5455. //m_textInfo.characterInfo[m_characterCount].vertex_BL.normal = normal;
  5456. //m_textInfo.characterInfo[m_characterCount].vertex_TL.normal = normal;
  5457. //m_textInfo.characterInfo[m_characterCount].vertex_TR.normal = normal;
  5458. //m_textInfo.characterInfo[m_characterCount].vertex_BR.normal = normal;
  5459. // Tangents
  5460. //Vector4 tangent = new Vector4(-1, 0, 0, 1);
  5461. //m_textInfo.characterInfo[m_characterCount].vertex_BL.tangent = tangent;
  5462. //m_textInfo.characterInfo[m_characterCount].vertex_TL.tangent = tangent;
  5463. //m_textInfo.characterInfo[m_characterCount].vertex_TR.tangent = tangent;
  5464. //m_textInfo.characterInfo[m_characterCount].vertex_BR.tangent = tangent;
  5465. #endregion end Normals & Tangents
  5466. }
  5467. /// <summary>
  5468. /// Store vertex attributes into the appropriate TMP_MeshInfo.
  5469. /// </summary>
  5470. /// <param name="i"></param>
  5471. /// <param name="index_X4"></param>
  5472. protected virtual void FillCharacterVertexBuffers(int i, int index_X4)
  5473. {
  5474. int materialIndex = m_textInfo.characterInfo[i].materialReferenceIndex;
  5475. index_X4 = m_textInfo.meshInfo[materialIndex].vertexCount;
  5476. // Check to make sure our current mesh buffer allocations can hold these new Quads.
  5477. if (index_X4 >= m_textInfo.meshInfo[materialIndex].vertices.Length)
  5478. m_textInfo.meshInfo[materialIndex].ResizeMeshInfo(Mathf.NextPowerOfTwo((index_X4 + 4) / 4));
  5479. TMP_CharacterInfo[] characterInfoArray = m_textInfo.characterInfo;
  5480. m_textInfo.characterInfo[i].vertexIndex = index_X4;
  5481. // Setup Vertices for Characters
  5482. m_textInfo.meshInfo[materialIndex].vertices[0 + index_X4] = characterInfoArray[i].vertex_BL.position;
  5483. m_textInfo.meshInfo[materialIndex].vertices[1 + index_X4] = characterInfoArray[i].vertex_TL.position;
  5484. m_textInfo.meshInfo[materialIndex].vertices[2 + index_X4] = characterInfoArray[i].vertex_TR.position;
  5485. m_textInfo.meshInfo[materialIndex].vertices[3 + index_X4] = characterInfoArray[i].vertex_BR.position;
  5486. // Setup UVS0
  5487. m_textInfo.meshInfo[materialIndex].uvs0[0 + index_X4] = characterInfoArray[i].vertex_BL.uv;
  5488. m_textInfo.meshInfo[materialIndex].uvs0[1 + index_X4] = characterInfoArray[i].vertex_TL.uv;
  5489. m_textInfo.meshInfo[materialIndex].uvs0[2 + index_X4] = characterInfoArray[i].vertex_TR.uv;
  5490. m_textInfo.meshInfo[materialIndex].uvs0[3 + index_X4] = characterInfoArray[i].vertex_BR.uv;
  5491. // Setup UVS2
  5492. m_textInfo.meshInfo[materialIndex].uvs2[0 + index_X4] = characterInfoArray[i].vertex_BL.uv2;
  5493. m_textInfo.meshInfo[materialIndex].uvs2[1 + index_X4] = characterInfoArray[i].vertex_TL.uv2;
  5494. m_textInfo.meshInfo[materialIndex].uvs2[2 + index_X4] = characterInfoArray[i].vertex_TR.uv2;
  5495. m_textInfo.meshInfo[materialIndex].uvs2[3 + index_X4] = characterInfoArray[i].vertex_BR.uv2;
  5496. // Setup UVS4
  5497. //m_textInfo.meshInfo[0].uvs4[0 + index_X4] = characterInfoArray[i].vertex_BL.uv4;
  5498. //m_textInfo.meshInfo[0].uvs4[1 + index_X4] = characterInfoArray[i].vertex_TL.uv4;
  5499. //m_textInfo.meshInfo[0].uvs4[2 + index_X4] = characterInfoArray[i].vertex_TR.uv4;
  5500. //m_textInfo.meshInfo[0].uvs4[3 + index_X4] = characterInfoArray[i].vertex_BR.uv4;
  5501. // setup Vertex Colors
  5502. m_textInfo.meshInfo[materialIndex].colors32[0 + index_X4] = characterInfoArray[i].vertex_BL.color;
  5503. m_textInfo.meshInfo[materialIndex].colors32[1 + index_X4] = characterInfoArray[i].vertex_TL.color;
  5504. m_textInfo.meshInfo[materialIndex].colors32[2 + index_X4] = characterInfoArray[i].vertex_TR.color;
  5505. m_textInfo.meshInfo[materialIndex].colors32[3 + index_X4] = characterInfoArray[i].vertex_BR.color;
  5506. m_textInfo.meshInfo[materialIndex].vertexCount = index_X4 + 4;
  5507. }
  5508. protected virtual void FillCharacterVertexBuffers(int i, int index_X4, bool isVolumetric)
  5509. {
  5510. int materialIndex = m_textInfo.characterInfo[i].materialReferenceIndex;
  5511. index_X4 = m_textInfo.meshInfo[materialIndex].vertexCount;
  5512. // Check to make sure our current mesh buffer allocations can hold these new Quads.
  5513. if (index_X4 >= m_textInfo.meshInfo[materialIndex].vertices.Length)
  5514. m_textInfo.meshInfo[materialIndex].ResizeMeshInfo(Mathf.NextPowerOfTwo((index_X4 + (isVolumetric ? 8 : 4)) / 4));
  5515. TMP_CharacterInfo[] characterInfoArray = m_textInfo.characterInfo;
  5516. m_textInfo.characterInfo[i].vertexIndex = index_X4;
  5517. // Setup Vertices for Characters
  5518. m_textInfo.meshInfo[materialIndex].vertices[0 + index_X4] = characterInfoArray[i].vertex_BL.position;
  5519. m_textInfo.meshInfo[materialIndex].vertices[1 + index_X4] = characterInfoArray[i].vertex_TL.position;
  5520. m_textInfo.meshInfo[materialIndex].vertices[2 + index_X4] = characterInfoArray[i].vertex_TR.position;
  5521. m_textInfo.meshInfo[materialIndex].vertices[3 + index_X4] = characterInfoArray[i].vertex_BR.position;
  5522. if (isVolumetric)
  5523. {
  5524. Vector3 depth = new Vector3(0, 0, m_fontSize * m_fontScale);
  5525. m_textInfo.meshInfo[materialIndex].vertices[4 + index_X4] = characterInfoArray[i].vertex_BL.position + depth;
  5526. m_textInfo.meshInfo[materialIndex].vertices[5 + index_X4] = characterInfoArray[i].vertex_TL.position + depth;
  5527. m_textInfo.meshInfo[materialIndex].vertices[6 + index_X4] = characterInfoArray[i].vertex_TR.position + depth;
  5528. m_textInfo.meshInfo[materialIndex].vertices[7 + index_X4] = characterInfoArray[i].vertex_BR.position + depth;
  5529. }
  5530. // Setup UVS0
  5531. m_textInfo.meshInfo[materialIndex].uvs0[0 + index_X4] = characterInfoArray[i].vertex_BL.uv;
  5532. m_textInfo.meshInfo[materialIndex].uvs0[1 + index_X4] = characterInfoArray[i].vertex_TL.uv;
  5533. m_textInfo.meshInfo[materialIndex].uvs0[2 + index_X4] = characterInfoArray[i].vertex_TR.uv;
  5534. m_textInfo.meshInfo[materialIndex].uvs0[3 + index_X4] = characterInfoArray[i].vertex_BR.uv;
  5535. if (isVolumetric)
  5536. {
  5537. m_textInfo.meshInfo[materialIndex].uvs0[4 + index_X4] = characterInfoArray[i].vertex_BL.uv;
  5538. m_textInfo.meshInfo[materialIndex].uvs0[5 + index_X4] = characterInfoArray[i].vertex_TL.uv;
  5539. m_textInfo.meshInfo[materialIndex].uvs0[6 + index_X4] = characterInfoArray[i].vertex_TR.uv;
  5540. m_textInfo.meshInfo[materialIndex].uvs0[7 + index_X4] = characterInfoArray[i].vertex_BR.uv;
  5541. }
  5542. // Setup UVS2
  5543. m_textInfo.meshInfo[materialIndex].uvs2[0 + index_X4] = characterInfoArray[i].vertex_BL.uv2;
  5544. m_textInfo.meshInfo[materialIndex].uvs2[1 + index_X4] = characterInfoArray[i].vertex_TL.uv2;
  5545. m_textInfo.meshInfo[materialIndex].uvs2[2 + index_X4] = characterInfoArray[i].vertex_TR.uv2;
  5546. m_textInfo.meshInfo[materialIndex].uvs2[3 + index_X4] = characterInfoArray[i].vertex_BR.uv2;
  5547. if (isVolumetric)
  5548. {
  5549. m_textInfo.meshInfo[materialIndex].uvs2[4 + index_X4] = characterInfoArray[i].vertex_BL.uv2;
  5550. m_textInfo.meshInfo[materialIndex].uvs2[5 + index_X4] = characterInfoArray[i].vertex_TL.uv2;
  5551. m_textInfo.meshInfo[materialIndex].uvs2[6 + index_X4] = characterInfoArray[i].vertex_TR.uv2;
  5552. m_textInfo.meshInfo[materialIndex].uvs2[7 + index_X4] = characterInfoArray[i].vertex_BR.uv2;
  5553. }
  5554. // Setup UVS4
  5555. //m_textInfo.meshInfo[0].uvs4[0 + index_X4] = characterInfoArray[i].vertex_BL.uv4;
  5556. //m_textInfo.meshInfo[0].uvs4[1 + index_X4] = characterInfoArray[i].vertex_TL.uv4;
  5557. //m_textInfo.meshInfo[0].uvs4[2 + index_X4] = characterInfoArray[i].vertex_TR.uv4;
  5558. //m_textInfo.meshInfo[0].uvs4[3 + index_X4] = characterInfoArray[i].vertex_BR.uv4;
  5559. // setup Vertex Colors
  5560. m_textInfo.meshInfo[materialIndex].colors32[0 + index_X4] = characterInfoArray[i].vertex_BL.color;
  5561. m_textInfo.meshInfo[materialIndex].colors32[1 + index_X4] = characterInfoArray[i].vertex_TL.color;
  5562. m_textInfo.meshInfo[materialIndex].colors32[2 + index_X4] = characterInfoArray[i].vertex_TR.color;
  5563. m_textInfo.meshInfo[materialIndex].colors32[3 + index_X4] = characterInfoArray[i].vertex_BR.color;
  5564. if (isVolumetric)
  5565. {
  5566. Color32 backColor = new Color32(255, 255, 128, 255);
  5567. m_textInfo.meshInfo[materialIndex].colors32[4 + index_X4] = backColor; //characterInfoArray[i].vertex_BL.color;
  5568. m_textInfo.meshInfo[materialIndex].colors32[5 + index_X4] = backColor; //characterInfoArray[i].vertex_TL.color;
  5569. m_textInfo.meshInfo[materialIndex].colors32[6 + index_X4] = backColor; //characterInfoArray[i].vertex_TR.color;
  5570. m_textInfo.meshInfo[materialIndex].colors32[7 + index_X4] = backColor; //characterInfoArray[i].vertex_BR.color;
  5571. }
  5572. m_textInfo.meshInfo[materialIndex].vertexCount = index_X4 + (!isVolumetric ? 4 : 8);
  5573. }
  5574. /// <summary>
  5575. /// Fill Vertex Buffers for Sprites
  5576. /// </summary>
  5577. /// <param name="i"></param>
  5578. /// <param name="spriteIndex_X4"></param>
  5579. protected virtual void FillSpriteVertexBuffers(int i, int index_X4)
  5580. {
  5581. int materialIndex = m_textInfo.characterInfo[i].materialReferenceIndex;
  5582. index_X4 = m_textInfo.meshInfo[materialIndex].vertexCount;
  5583. // Check to make sure our current mesh buffer allocations can hold these new Quads.
  5584. if (index_X4 >= m_textInfo.meshInfo[materialIndex].vertices.Length)
  5585. m_textInfo.meshInfo[materialIndex].ResizeMeshInfo(Mathf.NextPowerOfTwo((index_X4 + 4) / 4));
  5586. TMP_CharacterInfo[] characterInfoArray = m_textInfo.characterInfo;
  5587. m_textInfo.characterInfo[i].vertexIndex = index_X4;
  5588. // Setup Vertices for Characters
  5589. m_textInfo.meshInfo[materialIndex].vertices[0 + index_X4] = characterInfoArray[i].vertex_BL.position;
  5590. m_textInfo.meshInfo[materialIndex].vertices[1 + index_X4] = characterInfoArray[i].vertex_TL.position;
  5591. m_textInfo.meshInfo[materialIndex].vertices[2 + index_X4] = characterInfoArray[i].vertex_TR.position;
  5592. m_textInfo.meshInfo[materialIndex].vertices[3 + index_X4] = characterInfoArray[i].vertex_BR.position;
  5593. // Setup UVS0
  5594. m_textInfo.meshInfo[materialIndex].uvs0[0 + index_X4] = characterInfoArray[i].vertex_BL.uv;
  5595. m_textInfo.meshInfo[materialIndex].uvs0[1 + index_X4] = characterInfoArray[i].vertex_TL.uv;
  5596. m_textInfo.meshInfo[materialIndex].uvs0[2 + index_X4] = characterInfoArray[i].vertex_TR.uv;
  5597. m_textInfo.meshInfo[materialIndex].uvs0[3 + index_X4] = characterInfoArray[i].vertex_BR.uv;
  5598. // Setup UVS2
  5599. m_textInfo.meshInfo[materialIndex].uvs2[0 + index_X4] = characterInfoArray[i].vertex_BL.uv2;
  5600. m_textInfo.meshInfo[materialIndex].uvs2[1 + index_X4] = characterInfoArray[i].vertex_TL.uv2;
  5601. m_textInfo.meshInfo[materialIndex].uvs2[2 + index_X4] = characterInfoArray[i].vertex_TR.uv2;
  5602. m_textInfo.meshInfo[materialIndex].uvs2[3 + index_X4] = characterInfoArray[i].vertex_BR.uv2;
  5603. // Setup UVS4
  5604. //m_textInfo.meshInfo[0].uvs4[0 + index_X4] = characterInfoArray[i].vertex_BL.uv4;
  5605. //m_textInfo.meshInfo[0].uvs4[1 + index_X4] = characterInfoArray[i].vertex_TL.uv4;
  5606. //m_textInfo.meshInfo[0].uvs4[2 + index_X4] = characterInfoArray[i].vertex_TR.uv4;
  5607. //m_textInfo.meshInfo[0].uvs4[3 + index_X4] = characterInfoArray[i].vertex_BR.uv4;
  5608. // setup Vertex Colors
  5609. m_textInfo.meshInfo[materialIndex].colors32[0 + index_X4] = characterInfoArray[i].vertex_BL.color;
  5610. m_textInfo.meshInfo[materialIndex].colors32[1 + index_X4] = characterInfoArray[i].vertex_TL.color;
  5611. m_textInfo.meshInfo[materialIndex].colors32[2 + index_X4] = characterInfoArray[i].vertex_TR.color;
  5612. m_textInfo.meshInfo[materialIndex].colors32[3 + index_X4] = characterInfoArray[i].vertex_BR.color;
  5613. m_textInfo.meshInfo[materialIndex].vertexCount = index_X4 + 4;
  5614. }
  5615. /// <summary>
  5616. /// Method to add the underline geometry.
  5617. /// </summary>
  5618. /// <param name="start"></param>
  5619. /// <param name="end"></param>
  5620. /// <param name="startScale"></param>
  5621. /// <param name="endScale"></param>
  5622. /// <param name="maxScale"></param>
  5623. /// <param name="underlineColor"></param>
  5624. protected virtual void DrawUnderlineMesh(Vector3 start, Vector3 end, ref int index, float startScale, float endScale, float maxScale, float sdfScale, Color32 underlineColor)
  5625. {
  5626. // Get Underline special character from the primary font asset.
  5627. GetUnderlineSpecialCharacter(m_fontAsset);
  5628. if (m_Underline.character == null)
  5629. {
  5630. if (!TMP_Settings.warningsDisabled)
  5631. Debug.LogWarning("Unable to add underline since the primary Font Asset doesn't contain the underline character.", this);
  5632. return;
  5633. }
  5634. int underlineMaterialIndex = m_Underline.materialIndex;
  5635. int verticesCount = index + 12;
  5636. // Check to make sure our current mesh buffer allocations can hold these new Quads.
  5637. if (verticesCount > m_textInfo.meshInfo[underlineMaterialIndex].vertices.Length)
  5638. {
  5639. // Resize Mesh Buffers
  5640. m_textInfo.meshInfo[underlineMaterialIndex].ResizeMeshInfo(verticesCount / 4);
  5641. }
  5642. // Adjust the position of the underline based on the lowest character. This matters for subscript character.
  5643. start.y = Mathf.Min(start.y, end.y);
  5644. end.y = Mathf.Min(start.y, end.y);
  5645. GlyphMetrics underlineGlyphMetrics = m_Underline.character.glyph.metrics;
  5646. GlyphRect underlineGlyphRect = m_Underline.character.glyph.glyphRect;
  5647. float segmentWidth = underlineGlyphMetrics.width / 2 * maxScale;
  5648. if (end.x - start.x < underlineGlyphMetrics.width * maxScale)
  5649. {
  5650. segmentWidth = (end.x - start.x) / 2f;
  5651. }
  5652. float startPadding = m_padding * startScale / maxScale;
  5653. float endPadding = m_padding * endScale / maxScale;
  5654. float underlineThickness = m_Underline.fontAsset.faceInfo.underlineThickness;
  5655. // UNDERLINE VERTICES FOR (3) LINE SEGMENTS
  5656. #region UNDERLINE VERTICES
  5657. Vector3[] vertices = m_textInfo.meshInfo[underlineMaterialIndex].vertices;
  5658. // Front Part of the Underline
  5659. vertices[index + 0] = start + new Vector3(0, 0 - (underlineThickness + m_padding) * maxScale, 0); // BL
  5660. vertices[index + 1] = start + new Vector3(0, m_padding * maxScale, 0); // TL
  5661. vertices[index + 2] = vertices[index + 1] + new Vector3(segmentWidth, 0, 0); // TR
  5662. vertices[index + 3] = vertices[index + 0] + new Vector3(segmentWidth, 0, 0); // BR
  5663. // Middle Part of the Underline
  5664. vertices[index + 4] = vertices[index + 3]; // BL
  5665. vertices[index + 5] = vertices[index + 2]; // TL
  5666. vertices[index + 6] = end + new Vector3(-segmentWidth, m_padding * maxScale, 0); // TR
  5667. vertices[index + 7] = end + new Vector3(-segmentWidth, -(underlineThickness + m_padding) * maxScale, 0); // BR
  5668. // End Part of the Underline
  5669. vertices[index + 8] = vertices[index + 7]; // BL
  5670. vertices[index + 9] = vertices[index + 6]; // TL
  5671. vertices[index + 10] = end + new Vector3(0, m_padding * maxScale, 0); // TR
  5672. vertices[index + 11] = end + new Vector3(0, -(underlineThickness + m_padding) * maxScale, 0); // BR
  5673. #endregion
  5674. // UNDERLINE UV0
  5675. #region HANDLE UV0
  5676. Vector2[] uvs0 = m_textInfo.meshInfo[underlineMaterialIndex].uvs0;
  5677. int atlasWidth = m_Underline.fontAsset.atlasWidth;
  5678. int atlasHeight = m_Underline.fontAsset.atlasHeight;
  5679. // Calculate UV required to setup the 3 Quads for the Underline.
  5680. Vector2 uv0 = new Vector2((underlineGlyphRect.x - startPadding) / atlasWidth, (underlineGlyphRect.y - m_padding) / atlasHeight); // bottom left
  5681. Vector2 uv1 = new Vector2(uv0.x, (underlineGlyphRect.y + underlineGlyphRect.height + m_padding) / atlasHeight); // top left
  5682. Vector2 uv2 = new Vector2((underlineGlyphRect.x - startPadding + (float)underlineGlyphRect.width / 2) / atlasWidth, uv1.y); // Mid Top Left
  5683. Vector2 uv3 = new Vector2(uv2.x, uv0.y); // Mid Bottom Left
  5684. Vector2 uv4 = new Vector2((underlineGlyphRect.x + endPadding + (float)underlineGlyphRect.width / 2) / atlasWidth, uv1.y); // Mid Top Right
  5685. Vector2 uv5 = new Vector2(uv4.x, uv0.y); // Mid Bottom right
  5686. Vector2 uv6 = new Vector2((underlineGlyphRect.x + endPadding + underlineGlyphRect.width) / atlasWidth, uv1.y); // End Part - Bottom Right
  5687. Vector2 uv7 = new Vector2(uv6.x, uv0.y); // End Part - Top Right
  5688. // Left Part of the Underline
  5689. uvs0[0 + index] = uv0; // BL
  5690. uvs0[1 + index] = uv1; // TL
  5691. uvs0[2 + index] = uv2; // TR
  5692. uvs0[3 + index] = uv3; // BR
  5693. // Middle Part of the Underline
  5694. uvs0[4 + index] = new Vector2(uv2.x - uv2.x * 0.001f, uv0.y);
  5695. uvs0[5 + index] = new Vector2(uv2.x - uv2.x * 0.001f, uv1.y);
  5696. uvs0[6 + index] = new Vector2(uv2.x + uv2.x * 0.001f, uv1.y);
  5697. uvs0[7 + index] = new Vector2(uv2.x + uv2.x * 0.001f, uv0.y);
  5698. // Right Part of the Underline
  5699. uvs0[8 + index] = uv5;
  5700. uvs0[9 + index] = uv4;
  5701. uvs0[10 + index] = uv6;
  5702. uvs0[11 + index] = uv7;
  5703. #endregion
  5704. // UNDERLINE UV2
  5705. #region HANDLE UV2 - SDF SCALE
  5706. // UV1 contains Face / Border UV layout.
  5707. float min_UvX = 0;
  5708. float max_UvX = (vertices[index + 2].x - start.x) / (end.x - start.x);
  5709. //Calculate the xScale or how much the UV's are getting stretched on the X axis for the middle section of the underline.
  5710. float xScale = Mathf.Abs(sdfScale);
  5711. Vector2[] uvs2 = m_textInfo.meshInfo[underlineMaterialIndex].uvs2;
  5712. uvs2[0 + index] = PackUV(0, 0, xScale);
  5713. uvs2[1 + index] = PackUV(0, 1, xScale);
  5714. uvs2[2 + index] = PackUV(max_UvX, 1, xScale);
  5715. uvs2[3 + index] = PackUV(max_UvX, 0, xScale);
  5716. min_UvX = (vertices[index + 4].x - start.x) / (end.x - start.x);
  5717. max_UvX = (vertices[index + 6].x - start.x) / (end.x - start.x);
  5718. uvs2[4 + index] = PackUV(min_UvX, 0, xScale);
  5719. uvs2[5 + index] = PackUV(min_UvX, 1, xScale);
  5720. uvs2[6 + index] = PackUV(max_UvX, 1, xScale);
  5721. uvs2[7 + index] = PackUV(max_UvX, 0, xScale);
  5722. min_UvX = (vertices[index + 8].x - start.x) / (end.x - start.x);
  5723. uvs2[8 + index] = PackUV(min_UvX, 0, xScale);
  5724. uvs2[9 + index] = PackUV(min_UvX, 1, xScale);
  5725. uvs2[10 + index] = PackUV(1, 1, xScale);
  5726. uvs2[11 + index] = PackUV(1, 0, xScale);
  5727. #endregion
  5728. // UNDERLINE VERTEX COLORS
  5729. #region UNDERLINE VERTEX COLORS
  5730. // Alpha is the lower of the vertex color or tag color alpha used.
  5731. underlineColor.a = m_fontColor32.a < underlineColor.a ? m_fontColor32.a : underlineColor.a;
  5732. Color32[] colors32 = m_textInfo.meshInfo[underlineMaterialIndex].colors32;
  5733. colors32[0 + index] = underlineColor;
  5734. colors32[1 + index] = underlineColor;
  5735. colors32[2 + index] = underlineColor;
  5736. colors32[3 + index] = underlineColor;
  5737. colors32[4 + index] = underlineColor;
  5738. colors32[5 + index] = underlineColor;
  5739. colors32[6 + index] = underlineColor;
  5740. colors32[7 + index] = underlineColor;
  5741. colors32[8 + index] = underlineColor;
  5742. colors32[9 + index] = underlineColor;
  5743. colors32[10 + index] = underlineColor;
  5744. colors32[11 + index] = underlineColor;
  5745. #endregion
  5746. index += 12;
  5747. }
  5748. protected virtual void DrawTextHighlight(Vector3 start, Vector3 end, ref int index, Color32 highlightColor)
  5749. {
  5750. if (m_Underline.character == null)
  5751. {
  5752. GetUnderlineSpecialCharacter(m_fontAsset);
  5753. if (m_Underline.character == null)
  5754. {
  5755. if (!TMP_Settings.warningsDisabled)
  5756. Debug.LogWarning("Unable to add highlight since the primary Font Asset doesn't contain the underline character.", this);
  5757. return;
  5758. }
  5759. }
  5760. int underlineMaterialIndex = m_Underline.materialIndex;
  5761. int verticesCount = index + 4;
  5762. // Check to make sure our current mesh buffer allocations can hold these new Quads.
  5763. if (verticesCount > m_textInfo.meshInfo[underlineMaterialIndex].vertices.Length)
  5764. {
  5765. // Resize Mesh Buffers
  5766. m_textInfo.meshInfo[underlineMaterialIndex].ResizeMeshInfo(verticesCount / 4);
  5767. }
  5768. // UNDERLINE VERTICES FOR (3) LINE SEGMENTS
  5769. #region HIGHLIGHT VERTICES
  5770. Vector3[] vertices = m_textInfo.meshInfo[underlineMaterialIndex].vertices;
  5771. // Front Part of the Underline
  5772. vertices[index + 0] = start; // BL
  5773. vertices[index + 1] = new Vector3(start.x, end.y, 0); // TL
  5774. vertices[index + 2] = end; // TR
  5775. vertices[index + 3] = new Vector3(end.x, start.y, 0); // BR
  5776. #endregion
  5777. // UNDERLINE UV0
  5778. #region HANDLE UV0
  5779. Vector2[] uvs0 = m_textInfo.meshInfo[underlineMaterialIndex].uvs0;
  5780. int atlasWidth = m_Underline.fontAsset.atlasWidth;
  5781. int atlasHeight = m_Underline.fontAsset.atlasHeight;
  5782. GlyphRect glyphRect = m_Underline.character.glyph.glyphRect;
  5783. // Calculate UV
  5784. Vector2 uv0 = new Vector2(((float)glyphRect.x + glyphRect.width / 2) / atlasWidth, (glyphRect.y + (float)glyphRect.height / 2) / atlasHeight); // bottom left
  5785. // UVs for the Quad
  5786. uvs0[0 + index] = uv0; // BL
  5787. uvs0[1 + index] = uv0; // TL
  5788. uvs0[2 + index] = uv0; // TR
  5789. uvs0[3 + index] = uv0; // BR
  5790. #endregion
  5791. // HIGHLIGHT UV2
  5792. #region HANDLE UV2 - SDF SCALE
  5793. Vector2[] uvs2 = m_textInfo.meshInfo[underlineMaterialIndex].uvs2;
  5794. Vector2 customUV = new Vector2(0, 1);
  5795. uvs2[0 + index] = customUV;
  5796. uvs2[1 + index] = customUV;
  5797. uvs2[2 + index] = customUV;
  5798. uvs2[3 + index] = customUV;
  5799. #endregion
  5800. // HIGHLIGHT VERTEX COLORS
  5801. #region
  5802. // Alpha is the lower of the vertex color or tag color alpha used.
  5803. highlightColor.a = m_fontColor32.a < highlightColor.a ? m_fontColor32.a : highlightColor.a;
  5804. Color32[] colors32 = m_textInfo.meshInfo[underlineMaterialIndex].colors32;
  5805. colors32[0 + index] = highlightColor;
  5806. colors32[1 + index] = highlightColor;
  5807. colors32[2 + index] = highlightColor;
  5808. colors32[3 + index] = highlightColor;
  5809. #endregion
  5810. index += 4;
  5811. }
  5812. /// <summary>
  5813. /// Internal function used to load the default settings of text objects.
  5814. /// </summary>
  5815. protected void LoadDefaultSettings()
  5816. {
  5817. if (m_fontAsset == null || m_isWaitingOnResourceLoad)
  5818. {
  5819. m_rectTransform = this.rectTransform;
  5820. if (TMP_Settings.autoSizeTextContainer)
  5821. {
  5822. autoSizeTextContainer = true;
  5823. }
  5824. else
  5825. {
  5826. if (GetType() == typeof(TextMeshPro))
  5827. {
  5828. if (m_rectTransform.sizeDelta == new Vector2(100, 100))
  5829. m_rectTransform.sizeDelta = TMP_Settings.defaultTextMeshProTextContainerSize;
  5830. }
  5831. else
  5832. {
  5833. if (m_rectTransform.sizeDelta == new Vector2(100, 100))
  5834. m_rectTransform.sizeDelta = TMP_Settings.defaultTextMeshProUITextContainerSize;
  5835. }
  5836. }
  5837. m_enableWordWrapping = TMP_Settings.enableWordWrapping;
  5838. m_enableKerning = TMP_Settings.enableKerning;
  5839. m_enableExtraPadding = TMP_Settings.enableExtraPadding;
  5840. m_tintAllSprites = TMP_Settings.enableTintAllSprites;
  5841. m_parseCtrlCharacters = TMP_Settings.enableParseEscapeCharacters;
  5842. m_fontSize = m_fontSizeBase = TMP_Settings.defaultFontSize;
  5843. m_fontSizeMin = m_fontSize * TMP_Settings.defaultTextAutoSizingMinRatio;
  5844. m_fontSizeMax = m_fontSize * TMP_Settings.defaultTextAutoSizingMaxRatio;
  5845. m_isWaitingOnResourceLoad = false;
  5846. raycastTarget = TMP_Settings.enableRaycastTarget;
  5847. m_IsTextObjectScaleStatic = TMP_Settings.isTextObjectScaleStatic;
  5848. }
  5849. else if ((int)m_textAlignment < 0xFF)
  5850. {
  5851. // Convert Legacy TextAlignmentOptions enumerations from Unity 5.2 / 5.3.
  5852. m_textAlignment = TMP_Compatibility.ConvertTextAlignmentEnumValues(m_textAlignment);
  5853. }
  5854. // Convert text alignment to independent horizontal and vertical alignment properties
  5855. if (m_textAlignment != TextAlignmentOptions.Converted)
  5856. {
  5857. m_HorizontalAlignment = (HorizontalAlignmentOptions)((int)m_textAlignment & 0xFF);
  5858. m_VerticalAlignment = (VerticalAlignmentOptions)((int)m_textAlignment & 0xFF00);
  5859. m_textAlignment = TextAlignmentOptions.Converted;
  5860. }
  5861. }
  5862. /// <summary>
  5863. /// Method used to find and cache references to the Underline and Ellipsis characters.
  5864. /// </summary>
  5865. /// <param name=""></param>
  5866. protected void GetSpecialCharacters(TMP_FontAsset fontAsset)
  5867. {
  5868. GetEllipsisSpecialCharacter(fontAsset);
  5869. GetUnderlineSpecialCharacter(fontAsset);
  5870. }
  5871. protected void GetEllipsisSpecialCharacter(TMP_FontAsset fontAsset)
  5872. {
  5873. bool isUsingAlternativeTypeface;
  5874. // Search base font asset
  5875. TMP_Character character = TMP_FontAssetUtilities.GetCharacterFromFontAsset(0x2026, fontAsset, false, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface);
  5876. if (character == null)
  5877. {
  5878. // Search primary fallback list
  5879. if (fontAsset.m_FallbackFontAssetTable != null && fontAsset.m_FallbackFontAssetTable.Count > 0)
  5880. character = TMP_FontAssetUtilities.GetCharacterFromFontAssets(0x2026, fontAsset, fontAsset.m_FallbackFontAssetTable, true, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface);
  5881. }
  5882. // Search TMP Settings general fallback list
  5883. if (character == null)
  5884. {
  5885. if (TMP_Settings.fallbackFontAssets != null && TMP_Settings.fallbackFontAssets.Count > 0)
  5886. character = TMP_FontAssetUtilities.GetCharacterFromFontAssets(0x2026, fontAsset, TMP_Settings.fallbackFontAssets, true, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface);
  5887. }
  5888. // Search TMP Settings' default font asset
  5889. if (character == null)
  5890. {
  5891. if (TMP_Settings.defaultFontAsset != null)
  5892. character = TMP_FontAssetUtilities.GetCharacterFromFontAsset(0x2026, TMP_Settings.defaultFontAsset, true, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface);
  5893. }
  5894. if (character != null)
  5895. m_Ellipsis = new SpecialCharacter(character, 0);
  5896. }
  5897. protected void GetUnderlineSpecialCharacter(TMP_FontAsset fontAsset)
  5898. {
  5899. bool isUsingAlternativeTypeface;
  5900. // Search primary font asset for underline character while ignoring font style and weight as these do not affect the underline character.
  5901. TMP_Character character = TMP_FontAssetUtilities.GetCharacterFromFontAsset(0x5F, fontAsset, false, FontStyles.Normal, FontWeight.Regular, out isUsingAlternativeTypeface);
  5902. /*
  5903. if (m_Underline.character == null)
  5904. {
  5905. // Search primary fallback list
  5906. if (fontAsset.m_FallbackFontAssetTable != null && fontAsset.m_FallbackFontAssetTable.Count > 0)
  5907. m_Underline.character = TMP_FontAssetUtilities.GetCharacterFromFontAssets(0x5F, fontAsset.m_FallbackFontAssetTable, true, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface, out tempFontAsset);
  5908. }
  5909. // Search TMP Settings general fallback list
  5910. if (m_Underline.character == null)
  5911. {
  5912. if (TMP_Settings.fallbackFontAssets != null && TMP_Settings.fallbackFontAssets.Count > 0)
  5913. m_Underline.character = TMP_FontAssetUtilities.GetCharacterFromFontAssets(0x5F, TMP_Settings.fallbackFontAssets, true, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface, out tempFontAsset);
  5914. }
  5915. // Search TMP Settings' default font asset
  5916. if (m_Underline.character == null)
  5917. {
  5918. if (TMP_Settings.defaultFontAsset != null)
  5919. m_Underline.character = TMP_FontAssetUtilities.GetCharacterFromFontAsset(0x5F, TMP_Settings.defaultFontAsset, true, m_FontStyleInternal, m_FontWeightInternal, out isUsingAlternativeTypeface, out tempFontAsset);
  5920. }
  5921. */
  5922. if (character != null)
  5923. {
  5924. m_Underline = new SpecialCharacter(character, 0);
  5925. }
  5926. else
  5927. {
  5928. if (!TMP_Settings.warningsDisabled)
  5929. Debug.LogWarning("The character used for Underline is not available in font asset [" + fontAsset.name + "].", this);
  5930. }
  5931. }
  5932. /// <summary>
  5933. /// Replace a given number of characters (tag) in the array with a new character and shift subsequent characters in the array.
  5934. /// </summary>
  5935. /// <param name="chars">Array which contains the text.</param>
  5936. /// <param name="insertionIndex">The index of where the new character will be inserted</param>
  5937. /// <param name="tagLength">Length of the tag being replaced.</param>
  5938. /// <param name="c">The replacement character.</param>
  5939. protected void ReplaceTagWithCharacter(int[] chars, int insertionIndex, int tagLength, char c)
  5940. {
  5941. chars[insertionIndex] = c;
  5942. for (int i = insertionIndex + tagLength; i < chars.Length; i++)
  5943. {
  5944. chars[i - 3] = chars[i];
  5945. }
  5946. }
  5947. /// <summary>
  5948. ///
  5949. /// </summary>
  5950. /// <returns></returns>
  5951. //protected int GetMaterialReferenceForFontWeight()
  5952. //{
  5953. // //bool isItalic = (m_style & FontStyles.Italic) == FontStyles.Italic || (m_fontStyle & FontStyles.Italic) == FontStyles.Italic;
  5954. // m_currentMaterialIndex = MaterialReference.AddMaterialReference(m_currentFontAsset.fontWeights[0].italicTypeface.material, m_currentFontAsset.fontWeights[0].italicTypeface, m_materialReferences, m_materialReferenceIndexLookup);
  5955. // return 0;
  5956. //}
  5957. /// <summary>
  5958. ///
  5959. /// </summary>
  5960. /// <returns></returns>
  5961. protected TMP_FontAsset GetFontAssetForWeight(int fontWeight)
  5962. {
  5963. bool isItalic = (m_FontStyleInternal & FontStyles.Italic) == FontStyles.Italic || (m_fontStyle & FontStyles.Italic) == FontStyles.Italic;
  5964. TMP_FontAsset fontAsset = null;
  5965. int weightIndex = fontWeight / 100;
  5966. if (isItalic)
  5967. fontAsset = m_currentFontAsset.fontWeightTable[weightIndex].italicTypeface;
  5968. else
  5969. fontAsset = m_currentFontAsset.fontWeightTable[weightIndex].regularTypeface;
  5970. return fontAsset;
  5971. }
  5972. internal TMP_TextElement GetTextElement(uint unicode, TMP_FontAsset fontAsset, FontStyles fontStyle, FontWeight fontWeight, out bool isUsingAlternativeTypeface)
  5973. {
  5974. TMP_Character character = TMP_FontAssetUtilities.GetCharacterFromFontAsset(unicode, fontAsset, false, fontStyle, fontWeight, out isUsingAlternativeTypeface);
  5975. if (character != null)
  5976. return character;
  5977. // Search potential list of fallback font assets assigned to the font asset.
  5978. if (fontAsset.m_FallbackFontAssetTable != null && fontAsset.m_FallbackFontAssetTable.Count > 0)
  5979. character = TMP_FontAssetUtilities.GetCharacterFromFontAssets(unicode, fontAsset, fontAsset.m_FallbackFontAssetTable, true, fontStyle, fontWeight, out isUsingAlternativeTypeface);
  5980. if (character != null)
  5981. {
  5982. // Add character to font asset lookup cache
  5983. //fontAsset.AddCharacterToLookupCache(unicode, character);
  5984. return character;
  5985. }
  5986. // Search for the character in the primary font asset if not the current font asset
  5987. if (fontAsset.instanceID != m_fontAsset.instanceID)
  5988. {
  5989. // Search primary font asset
  5990. character = TMP_FontAssetUtilities.GetCharacterFromFontAsset(unicode, m_fontAsset, false, fontStyle, fontWeight, out isUsingAlternativeTypeface);
  5991. // Use material and index of primary font asset.
  5992. if (character != null)
  5993. {
  5994. m_currentMaterialIndex = 0;
  5995. m_currentMaterial = m_materialReferences[0].material;
  5996. // Add character to font asset lookup cache
  5997. //fontAsset.AddCharacterToLookupCache(unicode, character);
  5998. return character;
  5999. }
  6000. // Search list of potential fallback font assets assigned to the primary font asset.
  6001. if (m_fontAsset.m_FallbackFontAssetTable != null && m_fontAsset.m_FallbackFontAssetTable.Count > 0)
  6002. character = TMP_FontAssetUtilities.GetCharacterFromFontAssets(unicode, fontAsset, m_fontAsset.m_FallbackFontAssetTable, true, fontStyle, fontWeight, out isUsingAlternativeTypeface);
  6003. if (character != null)
  6004. {
  6005. // Add character to font asset lookup cache
  6006. //fontAsset.AddCharacterToLookupCache(unicode, character);
  6007. return character;
  6008. }
  6009. }
  6010. // Search for the character in potential local Sprite Asset assigned to the text object.
  6011. if (m_spriteAsset != null)
  6012. {
  6013. TMP_SpriteCharacter spriteCharacter = TMP_FontAssetUtilities.GetSpriteCharacterFromSpriteAsset(unicode, m_spriteAsset, true);
  6014. if (spriteCharacter != null)
  6015. return spriteCharacter;
  6016. }
  6017. // Search for the character in the list of fallback assigned in the TMP Settings (General Fallbacks).
  6018. if (TMP_Settings.fallbackFontAssets != null && TMP_Settings.fallbackFontAssets.Count > 0)
  6019. character = TMP_FontAssetUtilities.GetCharacterFromFontAssets(unicode, fontAsset, TMP_Settings.fallbackFontAssets, true, fontStyle, fontWeight, out isUsingAlternativeTypeface);
  6020. if (character != null)
  6021. {
  6022. // Add character to font asset lookup cache
  6023. //fontAsset.AddCharacterToLookupCache(unicode, character);
  6024. return character;
  6025. }
  6026. // Search for the character in the Default Font Asset assigned in the TMP Settings file.
  6027. if (TMP_Settings.defaultFontAsset != null)
  6028. character = TMP_FontAssetUtilities.GetCharacterFromFontAsset(unicode, TMP_Settings.defaultFontAsset, true, fontStyle, fontWeight, out isUsingAlternativeTypeface);
  6029. if (character != null)
  6030. {
  6031. // Add character to font asset lookup cache
  6032. //fontAsset.AddCharacterToLookupCache(unicode, character);
  6033. return character;
  6034. }
  6035. // Search for the character in the Default Sprite Asset assigned in the TMP Settings file.
  6036. if (TMP_Settings.defaultSpriteAsset != null)
  6037. {
  6038. TMP_SpriteCharacter spriteCharacter = TMP_FontAssetUtilities.GetSpriteCharacterFromSpriteAsset(unicode, TMP_Settings.defaultSpriteAsset, true);
  6039. if (spriteCharacter != null)
  6040. return spriteCharacter;
  6041. }
  6042. return null;
  6043. }
  6044. /// <summary>
  6045. /// Method to Enable or Disable child SubMesh objects.
  6046. /// </summary>
  6047. /// <param name="state"></param>
  6048. protected virtual void SetActiveSubMeshes(bool state) { }
  6049. /// <summary>
  6050. /// Destroy Sub Mesh Objects.
  6051. /// </summary>
  6052. protected virtual void DestroySubMeshObjects() { }
  6053. /// <summary>
  6054. /// Function to clear the geometry of the Primary and Sub Text objects.
  6055. /// </summary>
  6056. public virtual void ClearMesh() { }
  6057. /// <summary>
  6058. /// Function to clear the geometry of the Primary and Sub Text objects.
  6059. /// </summary>
  6060. public virtual void ClearMesh(bool uploadGeometry) { }
  6061. /// <summary>
  6062. /// Function which returns the text after it has been parsed and rich text tags removed.
  6063. /// </summary>
  6064. /// <returns></returns>
  6065. public virtual string GetParsedText()
  6066. {
  6067. if (m_textInfo == null)
  6068. return string.Empty;
  6069. int characterCount = m_textInfo.characterCount;
  6070. // TODO - Could implement some static buffer pool shared by all instances of TMP objects.
  6071. char[] buffer = new char[characterCount];
  6072. for (int i = 0; i < characterCount && i < m_textInfo.characterInfo.Length; i++)
  6073. {
  6074. buffer[i] = m_textInfo.characterInfo[i].character;
  6075. }
  6076. return new string(buffer);
  6077. }
  6078. internal bool IsSelfOrLinkedAncestor(TMP_Text targetTextComponent)
  6079. {
  6080. if (targetTextComponent == null)
  6081. return true;
  6082. if (parentLinkedComponent != null)
  6083. {
  6084. if (parentLinkedComponent.IsSelfOrLinkedAncestor(targetTextComponent))
  6085. return true;
  6086. }
  6087. if (this.GetInstanceID() == targetTextComponent.GetInstanceID())
  6088. return true;
  6089. return false;
  6090. }
  6091. internal void ReleaseLinkedTextComponent(TMP_Text targetTextComponent)
  6092. {
  6093. if (targetTextComponent == null)
  6094. return;
  6095. TMP_Text childLinkedComponent = targetTextComponent.linkedTextComponent;
  6096. if (childLinkedComponent != null)
  6097. ReleaseLinkedTextComponent(childLinkedComponent);
  6098. targetTextComponent.text = string.Empty;
  6099. targetTextComponent.firstVisibleCharacter = 0;
  6100. targetTextComponent.linkedTextComponent = null;
  6101. targetTextComponent.parentLinkedComponent = null;
  6102. }
  6103. /// <summary>
  6104. /// Function to pack scale information in the UV2 Channel.
  6105. /// </summary>
  6106. /// <param name="x"></param>
  6107. /// <param name="y"></param>
  6108. /// <param name="scale"></param>
  6109. /// <returns></returns>
  6110. //protected Vector2 PackUV(float x, float y, float scale)
  6111. //{
  6112. // Vector2 output;
  6113. // output.x = Mathf.Floor(x * 4095);
  6114. // output.y = Mathf.Floor(y * 4095);
  6115. // output.x = (output.x * 4096) + output.y;
  6116. // output.y = scale;
  6117. // return output;
  6118. //}
  6119. /// <summary>
  6120. /// Function to pack scale information in the UV2 Channel.
  6121. /// </summary>
  6122. /// <param name="x"></param>
  6123. /// <param name="y"></param>
  6124. /// <param name="scale"></param>
  6125. /// <returns></returns>
  6126. protected Vector2 PackUV(float x, float y, float scale)
  6127. {
  6128. Vector2 output;
  6129. output.x = (int)(x * 511);
  6130. output.y = (int)(y * 511);
  6131. output.x = (output.x * 4096) + output.y;
  6132. output.y = scale;
  6133. return output;
  6134. }
  6135. /// <summary>
  6136. ///
  6137. /// </summary>
  6138. /// <param name="x"></param>
  6139. /// <param name="y"></param>
  6140. /// <returns></returns>
  6141. protected float PackUV(float x, float y)
  6142. {
  6143. double x0 = (int)(x * 511);
  6144. double y0 = (int)(y * 511);
  6145. return (float)((x0 * 4096) + y0);
  6146. }
  6147. /// <summary>
  6148. /// Function used as a replacement for LateUpdate()
  6149. /// </summary>
  6150. internal virtual void InternalUpdate() { }
  6151. /// <summary>
  6152. /// Function to pack scale information in the UV2 Channel.
  6153. /// </summary>
  6154. /// <param name="x"></param>
  6155. /// <param name="y"></param>
  6156. /// <param name="scale"></param>
  6157. /// <returns></returns>
  6158. //protected Vector2 PackUV(float x, float y, float scale)
  6159. //{
  6160. // Vector2 output;
  6161. // output.x = Mathf.Floor(x * 4095);
  6162. // output.y = Mathf.Floor(y * 4095);
  6163. // return new Vector2((output.x * 4096) + output.y, scale);
  6164. //}
  6165. /// <summary>
  6166. ///
  6167. /// </summary>
  6168. /// <param name="x"></param>
  6169. /// <param name="y"></param>
  6170. /// <returns></returns>
  6171. //protected float PackUV(float x, float y)
  6172. //{
  6173. // x = (x % 5) / 5;
  6174. // y = (y % 5) / 5;
  6175. // return Mathf.Round(x * 4096) + y;
  6176. //}
  6177. /// <summary>
  6178. /// Method to convert Hex to Int
  6179. /// </summary>
  6180. /// <param name="hex"></param>
  6181. /// <returns></returns>
  6182. protected int HexToInt(char hex)
  6183. {
  6184. switch (hex)
  6185. {
  6186. case '0': return 0;
  6187. case '1': return 1;
  6188. case '2': return 2;
  6189. case '3': return 3;
  6190. case '4': return 4;
  6191. case '5': return 5;
  6192. case '6': return 6;
  6193. case '7': return 7;
  6194. case '8': return 8;
  6195. case '9': return 9;
  6196. case 'A': return 10;
  6197. case 'B': return 11;
  6198. case 'C': return 12;
  6199. case 'D': return 13;
  6200. case 'E': return 14;
  6201. case 'F': return 15;
  6202. case 'a': return 10;
  6203. case 'b': return 11;
  6204. case 'c': return 12;
  6205. case 'd': return 13;
  6206. case 'e': return 14;
  6207. case 'f': return 15;
  6208. }
  6209. return 15;
  6210. }
  6211. /// <summary>
  6212. /// Convert UTF-16 Hex to Char
  6213. /// </summary>
  6214. /// <returns>The Unicode hex.</returns>
  6215. /// <param name="i">The index.</param>
  6216. protected int GetUTF16(string text, int i)
  6217. {
  6218. int unicode = 0;
  6219. unicode += HexToInt(text[i]) << 12;
  6220. unicode += HexToInt(text[i + 1]) << 8;
  6221. unicode += HexToInt(text[i + 2]) << 4;
  6222. unicode += HexToInt(text[i + 3]);
  6223. return unicode;
  6224. }
  6225. protected int GetUTF16(int[] text, int i)
  6226. {
  6227. int unicode = 0;
  6228. unicode += HexToInt((char)text[i]) << 12;
  6229. unicode += HexToInt((char)text[i + 1]) << 8;
  6230. unicode += HexToInt((char)text[i + 2]) << 4;
  6231. unicode += HexToInt((char)text[i + 3]);
  6232. return unicode;
  6233. }
  6234. /// <summary>
  6235. /// Convert UTF-16 Hex to Char
  6236. /// </summary>
  6237. /// <returns>The Unicode hex.</returns>
  6238. /// <param name="i">The index.</param>
  6239. protected int GetUTF16(StringBuilder text, int i)
  6240. {
  6241. int unicode = 0;
  6242. unicode += HexToInt(text[i]) << 12;
  6243. unicode += HexToInt(text[i + 1]) << 8;
  6244. unicode += HexToInt(text[i + 2]) << 4;
  6245. unicode += HexToInt(text[i + 3]);
  6246. return unicode;
  6247. }
  6248. /// <summary>
  6249. /// Convert UTF-32 Hex to Char
  6250. /// </summary>
  6251. /// <returns>The Unicode hex.</returns>
  6252. /// <param name="i">The index.</param>
  6253. protected int GetUTF32(string text, int i)
  6254. {
  6255. int unicode = 0;
  6256. unicode += HexToInt(text[i]) << 28;
  6257. unicode += HexToInt(text[i + 1]) << 24;
  6258. unicode += HexToInt(text[i + 2]) << 20;
  6259. unicode += HexToInt(text[i + 3]) << 16;
  6260. unicode += HexToInt(text[i + 4]) << 12;
  6261. unicode += HexToInt(text[i + 5]) << 8;
  6262. unicode += HexToInt(text[i + 6]) << 4;
  6263. unicode += HexToInt(text[i + 7]);
  6264. return unicode;
  6265. }
  6266. protected int GetUTF32(int[] text, int i)
  6267. {
  6268. int unicode = 0;
  6269. unicode += HexToInt((char)text[i]) << 28;
  6270. unicode += HexToInt((char)text[i + 1]) << 24;
  6271. unicode += HexToInt((char)text[i + 2]) << 20;
  6272. unicode += HexToInt((char)text[i + 3]) << 16;
  6273. unicode += HexToInt((char)text[i + 4]) << 12;
  6274. unicode += HexToInt((char)text[i + 5]) << 8;
  6275. unicode += HexToInt((char)text[i + 6]) << 4;
  6276. unicode += HexToInt((char)text[i + 7]);
  6277. return unicode;
  6278. }
  6279. /// <summary>
  6280. /// Convert UTF-32 Hex to Char
  6281. /// </summary>
  6282. /// <returns>The Unicode hex.</returns>
  6283. /// <param name="i">The index.</param>
  6284. protected int GetUTF32(StringBuilder text, int i)
  6285. {
  6286. int unicode = 0;
  6287. unicode += HexToInt(text[i]) << 28;
  6288. unicode += HexToInt(text[i + 1]) << 24;
  6289. unicode += HexToInt(text[i + 2]) << 20;
  6290. unicode += HexToInt(text[i + 3]) << 16;
  6291. unicode += HexToInt(text[i + 4]) << 12;
  6292. unicode += HexToInt(text[i + 5]) << 8;
  6293. unicode += HexToInt(text[i + 6]) << 4;
  6294. unicode += HexToInt(text[i + 7]);
  6295. return unicode;
  6296. }
  6297. /// <summary>
  6298. /// Method to convert Hex color values to Color32
  6299. /// </summary>
  6300. /// <param name="hexChars"></param>
  6301. /// <param name="tagCount"></param>
  6302. /// <returns></returns>
  6303. protected Color32 HexCharsToColor(char[] hexChars, int tagCount)
  6304. {
  6305. if (tagCount == 4)
  6306. {
  6307. byte r = (byte)(HexToInt(hexChars[1]) * 16 + HexToInt(hexChars[1]));
  6308. byte g = (byte)(HexToInt(hexChars[2]) * 16 + HexToInt(hexChars[2]));
  6309. byte b = (byte)(HexToInt(hexChars[3]) * 16 + HexToInt(hexChars[3]));
  6310. return new Color32(r, g, b, 255);
  6311. }
  6312. else if (tagCount == 5)
  6313. {
  6314. byte r = (byte)(HexToInt(hexChars[1]) * 16 + HexToInt(hexChars[1]));
  6315. byte g = (byte)(HexToInt(hexChars[2]) * 16 + HexToInt(hexChars[2]));
  6316. byte b = (byte)(HexToInt(hexChars[3]) * 16 + HexToInt(hexChars[3]));
  6317. byte a = (byte)(HexToInt(hexChars[4]) * 16 + HexToInt(hexChars[4]));
  6318. return new Color32(r, g, b, a);
  6319. }
  6320. else if (tagCount == 7)
  6321. {
  6322. byte r = (byte)(HexToInt(hexChars[1]) * 16 + HexToInt(hexChars[2]));
  6323. byte g = (byte)(HexToInt(hexChars[3]) * 16 + HexToInt(hexChars[4]));
  6324. byte b = (byte)(HexToInt(hexChars[5]) * 16 + HexToInt(hexChars[6]));
  6325. return new Color32(r, g, b, 255);
  6326. }
  6327. else if (tagCount == 9)
  6328. {
  6329. byte r = (byte)(HexToInt(hexChars[1]) * 16 + HexToInt(hexChars[2]));
  6330. byte g = (byte)(HexToInt(hexChars[3]) * 16 + HexToInt(hexChars[4]));
  6331. byte b = (byte)(HexToInt(hexChars[5]) * 16 + HexToInt(hexChars[6]));
  6332. byte a = (byte)(HexToInt(hexChars[7]) * 16 + HexToInt(hexChars[8]));
  6333. return new Color32(r, g, b, a);
  6334. }
  6335. else if (tagCount == 10)
  6336. {
  6337. byte r = (byte)(HexToInt(hexChars[7]) * 16 + HexToInt(hexChars[7]));
  6338. byte g = (byte)(HexToInt(hexChars[8]) * 16 + HexToInt(hexChars[8]));
  6339. byte b = (byte)(HexToInt(hexChars[9]) * 16 + HexToInt(hexChars[9]));
  6340. return new Color32(r, g, b, 255);
  6341. }
  6342. else if (tagCount == 11)
  6343. {
  6344. byte r = (byte)(HexToInt(hexChars[7]) * 16 + HexToInt(hexChars[7]));
  6345. byte g = (byte)(HexToInt(hexChars[8]) * 16 + HexToInt(hexChars[8]));
  6346. byte b = (byte)(HexToInt(hexChars[9]) * 16 + HexToInt(hexChars[9]));
  6347. byte a = (byte)(HexToInt(hexChars[10]) * 16 + HexToInt(hexChars[10]));
  6348. return new Color32(r, g, b, a);
  6349. }
  6350. else if (tagCount == 13)
  6351. {
  6352. byte r = (byte)(HexToInt(hexChars[7]) * 16 + HexToInt(hexChars[8]));
  6353. byte g = (byte)(HexToInt(hexChars[9]) * 16 + HexToInt(hexChars[10]));
  6354. byte b = (byte)(HexToInt(hexChars[11]) * 16 + HexToInt(hexChars[12]));
  6355. return new Color32(r, g, b, 255);
  6356. }
  6357. else if (tagCount == 15)
  6358. {
  6359. byte r = (byte)(HexToInt(hexChars[7]) * 16 + HexToInt(hexChars[8]));
  6360. byte g = (byte)(HexToInt(hexChars[9]) * 16 + HexToInt(hexChars[10]));
  6361. byte b = (byte)(HexToInt(hexChars[11]) * 16 + HexToInt(hexChars[12]));
  6362. byte a = (byte)(HexToInt(hexChars[13]) * 16 + HexToInt(hexChars[14]));
  6363. return new Color32(r, g, b, a);
  6364. }
  6365. return new Color32(255, 255, 255, 255);
  6366. }
  6367. /// <summary>
  6368. /// Method to convert Hex Color values to Color32
  6369. /// </summary>
  6370. /// <param name="hexChars"></param>
  6371. /// <param name="startIndex"></param>
  6372. /// <param name="length"></param>
  6373. /// <returns></returns>
  6374. protected Color32 HexCharsToColor(char[] hexChars, int startIndex, int length)
  6375. {
  6376. if (length == 7)
  6377. {
  6378. byte r = (byte)(HexToInt(hexChars[startIndex + 1]) * 16 + HexToInt(hexChars[startIndex + 2]));
  6379. byte g = (byte)(HexToInt(hexChars[startIndex + 3]) * 16 + HexToInt(hexChars[startIndex + 4]));
  6380. byte b = (byte)(HexToInt(hexChars[startIndex + 5]) * 16 + HexToInt(hexChars[startIndex + 6]));
  6381. return new Color32(r, g, b, 255);
  6382. }
  6383. else if (length == 9)
  6384. {
  6385. byte r = (byte)(HexToInt(hexChars[startIndex + 1]) * 16 + HexToInt(hexChars[startIndex + 2]));
  6386. byte g = (byte)(HexToInt(hexChars[startIndex + 3]) * 16 + HexToInt(hexChars[startIndex + 4]));
  6387. byte b = (byte)(HexToInt(hexChars[startIndex + 5]) * 16 + HexToInt(hexChars[startIndex + 6]));
  6388. byte a = (byte)(HexToInt(hexChars[startIndex + 7]) * 16 + HexToInt(hexChars[startIndex + 8]));
  6389. return new Color32(r, g, b, a);
  6390. }
  6391. return s_colorWhite;
  6392. }
  6393. /// <summary>
  6394. /// Method which returns the number of parameters used in a tag attribute and populates an array with such values.
  6395. /// </summary>
  6396. /// <param name="chars">Char[] containing the tag attribute and data</param>
  6397. /// <param name="startIndex">The index of the first char of the data</param>
  6398. /// <param name="length">The length of the data</param>
  6399. /// <param name="parameters">The number of parameters contained in the Char[]</param>
  6400. /// <returns></returns>
  6401. int GetAttributeParameters(char[] chars, int startIndex, int length, ref float[] parameters)
  6402. {
  6403. int endIndex = startIndex;
  6404. int attributeCount = 0;
  6405. while (endIndex < startIndex + length)
  6406. {
  6407. parameters[attributeCount] = ConvertToFloat(chars, startIndex, length, out endIndex);
  6408. length -= (endIndex - startIndex) + 1;
  6409. startIndex = endIndex + 1;
  6410. attributeCount += 1;
  6411. }
  6412. return attributeCount;
  6413. }
  6414. /// <summary>
  6415. /// Extracts a float value from char[] assuming we know the position of the start, end and decimal point.
  6416. /// </summary>
  6417. /// <param name="chars"></param>
  6418. /// <param name="startIndex"></param>
  6419. /// <param name="length"></param>
  6420. /// <returns></returns>
  6421. protected float ConvertToFloat(char[] chars, int startIndex, int length)
  6422. {
  6423. int lastIndex;
  6424. return ConvertToFloat(chars, startIndex, length, out lastIndex);
  6425. }
  6426. /// <summary>
  6427. /// Extracts a float value from char[] given a start index and length.
  6428. /// </summary>
  6429. /// <param name="chars"></param> The Char[] containing the numerical sequence.
  6430. /// <param name="startIndex"></param> The index of the start of the numerical sequence.
  6431. /// <param name="length"></param> The length of the numerical sequence.
  6432. /// <param name="lastIndex"></param> Index of the last character in the validated sequence.
  6433. /// <returns></returns>
  6434. protected float ConvertToFloat(char[] chars, int startIndex, int length, out int lastIndex)
  6435. {
  6436. if (startIndex == 0)
  6437. {
  6438. lastIndex = 0;
  6439. return Int16.MinValue;
  6440. }
  6441. int endIndex = startIndex + length;
  6442. bool isIntegerValue = true;
  6443. float decimalPointMultiplier = 0;
  6444. // Set value multiplier checking the first character to determine if we are using '+' or '-'
  6445. int valueSignMultiplier = 1;
  6446. if (chars[startIndex] == '+')
  6447. {
  6448. valueSignMultiplier = 1;
  6449. startIndex += 1;
  6450. }
  6451. else if (chars[startIndex] == '-')
  6452. {
  6453. valueSignMultiplier = -1;
  6454. startIndex += 1;
  6455. }
  6456. float value = 0;
  6457. for (int i = startIndex; i < endIndex; i++)
  6458. {
  6459. uint c = chars[i];
  6460. if (c >= '0' && c <= '9' || c == '.')
  6461. {
  6462. if (c == '.')
  6463. {
  6464. isIntegerValue = false;
  6465. decimalPointMultiplier = 0.1f;
  6466. continue;
  6467. }
  6468. //Calculate integer and floating point value
  6469. if (isIntegerValue)
  6470. value = value * 10 + (c - 48) * valueSignMultiplier;
  6471. else
  6472. {
  6473. value = value + (c - 48) * decimalPointMultiplier * valueSignMultiplier;
  6474. decimalPointMultiplier *= 0.1f;
  6475. }
  6476. continue;
  6477. }
  6478. else if (c == ',')
  6479. {
  6480. if (i + 1 < endIndex && chars[i + 1] == ' ')
  6481. lastIndex = i + 1;
  6482. else
  6483. lastIndex = i;
  6484. // Make sure value is within reasonable range.
  6485. if (value > 32767)
  6486. return Int16.MinValue;
  6487. return value;
  6488. }
  6489. }
  6490. lastIndex = endIndex;
  6491. // Make sure value is within reasonable range.
  6492. if (value > 32767)
  6493. return Int16.MinValue;
  6494. return value;
  6495. }
  6496. /// <summary>
  6497. /// Function to identify and validate the rich tag. Returns the position of the > if the tag was valid.
  6498. /// </summary>
  6499. /// <param name="chars"></param>
  6500. /// <param name="startIndex"></param>
  6501. /// <param name="endIndex"></param>
  6502. /// <returns></returns>
  6503. protected bool ValidateHtmlTag(UnicodeChar[] chars, int startIndex, out int endIndex)
  6504. {
  6505. int tagCharCount = 0;
  6506. byte attributeFlag = 0;
  6507. int attributeIndex = 0;
  6508. m_xmlAttribute[attributeIndex].nameHashCode = 0;
  6509. m_xmlAttribute[attributeIndex].valueHashCode = 0;
  6510. m_xmlAttribute[attributeIndex].valueStartIndex = 0;
  6511. m_xmlAttribute[attributeIndex].valueLength = 0;
  6512. TagValueType tagValueType = m_xmlAttribute[attributeIndex].valueType = TagValueType.None;
  6513. TagUnitType tagUnitType = m_xmlAttribute[attributeIndex].unitType = TagUnitType.Pixels;
  6514. // Clear attribute name hash codes
  6515. m_xmlAttribute[1].nameHashCode = 0;
  6516. m_xmlAttribute[2].nameHashCode = 0;
  6517. m_xmlAttribute[3].nameHashCode = 0;
  6518. m_xmlAttribute[4].nameHashCode = 0;
  6519. endIndex = startIndex;
  6520. bool isTagSet = false;
  6521. bool isValidHtmlTag = false;
  6522. for (int i = startIndex; i < chars.Length && chars[i].unicode != 0 && tagCharCount < m_htmlTag.Length && chars[i].unicode != '<'; i++)
  6523. {
  6524. int unicode = chars[i].unicode;
  6525. if (unicode == '>') // ASCII Code of End HTML tag '>'
  6526. {
  6527. isValidHtmlTag = true;
  6528. endIndex = i;
  6529. m_htmlTag[tagCharCount] = (char)0;
  6530. break;
  6531. }
  6532. m_htmlTag[tagCharCount] = (char)unicode;
  6533. tagCharCount += 1;
  6534. if (attributeFlag == 1)
  6535. {
  6536. if (tagValueType == TagValueType.None)
  6537. {
  6538. // Check for attribute type
  6539. if (unicode == '+' || unicode == '-' || unicode == '.' || (unicode >= '0' && unicode <= '9'))
  6540. {
  6541. tagUnitType = TagUnitType.Pixels;
  6542. tagValueType = m_xmlAttribute[attributeIndex].valueType = TagValueType.NumericalValue;
  6543. m_xmlAttribute[attributeIndex].valueStartIndex = tagCharCount - 1;
  6544. m_xmlAttribute[attributeIndex].valueLength += 1;
  6545. }
  6546. else if (unicode == '#')
  6547. {
  6548. tagUnitType = TagUnitType.Pixels;
  6549. tagValueType = m_xmlAttribute[attributeIndex].valueType = TagValueType.ColorValue;
  6550. m_xmlAttribute[attributeIndex].valueStartIndex = tagCharCount - 1;
  6551. m_xmlAttribute[attributeIndex].valueLength += 1;
  6552. }
  6553. else if (unicode == '"')
  6554. {
  6555. tagUnitType = TagUnitType.Pixels;
  6556. tagValueType = m_xmlAttribute[attributeIndex].valueType = TagValueType.StringValue;
  6557. m_xmlAttribute[attributeIndex].valueStartIndex = tagCharCount;
  6558. }
  6559. else
  6560. {
  6561. tagUnitType = TagUnitType.Pixels;
  6562. tagValueType = m_xmlAttribute[attributeIndex].valueType = TagValueType.StringValue;
  6563. m_xmlAttribute[attributeIndex].valueStartIndex = tagCharCount - 1;
  6564. m_xmlAttribute[attributeIndex].valueHashCode = (m_xmlAttribute[attributeIndex].valueHashCode << 5) + m_xmlAttribute[attributeIndex].valueHashCode ^ unicode;
  6565. m_xmlAttribute[attributeIndex].valueLength += 1;
  6566. }
  6567. }
  6568. else
  6569. {
  6570. if (tagValueType == TagValueType.NumericalValue)
  6571. {
  6572. // Check for termination of numerical value.
  6573. if (unicode == 'p' || unicode == 'e' || unicode == '%' || unicode == ' ')
  6574. {
  6575. attributeFlag = 2;
  6576. tagValueType = TagValueType.None;
  6577. switch (unicode)
  6578. {
  6579. case 'e':
  6580. m_xmlAttribute[attributeIndex].unitType = tagUnitType = TagUnitType.FontUnits;
  6581. break;
  6582. case '%':
  6583. m_xmlAttribute[attributeIndex].unitType = tagUnitType = TagUnitType.Percentage;
  6584. break;
  6585. default:
  6586. m_xmlAttribute[attributeIndex].unitType = tagUnitType = TagUnitType.Pixels;
  6587. break;
  6588. }
  6589. attributeIndex += 1;
  6590. m_xmlAttribute[attributeIndex].nameHashCode = 0;
  6591. m_xmlAttribute[attributeIndex].valueHashCode = 0;
  6592. m_xmlAttribute[attributeIndex].valueType = TagValueType.None;
  6593. m_xmlAttribute[attributeIndex].unitType = TagUnitType.Pixels;
  6594. m_xmlAttribute[attributeIndex].valueStartIndex = 0;
  6595. m_xmlAttribute[attributeIndex].valueLength = 0;
  6596. }
  6597. else if (attributeFlag != 2)
  6598. {
  6599. m_xmlAttribute[attributeIndex].valueLength += 1;
  6600. }
  6601. }
  6602. else if (tagValueType == TagValueType.ColorValue)
  6603. {
  6604. if (unicode != ' ')
  6605. {
  6606. m_xmlAttribute[attributeIndex].valueLength += 1;
  6607. }
  6608. else
  6609. {
  6610. attributeFlag = 2;
  6611. tagValueType = TagValueType.None;
  6612. tagUnitType = TagUnitType.Pixels;
  6613. attributeIndex += 1;
  6614. m_xmlAttribute[attributeIndex].nameHashCode = 0;
  6615. m_xmlAttribute[attributeIndex].valueType = TagValueType.None;
  6616. m_xmlAttribute[attributeIndex].unitType = TagUnitType.Pixels;
  6617. m_xmlAttribute[attributeIndex].valueHashCode = 0;
  6618. m_xmlAttribute[attributeIndex].valueStartIndex = 0;
  6619. m_xmlAttribute[attributeIndex].valueLength = 0;
  6620. }
  6621. }
  6622. else if (tagValueType == TagValueType.StringValue)
  6623. {
  6624. // Compute HashCode value for the named tag.
  6625. if (unicode != '"')
  6626. {
  6627. m_xmlAttribute[attributeIndex].valueHashCode = (m_xmlAttribute[attributeIndex].valueHashCode << 5) + m_xmlAttribute[attributeIndex].valueHashCode ^ unicode;
  6628. m_xmlAttribute[attributeIndex].valueLength += 1;
  6629. }
  6630. else
  6631. {
  6632. attributeFlag = 2;
  6633. tagValueType = TagValueType.None;
  6634. tagUnitType = TagUnitType.Pixels;
  6635. attributeIndex += 1;
  6636. m_xmlAttribute[attributeIndex].nameHashCode = 0;
  6637. m_xmlAttribute[attributeIndex].valueType = TagValueType.None;
  6638. m_xmlAttribute[attributeIndex].unitType = TagUnitType.Pixels;
  6639. m_xmlAttribute[attributeIndex].valueHashCode = 0;
  6640. m_xmlAttribute[attributeIndex].valueStartIndex = 0;
  6641. m_xmlAttribute[attributeIndex].valueLength = 0;
  6642. }
  6643. }
  6644. }
  6645. }
  6646. if (unicode == '=') // '='
  6647. attributeFlag = 1;
  6648. // Compute HashCode for the name of the attribute
  6649. if (attributeFlag == 0 && unicode == ' ')
  6650. {
  6651. if (isTagSet) return false;
  6652. isTagSet = true;
  6653. attributeFlag = 2;
  6654. tagValueType = TagValueType.None;
  6655. tagUnitType = TagUnitType.Pixels;
  6656. attributeIndex += 1;
  6657. m_xmlAttribute[attributeIndex].nameHashCode = 0;
  6658. m_xmlAttribute[attributeIndex].valueType = TagValueType.None;
  6659. m_xmlAttribute[attributeIndex].unitType = TagUnitType.Pixels;
  6660. m_xmlAttribute[attributeIndex].valueHashCode = 0;
  6661. m_xmlAttribute[attributeIndex].valueStartIndex = 0;
  6662. m_xmlAttribute[attributeIndex].valueLength = 0;
  6663. }
  6664. if (attributeFlag == 0)
  6665. m_xmlAttribute[attributeIndex].nameHashCode = (m_xmlAttribute[attributeIndex].nameHashCode << 3) - m_xmlAttribute[attributeIndex].nameHashCode + unicode;
  6666. if (attributeFlag == 2 && unicode == ' ')
  6667. attributeFlag = 0;
  6668. }
  6669. if (!isValidHtmlTag)
  6670. {
  6671. return false;
  6672. }
  6673. //Debug.Log("Tag is [" + m_htmlTag.ArrayToString() + "]. Tag HashCode: " + m_xmlAttribute[0].nameHashCode + " Tag Value HashCode: " + m_xmlAttribute[0].valueHashCode + " Attribute 1 HashCode: " + m_xmlAttribute[1].nameHashCode + " Value HashCode: " + m_xmlAttribute[1].valueHashCode);
  6674. //for (int i = 0; i < attributeIndex; i++)
  6675. // Debug.Log("Tag [" + i + "] with HashCode: " + m_xmlAttribute[i].nameHashCode + " has value of [" + new string(m_htmlTag, m_xmlAttribute[i].valueStartIndex, m_xmlAttribute[i].valueLength) + "] Numerical Value: " + ConvertToFloat(m_htmlTag, m_xmlAttribute[i].valueStartIndex, m_xmlAttribute[i].valueLength));
  6676. #region Rich Text Tag Processing
  6677. #if !RICH_TEXT_ENABLED
  6678. // Special handling of the no parsing tag </noparse> </NOPARSE> tag
  6679. if (tag_NoParsing && (m_xmlAttribute[0].nameHashCode != 53822163 && m_xmlAttribute[0].nameHashCode != 49429939))
  6680. return false;
  6681. else if (m_xmlAttribute[0].nameHashCode == 53822163 || m_xmlAttribute[0].nameHashCode == 49429939)
  6682. {
  6683. tag_NoParsing = false;
  6684. return true;
  6685. }
  6686. // Color <#FFF> 3 Hex values (short form)
  6687. if (m_htmlTag[0] == 35 && tagCharCount == 4)
  6688. {
  6689. m_htmlColor = HexCharsToColor(m_htmlTag, tagCharCount);
  6690. m_colorStack.Add(m_htmlColor);
  6691. return true;
  6692. }
  6693. // Color <#FFF7> 4 Hex values with alpha (short form)
  6694. else if (m_htmlTag[0] == 35 && tagCharCount == 5)
  6695. {
  6696. m_htmlColor = HexCharsToColor(m_htmlTag, tagCharCount);
  6697. m_colorStack.Add(m_htmlColor);
  6698. return true;
  6699. }
  6700. // Color <#FF00FF>
  6701. else if (m_htmlTag[0] == 35 && tagCharCount == 7) // if Tag begins with # and contains 7 characters.
  6702. {
  6703. m_htmlColor = HexCharsToColor(m_htmlTag, tagCharCount);
  6704. m_colorStack.Add(m_htmlColor);
  6705. return true;
  6706. }
  6707. // Color <#FF00FF00> with alpha
  6708. else if (m_htmlTag[0] == 35 && tagCharCount == 9) // if Tag begins with # and contains 9 characters.
  6709. {
  6710. m_htmlColor = HexCharsToColor(m_htmlTag, tagCharCount);
  6711. m_colorStack.Add(m_htmlColor);
  6712. return true;
  6713. }
  6714. else
  6715. {
  6716. float value = 0;
  6717. switch (m_xmlAttribute[0].nameHashCode)
  6718. {
  6719. case 98: // <b>
  6720. case 66: // <B>
  6721. m_FontStyleInternal |= FontStyles.Bold;
  6722. m_fontStyleStack.Add(FontStyles.Bold);
  6723. m_FontWeightInternal = FontWeight.Bold;
  6724. return true;
  6725. case 427: // </b>
  6726. case 395: // </B>
  6727. if ((m_fontStyle & FontStyles.Bold) != FontStyles.Bold)
  6728. {
  6729. if (m_fontStyleStack.Remove(FontStyles.Bold) == 0)
  6730. {
  6731. m_FontStyleInternal &= ~FontStyles.Bold;
  6732. m_FontWeightInternal = m_FontWeightStack.Peek();
  6733. }
  6734. }
  6735. return true;
  6736. case 105: // <i>
  6737. case 73: // <I>
  6738. m_FontStyleInternal |= FontStyles.Italic;
  6739. m_fontStyleStack.Add(FontStyles.Italic);
  6740. if (m_xmlAttribute[1].nameHashCode == 276531 || m_xmlAttribute[1].nameHashCode == 186899)
  6741. {
  6742. m_ItalicAngle = (int)ConvertToFloat(m_htmlTag, m_xmlAttribute[1].valueStartIndex, m_xmlAttribute[1].valueLength);
  6743. // Make sure angle is within valid range.
  6744. if (m_ItalicAngle < -180 || m_ItalicAngle > 180) return false;
  6745. }
  6746. else
  6747. m_ItalicAngle = m_currentFontAsset.italicStyle;
  6748. m_ItalicAngleStack.Add(m_ItalicAngle);
  6749. return true;
  6750. case 434: // </i>
  6751. case 402: // </I>
  6752. if ((m_fontStyle & FontStyles.Italic) != FontStyles.Italic)
  6753. {
  6754. m_ItalicAngle = m_ItalicAngleStack.Remove();
  6755. if (m_fontStyleStack.Remove(FontStyles.Italic) == 0)
  6756. m_FontStyleInternal &= ~FontStyles.Italic;
  6757. }
  6758. return true;
  6759. case 115: // <s>
  6760. case 83: // <S>
  6761. m_FontStyleInternal |= FontStyles.Strikethrough;
  6762. m_fontStyleStack.Add(FontStyles.Strikethrough);
  6763. if (m_xmlAttribute[1].nameHashCode == 281955 || m_xmlAttribute[1].nameHashCode == 192323)
  6764. {
  6765. m_strikethroughColor = HexCharsToColor(m_htmlTag, m_xmlAttribute[1].valueStartIndex, m_xmlAttribute[1].valueLength);
  6766. m_strikethroughColor.a = m_htmlColor.a < m_strikethroughColor.a ? (byte)(m_htmlColor.a) : (byte)(m_strikethroughColor .a);
  6767. }
  6768. else
  6769. m_strikethroughColor = m_htmlColor;
  6770. m_strikethroughColorStack.Add(m_strikethroughColor);
  6771. return true;
  6772. case 444: // </s>
  6773. case 412: // </S>
  6774. if ((m_fontStyle & FontStyles.Strikethrough) != FontStyles.Strikethrough)
  6775. {
  6776. if (m_fontStyleStack.Remove(FontStyles.Strikethrough) == 0)
  6777. m_FontStyleInternal &= ~FontStyles.Strikethrough;
  6778. }
  6779. m_strikethroughColor = m_strikethroughColorStack.Remove();
  6780. return true;
  6781. case 117: // <u>
  6782. case 85: // <U>
  6783. m_FontStyleInternal |= FontStyles.Underline;
  6784. m_fontStyleStack.Add(FontStyles.Underline);
  6785. if (m_xmlAttribute[1].nameHashCode == 281955 || m_xmlAttribute[1].nameHashCode == 192323)
  6786. {
  6787. m_underlineColor = HexCharsToColor(m_htmlTag, m_xmlAttribute[1].valueStartIndex, m_xmlAttribute[1].valueLength);
  6788. m_underlineColor.a = m_htmlColor.a < m_underlineColor.a ? (byte)(m_htmlColor.a) : (byte)(m_underlineColor.a);
  6789. }
  6790. else
  6791. m_underlineColor = m_htmlColor;
  6792. m_underlineColorStack.Add(m_underlineColor);
  6793. return true;
  6794. case 446: // </u>
  6795. case 414: // </U>
  6796. if ((m_fontStyle & FontStyles.Underline) != FontStyles.Underline)
  6797. {
  6798. m_underlineColor = m_underlineColorStack.Remove();
  6799. if (m_fontStyleStack.Remove(FontStyles.Underline) == 0)
  6800. m_FontStyleInternal &= ~FontStyles.Underline;
  6801. }
  6802. m_underlineColor = m_underlineColorStack.Remove();
  6803. return true;
  6804. case 43045: // <mark=#FF00FF80>
  6805. case 30245: // <MARK>
  6806. m_FontStyleInternal |= FontStyles.Highlight;
  6807. m_fontStyleStack.Add(FontStyles.Highlight);
  6808. Color32 highlightColor = new Color32(255, 255, 0, 64);
  6809. TMP_Offset highlightPadding = TMP_Offset.zero;
  6810. // Handle Mark Tag and potential attributes
  6811. for (int i = 0; i < m_xmlAttribute.Length && m_xmlAttribute[i].nameHashCode != 0; i++)
  6812. {
  6813. int nameHashCode = m_xmlAttribute[i].nameHashCode;
  6814. switch (nameHashCode)
  6815. {
  6816. // Mark tag
  6817. case 43045:
  6818. case 30245:
  6819. if (m_xmlAttribute[i].valueType == TagValueType.ColorValue)
  6820. highlightColor = HexCharsToColor(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength);
  6821. break;
  6822. // Color attribute
  6823. case 281955:
  6824. highlightColor = HexCharsToColor(m_htmlTag, m_xmlAttribute[i].valueStartIndex, m_xmlAttribute[i].valueLength);
  6825. break;
  6826. // Padding attribute
  6827. case 15087385:
  6828. int paramCount = GetAttributeParameters(m_htmlTag, m_xmlAttribute[i].valueStartIndex, m_xmlAttribute[i].valueLength, ref m_attributeParameterValues);
  6829. if (paramCount != 4) return false;
  6830. highlightPadding = new TMP_Offset(m_attributeParameterValues[0], m_attributeParameterValues[1], m_attributeParameterValues[2], m_attributeParameterValues[3]);
  6831. highlightPadding *= m_fontSize * 0.01f * (m_isOrthographic ? 1 : 0.1f);
  6832. break;
  6833. }
  6834. }
  6835. highlightColor.a = m_htmlColor.a < highlightColor.a ? (byte)(m_htmlColor.a) : (byte)(highlightColor.a);
  6836. HighlightState state = new HighlightState(highlightColor, highlightPadding);
  6837. m_HighlightStateStack.Push(state);
  6838. return true;
  6839. case 155892: // </mark>
  6840. case 143092: // </MARK>
  6841. if ((m_fontStyle & FontStyles.Highlight) != FontStyles.Highlight)
  6842. {
  6843. m_HighlightStateStack.Remove();
  6844. if (m_fontStyleStack.Remove(FontStyles.Highlight) == 0)
  6845. m_FontStyleInternal &= ~FontStyles.Highlight;
  6846. }
  6847. return true;
  6848. case 6552: // <sub>
  6849. case 4728: // <SUB>
  6850. m_fontScaleMultiplier *= m_currentFontAsset.faceInfo.subscriptSize > 0 ? m_currentFontAsset.faceInfo.subscriptSize : 1;
  6851. m_baselineOffsetStack.Push(m_baselineOffset);
  6852. m_baselineOffset += m_currentFontAsset.faceInfo.subscriptOffset * m_fontScale * m_fontScaleMultiplier;
  6853. m_fontStyleStack.Add(FontStyles.Subscript);
  6854. m_FontStyleInternal |= FontStyles.Subscript;
  6855. return true;
  6856. case 22673: // </sub>
  6857. case 20849: // </SUB>
  6858. if ((m_FontStyleInternal & FontStyles.Subscript) == FontStyles.Subscript)
  6859. {
  6860. if (m_fontScaleMultiplier < 1)
  6861. {
  6862. //m_baselineOffset -= m_currentFontAsset.fontInfo.SubscriptOffset * m_fontScale * m_fontScaleMultiplier;
  6863. m_baselineOffset = m_baselineOffsetStack.Pop();
  6864. m_fontScaleMultiplier /= m_currentFontAsset.faceInfo.subscriptSize > 0 ? m_currentFontAsset.faceInfo.subscriptSize : 1;
  6865. }
  6866. if (m_fontStyleStack.Remove(FontStyles.Subscript) == 0)
  6867. m_FontStyleInternal &= ~FontStyles.Subscript;
  6868. }
  6869. return true;
  6870. case 6566: // <sup>
  6871. case 4742: // <SUP>
  6872. m_fontScaleMultiplier *= m_currentFontAsset.faceInfo.superscriptSize > 0 ? m_currentFontAsset.faceInfo.superscriptSize : 1;
  6873. m_baselineOffsetStack.Push(m_baselineOffset);
  6874. m_baselineOffset += m_currentFontAsset.faceInfo.superscriptOffset * m_fontScale * m_fontScaleMultiplier;
  6875. m_fontStyleStack.Add(FontStyles.Superscript);
  6876. m_FontStyleInternal |= FontStyles.Superscript;
  6877. return true;
  6878. case 22687: // </sup>
  6879. case 20863: // </SUP>
  6880. if ((m_FontStyleInternal & FontStyles.Superscript) == FontStyles.Superscript)
  6881. {
  6882. if (m_fontScaleMultiplier < 1)
  6883. {
  6884. //m_baselineOffset -= m_currentFontAsset.fontInfo.SuperscriptOffset * m_fontScale * m_fontScaleMultiplier;
  6885. m_baselineOffset = m_baselineOffsetStack.Pop();
  6886. m_fontScaleMultiplier /= m_currentFontAsset.faceInfo.superscriptSize > 0 ? m_currentFontAsset.faceInfo.superscriptSize : 1;
  6887. }
  6888. if (m_fontStyleStack.Remove(FontStyles.Superscript) == 0)
  6889. m_FontStyleInternal &= ~FontStyles.Superscript;
  6890. }
  6891. return true;
  6892. case -330774850: // <font-weight>
  6893. case 2012149182: // <FONT-WEIGHT>
  6894. value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength);
  6895. // Reject tag if value is invalid.
  6896. if (value == Int16.MinValue) return false;
  6897. switch ((int)value)
  6898. {
  6899. case 100:
  6900. m_FontWeightInternal = FontWeight.Thin;
  6901. break;
  6902. case 200:
  6903. m_FontWeightInternal = FontWeight.ExtraLight;
  6904. break;
  6905. case 300:
  6906. m_FontWeightInternal = FontWeight.Light;
  6907. break;
  6908. case 400:
  6909. m_FontWeightInternal = FontWeight.Regular;
  6910. break;
  6911. case 500:
  6912. m_FontWeightInternal = FontWeight.Medium;
  6913. break;
  6914. case 600:
  6915. m_FontWeightInternal = FontWeight.SemiBold;
  6916. break;
  6917. case 700:
  6918. m_FontWeightInternal = FontWeight.Bold;
  6919. break;
  6920. case 800:
  6921. m_FontWeightInternal = FontWeight.Heavy;
  6922. break;
  6923. case 900:
  6924. m_FontWeightInternal = FontWeight.Black;
  6925. break;
  6926. }
  6927. m_FontWeightStack.Add(m_FontWeightInternal);
  6928. return true;
  6929. case -1885698441: // </font-weight>
  6930. case 457225591: // </FONT-WEIGHT>
  6931. m_FontWeightStack.Remove();
  6932. if (m_FontStyleInternal == FontStyles.Bold)
  6933. m_FontWeightInternal = FontWeight.Bold;
  6934. else
  6935. m_FontWeightInternal = m_FontWeightStack.Peek();
  6936. return true;
  6937. case 6380: // <pos=000.00px> <pos=0em> <pos=50%>
  6938. case 4556: // <POS>
  6939. value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength);
  6940. // Reject tag if value is invalid.
  6941. if (value == Int16.MinValue) return false;
  6942. switch (tagUnitType)
  6943. {
  6944. case TagUnitType.Pixels:
  6945. m_xAdvance = value * (m_isOrthographic ? 1.0f : 0.1f);
  6946. //m_isIgnoringAlignment = true;
  6947. return true;
  6948. case TagUnitType.FontUnits:
  6949. m_xAdvance = value * m_currentFontSize * (m_isOrthographic ? 1.0f : 0.1f);
  6950. //m_isIgnoringAlignment = true;
  6951. return true;
  6952. case TagUnitType.Percentage:
  6953. m_xAdvance = m_marginWidth * value / 100;
  6954. //m_isIgnoringAlignment = true;
  6955. return true;
  6956. }
  6957. return false;
  6958. case 22501: // </pos>
  6959. case 20677: // </POS>
  6960. m_isIgnoringAlignment = false;
  6961. return true;
  6962. case 16034505: // <voffset>
  6963. case 11642281: // <VOFFSET>
  6964. value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength);
  6965. // Reject tag if value is invalid.
  6966. if (value == Int16.MinValue) return false;
  6967. switch (tagUnitType)
  6968. {
  6969. case TagUnitType.Pixels:
  6970. m_baselineOffset = value * (m_isOrthographic ? 1 : 0.1f);
  6971. return true;
  6972. case TagUnitType.FontUnits:
  6973. m_baselineOffset = value * (m_isOrthographic ? 1 : 0.1f) * m_currentFontSize;
  6974. return true;
  6975. case TagUnitType.Percentage:
  6976. //m_baselineOffset = m_marginHeight * val / 100;
  6977. return false;
  6978. }
  6979. return false;
  6980. case 54741026: // </voffset>
  6981. case 50348802: // </VOFFSET>
  6982. m_baselineOffset = 0;
  6983. return true;
  6984. case 43991: // <page>
  6985. case 31191: // <PAGE>
  6986. // This tag only works when Overflow - Page mode is used.
  6987. if (m_overflowMode == TextOverflowModes.Page)
  6988. {
  6989. m_xAdvance = 0 + tag_LineIndent + tag_Indent;
  6990. m_lineOffset = 0;
  6991. m_pageNumber += 1;
  6992. m_isNewPage = true;
  6993. }
  6994. return true;
  6995. // <BR> tag is now handled inline where it is replaced by a linefeed or \n.
  6996. //case 544: // <BR>
  6997. //case 800: // <br>
  6998. // m_forceLineBreak = true;
  6999. // return true;
  7000. case 43969: // <nobr>
  7001. case 31169: // <NOBR>
  7002. m_isNonBreakingSpace = true;
  7003. return true;
  7004. case 156816: // </nobr>
  7005. case 144016: // </NOBR>
  7006. m_isNonBreakingSpace = false;
  7007. return true;
  7008. case 45545: // <size=>
  7009. case 32745: // <SIZE>
  7010. value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength);
  7011. // Reject tag if value is invalid.
  7012. if (value == Int16.MinValue) return false;
  7013. switch (tagUnitType)
  7014. {
  7015. case TagUnitType.Pixels:
  7016. if (m_htmlTag[5] == 43) // <size=+00>
  7017. {
  7018. m_currentFontSize = m_fontSize + value;
  7019. m_sizeStack.Add(m_currentFontSize);
  7020. m_fontScale = (m_currentFontSize / m_currentFontAsset.faceInfo.pointSize * m_currentFontAsset.faceInfo.scale * (m_isOrthographic ? 1 : 0.1f));
  7021. return true;
  7022. }
  7023. else if (m_htmlTag[5] == 45) // <size=-00>
  7024. {
  7025. m_currentFontSize = m_fontSize + value;
  7026. m_sizeStack.Add(m_currentFontSize);
  7027. m_fontScale = (m_currentFontSize / m_currentFontAsset.faceInfo.pointSize * m_currentFontAsset.faceInfo.scale * (m_isOrthographic ? 1 : 0.1f));
  7028. return true;
  7029. }
  7030. else // <size=00.0>
  7031. {
  7032. m_currentFontSize = value;
  7033. m_sizeStack.Add(m_currentFontSize);
  7034. m_fontScale = (m_currentFontSize / m_currentFontAsset.faceInfo.pointSize * m_currentFontAsset.faceInfo.scale * (m_isOrthographic ? 1 : 0.1f));
  7035. return true;
  7036. }
  7037. case TagUnitType.FontUnits:
  7038. m_currentFontSize = m_fontSize * value;
  7039. m_sizeStack.Add(m_currentFontSize);
  7040. m_fontScale = (m_currentFontSize / m_currentFontAsset.faceInfo.pointSize * m_currentFontAsset.faceInfo.scale * (m_isOrthographic ? 1 : 0.1f));
  7041. return true;
  7042. case TagUnitType.Percentage:
  7043. m_currentFontSize = m_fontSize * value / 100;
  7044. m_sizeStack.Add(m_currentFontSize);
  7045. m_fontScale = (m_currentFontSize / m_currentFontAsset.faceInfo.pointSize * m_currentFontAsset.faceInfo.scale * (m_isOrthographic ? 1 : 0.1f));
  7046. return true;
  7047. }
  7048. return false;
  7049. case 158392: // </size>
  7050. case 145592: // </SIZE>
  7051. m_currentFontSize = m_sizeStack.Remove();
  7052. m_fontScale = (m_currentFontSize / m_currentFontAsset.faceInfo.pointSize * m_currentFontAsset.faceInfo.scale * (m_isOrthographic ? 1 : 0.1f));
  7053. return true;
  7054. case 41311: // <font=xx>
  7055. case 28511: // <FONT>
  7056. int fontHashCode = m_xmlAttribute[0].valueHashCode;
  7057. int materialAttributeHashCode = m_xmlAttribute[1].nameHashCode;
  7058. int materialHashCode = m_xmlAttribute[1].valueHashCode;
  7059. // Special handling for <font=default> or <font=Default>
  7060. if (fontHashCode == 764638571 || fontHashCode == 523367755)
  7061. {
  7062. m_currentFontAsset = m_materialReferences[0].fontAsset;
  7063. m_currentMaterial = m_materialReferences[0].material;
  7064. m_currentMaterialIndex = 0;
  7065. //Debug.Log("<font=Default> assigning Font Asset [" + m_currentFontAsset.name + "] with Material [" + m_currentMaterial.name + "].");
  7066. m_fontScale = (m_currentFontSize / m_currentFontAsset.faceInfo.pointSize * m_currentFontAsset.faceInfo.scale * (m_isOrthographic ? 1 : 0.1f));
  7067. m_materialReferenceStack.Add(m_materialReferences[0]);
  7068. return true;
  7069. }
  7070. TMP_FontAsset tempFont;
  7071. Material tempMaterial;
  7072. // HANDLE NEW FONT ASSET
  7073. //TMP_ResourceManager.TryGetFontAsset(fontHashCode, out tempFont);
  7074. // Check if we already have a reference to this font asset.
  7075. MaterialReferenceManager.TryGetFontAsset(fontHashCode, out tempFont);
  7076. // Try loading font asset from potential delegate or resources.
  7077. if (tempFont == null)
  7078. {
  7079. // Check for anyone registered to this callback
  7080. tempFont = OnFontAssetRequest?.Invoke(fontHashCode, new string(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength));
  7081. if (tempFont == null)
  7082. {
  7083. // Load Font Asset
  7084. tempFont = Resources.Load<TMP_FontAsset>(TMP_Settings.defaultFontAssetPath + new string(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength));
  7085. }
  7086. if (tempFont == null)
  7087. return false;
  7088. // Add new reference to the font asset as well as default material to the MaterialReferenceManager
  7089. MaterialReferenceManager.AddFontAsset(tempFont);
  7090. }
  7091. // HANDLE NEW MATERIAL
  7092. if (materialAttributeHashCode == 0 && materialHashCode == 0)
  7093. {
  7094. // No material specified then use default font asset material.
  7095. m_currentMaterial = tempFont.material;
  7096. m_currentMaterialIndex = MaterialReference.AddMaterialReference(m_currentMaterial, tempFont, m_materialReferences, m_materialReferenceIndexLookup);
  7097. m_materialReferenceStack.Add(m_materialReferences[m_currentMaterialIndex]);
  7098. }
  7099. else if (materialAttributeHashCode == 103415287 || materialAttributeHashCode == 72669687) // using material attribute
  7100. {
  7101. if (MaterialReferenceManager.TryGetMaterial(materialHashCode, out tempMaterial))
  7102. {
  7103. m_currentMaterial = tempMaterial;
  7104. m_currentMaterialIndex = MaterialReference.AddMaterialReference(m_currentMaterial, tempFont, m_materialReferences, m_materialReferenceIndexLookup);
  7105. m_materialReferenceStack.Add(m_materialReferences[m_currentMaterialIndex]);
  7106. }
  7107. else
  7108. {
  7109. // Load new material
  7110. tempMaterial = Resources.Load<Material>(TMP_Settings.defaultFontAssetPath + new string(m_htmlTag, m_xmlAttribute[1].valueStartIndex, m_xmlAttribute[1].valueLength));
  7111. if (tempMaterial == null)
  7112. return false;
  7113. // Add new reference to this material in the MaterialReferenceManager
  7114. MaterialReferenceManager.AddFontMaterial(materialHashCode, tempMaterial);
  7115. m_currentMaterial = tempMaterial;
  7116. m_currentMaterialIndex = MaterialReference.AddMaterialReference(m_currentMaterial, tempFont, m_materialReferences, m_materialReferenceIndexLookup);
  7117. m_materialReferenceStack.Add(m_materialReferences[m_currentMaterialIndex]);
  7118. }
  7119. }
  7120. else
  7121. return false;
  7122. m_currentFontAsset = tempFont;
  7123. m_fontScale = (m_currentFontSize / m_currentFontAsset.faceInfo.pointSize * m_currentFontAsset.faceInfo.scale * (m_isOrthographic ? 1 : 0.1f));
  7124. return true;
  7125. case 154158: // </font>
  7126. case 141358: // </FONT>
  7127. {
  7128. MaterialReference materialReference = m_materialReferenceStack.Remove();
  7129. m_currentFontAsset = materialReference.fontAsset;
  7130. m_currentMaterial = materialReference.material;
  7131. m_currentMaterialIndex = materialReference.index;
  7132. m_fontScale = (m_currentFontSize / m_currentFontAsset.faceInfo.pointSize * m_currentFontAsset.faceInfo.scale * (m_isOrthographic ? 1 : 0.1f));
  7133. return true;
  7134. }
  7135. case 103415287: // <material="material name">
  7136. case 72669687: // <MATERIAL>
  7137. materialHashCode = m_xmlAttribute[0].valueHashCode;
  7138. // Special handling for <material=default> or <material=Default>
  7139. if (materialHashCode == 764638571 || materialHashCode == 523367755)
  7140. {
  7141. // Check if material font atlas texture matches that of the current font asset.
  7142. //if (m_currentFontAsset.atlas.GetInstanceID() != m_currentMaterial.GetTexture(ShaderUtilities.ID_MainTex).GetInstanceID()) return false;
  7143. m_currentMaterial = m_materialReferences[0].material;
  7144. m_currentMaterialIndex = 0;
  7145. m_materialReferenceStack.Add(m_materialReferences[0]);
  7146. return true;
  7147. }
  7148. // Check if material
  7149. if (MaterialReferenceManager.TryGetMaterial(materialHashCode, out tempMaterial))
  7150. {
  7151. // Check if material font atlas texture matches that of the current font asset.
  7152. //if (m_currentFontAsset.atlas.GetInstanceID() != tempMaterial.GetTexture(ShaderUtilities.ID_MainTex).GetInstanceID()) return false;
  7153. m_currentMaterial = tempMaterial;
  7154. m_currentMaterialIndex = MaterialReference.AddMaterialReference(m_currentMaterial, m_currentFontAsset, m_materialReferences, m_materialReferenceIndexLookup);
  7155. m_materialReferenceStack.Add(m_materialReferences[m_currentMaterialIndex]);
  7156. }
  7157. else
  7158. {
  7159. // Load new material
  7160. tempMaterial = Resources.Load<Material>(TMP_Settings.defaultFontAssetPath + new string(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength));
  7161. if (tempMaterial == null)
  7162. return false;
  7163. // Check if material font atlas texture matches that of the current font asset.
  7164. //if (m_currentFontAsset.atlas.GetInstanceID() != tempMaterial.GetTexture(ShaderUtilities.ID_MainTex).GetInstanceID()) return false;
  7165. // Add new reference to this material in the MaterialReferenceManager
  7166. MaterialReferenceManager.AddFontMaterial(materialHashCode, tempMaterial);
  7167. m_currentMaterial = tempMaterial;
  7168. m_currentMaterialIndex = MaterialReference.AddMaterialReference(m_currentMaterial, m_currentFontAsset , m_materialReferences, m_materialReferenceIndexLookup);
  7169. m_materialReferenceStack.Add(m_materialReferences[m_currentMaterialIndex]);
  7170. }
  7171. return true;
  7172. case 374360934: // </material>
  7173. case 343615334: // </MATERIAL>
  7174. {
  7175. //if (m_currentMaterial.GetTexture(ShaderUtilities.ID_MainTex).GetInstanceID() != m_materialReferenceStack.PreviousItem().material.GetTexture(ShaderUtilities.ID_MainTex).GetInstanceID())
  7176. // return false;
  7177. MaterialReference materialReference = m_materialReferenceStack.Remove();
  7178. m_currentMaterial = materialReference.material;
  7179. m_currentMaterialIndex = materialReference.index;
  7180. return true;
  7181. }
  7182. case 320078: // <space=000.00>
  7183. case 230446: // <SPACE>
  7184. value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength);
  7185. // Reject tag if value is invalid.
  7186. if (value == Int16.MinValue) return false;
  7187. switch (tagUnitType)
  7188. {
  7189. case TagUnitType.Pixels:
  7190. m_xAdvance += value * (m_isOrthographic ? 1 : 0.1f);
  7191. return true;
  7192. case TagUnitType.FontUnits:
  7193. m_xAdvance += value * (m_isOrthographic ? 1 : 0.1f) * m_currentFontSize;
  7194. return true;
  7195. case TagUnitType.Percentage:
  7196. // Not applicable
  7197. return false;
  7198. }
  7199. return false;
  7200. case 276254: // <alpha=#FF>
  7201. case 186622: // <ALPHA>
  7202. if (m_xmlAttribute[0].valueLength != 3) return false;
  7203. m_htmlColor.a = (byte)(HexToInt(m_htmlTag[7]) * 16 + HexToInt(m_htmlTag[8]));
  7204. return true;
  7205. case 1750458: // <a name=" ">
  7206. return false;
  7207. case 426: // </a>
  7208. return true;
  7209. case 43066: // <link="name">
  7210. case 30266: // <LINK>
  7211. if (m_isParsingText && !m_isCalculatingPreferredValues)
  7212. {
  7213. int index = m_textInfo.linkCount;
  7214. if (index + 1 > m_textInfo.linkInfo.Length)
  7215. TMP_TextInfo.Resize(ref m_textInfo.linkInfo, index + 1);
  7216. m_textInfo.linkInfo[index].textComponent = this;
  7217. m_textInfo.linkInfo[index].hashCode = m_xmlAttribute[0].valueHashCode;
  7218. m_textInfo.linkInfo[index].linkTextfirstCharacterIndex = m_characterCount;
  7219. m_textInfo.linkInfo[index].linkIdFirstCharacterIndex = startIndex + m_xmlAttribute[0].valueStartIndex;
  7220. m_textInfo.linkInfo[index].linkIdLength = m_xmlAttribute[0].valueLength;
  7221. m_textInfo.linkInfo[index].SetLinkID(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength);
  7222. }
  7223. return true;
  7224. case 155913: // </link>
  7225. case 143113: // </LINK>
  7226. if (m_isParsingText && !m_isCalculatingPreferredValues)
  7227. {
  7228. if (m_textInfo.linkCount < m_textInfo.linkInfo.Length)
  7229. {
  7230. m_textInfo.linkInfo[m_textInfo.linkCount].linkTextLength = m_characterCount - m_textInfo.linkInfo[m_textInfo.linkCount].linkTextfirstCharacterIndex;
  7231. m_textInfo.linkCount += 1;
  7232. }
  7233. }
  7234. return true;
  7235. case 275917: // <align=>
  7236. case 186285: // <ALIGN>
  7237. switch (m_xmlAttribute[0].valueHashCode)
  7238. {
  7239. case 3774683: // <align=left>
  7240. m_lineJustification = HorizontalAlignmentOptions.Left;
  7241. m_lineJustificationStack.Add(m_lineJustification);
  7242. return true;
  7243. case 136703040: // <align=right>
  7244. m_lineJustification = HorizontalAlignmentOptions.Right;
  7245. m_lineJustificationStack.Add(m_lineJustification);
  7246. return true;
  7247. case -458210101: // <align=center>
  7248. m_lineJustification = HorizontalAlignmentOptions.Center;
  7249. m_lineJustificationStack.Add(m_lineJustification);
  7250. return true;
  7251. case -523808257: // <align=justified>
  7252. m_lineJustification = HorizontalAlignmentOptions.Justified;
  7253. m_lineJustificationStack.Add(m_lineJustification);
  7254. return true;
  7255. case 122383428: // <align=flush>
  7256. m_lineJustification = HorizontalAlignmentOptions.Flush;
  7257. m_lineJustificationStack.Add(m_lineJustification);
  7258. return true;
  7259. }
  7260. return false;
  7261. case 1065846: // </align>
  7262. case 976214: // </ALIGN>
  7263. m_lineJustification = m_lineJustificationStack.Remove();
  7264. return true;
  7265. case 327550: // <width=xx>
  7266. case 237918: // <WIDTH>
  7267. value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength);
  7268. // Reject tag if value is invalid.
  7269. if (value == Int16.MinValue) return false;
  7270. switch (tagUnitType)
  7271. {
  7272. case TagUnitType.Pixels:
  7273. m_width = value * (m_isOrthographic ? 1 : 0.1f);
  7274. break;
  7275. case TagUnitType.FontUnits:
  7276. return false;
  7277. //break;
  7278. case TagUnitType.Percentage:
  7279. m_width = m_marginWidth * value / 100;
  7280. break;
  7281. }
  7282. return true;
  7283. case 1117479: // </width>
  7284. case 1027847: // </WIDTH>
  7285. m_width = -1;
  7286. return true;
  7287. // STYLE tag is now handled inline and replaced by its definition.
  7288. //case 322689: // <style="name">
  7289. //case 233057: // <STYLE>
  7290. // TMP_Style style = TMP_StyleSheet.GetStyle(m_xmlAttribute[0].valueHashCode);
  7291. // if (style == null) return false;
  7292. // m_styleStack.Add(style.hashCode);
  7293. // // Parse Style Macro
  7294. // for (int i = 0; i < style.styleOpeningTagArray.Length; i++)
  7295. // {
  7296. // if (style.styleOpeningTagArray[i] == 60)
  7297. // {
  7298. // if (ValidateHtmlTag(style.styleOpeningTagArray, i + 1, out i) == false) return false;
  7299. // }
  7300. // }
  7301. // return true;
  7302. //case 1112618: // </style>
  7303. //case 1022986: // </STYLE>
  7304. // style = TMP_StyleSheet.GetStyle(m_xmlAttribute[0].valueHashCode);
  7305. // if (style == null)
  7306. // {
  7307. // // Get style from the Style Stack
  7308. // int styleHashCode = m_styleStack.CurrentItem();
  7309. // style = TMP_StyleSheet.GetStyle(styleHashCode);
  7310. // m_styleStack.Remove();
  7311. // }
  7312. // if (style == null) return false;
  7313. // //// Parse Style Macro
  7314. // for (int i = 0; i < style.styleClosingTagArray.Length; i++)
  7315. // {
  7316. // if (style.styleClosingTagArray[i] == 60)
  7317. // ValidateHtmlTag(style.styleClosingTagArray, i + 1, out i);
  7318. // }
  7319. // return true;
  7320. case 281955: // <color> <color=#FF00FF> or <color=#FF00FF00>
  7321. case 192323: // <COLOR=#FF00FF>
  7322. // <color=#FFF> 3 Hex (short hand)
  7323. if (m_htmlTag[6] == 35 && tagCharCount == 10)
  7324. {
  7325. m_htmlColor = HexCharsToColor(m_htmlTag, tagCharCount);
  7326. m_colorStack.Add(m_htmlColor);
  7327. return true;
  7328. }
  7329. // <color=#FFF7> 4 Hex (short hand)
  7330. else if (m_htmlTag[6] == 35 && tagCharCount == 11)
  7331. {
  7332. m_htmlColor = HexCharsToColor(m_htmlTag, tagCharCount);
  7333. m_colorStack.Add(m_htmlColor);
  7334. return true;
  7335. }
  7336. // <color=#FF00FF> 3 Hex pairs
  7337. if (m_htmlTag[6] == 35 && tagCharCount == 13)
  7338. {
  7339. m_htmlColor = HexCharsToColor(m_htmlTag, tagCharCount);
  7340. m_colorStack.Add(m_htmlColor);
  7341. return true;
  7342. }
  7343. // <color=#FF00FF00> 4 Hex pairs
  7344. else if (m_htmlTag[6] == 35 && tagCharCount == 15)
  7345. {
  7346. m_htmlColor = HexCharsToColor(m_htmlTag, tagCharCount);
  7347. m_colorStack.Add(m_htmlColor);
  7348. return true;
  7349. }
  7350. // <color=name>
  7351. switch (m_xmlAttribute[0].valueHashCode)
  7352. {
  7353. case 125395: // <color=red>
  7354. m_htmlColor = Color.red;
  7355. m_colorStack.Add(m_htmlColor);
  7356. return true;
  7357. case -992792864: // <color=lightblue>
  7358. m_htmlColor = new Color32(173, 216, 230, 255);
  7359. m_colorStack.Add(m_htmlColor);
  7360. return true;
  7361. case 3573310: // <color=blue>
  7362. m_htmlColor = Color.blue;
  7363. m_colorStack.Add(m_htmlColor);
  7364. return true;
  7365. case 3680713: // <color=grey>
  7366. m_htmlColor = new Color32(128, 128, 128, 255);
  7367. m_colorStack.Add(m_htmlColor);
  7368. return true;
  7369. case 117905991: // <color=black>
  7370. m_htmlColor = Color.black;
  7371. m_colorStack.Add(m_htmlColor);
  7372. return true;
  7373. case 121463835: // <color=green>
  7374. m_htmlColor = Color.green;
  7375. m_colorStack.Add(m_htmlColor);
  7376. return true;
  7377. case 140357351: // <color=white>
  7378. m_htmlColor = Color.white;
  7379. m_colorStack.Add(m_htmlColor);
  7380. return true;
  7381. case 26556144: // <color=orange>
  7382. m_htmlColor = new Color32(255, 128, 0, 255);
  7383. m_colorStack.Add(m_htmlColor);
  7384. return true;
  7385. case -36881330: // <color=purple>
  7386. m_htmlColor = new Color32(160, 32, 240, 255);
  7387. m_colorStack.Add(m_htmlColor);
  7388. return true;
  7389. case 554054276: // <color=yellow>
  7390. m_htmlColor = Color.yellow;
  7391. m_colorStack.Add(m_htmlColor);
  7392. return true;
  7393. }
  7394. return false;
  7395. case 100149144: //<gradient>
  7396. case 69403544: // <GRADIENT>
  7397. int gradientPresetHashCode = m_xmlAttribute[0].valueHashCode;
  7398. TMP_ColorGradient tempColorGradientPreset;
  7399. // Check if Color Gradient Preset has already been loaded.
  7400. if (MaterialReferenceManager.TryGetColorGradientPreset(gradientPresetHashCode, out tempColorGradientPreset))
  7401. {
  7402. m_colorGradientPreset = tempColorGradientPreset;
  7403. }
  7404. else
  7405. {
  7406. // Load Color Gradient Preset
  7407. if (tempColorGradientPreset == null)
  7408. {
  7409. tempColorGradientPreset = Resources.Load<TMP_ColorGradient>(TMP_Settings.defaultColorGradientPresetsPath + new string(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength));
  7410. }
  7411. if (tempColorGradientPreset == null)
  7412. return false;
  7413. MaterialReferenceManager.AddColorGradientPreset(gradientPresetHashCode, tempColorGradientPreset);
  7414. m_colorGradientPreset = tempColorGradientPreset;
  7415. }
  7416. m_colorGradientPresetIsTinted = false;
  7417. // Check Attributes
  7418. for (int i = 1; i < m_xmlAttribute.Length && m_xmlAttribute[i].nameHashCode != 0; i++)
  7419. {
  7420. // Get attribute name
  7421. int nameHashCode = m_xmlAttribute[i].nameHashCode;
  7422. switch (nameHashCode)
  7423. {
  7424. case 45819: // tint
  7425. case 33019: // TINT
  7426. m_colorGradientPresetIsTinted = ConvertToFloat(m_htmlTag, m_xmlAttribute[i].valueStartIndex, m_xmlAttribute[i].valueLength) != 0;
  7427. break;
  7428. }
  7429. }
  7430. m_colorGradientStack.Add(m_colorGradientPreset);
  7431. // TODO : Add support for defining preset in the tag itself
  7432. return true;
  7433. case 371094791: // </gradient>
  7434. case 340349191: // </GRADIENT>
  7435. m_colorGradientPreset = m_colorGradientStack.Remove();
  7436. return true;
  7437. case 1983971: // <cspace=xx.x>
  7438. case 1356515: // <CSPACE>
  7439. value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength);
  7440. // Reject tag if value is invalid.
  7441. if (value == Int16.MinValue) return false;
  7442. switch (tagUnitType)
  7443. {
  7444. case TagUnitType.Pixels:
  7445. m_cSpacing = value * (m_isOrthographic ? 1 : 0.1f);
  7446. break;
  7447. case TagUnitType.FontUnits:
  7448. m_cSpacing = value * (m_isOrthographic ? 1 : 0.1f) * m_currentFontSize;
  7449. break;
  7450. case TagUnitType.Percentage:
  7451. return false;
  7452. }
  7453. return true;
  7454. case 7513474: // </cspace>
  7455. case 6886018: // </CSPACE>
  7456. if (!m_isParsingText) return true;
  7457. // Adjust xAdvance to remove extra space from last character.
  7458. if (m_characterCount > 0)
  7459. {
  7460. m_xAdvance -= m_cSpacing;
  7461. m_textInfo.characterInfo[m_characterCount - 1].xAdvance = m_xAdvance;
  7462. }
  7463. m_cSpacing = 0;
  7464. return true;
  7465. case 2152041: // <mspace=xx.x>
  7466. case 1524585: // <MSPACE>
  7467. value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength);
  7468. // Reject tag if value is invalid.
  7469. if (value == Int16.MinValue) return false;
  7470. switch (tagUnitType)
  7471. {
  7472. case TagUnitType.Pixels:
  7473. m_monoSpacing = value * (m_isOrthographic ? 1 : 0.1f);
  7474. break;
  7475. case TagUnitType.FontUnits:
  7476. m_monoSpacing = value * (m_isOrthographic ? 1 : 0.1f) * m_currentFontSize;
  7477. break;
  7478. case TagUnitType.Percentage:
  7479. return false;
  7480. }
  7481. return true;
  7482. case 7681544: // </mspace>
  7483. case 7054088: // </MSPACE>
  7484. m_monoSpacing = 0;
  7485. return true;
  7486. case 280416: // <class="name">
  7487. return false;
  7488. case 1071884: // </color>
  7489. case 982252: // </COLOR>
  7490. m_htmlColor = m_colorStack.Remove();
  7491. return true;
  7492. case 2068980: // <indent=10px> <indent=10em> <indent=50%>
  7493. case 1441524: // <INDENT>
  7494. value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength);
  7495. // Reject tag if value is invalid.
  7496. if (value == Int16.MinValue) return false;
  7497. switch (tagUnitType)
  7498. {
  7499. case TagUnitType.Pixels:
  7500. tag_Indent = value * (m_isOrthographic ? 1 : 0.1f);
  7501. break;
  7502. case TagUnitType.FontUnits:
  7503. tag_Indent = value * (m_isOrthographic ? 1 : 0.1f) * m_currentFontSize;
  7504. break;
  7505. case TagUnitType.Percentage:
  7506. tag_Indent = m_marginWidth * value / 100;
  7507. break;
  7508. }
  7509. m_indentStack.Add(tag_Indent);
  7510. m_xAdvance = tag_Indent;
  7511. return true;
  7512. case 7598483: // </indent>
  7513. case 6971027: // </INDENT>
  7514. tag_Indent = m_indentStack.Remove();
  7515. //m_xAdvance = tag_Indent;
  7516. return true;
  7517. case 1109386397: // <line-indent>
  7518. case -842656867: // <LINE-INDENT>
  7519. value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength);
  7520. // Reject tag if value is invalid.
  7521. if (value == Int16.MinValue) return false;
  7522. switch (tagUnitType)
  7523. {
  7524. case TagUnitType.Pixels:
  7525. tag_LineIndent = value * (m_isOrthographic ? 1 : 0.1f);
  7526. break;
  7527. case TagUnitType.FontUnits:
  7528. tag_LineIndent = value * (m_isOrthographic ? 1 : 0.1f) * m_currentFontSize;
  7529. break;
  7530. case TagUnitType.Percentage:
  7531. tag_LineIndent = m_marginWidth * value / 100;
  7532. break;
  7533. }
  7534. m_xAdvance += tag_LineIndent;
  7535. return true;
  7536. case -445537194: // </line-indent>
  7537. case 1897386838: // </LINE-INDENT>
  7538. tag_LineIndent = 0;
  7539. return true;
  7540. case 2246877: // <sprite=x>
  7541. case 1619421: // <SPRITE>
  7542. int spriteAssetHashCode = m_xmlAttribute[0].valueHashCode;
  7543. TMP_SpriteAsset tempSpriteAsset;
  7544. m_spriteIndex = -1;
  7545. // CHECK TAG FORMAT
  7546. if (m_xmlAttribute[0].valueType == TagValueType.None || m_xmlAttribute[0].valueType == TagValueType.NumericalValue)
  7547. {
  7548. // No Sprite Asset is assigned to the text object
  7549. if (m_spriteAsset != null)
  7550. {
  7551. m_currentSpriteAsset = m_spriteAsset;
  7552. }
  7553. else if (m_defaultSpriteAsset != null)
  7554. {
  7555. m_currentSpriteAsset = m_defaultSpriteAsset;
  7556. }
  7557. else if (m_defaultSpriteAsset == null)
  7558. {
  7559. if (TMP_Settings.defaultSpriteAsset != null)
  7560. m_defaultSpriteAsset = TMP_Settings.defaultSpriteAsset;
  7561. else
  7562. m_defaultSpriteAsset = Resources.Load<TMP_SpriteAsset>("Sprite Assets/Default Sprite Asset");
  7563. m_currentSpriteAsset = m_defaultSpriteAsset;
  7564. }
  7565. // No valid sprite asset available
  7566. if (m_currentSpriteAsset == null)
  7567. return false;
  7568. }
  7569. else
  7570. {
  7571. // A Sprite Asset has been specified
  7572. if (MaterialReferenceManager.TryGetSpriteAsset(spriteAssetHashCode, out tempSpriteAsset))
  7573. {
  7574. m_currentSpriteAsset = tempSpriteAsset;
  7575. }
  7576. else
  7577. {
  7578. // Load Sprite Asset
  7579. if (tempSpriteAsset == null)
  7580. {
  7581. //
  7582. tempSpriteAsset = OnSpriteAssetRequest?.Invoke(spriteAssetHashCode, new string(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength));
  7583. if (tempSpriteAsset == null)
  7584. tempSpriteAsset = Resources.Load<TMP_SpriteAsset>(TMP_Settings.defaultSpriteAssetPath + new string(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength));
  7585. }
  7586. if (tempSpriteAsset == null)
  7587. return false;
  7588. //Debug.Log("Loading & assigning new Sprite Asset: " + tempSpriteAsset.name);
  7589. MaterialReferenceManager.AddSpriteAsset(spriteAssetHashCode, tempSpriteAsset);
  7590. m_currentSpriteAsset = tempSpriteAsset;
  7591. }
  7592. }
  7593. // Handling of <sprite=index> legacy tag format.
  7594. if (m_xmlAttribute[0].valueType == TagValueType.NumericalValue) // <sprite=index>
  7595. {
  7596. int index = (int)ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength);
  7597. // Reject tag if value is invalid.
  7598. if (index == Int16.MinValue) return false;
  7599. // Check to make sure sprite index is valid
  7600. if (index > m_currentSpriteAsset.spriteCharacterTable.Count - 1) return false;
  7601. m_spriteIndex = index;
  7602. }
  7603. m_spriteColor = s_colorWhite;
  7604. m_tintSprite = false;
  7605. // Handle Sprite Tag Attributes
  7606. for (int i = 0; i < m_xmlAttribute.Length && m_xmlAttribute[i].nameHashCode != 0; i++)
  7607. {
  7608. //Debug.Log("Attribute[" + i + "].nameHashCode=" + m_xmlAttribute[i].nameHashCode + " Value:" + ConvertToFloat(m_htmlTag, m_xmlAttribute[i].valueStartIndex, m_xmlAttribute[i].valueLength));
  7609. int nameHashCode = m_xmlAttribute[i].nameHashCode;
  7610. int index = 0;
  7611. switch (nameHashCode)
  7612. {
  7613. case 43347: // <sprite name="">
  7614. case 30547: // <SPRITE NAME="">
  7615. m_currentSpriteAsset = TMP_SpriteAsset.SearchForSpriteByHashCode(m_currentSpriteAsset, m_xmlAttribute[i].valueHashCode, true, out index);
  7616. if (index == -1) return false;
  7617. m_spriteIndex = index;
  7618. break;
  7619. case 295562: // <sprite index=>
  7620. case 205930: // <SPRITE INDEX=>
  7621. index = (int)ConvertToFloat(m_htmlTag, m_xmlAttribute[1].valueStartIndex, m_xmlAttribute[1].valueLength);
  7622. // Reject tag if value is invalid.
  7623. if (index == Int16.MinValue) return false;
  7624. // Check to make sure sprite index is valid
  7625. if (index > m_currentSpriteAsset.spriteCharacterTable.Count - 1) return false;
  7626. m_spriteIndex = index;
  7627. break;
  7628. case 45819: // tint
  7629. case 33019: // TINT
  7630. m_tintSprite = ConvertToFloat(m_htmlTag, m_xmlAttribute[i].valueStartIndex, m_xmlAttribute[i].valueLength) != 0;
  7631. break;
  7632. case 281955: // color=#FF00FF80
  7633. case 192323: // COLOR
  7634. m_spriteColor = HexCharsToColor(m_htmlTag, m_xmlAttribute[i].valueStartIndex, m_xmlAttribute[i].valueLength);
  7635. break;
  7636. case 39505: // anim="0,16,12" start, end, fps
  7637. case 26705: // ANIM
  7638. //Debug.Log("Start: " + m_xmlAttribute[i].valueStartIndex + " Length: " + m_xmlAttribute[i].valueLength);
  7639. int paramCount = GetAttributeParameters(m_htmlTag, m_xmlAttribute[i].valueStartIndex, m_xmlAttribute[i].valueLength, ref m_attributeParameterValues);
  7640. if (paramCount != 3) return false;
  7641. m_spriteIndex = (int)m_attributeParameterValues[0];
  7642. if (m_isParsingText)
  7643. {
  7644. // TODO : fix this!
  7645. //if (m_attributeParameterValues[0] > m_currentSpriteAsset.spriteInfoList.Count - 1 || m_attributeParameterValues[1] > m_currentSpriteAsset.spriteInfoList.Count - 1)
  7646. // return false;
  7647. spriteAnimator.DoSpriteAnimation(m_characterCount, m_currentSpriteAsset, m_spriteIndex, (int)m_attributeParameterValues[1], (int)m_attributeParameterValues[2]);
  7648. }
  7649. break;
  7650. //case 45545: // size
  7651. //case 32745: // SIZE
  7652. // break;
  7653. default:
  7654. if (nameHashCode != 2246877 && nameHashCode != 1619421)
  7655. return false;
  7656. break;
  7657. }
  7658. }
  7659. if (m_spriteIndex == -1) return false;
  7660. // Material HashCode for the Sprite Asset is the Sprite Asset Hash Code
  7661. m_currentMaterialIndex = MaterialReference.AddMaterialReference(m_currentSpriteAsset.material, m_currentSpriteAsset, m_materialReferences, m_materialReferenceIndexLookup);
  7662. m_textElementType = TMP_TextElementType.Sprite;
  7663. return true;
  7664. case 730022849: // <lowercase>
  7665. case 514803617: // <LOWERCASE>
  7666. m_FontStyleInternal |= FontStyles.LowerCase;
  7667. m_fontStyleStack.Add(FontStyles.LowerCase);
  7668. return true;
  7669. case -1668324918: // </lowercase>
  7670. case -1883544150: // </LOWERCASE>
  7671. if ((m_fontStyle & FontStyles.LowerCase) != FontStyles.LowerCase)
  7672. {
  7673. if (m_fontStyleStack.Remove(FontStyles.LowerCase) == 0)
  7674. m_FontStyleInternal &= ~FontStyles.LowerCase;
  7675. }
  7676. return true;
  7677. case 13526026: // <allcaps>
  7678. case 9133802: // <ALLCAPS>
  7679. case 781906058: // <uppercase>
  7680. case 566686826: // <UPPERCASE>
  7681. m_FontStyleInternal |= FontStyles.UpperCase;
  7682. m_fontStyleStack.Add(FontStyles.UpperCase);
  7683. return true;
  7684. case 52232547: // </allcaps>
  7685. case 47840323: // </ALLCAPS>
  7686. case -1616441709: // </uppercase>
  7687. case -1831660941: // </UPPERCASE>
  7688. if ((m_fontStyle & FontStyles.UpperCase) != FontStyles.UpperCase)
  7689. {
  7690. if (m_fontStyleStack.Remove(FontStyles.UpperCase) == 0)
  7691. m_FontStyleInternal &= ~FontStyles.UpperCase;
  7692. }
  7693. return true;
  7694. case 766244328: // <smallcaps>
  7695. case 551025096: // <SMALLCAPS>
  7696. m_FontStyleInternal |= FontStyles.SmallCaps;
  7697. m_fontStyleStack.Add(FontStyles.SmallCaps);
  7698. return true;
  7699. case -1632103439: // </smallcaps>
  7700. case -1847322671: // </SMALLCAPS>
  7701. if ((m_fontStyle & FontStyles.SmallCaps) != FontStyles.SmallCaps)
  7702. {
  7703. if (m_fontStyleStack.Remove(FontStyles.SmallCaps) == 0)
  7704. m_FontStyleInternal &= ~FontStyles.SmallCaps;
  7705. }
  7706. return true;
  7707. case 2109854: // <margin=00.0> <margin=00em> <margin=50%>
  7708. case 1482398: // <MARGIN>
  7709. // Check value type
  7710. switch (m_xmlAttribute[0].valueType)
  7711. {
  7712. case TagValueType.NumericalValue:
  7713. value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength); // px
  7714. // Reject tag if value is invalid.
  7715. if (value == Int16.MinValue) return false;
  7716. // Determine tag unit type
  7717. switch (tagUnitType)
  7718. {
  7719. case TagUnitType.Pixels:
  7720. m_marginLeft = value * (m_isOrthographic ? 1 : 0.1f);
  7721. break;
  7722. case TagUnitType.FontUnits:
  7723. m_marginLeft = value * (m_isOrthographic ? 1 : 0.1f) * m_currentFontSize;
  7724. break;
  7725. case TagUnitType.Percentage:
  7726. m_marginLeft = (m_marginWidth - (m_width != -1 ? m_width : 0)) * value / 100;
  7727. break;
  7728. }
  7729. m_marginLeft = m_marginLeft >= 0 ? m_marginLeft : 0;
  7730. m_marginRight = m_marginLeft;
  7731. return true;
  7732. case TagValueType.None:
  7733. for (int i = 1; i < m_xmlAttribute.Length && m_xmlAttribute[i].nameHashCode != 0; i++)
  7734. {
  7735. // Get attribute name
  7736. int nameHashCode = m_xmlAttribute[i].nameHashCode;
  7737. switch (nameHashCode)
  7738. {
  7739. case 42823: // <margin left=value>
  7740. value = ConvertToFloat(m_htmlTag, m_xmlAttribute[i].valueStartIndex, m_xmlAttribute[i].valueLength); // px
  7741. // Reject tag if value is invalid.
  7742. if (value == Int16.MinValue) return false;
  7743. switch (m_xmlAttribute[i].unitType)
  7744. {
  7745. case TagUnitType.Pixels:
  7746. m_marginLeft = value * (m_isOrthographic ? 1 : 0.1f);
  7747. break;
  7748. case TagUnitType.FontUnits:
  7749. m_marginLeft = value * (m_isOrthographic ? 1 : 0.1f) * m_currentFontSize;
  7750. break;
  7751. case TagUnitType.Percentage:
  7752. m_marginLeft = (m_marginWidth - (m_width != -1 ? m_width : 0)) * value / 100;
  7753. break;
  7754. }
  7755. m_marginLeft = m_marginLeft >= 0 ? m_marginLeft : 0;
  7756. break;
  7757. case 315620: // <margin right=value>
  7758. value = ConvertToFloat(m_htmlTag, m_xmlAttribute[i].valueStartIndex, m_xmlAttribute[i].valueLength); // px
  7759. // Reject tag if value is invalid.
  7760. if (value == Int16.MinValue) return false;
  7761. switch (m_xmlAttribute[i].unitType)
  7762. {
  7763. case TagUnitType.Pixels:
  7764. m_marginRight = value * (m_isOrthographic ? 1 : 0.1f);
  7765. break;
  7766. case TagUnitType.FontUnits:
  7767. m_marginRight = value * (m_isOrthographic ? 1 : 0.1f) * m_currentFontSize;
  7768. break;
  7769. case TagUnitType.Percentage:
  7770. m_marginRight = (m_marginWidth - (m_width != -1 ? m_width : 0)) * value / 100;
  7771. break;
  7772. }
  7773. m_marginRight = m_marginRight >= 0 ? m_marginRight : 0;
  7774. break;
  7775. }
  7776. }
  7777. return true;
  7778. }
  7779. return false;
  7780. case 7639357: // </margin>
  7781. case 7011901: // </MARGIN>
  7782. m_marginLeft = 0;
  7783. m_marginRight = 0;
  7784. return true;
  7785. case 1100728678: // <margin-left=xx.x>
  7786. case -855002522: // <MARGIN-LEFT>
  7787. value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength); // px
  7788. // Reject tag if value is invalid.
  7789. if (value == Int16.MinValue) return false;
  7790. switch (tagUnitType)
  7791. {
  7792. case TagUnitType.Pixels:
  7793. m_marginLeft = value * (m_isOrthographic ? 1 : 0.1f);
  7794. break;
  7795. case TagUnitType.FontUnits:
  7796. m_marginLeft = value * (m_isOrthographic ? 1 : 0.1f) * m_currentFontSize;
  7797. break;
  7798. case TagUnitType.Percentage:
  7799. m_marginLeft = (m_marginWidth - (m_width != -1 ? m_width : 0)) * value / 100;
  7800. break;
  7801. }
  7802. m_marginLeft = m_marginLeft >= 0 ? m_marginLeft : 0;
  7803. return true;
  7804. case -884817987: // <margin-right=xx.x>
  7805. case -1690034531: // <MARGIN-RIGHT>
  7806. value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength); // px
  7807. // Reject tag if value is invalid.
  7808. if (value == Int16.MinValue) return false;
  7809. switch (tagUnitType)
  7810. {
  7811. case TagUnitType.Pixels:
  7812. m_marginRight = value * (m_isOrthographic ? 1 : 0.1f);
  7813. break;
  7814. case TagUnitType.FontUnits:
  7815. m_marginRight = value * (m_isOrthographic ? 1 : 0.1f) * m_currentFontSize;
  7816. break;
  7817. case TagUnitType.Percentage:
  7818. m_marginRight = (m_marginWidth - (m_width != -1 ? m_width : 0)) * value / 100;
  7819. break;
  7820. }
  7821. m_marginRight = m_marginRight >= 0 ? m_marginRight : 0;
  7822. return true;
  7823. case 1109349752: // <line-height=xx.x>
  7824. case -842693512: // <LINE-HEIGHT>
  7825. value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength);
  7826. // Reject tag if value is invalid.
  7827. if (value == Int16.MinValue) return false;
  7828. switch (tagUnitType)
  7829. {
  7830. case TagUnitType.Pixels:
  7831. m_lineHeight = value * (m_isOrthographic ? 1 : 0.1f);
  7832. break;
  7833. case TagUnitType.FontUnits:
  7834. m_lineHeight = value * (m_isOrthographic ? 1 : 0.1f) * m_currentFontSize;
  7835. break;
  7836. case TagUnitType.Percentage:
  7837. m_lineHeight = m_fontAsset.faceInfo.lineHeight * value / 100 * m_fontScale;
  7838. break;
  7839. }
  7840. return true;
  7841. case -445573839: // </line-height>
  7842. case 1897350193: // </LINE-HEIGHT>
  7843. m_lineHeight = TMP_Math.FLOAT_UNSET;
  7844. return true;
  7845. case 15115642: // <noparse>
  7846. case 10723418: // <NOPARSE>
  7847. tag_NoParsing = true;
  7848. return true;
  7849. case 1913798: // <action>
  7850. case 1286342: // <ACTION>
  7851. int actionID = m_xmlAttribute[0].valueHashCode;
  7852. if (m_isParsingText)
  7853. {
  7854. m_actionStack.Add(actionID);
  7855. Debug.Log("Action ID: [" + actionID + "] First character index: " + m_characterCount);
  7856. }
  7857. //if (m_isParsingText)
  7858. //{
  7859. // TMP_Action action = TMP_Action.GetAction(m_xmlAttribute[0].valueHashCode);
  7860. //}
  7861. return true;
  7862. case 7443301: // </action>
  7863. case 6815845: // </ACTION>
  7864. if (m_isParsingText)
  7865. {
  7866. Debug.Log("Action ID: [" + m_actionStack.CurrentItem() + "] Last character index: " + (m_characterCount - 1));
  7867. }
  7868. m_actionStack.Remove();
  7869. return true;
  7870. case 315682: // <scale=xx.x>
  7871. case 226050: // <SCALE=xx.x>
  7872. value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength);
  7873. // Reject tag if value is invalid.
  7874. if (value == Int16.MinValue) return false;
  7875. m_FXMatrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(value, 1, 1));
  7876. m_isFXMatrixSet = true;
  7877. return true;
  7878. case 1105611: // </scale>
  7879. case 1015979: // </SCALE>
  7880. m_isFXMatrixSet = false;
  7881. return true;
  7882. case 2227963: // <rotate=xx.x>
  7883. case 1600507: // <ROTATE=xx.x>
  7884. // TODO: Add ability to use Random Rotation
  7885. value = ConvertToFloat(m_htmlTag, m_xmlAttribute[0].valueStartIndex, m_xmlAttribute[0].valueLength);
  7886. // Reject tag if value is invalid.
  7887. if (value == Int16.MinValue) return false;
  7888. m_FXMatrix = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0, 0, value), Vector3.one);
  7889. m_isFXMatrixSet = true;
  7890. return true;
  7891. case 7757466: // </rotate>
  7892. case 7130010: // </ROTATE>
  7893. m_isFXMatrixSet = false;
  7894. return true;
  7895. case 317446: // <table>
  7896. case 227814: // <TABLE>
  7897. //switch (m_xmlAttribute[1].nameHashCode)
  7898. //{
  7899. // case 327550: // width
  7900. // float tableWidth = ConvertToFloat(m_htmlTag, m_xmlAttribute[1].valueStartIndex, m_xmlAttribute[1].valueLength);
  7901. // // Reject tag if value is invalid.
  7902. // if (tableWidth == Int16.MinValue) return false;
  7903. // switch (tagUnitType)
  7904. // {
  7905. // case TagUnitType.Pixels:
  7906. // Debug.Log("Table width = " + tableWidth + "px.");
  7907. // break;
  7908. // case TagUnitType.FontUnits:
  7909. // Debug.Log("Table width = " + tableWidth + "em.");
  7910. // break;
  7911. // case TagUnitType.Percentage:
  7912. // Debug.Log("Table width = " + tableWidth + "%.");
  7913. // break;
  7914. // }
  7915. // break;
  7916. //}
  7917. return false;
  7918. case 1107375: // </table>
  7919. case 1017743: // </TABLE>
  7920. return true;
  7921. case 926: // <tr>
  7922. case 670: // <TR>
  7923. return true;
  7924. case 3229: // </tr>
  7925. case 2973: // </TR>
  7926. return true;
  7927. case 916: // <th>
  7928. case 660: // <TH>
  7929. // Set style to bold and center alignment
  7930. return true;
  7931. case 3219: // </th>
  7932. case 2963: // </TH>
  7933. return true;
  7934. case 912: // <td>
  7935. case 656: // <TD>
  7936. // Style options
  7937. //for (int i = 1; i < m_xmlAttribute.Length && m_xmlAttribute[i].nameHashCode != 0; i++)
  7938. //{
  7939. // switch (m_xmlAttribute[i].nameHashCode)
  7940. // {
  7941. // case 327550: // width
  7942. // float tableWidth = ConvertToFloat(m_htmlTag, m_xmlAttribute[i].valueStartIndex, m_xmlAttribute[i].valueLength);
  7943. // switch (tagUnitType)
  7944. // {
  7945. // case TagUnitType.Pixels:
  7946. // Debug.Log("Table width = " + tableWidth + "px.");
  7947. // break;
  7948. // case TagUnitType.FontUnits:
  7949. // Debug.Log("Table width = " + tableWidth + "em.");
  7950. // break;
  7951. // case TagUnitType.Percentage:
  7952. // Debug.Log("Table width = " + tableWidth + "%.");
  7953. // break;
  7954. // }
  7955. // break;
  7956. // case 275917: // align
  7957. // switch (m_xmlAttribute[i].valueHashCode)
  7958. // {
  7959. // case 3774683: // left
  7960. // Debug.Log("TD align=\"left\".");
  7961. // break;
  7962. // case 136703040: // right
  7963. // Debug.Log("TD align=\"right\".");
  7964. // break;
  7965. // case -458210101: // center
  7966. // Debug.Log("TD align=\"center\".");
  7967. // break;
  7968. // case -523808257: // justified
  7969. // Debug.Log("TD align=\"justified\".");
  7970. // break;
  7971. // }
  7972. // break;
  7973. // }
  7974. //}
  7975. return false;
  7976. case 3215: // </td>
  7977. case 2959: // </TD>
  7978. return false;
  7979. }
  7980. }
  7981. #endif
  7982. #endregion
  7983. return false;
  7984. }
  7985. }
  7986. }