0002-infinality-2.11.1-2021.12.10.patch 219 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396
  1. diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/config.mk a/config.mk
  2. --- b/config.mk 1970-01-01 03:00:00.000000000 +0300
  3. +++ a/config.mk 2021-09-16 09:19:40.891396586 +0300
  4. @@ -0,0 +1,62 @@
  5. +#
  6. +# FreeType 2 configuration rules for UNIX platforms
  7. +#
  8. +
  9. +
  10. +# Copyright (C) 1996-2021 by
  11. +# David Turner, Robert Wilhelm, and Werner Lemberg.
  12. +#
  13. +# This file is part of the FreeType project, and may only be used, modified,
  14. +# and distributed under the terms of the FreeType project license,
  15. +# LICENSE.TXT. By continuing to use, modify, or distribute this file you
  16. +# indicate that you have read the license and understand and accept it
  17. +# fully.
  18. +
  19. +# We need these declarations here since unix-def.mk is a generated file.
  20. +PLATFORM_DIR := $(TOP_DIR)/builds/unix
  21. +PLATFORM := unix
  22. +
  23. +have_mk := $(wildcard $(OBJ_DIR)/unix-def.mk)
  24. +ifneq ($(have_mk),)
  25. + # We are building FreeType 2 not in the src tree.
  26. + include $(OBJ_DIR)/unix-def.mk
  27. + include $(OBJ_DIR)/unix-cc.mk
  28. +else
  29. + include $(PLATFORM_DIR)/unix-def.mk
  30. + include $(PLATFORM_DIR)/unix-cc.mk
  31. +endif
  32. +
  33. +ifdef BUILD_PROJECT
  34. +
  35. + .PHONY: clean_project distclean_project
  36. +
  37. + # Now include the main sub-makefile. It contains all the rules used to
  38. + # build the library with the previous variables defined.
  39. + #
  40. + include $(TOP_DIR)/builds/$(PROJECT).mk
  41. +
  42. +
  43. + # The cleanup targets.
  44. + #
  45. + clean_project: clean_project_unix
  46. + distclean_project: distclean_project_unix
  47. +
  48. +
  49. + # This final rule is used to link all object files into a single library.
  50. + # It is part of the system-specific sub-Makefile because not all
  51. + # librarians accept a simple syntax like
  52. + #
  53. + # librarian library_file {list of object files}
  54. + #
  55. + $(PROJECT_LIBRARY): $(OBJECTS_LIST)
  56. + ifdef CLEAN_LIBRARY
  57. + -$(CLEAN_LIBRARY) $(NO_OUTPUT)
  58. + endif
  59. + $(LINK_LIBRARY)
  60. +
  61. + include $(TOP_DIR)/builds/unix/install.mk
  62. +
  63. +endif
  64. +
  65. +
  66. +# EOF
  67. diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/configure a/configure
  68. --- b/configure 2021-02-13 10:16:54.000000000 +0200
  69. +++ a/configure 2021-09-16 09:15:05.050379727 +0300
  70. @@ -13,6 +13,8 @@
  71. # Call the `configure' script located in `builds/unix'.
  72. #
  73. +export LDFLAGS="$LDFLAGS -lm"
  74. +
  75. rm -f config.mk builds/unix/unix-def.mk builds/unix/unix-cc.mk
  76. # respect GNUMAKE environment variable for backward compatibility
  77. diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/devel/ftoption.h a/devel/ftoption.h
  78. --- b/devel/ftoption.h 2021-07-15 13:09:04.000000000 +0300
  79. +++ a/devel/ftoption.h 2021-09-16 09:15:05.050379727 +0300
  80. @@ -629,6 +629,16 @@
  81. */
  82. #define TT_CONFIG_OPTION_BYTECODE_INTERPRETER
  83. + /*************************************************************************/
  84. + /* */
  85. + /* Define FT_CONFIG_OPTION_INFINALITY_PATCHSET if you want to enable */
  86. + /* all additional infinality patches, which are configured via env */
  87. + /* variables. */
  88. + /* */
  89. + /* This option requires TT_CONFIG_OPTION_SUBPIXEL_HINTING to */
  90. + /* defined. */
  91. + /* */
  92. +#define FT_CONFIG_OPTION_INFINALITY_PATCHSET
  93. /**************************************************************************
  94. *
  95. diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/include/freetype/config/ftoption.h a/include/freetype/config/ftoption.h
  96. --- b/include/freetype/config/ftoption.h 2021-07-15 13:09:04.000000000 +0300
  97. +++ a/include/freetype/config/ftoption.h 2021-09-16 09:15:05.051379735 +0300
  98. @@ -112,18 +112,21 @@
  99. #define FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
  100. - /**************************************************************************
  101. - *
  102. - * Uncomment the line below if you want to activate LCD rendering
  103. - * technology similar to ClearType in this build of the library. This
  104. - * technology triples the resolution in the direction color subpixels. To
  105. - * mitigate color fringes inherent to this technology, you also need to
  106. - * explicitly set up LCD filtering.
  107. - *
  108. - * When this macro is not defined, FreeType offers alternative LCD
  109. - * rendering technology that produces excellent output.
  110. - */
  111. -/* #define FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
  112. + /*************************************************************************/
  113. + /* */
  114. + /* Uncomment the line below if you want to activate LCD rendering */
  115. + /* technology similar to ClearType in this build of the library. This */
  116. + /* technology triples the resolution in the direction color subpixels. */
  117. + /* To mitigate color fringes inherent to this technology, you also need */
  118. + /* to explicitly set up LCD filtering. */
  119. + /* */
  120. + /* Note that this feature is covered by several Microsoft patents */
  121. + /* and should not be activated in any default build of the library. */
  122. + /* When this macro is not defined, FreeType offers alternative LCD */
  123. + /* rendering technology that produces excellent output without LCD */
  124. + /* filtering. */
  125. + /* */
  126. +#define FT_CONFIG_OPTION_SUBPIXEL_RENDERING
  127. /**************************************************************************
  128. @@ -631,6 +634,17 @@
  129. */
  130. #define TT_CONFIG_OPTION_BYTECODE_INTERPRETER
  131. + /*************************************************************************/
  132. + /* */
  133. + /* Define FT_CONFIG_OPTION_INFINALITY_PATCHSET if you want to enable */
  134. + /* all additional infinality patches, which are configured via env */
  135. + /* variables. */
  136. + /* */
  137. + /* This option requires TT_CONFIG_OPTION_SUBPIXEL_HINTING to */
  138. + /* defined. */
  139. + /* */
  140. +#define FT_CONFIG_OPTION_INFINALITY_PATCHSET
  141. +
  142. /**************************************************************************
  143. *
  144. @@ -688,8 +702,8 @@
  145. * https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx
  146. */
  147. /* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING 1 */
  148. -#define TT_CONFIG_OPTION_SUBPIXEL_HINTING 2
  149. -/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING ( 1 | 2 ) */
  150. +/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING 1 */
  151. +#define TT_CONFIG_OPTION_SUBPIXEL_HINTING ( 1 | 2 )
  152. /**************************************************************************
  153. diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/include/freetype/internal/ftobjs.h a/include/freetype/internal/ftobjs.h
  154. --- b/include/freetype/internal/ftobjs.h 2021-02-13 10:16:54.000000000 +0200
  155. +++ a/include/freetype/internal/ftobjs.h 2021-09-16 09:15:05.051379735 +0300
  156. @@ -278,12 +278,14 @@
  157. #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
  158. typedef void (*FT_Bitmap_LcdFilterFunc)( FT_Bitmap* bitmap,
  159. + FT_Render_Mode render_mode,
  160. FT_Byte* weights );
  161. /* This is the default LCD filter, an in-place, 5-tap FIR filter. */
  162. FT_BASE( void )
  163. ft_lcd_filter_fir( FT_Bitmap* bitmap,
  164. + FT_Render_Mode mode,
  165. FT_LcdFiveTapFilter weights );
  166. #endif /* FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
  167. @@ -908,6 +910,7 @@
  168. FT_DebugHook_Func debug_hooks[4];
  169. #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
  170. + FT_Int lcd_extra; /* number of extra pixels */
  171. FT_LcdFiveTapFilter lcd_weights; /* filter weights, if any */
  172. FT_Bitmap_LcdFilterFunc lcd_filter_func; /* filtering callback */
  173. #else
  174. diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/src/autofit/aflatin.c a/src/autofit/aflatin.c
  175. --- b/src/autofit/aflatin.c 2021-07-12 15:07:00.000000000 +0300
  176. +++ a/src/autofit/aflatin.c 2021-09-16 09:15:05.051379735 +0300
  177. @@ -22,7 +22,10 @@
  178. #include "afglobal.h"
  179. #include "aflatin.h"
  180. #include "aferrors.h"
  181. -
  182. +#include "strings.h"
  183. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  184. +#include "../base/ftinf.h"
  185. +#endif
  186. /**************************************************************************
  187. *
  188. @@ -33,6 +36,10 @@
  189. #undef FT_COMPONENT
  190. #define FT_COMPONENT aflatin
  191. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  192. +FT_Pos infinality_cur_width = 0;
  193. +#endif
  194. +
  195. /* needed for computation of round vs. flat segments */
  196. #define FLAT_THRESHOLD( x ) ( x / 14 )
  197. @@ -1174,7 +1181,10 @@
  198. FT_Pos delta;
  199. AF_LatinAxis axis;
  200. FT_UInt nn;
  201. -
  202. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  203. + FT_Bool adjust_heights = FALSE;
  204. + if(ftinf) adjust_heights=ftinf->autohint_increase_glyph_heights;
  205. +#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */
  206. if ( dim == AF_DIMENSION_HORZ )
  207. {
  208. @@ -1202,7 +1212,7 @@
  209. {
  210. AF_LatinAxis Axis = &metrics->axis[AF_DIMENSION_VERT];
  211. AF_LatinBlue blue = NULL;
  212. -
  213. + int threshold = 40;
  214. for ( nn = 0; nn < Axis->blue_count; nn++ )
  215. {
  216. @@ -1212,7 +1222,12 @@
  217. break;
  218. }
  219. }
  220. -
  221. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  222. + if ( adjust_heights &&
  223. + metrics->root.scaler.face->size->metrics.x_ppem < 15 &&
  224. + metrics->root.scaler.face->size->metrics.x_ppem > 5 )
  225. + threshold = 52;
  226. +#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */
  227. if ( blue )
  228. {
  229. FT_Pos scaled;
  230. @@ -1369,7 +1384,13 @@
  231. /* a blue zone is only active if it is less than 3/4 pixels tall */
  232. dist = FT_MulFix( blue->ref.org - blue->shoot.org, scale );
  233. +
  234. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  235. + /* Do at low ppems ( ~< 200 ), in order to prevent fringes */
  236. + if ( dist <= 256 && dist >= -256 )
  237. +#else
  238. if ( dist <= 48 && dist >= -48 )
  239. +#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */
  240. {
  241. #if 0
  242. FT_Pos delta1;
  243. @@ -1420,7 +1441,12 @@
  244. delta2 = -delta2;
  245. blue->ref.fit = FT_PIX_ROUND( blue->ref.cur );
  246. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  247. + /* Round to prevent fringes */
  248. + blue->shoot.fit = FT_PIX_ROUND( blue->ref.fit - delta2 );
  249. +#else
  250. blue->shoot.fit = blue->ref.fit - delta2;
  251. +#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */
  252. #endif
  253. @@ -2583,7 +2609,10 @@
  254. dist = edge->fpos - blue->shoot.org;
  255. if ( dist < 0 )
  256. dist = -dist;
  257. -
  258. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  259. + /* round down to pixels */
  260. + /*dist = FT_MulFix( dist, scale ) & ~63;*/
  261. +#endif
  262. dist = FT_MulFix( dist, scale );
  263. if ( dist < best_dist )
  264. {
  265. @@ -2748,8 +2777,17 @@
  266. FT_Pos dist = width;
  267. FT_Int sign = 0;
  268. FT_Int vertical = ( dim == AF_DIMENSION_VERT );
  269. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  270. + FT_Int infinality_dist = 0;
  271. + FT_UInt autohint_snap_stem_height = 0;
  272. + if( ftinf ) autohint_snap_stem_height=ftinf->autohint_snap_stem_height;
  273. + if ( autohint_snap_stem_height > 100 )
  274. + autohint_snap_stem_height = 100;
  275. + else if ( autohint_snap_stem_height < 0 )
  276. + autohint_snap_stem_height = 0;
  277. -
  278. + if ( autohint_snap_stem_height == 0 )
  279. +#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */
  280. if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) ||
  281. axis->extra_light )
  282. return width;
  283. @@ -2759,9 +2797,76 @@
  284. dist = -width;
  285. sign = 1;
  286. }
  287. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  288. + /* Calculate snap value differently than standard freetype */
  289. + if ( autohint_snap_stem_height > 0 &&
  290. + ( ( vertical && !AF_LATIN_HINTS_DO_VERT_SNAP( hints ) ) ||
  291. + ( !vertical && !AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) ) ) )
  292. + {
  293. + infinality_dist = af_latin_snap_width( axis->widths,
  294. + axis->width_count, dist );
  295. +
  296. + if ( metrics->root.scaler.face->size->metrics.x_ppem > 9 &&
  297. + axis->width_count > 0 &&
  298. + abs( axis->widths[0].cur - infinality_dist ) < 32 &&
  299. + axis->widths[0].cur > 52 )
  300. + {
  301. + const char *style_name=metrics->root.scaler.face->style_name;
  302. + if ( style_name!=NULL &&
  303. + ( strstr( style_name, "Regular" ) ||
  304. + strstr( style_name, "Book" ) ||
  305. + strstr( style_name, "Medium" ) ||
  306. + strcmp( style_name, "Italic" ) == 0 ||
  307. + strcmp( style_name, "Oblique" ) == 0 )
  308. + )
  309. + {
  310. + /* regular weight */
  311. + if ( axis->widths[0].cur < 64 )
  312. + infinality_dist = 64;
  313. + else if ( axis->widths[0].cur < 88 )
  314. + infinality_dist = 64;
  315. + else if ( axis->widths[0].cur < 160 )
  316. + infinality_dist = 128;
  317. + else if ( axis->widths[0].cur < 240 )
  318. + infinality_dist = 190;
  319. + else infinality_dist = ( infinality_dist ) & ~63;
  320. + }
  321. + else
  322. + {
  323. + /* bold gets a different threshold */
  324. + if ( axis->widths[0].cur < 64 )
  325. + infinality_dist = 64 ;
  326. + else if ( axis->widths[0].cur < 108 )
  327. + infinality_dist = 64;
  328. + else if ( axis->widths[0].cur < 160 )
  329. + infinality_dist = 128;
  330. + else if ( axis->widths[0].cur < 222 )
  331. + infinality_dist = 190;
  332. + else if ( axis->widths[0].cur < 288 )
  333. + infinality_dist = 254;
  334. + else infinality_dist = ( infinality_dist + 16 ) & ~63;
  335. + }
  336. +
  337. + }
  338. + if ( infinality_dist < 52 )
  339. + {
  340. + if ( metrics->root.scaler.face->size->metrics.x_ppem < 9 )
  341. + {
  342. + if ( infinality_dist < 32 )
  343. + infinality_dist = 32;
  344. + }
  345. + else
  346. + infinality_dist = 64;
  347. + }
  348. + }
  349. + else if ( autohint_snap_stem_height < 100 &&
  350. + ( ( vertical && !AF_LATIN_HINTS_DO_VERT_SNAP( hints ) ) ||
  351. + ( !vertical && !AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) ) ) )
  352. +#else
  353. if ( ( vertical && !AF_LATIN_HINTS_DO_VERT_SNAP( hints ) ) ||
  354. ( !vertical && !AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) ) )
  355. +#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */
  356. {
  357. /* smooth hinting process: very lightly quantize the stem width */
  358. @@ -2853,6 +2958,9 @@
  359. }
  360. }
  361. else
  362. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  363. + if ( autohint_snap_stem_height < 100 )
  364. +#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */
  365. {
  366. /* strong hinting process: snap the stem width to integer pixels */
  367. @@ -2860,7 +2968,10 @@
  368. dist = af_latin_snap_width( axis->widths, axis->width_count, dist );
  369. -
  370. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  371. + if ( autohint_snap_stem_height > 0 )
  372. + goto Done_Width;
  373. +#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */
  374. if ( vertical )
  375. {
  376. /* in the case of vertical hinting, always round */
  377. @@ -2923,6 +3034,32 @@
  378. }
  379. Done_Width:
  380. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  381. + if ( axis->widths[0].cur > 42 )
  382. + /* weighted average */
  383. + dist = (dist * ( 100 - autohint_snap_stem_height )
  384. + + infinality_dist * autohint_snap_stem_height ) / 100;
  385. +
  386. + {
  387. + int factor = 100;
  388. + if ( axis->standard_width < 100 )
  389. + factor = axis->standard_width;
  390. +
  391. + if ( metrics->root.scaler.face->size->metrics.x_ppem >= 9 && dist < 52 )
  392. + dist += ( (52 - dist) * factor ) / 100;
  393. + if ( metrics->root.scaler.face->size->metrics.x_ppem < 9 && dist < 32 )
  394. + dist += ( (32 - dist) * factor ) / 100;
  395. +
  396. + if ( axis->standard_width > 100 &&
  397. + metrics->root.scaler.face->size->metrics.x_ppem >= 11 &&
  398. + dist < 64 )
  399. + dist = 64;
  400. + if ( axis->standard_width > 100 &&
  401. + metrics->root.scaler.face->size->metrics.x_ppem >= 9 &&
  402. + dist < 52 )
  403. + dist = 52;
  404. + }
  405. +#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */
  406. if ( sign )
  407. dist = -dist;
  408. @@ -2941,6 +3078,8 @@
  409. FT_Pos dist, base_delta;
  410. FT_Pos fitted_width;
  411. +/* if fitted_width causes stem_edge->pos to land basically on top of an existing
  412. + * stem_edge->pos, then add or remove 64. Need to figure out a way to do this */
  413. dist = stem_edge->opos - base_edge->opos;
  414. base_delta = base_edge->pos - base_edge->opos;
  415. @@ -3548,8 +3687,11 @@
  416. int dim;
  417. AF_LatinAxis axis;
  418. -
  419. -
  420. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  421. + FT_Int emboldening_strength = 0;
  422. + FT_Bool use_various_tweaks = FALSE;
  423. + if( ftinf ) use_various_tweaks=ftinf->use_various_tweaks;
  424. +#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */
  425. error = af_glyph_hints_reload( hints, outline );
  426. if ( error )
  427. goto Exit;
  428. @@ -3595,7 +3737,11 @@
  429. }
  430. af_glyph_hints_save( hints, outline );
  431. -
  432. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  433. + {
  434. + infinality_cur_width = metrics->axis->widths[0].cur;
  435. + }
  436. +#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */
  437. Exit:
  438. return error;
  439. }
  440. diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/src/autofit/aflatin.h a/src/autofit/aflatin.h
  441. --- b/src/autofit/aflatin.h 2021-02-13 10:16:54.000000000 +0200
  442. +++ a/src/autofit/aflatin.h 2021-09-16 09:15:05.051379735 +0300
  443. @@ -64,6 +64,9 @@
  444. #define AF_LATIN_MAX_WIDTHS 16
  445. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  446. + extern FT_Pos infinality_cur_width;
  447. +#endif
  448. #define AF_LATIN_BLUE_ACTIVE ( 1U << 0 ) /* zone height is <= 3/4px */
  449. #define AF_LATIN_BLUE_TOP ( 1U << 1 ) /* we have a top blue zone */
  450. diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/src/autofit/afmodule.c a/src/autofit/afmodule.c
  451. --- b/src/autofit/afmodule.c 2021-07-12 15:07:00.000000000 +0300
  452. +++ a/src/autofit/afmodule.c 2021-09-16 09:15:05.051379735 +0300
  453. @@ -21,6 +21,10 @@
  454. #include "afloader.h"
  455. #include "aferrors.h"
  456. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  457. +#include "../base/ftinf.h"
  458. +#endif
  459. +
  460. #ifdef FT_DEBUG_AUTOFIT
  461. #ifndef FT_MAKE_OPTION_SINGLE_OBJECT
  462. @@ -405,6 +409,9 @@
  463. module->fallback_style = AF_STYLE_FALLBACK;
  464. module->default_script = AF_SCRIPT_DEFAULT;
  465. module->no_stem_darkening = TRUE;
  466. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  467. + if(ftinf) module->no_stem_darkening = !ftinf->stem_darkening_autofit;
  468. +#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */
  469. module->darken_params[0] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1;
  470. module->darken_params[1] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1;
  471. diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/src/base/ftbase.c a/src/base/ftbase.c
  472. --- b/src/base/ftbase.c 2021-02-13 10:16:54.000000000 +0200
  473. +++ a/src/base/ftbase.c 2021-09-16 09:15:05.051379735 +0300
  474. @@ -36,6 +36,9 @@
  475. #include "ftstream.c"
  476. #include "fttrigon.c"
  477. #include "ftutil.c"
  478. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  479. +#include "ftinf.c"
  480. +#endif
  481. /* END */
  482. diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/src/base/ftinf.c a/src/base/ftinf.c
  483. --- b/src/base/ftinf.c 1970-01-01 03:00:00.000000000 +0300
  484. +++ a/src/base/ftinf.c 2021-09-16 09:15:05.052379743 +0300
  485. @@ -0,0 +1,363 @@
  486. +#include <stdlib.h>
  487. +#include "ftinf.h"
  488. +#define true 1
  489. +#define false 0
  490. +
  491. +#define on 1
  492. +#define off 0
  493. +#define end (-128)
  494. +
  495. +#define sw2pv 18 /* STEM_WIDTH_2_PPEM */
  496. +#define maxp 100 /* MAX_PPEM */
  497. +
  498. +typedef signed char pv; /* ppm and values type */
  499. +/* the arrays start with existence flag + values */
  500. +typedef struct sa_rules_s {
  501. + const char *name;
  502. + pv always_use_100[1+4+1];
  503. + pv brightness[1+2+1];
  504. + pv contrast[1+2+1];
  505. + pv edge_detection[1+4+1];
  506. + pv m[1+4+1];
  507. + pv bearing_correction[1+2+1];
  508. + pv spacing[1+5+1];
  509. + pv start[1+5+1];
  510. + pv stem_scaling[1+6+1];
  511. + pv stem_translating[1+2+1];
  512. + pv stem_translating_only[1+10+1];
  513. + pv stem_widths[1+4]; /* these end with maxp */
  514. + pv synthesize_stems[1+2+1];
  515. +} sa_rules_t;
  516. +
  517. +#pragma GCC diagnostic ignored "-Wpedantic" /* C99 struct initializer tags are needed */
  518. +#pragma GCC diagnostic ignored "-Wunused-function"
  519. +
  520. +const ftinf_t *ftinf;
  521. +/* final settings, updated from environment */
  522. +ftinf_t _env;
  523. +
  524. +/* rules and hashing function */
  525. +#include "ftinf_rh.c"
  526. +
  527. +/* rules selection */
  528. +void ftinf_fill_stem_values( Stem_Data *stem_values,
  529. + const char *family, int ppem, int use_known ){
  530. + /* set the defaults */
  531. + stem_values->bearing_correction = TRUE;
  532. + stem_values->brightness = 0.0;
  533. + stem_values->contrast = 0.0;
  534. + stem_values->edge_detection = FALSE;
  535. + stem_values->m = -1;
  536. + stem_values->stem_scaling = -1;
  537. + stem_values->stem_spacing = -1;
  538. + stem_values->stem_start = -1;
  539. + stem_values->stem_translating = 0;
  540. + stem_values->stem_translating_only = -1024;
  541. + stem_values->stem_width = -1;
  542. + stem_values->synth_stems = FALSE;
  543. + stem_values->use_100 = FALSE;
  544. + /* pick from known rules if requested and they exist for current family */
  545. + if( !use_known )
  546. + return;
  547. + else {
  548. + const sa_rules_t *r=ftinf_rules( family );
  549. + int i;
  550. + if( r==NULL ) return;
  551. + if( r->stem_widths[0]==on )
  552. + for( i=1; r->stem_widths[i]!=maxp; ++i )
  553. + if( ppem < r->stem_widths[i] ){
  554. + stem_values->stem_width = i-1;
  555. + break;
  556. + }
  557. +
  558. + if( r->stem_scaling[0]==on )
  559. + for( i=1; r->stem_scaling[i]!=end; i+=2 )
  560. + if( ppem==r->stem_scaling[i] ){
  561. + stem_values->stem_scaling = r->stem_scaling[i+1];
  562. + break;
  563. + }
  564. +
  565. + if( r->m[0]==on )
  566. + for( i=1; r->m[i]!=end; i+=2 )
  567. + if( ppem==r->m[i] ){
  568. + stem_values->m = r->m[i+1];
  569. + break;
  570. + }
  571. +
  572. + if( r->stem_translating_only[0]==on )
  573. + for( i=1; r->stem_translating_only[i]!=end; i+=2 )
  574. + if( ppem==r->stem_translating_only[i] || r->stem_translating_only[i]==0 ){
  575. + stem_values->stem_translating_only = r->stem_translating_only[i+1];
  576. + break;
  577. + }
  578. +
  579. + if( r->stem_translating[0]==on )
  580. + for( i=1; r->stem_translating[i]!=end; i+=2 )
  581. + if( ppem==r->stem_translating[i] || r->stem_translating[i]==0 ){
  582. + stem_values->stem_translating = r->stem_translating[i+1];
  583. + break;
  584. + }
  585. +
  586. + if( r->always_use_100[0]==on )
  587. + for( i=1; r->always_use_100[i]!=end; i+=2 )
  588. + if( ppem>=r->always_use_100[i] && ppem<=r->always_use_100[i+1] ){
  589. + stem_values->use_100 = TRUE;
  590. + break;
  591. + }
  592. +
  593. + if( r->synthesize_stems[0]==on )
  594. + for( i=1; r->synthesize_stems[i]!=end; i+=2 )
  595. + if( ppem>=r->synthesize_stems[i] && ppem<=r->synthesize_stems[i+1] ){
  596. + stem_values->synth_stems = TRUE;
  597. + break;
  598. + }
  599. +
  600. + if( r->edge_detection[0]==on )
  601. + for( i=1; r->edge_detection[i]!=end; i+=2 )
  602. + if( ppem>=r->edge_detection[i] && ppem<=r->edge_detection[i+1] ){
  603. + stem_values->edge_detection = TRUE;
  604. + break;
  605. + }
  606. +
  607. + if( r->bearing_correction[0]==on )
  608. + for( i=1; r->bearing_correction[i]!=end; i+=2 )
  609. + if( ppem>=r->bearing_correction[i] && ppem<=r->bearing_correction[i+1] ){
  610. + stem_values->bearing_correction = FALSE;
  611. + break;
  612. + }
  613. +
  614. +#if(0)
  615. + if( r->brightness[0]==on )
  616. + for( i=1; r->brightness[i]!=end; i+=2 )
  617. + if( ppem==r->brightness[i]||r->brightness[i]==0 ){
  618. + stem_values->brightness=r->brightness[i+1]*(1.0f/300.0f);
  619. + break;
  620. + }
  621. +
  622. + if( r->contrast[0]==on )
  623. + for( i=1; r->contrast[i]!=end; i+=2 )
  624. + if( ppem==r->contrast[i]||r->contrast[i]==0 ){
  625. + stem_values->contrast=r->contrast[i+1]*(1.0f/300.0f);
  626. + break;
  627. + }
  628. + if( r->spacing[0]==on ){
  629. + /* not used by original code */
  630. + }
  631. + if( r->start[0]==on ){
  632. + /* not used by original code */
  633. + }
  634. +#endif
  635. + }
  636. + return;
  637. +}
  638. +
  639. +void ftinf_get_bc( const char *family, int ppem, float *brightness, float *contrast ){
  640. + const sa_rules_t *r=ftinf_rules( family );
  641. + *brightness=0;
  642. + *contrast=0;
  643. + if( r ){
  644. + int i;
  645. + if( r->brightness[0]==on )
  646. + for( i=1; r->brightness[i]!=end; i+=2 )
  647. + if( ppem==r->brightness[i]||r->brightness[i]==0 ){
  648. + *brightness=r->brightness[i+1]*(1.0f/300.0f);
  649. + break;
  650. + }
  651. +
  652. + if( r->contrast[0]==on )
  653. + for( i=1; r->contrast[i]!=end; i+=2 )
  654. + if( ppem==r->contrast[i]||r->contrast[i]==0 ){
  655. + *contrast=r->contrast[i+1]*(1.0f/300.0f);
  656. + break;
  657. + }
  658. + }
  659. + return;
  660. +}
  661. +
  662. +static int
  663. +bool_val( const char *s ){
  664. + if ( s != NULL )
  665. + return strcasecmp(s, "true") == 0
  666. + || strcasecmp(s, "1") == 0
  667. + || strcasecmp(s, "on") == 0
  668. + || strcasecmp(s, "yes") ==0;
  669. + else
  670. + return 0;
  671. +}
  672. +
  673. +static int
  674. +int_val( const char *s, int min, int max ){
  675. + int val;
  676. + sscanf ( s, "%d", &val );
  677. + if ( val > max )
  678. + val = max;
  679. + else if ( val < min )
  680. + val = min;
  681. + return val;
  682. +}
  683. +
  684. +/* settings and hashing function */
  685. +#include "ftinf_sh.c"
  686. +
  687. +/*
  688. + Get active Infinality settings
  689. + */
  690. +void ftinf_env(){
  691. + const char *s;
  692. + ftinf=ftinf_settings( getenv( "INFINALITY_FT" ) );
  693. +
  694. + if( ftinf==NULL ){
  695. + ftinf=ftinf_settings( "ultimate3" );
  696. + /* this should always succeed */
  697. +#if(0)
  698. + if( ftinf==NULL ){
  699. + /* put an error here */
  700. + exit(-1);
  701. + }
  702. +#endif
  703. + }
  704. + _env=ftinf[0]; /* copy as defaults */
  705. +
  706. + /* check if custom environment values are set and update with them */
  707. + s=getenv( "INFINALITY_FT_AUTOHINT_INCREASE_GLYPH_HEIGHTS" );
  708. + if( s ) _env.autohint_increase_glyph_heights=bool_val( s );
  709. + s=getenv( "INFINALITY_FT_AUTOHINT_SNAP_STEM_HEIGHT" );
  710. + if( s ) _env.autohint_snap_stem_height=int_val( s, 0, 100 );
  711. + s=getenv( "INFINALITY_FT_USE_VARIOUS_TWEAKS" );
  712. + if( s ) _env.use_various_tweaks=bool_val( s );
  713. + s=getenv( "INFINALITY_FT_USE_KNOWN_SETTINGS_ON_SELECTED_FONTS" );
  714. + if( s ) _env.use_known_settings_on_selected_fonts=bool_val(s);
  715. +#if(0) /* not used (naming error also) */
  716. + s=getenv( "INFINALITY_FT_AUTOHINT_MINIMUM_STEM_WIDTH" );
  717. + if( s ) _env.autohint_minimum_stem_height=int_val( s, 0, 100 );
  718. +#endif
  719. + s=getenv( "INFINALITY_FT_STEM_SNAPPING_SLIDING_SCALE" );
  720. + if( s ) sscanf( s, "%d", &_env.stem_snapping_sliding_scale );
  721. + s=getenv( "INFINALITY_FT_STEM_ALIGNMENT_STRENGTH" );
  722. + if( s ) sscanf( s, "%d", &_env.stem_alignment_strength );
  723. + s=getenv( "INFINALITY_FT_STEM_DARKENING_AUTOFIT" );
  724. + if( s ) _env.stem_darkening_autofit=bool_val( s );
  725. + s=getenv( "INFINALITY_FT_STEM_DARKENING_CFF" );
  726. + if( s ) _env.stem_darkening_cff=bool_val( s );
  727. + s=getenv( "INFINALITY_FT_STEM_FITTING_STRENGTH" );
  728. + if( s ) sscanf( s, "%d", &_env.stem_fitting_strength );
  729. + s=getenv( "INFINALITY_FT_CHROMEOS_STYLE_SHARPENING_STRENGTH" );
  730. + if( s ) _env.chromeos_style_sharpening_strength=int_val( s, 0, 100 );
  731. + s=getenv( "INFINALITY_FT_BRIGHTNESS" );
  732. + if( s ) sscanf( s, "%d", &_env.brightness );
  733. + s=getenv( "INFINALITY_FT_CONTRAST" );
  734. + if( s ) sscanf( s, "%d", &_env.contrast );
  735. + s=getenv( "INFINALITY_FT_WINDOWS_STYLE_SHARPENING_STRENGTH" );
  736. + if( s ) _env.windows_style_sharpening_strength=int_val( s, 0, 100 );
  737. + s=getenv( "INFINALITY_FT_GAMMA_CORRECTION" );
  738. + if( s ){
  739. + float *f=_env.gamma_correction;
  740. + sscanf ( s, "%f %f", &f[0], &f[1] );
  741. + if( f[1] < 1.0f ) f[1]=1.0f;
  742. + }
  743. + s=getenv( "INFINALITY_FT_FRINGE_FILTER_STRENGTH" );
  744. + if( s ) sscanf( s, "%d", &_env.fringe_filter_strength );
  745. + s=getenv( "INFINALITY_FT_GRAYSCALE_FILTER_STRENGTH" );
  746. + if( s ) sscanf( s, "%d", &_env.grayscale_filter_strength );
  747. + s=getenv( "INFINALITY_FT_AUTOHINT_HORIZONTAL_STEM_DARKEN_STRENGTH" );
  748. + if( s ) sscanf( s, "%d", &_env.autohint_horizontal_stem_darken_strength );
  749. + s=getenv( "INFINALITY_FT_AUTOHINT_VERTICAL_STEM_DARKEN_STRENGTH" );
  750. + if( s ) sscanf( s, "%d", &_env.autohint_vertical_stem_darken_strength );
  751. + s=getenv( "INFINALITY_FT_GLOBAL_EMBOLDEN_X_VALUE" );
  752. + if( s ) sscanf( s, "%d", &_env.global_embolden_x_value );
  753. + s=getenv( "INFINALITY_FT_GLOBAL_EMBOLDEN_Y_VALUE" );
  754. + if( s ) sscanf( s, "%d", &_env.global_embolden_y_value );
  755. + s=getenv( "INFINALITY_FT_BOLD_EMBOLDEN_X_VALUE" );
  756. + if( s ) sscanf( s, "%d", &_env.bold_embolden_x_value );
  757. + s=getenv( "INFINALITY_FT_BOLD_EMBOLDEN_Y_VALUE" );
  758. + if( s ) sscanf( s, "%d", &_env.bold_embolden_y_value );
  759. + s=getenv( "INFINALITY_FT_FILTER_PARAMS" );
  760. + if( s ) {
  761. + int *f=_env.filter_params;
  762. + if( sscanf( s, "%d %d %d %d %d", f+1, f+2, f+3, f+4, f+5 )==5 )
  763. + f[0]=on;
  764. + else
  765. + f[0]=off; /* FIXME: put a warning? */
  766. + }
  767. + /* do the range verifications as in original code */
  768. + if ( _env.stem_snapping_sliding_scale > maxp )
  769. + _env.stem_snapping_sliding_scale = 0;
  770. + else if ( _env.stem_snapping_sliding_scale < 0 )
  771. + _env.stem_snapping_sliding_scale = 0;
  772. + if (_env.stem_snapping_sliding_scale < 11 &&
  773. + _env.stem_snapping_sliding_scale > 0 )
  774. + _env.stem_snapping_sliding_scale = 11;
  775. +
  776. + if ( _env.stem_alignment_strength > 100 )
  777. + _env.stem_alignment_strength = 100;
  778. + else if ( _env.stem_alignment_strength < 0 )
  779. + _env.stem_alignment_strength = 0;
  780. +
  781. + if ( _env.stem_fitting_strength > 100 )
  782. + _env.stem_fitting_strength = 100;
  783. + else if ( _env.stem_fitting_strength < 0 )
  784. + _env.stem_fitting_strength = 0;
  785. +
  786. + if ( _env.chromeos_style_sharpening_strength > 100 )
  787. + _env.chromeos_style_sharpening_strength = 100;
  788. + else if ( _env.chromeos_style_sharpening_strength < 0 )
  789. + _env.chromeos_style_sharpening_strength = 0;
  790. +
  791. + if ( _env.brightness > 100 )
  792. + _env.brightness = 100;
  793. + else if ( _env.brightness < -100 )
  794. + _env.brightness = 0;
  795. +
  796. + if ( _env.contrast > 100 )
  797. + _env.contrast = 100;
  798. + else if ( _env.contrast < -100 )
  799. + _env.contrast = 0;
  800. +
  801. + if ( _env.windows_style_sharpening_strength > 100 )
  802. + _env.windows_style_sharpening_strength = 100;
  803. + else if ( _env.windows_style_sharpening_strength < 0 )
  804. + _env.windows_style_sharpening_strength = 0;
  805. +
  806. + if ( _env.fringe_filter_strength > 100 )
  807. + _env.fringe_filter_strength = 100;
  808. + else if ( _env.fringe_filter_strength < 0 )
  809. + _env.fringe_filter_strength = 0;
  810. +
  811. + if ( _env.grayscale_filter_strength > 100 )
  812. + _env.grayscale_filter_strength = 100;
  813. + else if ( _env.grayscale_filter_strength < 0 )
  814. + _env.grayscale_filter_strength = 0;
  815. +
  816. + if ( _env.autohint_horizontal_stem_darken_strength > 100 )
  817. + _env.autohint_horizontal_stem_darken_strength = 100;
  818. + else if ( _env.autohint_horizontal_stem_darken_strength < 0 )
  819. + _env.autohint_horizontal_stem_darken_strength = 0;
  820. +
  821. + if ( _env.autohint_vertical_stem_darken_strength > 100 )
  822. + _env.autohint_vertical_stem_darken_strength = 100;
  823. + else if ( _env.autohint_horizontal_stem_darken_strength < 0 )
  824. + _env.autohint_vertical_stem_darken_strength = 0;
  825. +
  826. + if ( _env.global_embolden_x_value > 128 )
  827. + _env.global_embolden_x_value = 128;
  828. + else if ( _env.global_embolden_x_value < -128 )
  829. + _env.global_embolden_x_value = -128;
  830. +
  831. + if ( _env.global_embolden_y_value > 128 )
  832. + _env.global_embolden_y_value = 128;
  833. + else if ( _env.global_embolden_y_value < -128 )
  834. + _env.global_embolden_y_value = -128;
  835. +
  836. + if ( _env.bold_embolden_x_value > 128 )
  837. + _env.bold_embolden_x_value = 128;
  838. + else if (_env.bold_embolden_x_value < -128 )
  839. + _env.bold_embolden_x_value = -128;
  840. +
  841. + if ( _env.bold_embolden_y_value > 128 )
  842. + _env.bold_embolden_y_value = 128;
  843. + else if ( _env.bold_embolden_y_value < -128 )
  844. + _env.bold_embolden_y_value = -128;
  845. +
  846. + /* point to the combined and checked settings */
  847. + ftinf=&_env;
  848. +}
  849. diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/src/base/ftinf.h a/src/base/ftinf.h
  850. --- b/src/base/ftinf.h 1970-01-01 03:00:00.000000000 +0300
  851. +++ a/src/base/ftinf.h 2021-09-16 09:15:05.052379743 +0300
  852. @@ -0,0 +1,66 @@
  853. +#ifndef _FTINF_H_
  854. +#define _FTINF_H_
  855. +/*
  856. + Stem snapping rules
  857. + (base freetype typedefs assumed already included)
  858. + */
  859. +typedef struct
  860. +{
  861. + FT_Int stem_width;
  862. + FT_Int stem_spacing;
  863. + FT_Int stem_start;
  864. + FT_Int stem_scaling;
  865. + FT_Int stem_translating_only;
  866. + FT_Int stem_translating;
  867. + float brightness;
  868. + float contrast;
  869. + FT_Bool use_100;
  870. + FT_Bool synth_stems;
  871. + FT_Bool edge_detection;
  872. + FT_Bool bearing_correction;
  873. + FT_Int m;
  874. +} Stem_Data;
  875. +
  876. +/*
  877. + Infinality settings
  878. + */
  879. +typedef struct ftinf_s {
  880. + const char *name;
  881. + int autohint_horizontal_stem_darken_strength;
  882. + int autohint_snap_stem_height;
  883. + int autohint_increase_glyph_heights;
  884. + int autohint_vertical_stem_darken_strength;
  885. + int bold_embolden_x_value;
  886. + int bold_embolden_y_value;
  887. + int brightness;
  888. + int chromeos_style_sharpening_strength;
  889. + int contrast;
  890. + int filter_params[6]; /* 1st one used as existence flag */
  891. + int fringe_filter_strength;
  892. + float gamma_correction[2];
  893. + int global_embolden_x_value;
  894. + int global_embolden_y_value;
  895. + int grayscale_filter_strength;
  896. + int stem_alignment_strength;
  897. + int stem_darkening_autofit;
  898. + int stem_darkening_cff;
  899. + int stem_fitting_strength;
  900. + int stem_snapping_sliding_scale;
  901. + int use_known_settings_on_selected_fonts;
  902. + int use_various_tweaks;
  903. + int windows_style_sharpening_strength;
  904. +} ftinf_t;
  905. +
  906. +extern FT_Pos infinality_cur_width; /* defined in aflatin.c */
  907. +
  908. +extern const ftinf_t *ftinf; /* active settings */
  909. +
  910. +extern void ftinf_fill_stem_values( Stem_Data *stem_values,
  911. + const char *family, int ppem, int use_known );
  912. +extern void ftinf_get_bc( const char *family, int ppem,
  913. + float *brightness, float *contrast );
  914. +
  915. +/* get values from environment (FIXME: maybe update with using user files) */
  916. +extern void ftinf_env();
  917. +
  918. +#endif
  919. diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/src/base/ftinf_rh.c a/src/base/ftinf_rh.c
  920. --- b/src/base/ftinf_rh.c 1970-01-01 03:00:00.000000000 +0300
  921. +++ a/src/base/ftinf_rh.c 2021-09-16 09:15:05.052379743 +0300
  922. @@ -0,0 +1,626 @@
  923. +/* ANSI-C code produced by gperf version 3.1 */
  924. +/* Command-line: gperf --output-file=ftinf_rh.c ftinf_rh.gperf */
  925. +/* Computed positions: -k'1,$' */
  926. +
  927. +#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
  928. + && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
  929. + && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
  930. + && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
  931. + && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
  932. + && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
  933. + && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
  934. + && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
  935. + && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
  936. + && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
  937. + && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
  938. + && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
  939. + && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
  940. + && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
  941. + && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
  942. + && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
  943. + && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
  944. + && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
  945. + && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
  946. + && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
  947. + && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
  948. + && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
  949. + && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
  950. +/* The character set is not based on ISO-646. */
  951. +#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>."
  952. +#endif
  953. +
  954. +#line 9 "ftinf_rh.gperf"
  955. +
  956. +#include <ctype.h>
  957. +static const struct sa_rules_s* _rules_get( const char*str, unsigned len );
  958. +/* maximum key range = 82, duplicates = 0 */
  959. +
  960. +#ifdef __GNUC__
  961. +__inline
  962. +#else
  963. +#ifdef __cplusplus
  964. +inline
  965. +#endif
  966. +#endif
  967. +static unsigned int
  968. +_rules_hash (register const char *str, register unsigned int len)
  969. +{
  970. + static const unsigned char asso_values[] =
  971. + {
  972. + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
  973. + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
  974. + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
  975. + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
  976. + 85, 85, 85, 85, 85, 0, 85, 85, 85, 85,
  977. + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
  978. + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
  979. + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
  980. + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
  981. + 85, 85, 85, 85, 85, 85, 85, 5, 45, 5,
  982. + 35, 25, 35, 35, 50, 45, 85, 85, 0, 25,
  983. + 40, 5, 0, 85, 50, 20, 20, 0, 10, 10,
  984. + 85, 10, 85, 85, 85, 85, 85, 85, 85, 85,
  985. + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
  986. + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
  987. + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
  988. + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
  989. + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
  990. + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
  991. + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
  992. + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
  993. + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
  994. + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
  995. + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
  996. + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
  997. + 85, 85, 85, 85, 85, 85
  998. + };
  999. + return len + asso_values[(unsigned char)str[len - 1]] + asso_values[(unsigned char)str[0]];
  1000. +}
  1001. +
  1002. +#ifdef __GNUC__
  1003. +__inline
  1004. +#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
  1005. +__attribute__ ((__gnu_inline__))
  1006. +#endif
  1007. +#endif
  1008. +const struct sa_rules_s *
  1009. +_rules_get (register const char *str, register unsigned int len)
  1010. +{
  1011. + enum
  1012. + {
  1013. + TOTAL_KEYWORDS = 58,
  1014. + MIN_WORD_LENGTH = 3,
  1015. + MAX_WORD_LENGTH = 24,
  1016. + MIN_HASH_VALUE = 3,
  1017. + MAX_HASH_VALUE = 84
  1018. + };
  1019. +
  1020. + static const struct sa_rules_s wordlist[] =
  1021. + {
  1022. +#line 15 "ftinf_rh.gperf"
  1023. +{ .name="---",
  1024. + .synthesize_stems={on, 13, 13, end}
  1025. +},
  1026. +#line 253 "ftinf_rh.gperf"
  1027. +{ .name="ubuntu",
  1028. + .always_use_100={on, 12, 13, 15, 15, end}
  1029. +},
  1030. +#line 31 "ftinf_rh.gperf"
  1031. +{ .name="arial",
  1032. + .always_use_100={on, 0, maxp, end},
  1033. + .edge_detection={on, 11, 11, 13, 13, end},
  1034. + .spacing={on, 10, 11, 23, 25, 30, end},
  1035. + .start={on, 11, 18, 23, 30, 30, end},
  1036. + .stem_translating={on, 11, 32, end},
  1037. + .stem_translating_only={on, 10, 16, 8, 32, 9, 32, 16, -24, end}
  1038. +},
  1039. +#line 87 "ftinf_rh.gperf"
  1040. +{ .name="corbel",
  1041. + .stem_translating_only={on, 10, 16, end},
  1042. + .stem_widths={on, 10, 21, maxp}
  1043. +},
  1044. +#line 71 "ftinf_rh.gperf"
  1045. +{ .name="canwell",
  1046. + .stem_scaling={on, 13, 0, end}
  1047. +},
  1048. +#line 216 "ftinf_rh.gperf"
  1049. +{ .name="pragmata",
  1050. + .always_use_100={on, 0, maxp, end}
  1051. +},
  1052. +#line 67 "ftinf_rh.gperf"
  1053. +{ .name="cantarell",
  1054. + .stem_translating_only={on, 11, 0, 12, 0, end},
  1055. + .stem_widths={on, 10, 22, maxp,}
  1056. +},
  1057. +#line 39 "ftinf_rh.gperf"
  1058. +{ .name="arimo",
  1059. + .always_use_100={on, 0, maxp, end},
  1060. + .stem_translating={on, 11, 32, end},
  1061. + .stem_translating_only={on, 10, 8, 8, 32, 9, 32, end}
  1062. +},
  1063. +#line 207 "ftinf_rh.gperf"
  1064. +{ .name="optima",
  1065. + .brightness={on, 0, -20, end},
  1066. + .contrast={on, 0, 25, end},
  1067. + .stem_scaling={on, 17, 1, end},
  1068. + .stem_translating_only={on, 10, 0, 11, 0, 12, 0, end}
  1069. +},
  1070. +#line 63 "ftinf_rh.gperf"
  1071. +{ .name="candara",
  1072. + .stem_scaling={on, 14, 1, 17, 1, end},
  1073. + .stem_translating_only={on, 10, 16, end}
  1074. +},
  1075. +#line 77 "ftinf_rh.gperf"
  1076. +{ .name="comfortaa",
  1077. + .stem_widths={on, 10, 19, 22, maxp},
  1078. + .stem_scaling={on, 11, 0, end}
  1079. +},
  1080. +#line 161 "ftinf_rh.gperf"
  1081. +{ .name="liberation mono",
  1082. + .always_use_100={on, 0, maxp, end}
  1083. +},
  1084. +#line 18 "ftinf_rh.gperf"
  1085. +{ .name="andale mono",
  1086. + .always_use_100={on, 0, maxp, end},
  1087. + .stem_scaling={on, 11, 1, end},
  1088. + .stem_widths={on, 10, 21, maxp,}
  1089. +},
  1090. +#line 256 "ftinf_rh.gperf"
  1091. +{ .name="verdana",
  1092. + .always_use_100={on, 0, 14, 16, maxp, end},
  1093. + .stem_scaling={on, 12, 1, 15, 1, end},
  1094. + .stem_translating_only={on, 8, 16, 15, 16, 14, 32, 18, 32, 19, 24, end}
  1095. +},
  1096. +#line 74 "ftinf_rh.gperf"
  1097. +{ .name="century gothic",
  1098. + .stem_widths={on, 10, 22, maxp,}
  1099. +},
  1100. +#line 91 "ftinf_rh.gperf"
  1101. +{ .name="courier new",
  1102. + .always_use_100={on, 12, 12, end},
  1103. + .edge_detection={on, 10, 12, end},
  1104. + .m={on, 13, 1, 14, 1, end}
  1105. +},
  1106. +#line 23 "ftinf_rh.gperf"
  1107. +{ .name="arial narrow",
  1108. + .stem_widths={on, 10, 21, maxp,}
  1109. +},
  1110. +#line 185 "ftinf_rh.gperf"
  1111. +{ .name="luxi sans",
  1112. + .always_use_100={on, 13, 13, end},
  1113. + .stem_widths={on, 10, 17, sw2pv, maxp,}
  1114. +},
  1115. +#line 225 "ftinf_rh.gperf"
  1116. +{ .name="samba",
  1117. + .stem_scaling={on, 11, 0, end}
  1118. +},
  1119. +#line 233 "ftinf_rh.gperf"
  1120. +{ .name="tahoma",
  1121. + .always_use_100={on, 11, 11, 14, maxp, end},
  1122. + .edge_detection={on, 11, 11, end},
  1123. + .spacing={on, 10, 12, 18, 18, 30, end},
  1124. + .start={on, 14, 17, 30, 100, 100, end},
  1125. + .stem_translating={on, 11, 32, end},
  1126. + .stem_translating_only={on, 7, 32, 8, 32, 9, 32, end},
  1127. +},
  1128. +#line 164 "ftinf_rh.gperf"
  1129. +{ .name="liberation sans narrow",
  1130. + .stem_widths={on,10, 22, maxp,}
  1131. +},
  1132. +#line 81 "ftinf_rh.gperf"
  1133. +{ .name="consolas",
  1134. + .always_use_100={on, 0, maxp, end},
  1135. + .stem_translating_only={on, 8, 32, 9, 32, end},
  1136. + .stem_widths={on, 10, 20, maxp,},
  1137. + .stem_scaling={on, 11, 1, end}
  1138. +},
  1139. +#line 203 "ftinf_rh.gperf"
  1140. +{ .name="open sans",
  1141. + .stem_translating_only={on, 10, 16, 9, 16, end},
  1142. + .stem_widths={on, 10, 20, maxp,}
  1143. +},
  1144. +#line 167 "ftinf_rh.gperf"
  1145. +{ .name="liberation sans",
  1146. + .edge_detection={on, 11, 11, end},
  1147. + .stem_translating={on, 11, 32, end},
  1148. + .stem_translating_only={on, 10, 8, 8, 32, 9, 32, end},
  1149. + .stem_widths={on,10, 19, maxp,}
  1150. +},
  1151. +#line 193 "ftinf_rh.gperf"
  1152. +{ .name="monaco",
  1153. + .always_use_100={on, 0, maxp, end}
  1154. +},
  1155. +#line 101 "ftinf_rh.gperf"
  1156. +{ .name="cousine",
  1157. + .always_use_100={on, 0, maxp, end}
  1158. +},
  1159. +#line 176 "ftinf_rh.gperf"
  1160. +{ .name="lucida grande",
  1161. + .stem_scaling={on, 13, 1, end},
  1162. + .stem_translating_only={on, 13, 24, 14, 24, 8, 16, 9, 16, end},
  1163. + .stem_widths={on, 10, 16, sw2pv, maxp},
  1164. +},
  1165. +#line 173 "ftinf_rh.gperf"
  1166. +{ .name="lucida console",
  1167. + .always_use_100={on, 0, maxp, end}
  1168. +},
  1169. +#line 196 "ftinf_rh.gperf"
  1170. +{ .name="myriad pro",
  1171. + .stem_scaling={on, 14, 1, 17, 1, end},
  1172. + .stem_translating_only={on, 10, 16, 11, 0, 9, 16, end}
  1173. +},
  1174. +#line 26 "ftinf_rh.gperf"
  1175. +{ .name="arial unicode ms",
  1176. + .always_use_100={on, 0, maxp, end},
  1177. + .stem_translating={on, 11, 32, end},
  1178. + .stem_translating_only={on, 10, 16, 8, 32, 9, 32, end}
  1179. +},
  1180. +#line 213 "ftinf_rh.gperf"
  1181. +{ .name="palatino linotype",
  1182. + .edge_detection={on, 0, 100, end}
  1183. +},
  1184. +#line 181 "ftinf_rh.gperf"
  1185. +{ .name="lucida sans unicode",
  1186. + .stem_translating_only={on, 13, 24, 14, 24, 8, 16, 9, 16, end},
  1187. + .stem_widths={on,10, 16, sw2pv, maxp,}
  1188. +},
  1189. +#line 140 "ftinf_rh.gperf"
  1190. +{ .name="futura",
  1191. + .stem_widths={on, 10, 14, sw2pv, maxp,}
  1192. +},
  1193. +#line 147 "ftinf_rh.gperf"
  1194. +{ .name="georgia",
  1195. + .stem_translating_only={on, 13, 16, 14, 16, 15, 0, end}
  1196. +},
  1197. +#line 125 "ftinf_rh.gperf"
  1198. +{ .name="freemono",
  1199. + .always_use_100={on, 0, maxp, end}
  1200. +},
  1201. +#line 200 "ftinf_rh.gperf"
  1202. +{ .name="nina",
  1203. + .stem_scaling={on, 11, 0, 12, 0, 13, 0, end}
  1204. +},
  1205. +#line 121 "ftinf_rh.gperf"
  1206. +{ .name="essential pragmatapro",
  1207. + .always_use_100={on, 0, maxp, end},
  1208. + .m={on, 13, 0, 14, 0, end}
  1209. +},
  1210. +#line 247 "ftinf_rh.gperf"
  1211. +{ .name="trebuchet ms",
  1212. + .always_use_100={on, 13, 13, end},
  1213. + .stem_scaling={on, 13, 0, 17, 0, 20, 1, end},
  1214. + .stem_translating_only={on, 10, 16, 11, 0, 8, 32, 9, 32, end},
  1215. + .stem_widths={on, 10, 17, sw2pv, maxp,}
  1216. +},
  1217. +#line 114 "ftinf_rh.gperf"
  1218. +{ .name="droid sans mono",
  1219. + .m={on, 12, 0, end}
  1220. +},
  1221. +#line 104 "ftinf_rh.gperf"
  1222. +{ .name="dejavu sans mono",
  1223. + .always_use_100={on, 0, maxp, end},
  1224. + .stem_translating_only={on, 7, 16, 8, 32, 9, 16, end}
  1225. +},
  1226. +#line 57 "ftinf_rh.gperf"
  1227. +{ .name="calibri",
  1228. + .always_use_100={on, 23, maxp, end},
  1229. + .stem_scaling={on, 15, 1, 17, 1, 18, 1, end},
  1230. + .stem_translating_only={on, 10, 16, 15, 0, end},
  1231. + .stem_widths={on, 1, 10, 19, maxp,}
  1232. +},
  1233. +#line 156 "ftinf_rh.gperf"
  1234. +{ .name="inconsolata",
  1235. + .stem_scaling={on, 12, 1, 15, 1, end},
  1236. + .stem_translating_only={on, 10, 24, 9, 32, end},
  1237. + .stem_widths={on, 10, 23, maxp,},
  1238. +},
  1239. +#line 96 "ftinf_rh.gperf"
  1240. +{ .name="courier",
  1241. + .always_use_100={on, 0, maxp, end},
  1242. + .m={on, 13, 1, 14, 1, end},
  1243. + .stem_translating_only={on, 13, 16, 15, 0, end}
  1244. +},
  1245. +#line 128 "ftinf_rh.gperf"
  1246. +{ .name="freesans",
  1247. + .always_use_100={on, 0, maxp, end},
  1248. + .edge_detection={on, 11, 11, 13, 13, end},
  1249. + .spacing={on, 10, 12, 18, 18, 30, end},
  1250. + .start={on, 10, 18, 18, 25, 30, end},
  1251. + .stem_scaling={on, 16, 0, end},
  1252. + .stem_translating={on, 11, 32, end},
  1253. + .stem_translating_only={on, 10, 16, 9, 8, end}
  1254. +},
  1255. +#line 150 "ftinf_rh.gperf"
  1256. +{ .name="gill sans",
  1257. + .stem_widths={on, 10, 17, sw2pv, maxp,}
  1258. +},
  1259. +#line 117 "ftinf_rh.gperf"
  1260. +{ .name="droid sans",
  1261. + .always_use_100={on, 12, 12, 15, 15, end},
  1262. + .stem_translating_only={on, 8, 16, 9, 16, end}
  1263. +},
  1264. +#line 108 "ftinf_rh.gperf"
  1265. +{ .name="dejavu sans",
  1266. + .always_use_100={on, 10, 14, 16, 17, end},
  1267. + .m={on, 12, 0, end},
  1268. + .stem_scaling={on, 12, 1, end},
  1269. + .stem_translating_only={on, 8, 16, 15, -20, end}
  1270. +},
  1271. +#line 219 "ftinf_rh.gperf"
  1272. +{ .name="raleway",
  1273. + .stem_scaling={on, 15, 0, end}
  1274. +},
  1275. +#line 153 "ftinf_rh.gperf"
  1276. +{ .name="helvetica cy",
  1277. + .stem_widths={on, 10, 23, maxp,}
  1278. +},
  1279. +#line 228 "ftinf_rh.gperf"
  1280. +{ .name="segoe ui",
  1281. + .always_use_100={on, 11, 12, 14, 14, end},
  1282. + .stem_translating_only={on, 10, 0, 7, 32, 8, 16, 9, 24, end},
  1283. + .stem_widths={on, 10, 23, maxp,}
  1284. +},
  1285. +#line 48 "ftinf_rh.gperf"
  1286. +{ .name="bitstream vera sans mono",
  1287. + .always_use_100={on, 0, maxp, end}
  1288. +},
  1289. +#line 241 "ftinf_rh.gperf"
  1290. +{ .name="times new roman",
  1291. + .always_use_100={on, 14, 14, 16, 16, end},
  1292. + .bearing_correction={0, 100, end},
  1293. + .stem_scaling={on, 17, 1, end},
  1294. + .stem_translating_only={on, 17, 8, end}
  1295. +},
  1296. +#line 222 "ftinf_rh.gperf"
  1297. +{ .name="rokkitt",
  1298. + .stem_widths={on, 10, 21, maxp,}
  1299. +},
  1300. +#line 143 "ftinf_rh.gperf"
  1301. +{ .name="garamond",
  1302. + .brightness={on, 0, -20, end},
  1303. + .contrast={on, 0, 25, end}
  1304. +},
  1305. +#line 137 "ftinf_rh.gperf"
  1306. +{ .name="freeserif",
  1307. + .stem_scaling={on, 13, 1, 17, 1, end}
  1308. +},
  1309. +#line 189 "ftinf_rh.gperf"
  1310. +{ .name="microsoft sans serif",
  1311. + .always_use_100={on, 0, maxp, end},
  1312. + .stem_translating_only={on, 10, 16, 8, 32, 9, 32, end}
  1313. +},
  1314. +#line 44 "ftinf_rh.gperf"
  1315. +{ .name="baskerville",
  1316. + .brightness={on, 0, -20, end},
  1317. + .contrast={on, 0, 25, end}
  1318. +},
  1319. +#line 51 "ftinf_rh.gperf"
  1320. +{ .name="bitstream vera sans",
  1321. + .always_use_100={on, 10, 14, 16, 17, end},
  1322. + .m={on, 12, 0, end},
  1323. + .stem_scaling={on ,12, 1, end},
  1324. + .stem_translating_only={on, 8, 16, end}
  1325. +}
  1326. + };
  1327. +
  1328. + if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
  1329. + {
  1330. + register int key = _rules_hash (str, len);
  1331. +
  1332. + if (key <= MAX_HASH_VALUE && key >= MIN_HASH_VALUE)
  1333. + {
  1334. + register const struct sa_rules_s *resword;
  1335. +
  1336. + switch (key - 3)
  1337. + {
  1338. + case 0:
  1339. + resword = &wordlist[0];
  1340. + goto compare;
  1341. + case 3:
  1342. + resword = &wordlist[1];
  1343. + goto compare;
  1344. + case 7:
  1345. + resword = &wordlist[2];
  1346. + goto compare;
  1347. + case 8:
  1348. + resword = &wordlist[3];
  1349. + goto compare;
  1350. + case 9:
  1351. + resword = &wordlist[4];
  1352. + goto compare;
  1353. + case 10:
  1354. + resword = &wordlist[5];
  1355. + goto compare;
  1356. + case 11:
  1357. + resword = &wordlist[6];
  1358. + goto compare;
  1359. + case 12:
  1360. + resword = &wordlist[7];
  1361. + goto compare;
  1362. + case 13:
  1363. + resword = &wordlist[8];
  1364. + goto compare;
  1365. + case 14:
  1366. + resword = &wordlist[9];
  1367. + goto compare;
  1368. + case 16:
  1369. + resword = &wordlist[10];
  1370. + goto compare;
  1371. + case 17:
  1372. + resword = &wordlist[11];
  1373. + goto compare;
  1374. + case 18:
  1375. + resword = &wordlist[12];
  1376. + goto compare;
  1377. + case 19:
  1378. + resword = &wordlist[13];
  1379. + goto compare;
  1380. + case 21:
  1381. + resword = &wordlist[14];
  1382. + goto compare;
  1383. + case 23:
  1384. + resword = &wordlist[15];
  1385. + goto compare;
  1386. + case 24:
  1387. + resword = &wordlist[16];
  1388. + goto compare;
  1389. + case 26:
  1390. + resword = &wordlist[17];
  1391. + goto compare;
  1392. + case 27:
  1393. + resword = &wordlist[18];
  1394. + goto compare;
  1395. + case 28:
  1396. + resword = &wordlist[19];
  1397. + goto compare;
  1398. + case 29:
  1399. + resword = &wordlist[20];
  1400. + goto compare;
  1401. + case 30:
  1402. + resword = &wordlist[21];
  1403. + goto compare;
  1404. + case 31:
  1405. + resword = &wordlist[22];
  1406. + goto compare;
  1407. + case 32:
  1408. + resword = &wordlist[23];
  1409. + goto compare;
  1410. + case 33:
  1411. + resword = &wordlist[24];
  1412. + goto compare;
  1413. + case 34:
  1414. + resword = &wordlist[25];
  1415. + goto compare;
  1416. + case 35:
  1417. + resword = &wordlist[26];
  1418. + goto compare;
  1419. + case 36:
  1420. + resword = &wordlist[27];
  1421. + goto compare;
  1422. + case 37:
  1423. + resword = &wordlist[28];
  1424. + goto compare;
  1425. + case 38:
  1426. + resword = &wordlist[29];
  1427. + goto compare;
  1428. + case 39:
  1429. + resword = &wordlist[30];
  1430. + goto compare;
  1431. + case 41:
  1432. + resword = &wordlist[31];
  1433. + goto compare;
  1434. + case 43:
  1435. + resword = &wordlist[32];
  1436. + goto compare;
  1437. + case 44:
  1438. + resword = &wordlist[33];
  1439. + goto compare;
  1440. + case 45:
  1441. + resword = &wordlist[34];
  1442. + goto compare;
  1443. + case 46:
  1444. + resword = &wordlist[35];
  1445. + goto compare;
  1446. + case 48:
  1447. + resword = &wordlist[36];
  1448. + goto compare;
  1449. + case 49:
  1450. + resword = &wordlist[37];
  1451. + goto compare;
  1452. + case 52:
  1453. + resword = &wordlist[38];
  1454. + goto compare;
  1455. + case 53:
  1456. + resword = &wordlist[39];
  1457. + goto compare;
  1458. + case 54:
  1459. + resword = &wordlist[40];
  1460. + goto compare;
  1461. + case 58:
  1462. + resword = &wordlist[41];
  1463. + goto compare;
  1464. + case 59:
  1465. + resword = &wordlist[42];
  1466. + goto compare;
  1467. + case 60:
  1468. + resword = &wordlist[43];
  1469. + goto compare;
  1470. + case 61:
  1471. + resword = &wordlist[44];
  1472. + goto compare;
  1473. + case 62:
  1474. + resword = &wordlist[45];
  1475. + goto compare;
  1476. + case 63:
  1477. + resword = &wordlist[46];
  1478. + goto compare;
  1479. + case 64:
  1480. + resword = &wordlist[47];
  1481. + goto compare;
  1482. + case 69:
  1483. + resword = &wordlist[48];
  1484. + goto compare;
  1485. + case 70:
  1486. + resword = &wordlist[49];
  1487. + goto compare;
  1488. + case 71:
  1489. + resword = &wordlist[50];
  1490. + goto compare;
  1491. + case 72:
  1492. + resword = &wordlist[51];
  1493. + goto compare;
  1494. + case 74:
  1495. + resword = &wordlist[52];
  1496. + goto compare;
  1497. + case 75:
  1498. + resword = &wordlist[53];
  1499. + goto compare;
  1500. + case 76:
  1501. + resword = &wordlist[54];
  1502. + goto compare;
  1503. + case 77:
  1504. + resword = &wordlist[55];
  1505. + goto compare;
  1506. + case 78:
  1507. + resword = &wordlist[56];
  1508. + goto compare;
  1509. + case 81:
  1510. + resword = &wordlist[57];
  1511. + goto compare;
  1512. + }
  1513. + return 0;
  1514. + compare:
  1515. + {
  1516. + register const char *s = resword->name;
  1517. +
  1518. + if (*str == *s && !strcmp (str + 1, s + 1))
  1519. + return resword;
  1520. + }
  1521. + }
  1522. + }
  1523. + return 0;
  1524. +}
  1525. +#line 261 "ftinf_rh.gperf"
  1526. +
  1527. +
  1528. +static const sa_rules_t*
  1529. +ftinf_rules( const char *name ){
  1530. + if( name ){
  1531. + enum {
  1532. + max_wlen=31
  1533. + };
  1534. + char buf[max_wlen+1];
  1535. + int len=strlen( name );
  1536. + if( len <= max_wlen ){
  1537. + int i;
  1538. + for( i=0; i<len; ++i )
  1539. + buf[i]=tolower( name[i] );
  1540. + buf[len]='\0';
  1541. + return _rules_get( buf, len );
  1542. + }
  1543. + }
  1544. + return NULL;
  1545. +}
  1546. +/*
  1547. + gperf --output-file=ftinf_rh.c ftinf_rh.gperf
  1548. +*/
  1549. diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/src/base/ftinf_rh.gperf a/src/base/ftinf_rh.gperf
  1550. --- b/src/base/ftinf_rh.gperf 1970-01-01 03:00:00.000000000 +0300
  1551. +++ a/src/base/ftinf_rh.gperf 2021-09-16 09:15:05.052379743 +0300
  1552. @@ -0,0 +1,283 @@
  1553. +%struct-type
  1554. +%define slot-name name
  1555. +%enum
  1556. +%switch=1
  1557. +%readonly-tables
  1558. +%omit-struct-type
  1559. +%define lookup-function-name _rules_get
  1560. +%define hash-function-name _rules_hash
  1561. +%{
  1562. +#include <ctype.h>
  1563. +static const struct sa_rules_s* _rules_get( const char*str, unsigned len );
  1564. +%}
  1565. +struct sa_rules_s;
  1566. +%%
  1567. +{ .name="---",
  1568. + .synthesize_stems={on, 13, 13, end}
  1569. +},
  1570. +{ .name="andale mono",
  1571. + .always_use_100={on, 0, maxp, end},
  1572. + .stem_scaling={on, 11, 1, end},
  1573. + .stem_widths={on, 10, 21, maxp,}
  1574. +},
  1575. +{ .name="arial narrow",
  1576. + .stem_widths={on, 10, 21, maxp,}
  1577. +},
  1578. +{ .name="arial unicode ms",
  1579. + .always_use_100={on, 0, maxp, end},
  1580. + .stem_translating={on, 11, 32, end},
  1581. + .stem_translating_only={on, 10, 16, 8, 32, 9, 32, end}
  1582. +},
  1583. +{ .name="arial",
  1584. + .always_use_100={on, 0, maxp, end},
  1585. + .edge_detection={on, 11, 11, 13, 13, end},
  1586. + .spacing={on, 10, 11, 23, 25, 30, end},
  1587. + .start={on, 11, 18, 23, 30, 30, end},
  1588. + .stem_translating={on, 11, 32, end},
  1589. + .stem_translating_only={on, 10, 16, 8, 32, 9, 32, 16, -24, end}
  1590. +},
  1591. +{ .name="arimo",
  1592. + .always_use_100={on, 0, maxp, end},
  1593. + .stem_translating={on, 11, 32, end},
  1594. + .stem_translating_only={on, 10, 8, 8, 32, 9, 32, end}
  1595. +},
  1596. +{ .name="baskerville",
  1597. + .brightness={on, 0, -20, end},
  1598. + .contrast={on, 0, 25, end}
  1599. +},
  1600. +{ .name="bitstream vera sans mono",
  1601. + .always_use_100={on, 0, maxp, end}
  1602. +},
  1603. +{ .name="bitstream vera sans",
  1604. + .always_use_100={on, 10, 14, 16, 17, end},
  1605. + .m={on, 12, 0, end},
  1606. + .stem_scaling={on ,12, 1, end},
  1607. + .stem_translating_only={on, 8, 16, end}
  1608. +},
  1609. +{ .name="calibri",
  1610. + .always_use_100={on, 23, maxp, end},
  1611. + .stem_scaling={on, 15, 1, 17, 1, 18, 1, end},
  1612. + .stem_translating_only={on, 10, 16, 15, 0, end},
  1613. + .stem_widths={on, 1, 10, 19, maxp,}
  1614. +},
  1615. +{ .name="candara",
  1616. + .stem_scaling={on, 14, 1, 17, 1, end},
  1617. + .stem_translating_only={on, 10, 16, end}
  1618. +},
  1619. +{ .name="cantarell",
  1620. + .stem_translating_only={on, 11, 0, 12, 0, end},
  1621. + .stem_widths={on, 10, 22, maxp,}
  1622. +},
  1623. +{ .name="canwell",
  1624. + .stem_scaling={on, 13, 0, end}
  1625. +},
  1626. +{ .name="century gothic",
  1627. + .stem_widths={on, 10, 22, maxp,}
  1628. +},
  1629. +{ .name="comfortaa",
  1630. + .stem_widths={on, 10, 19, 22, maxp},
  1631. + .stem_scaling={on, 11, 0, end}
  1632. +},
  1633. +{ .name="consolas",
  1634. + .always_use_100={on, 0, maxp, end},
  1635. + .stem_translating_only={on, 8, 32, 9, 32, end},
  1636. + .stem_widths={on, 10, 20, maxp,},
  1637. + .stem_scaling={on, 11, 1, end}
  1638. +},
  1639. +{ .name="corbel",
  1640. + .stem_translating_only={on, 10, 16, end},
  1641. + .stem_widths={on, 10, 21, maxp}
  1642. +},
  1643. +{ .name="courier new",
  1644. + .always_use_100={on, 12, 12, end},
  1645. + .edge_detection={on, 10, 12, end},
  1646. + .m={on, 13, 1, 14, 1, end}
  1647. +},
  1648. +{ .name="courier",
  1649. + .always_use_100={on, 0, maxp, end},
  1650. + .m={on, 13, 1, 14, 1, end},
  1651. + .stem_translating_only={on, 13, 16, 15, 0, end}
  1652. +},
  1653. +{ .name="cousine",
  1654. + .always_use_100={on, 0, maxp, end}
  1655. +},
  1656. +{ .name="dejavu sans mono",
  1657. + .always_use_100={on, 0, maxp, end},
  1658. + .stem_translating_only={on, 7, 16, 8, 32, 9, 16, end}
  1659. +},
  1660. +{ .name="dejavu sans",
  1661. + .always_use_100={on, 10, 14, 16, 17, end},
  1662. + .m={on, 12, 0, end},
  1663. + .stem_scaling={on, 12, 1, end},
  1664. + .stem_translating_only={on, 8, 16, 15, -20, end}
  1665. +},
  1666. +{ .name="droid sans mono",
  1667. + .m={on, 12, 0, end}
  1668. +},
  1669. +{ .name="droid sans",
  1670. + .always_use_100={on, 12, 12, 15, 15, end},
  1671. + .stem_translating_only={on, 8, 16, 9, 16, end}
  1672. +},
  1673. +{ .name="essential pragmatapro",
  1674. + .always_use_100={on, 0, maxp, end},
  1675. + .m={on, 13, 0, 14, 0, end}
  1676. +},
  1677. +{ .name="freemono",
  1678. + .always_use_100={on, 0, maxp, end}
  1679. +},
  1680. +{ .name="freesans",
  1681. + .always_use_100={on, 0, maxp, end},
  1682. + .edge_detection={on, 11, 11, 13, 13, end},
  1683. + .spacing={on, 10, 12, 18, 18, 30, end},
  1684. + .start={on, 10, 18, 18, 25, 30, end},
  1685. + .stem_scaling={on, 16, 0, end},
  1686. + .stem_translating={on, 11, 32, end},
  1687. + .stem_translating_only={on, 10, 16, 9, 8, end}
  1688. +},
  1689. +{ .name="freeserif",
  1690. + .stem_scaling={on, 13, 1, 17, 1, end}
  1691. +},
  1692. +{ .name="futura",
  1693. + .stem_widths={on, 10, 14, sw2pv, maxp,}
  1694. +},
  1695. +{ .name="garamond",
  1696. + .brightness={on, 0, -20, end},
  1697. + .contrast={on, 0, 25, end}
  1698. +},
  1699. +{ .name="georgia",
  1700. + .stem_translating_only={on, 13, 16, 14, 16, 15, 0, end}
  1701. +},
  1702. +{ .name="gill sans",
  1703. + .stem_widths={on, 10, 17, sw2pv, maxp,}
  1704. +},
  1705. +{ .name="helvetica cy",
  1706. + .stem_widths={on, 10, 23, maxp,}
  1707. +},
  1708. +{ .name="inconsolata",
  1709. + .stem_scaling={on, 12, 1, 15, 1, end},
  1710. + .stem_translating_only={on, 10, 24, 9, 32, end},
  1711. + .stem_widths={on, 10, 23, maxp,},
  1712. +},
  1713. +{ .name="liberation mono",
  1714. + .always_use_100={on, 0, maxp, end}
  1715. +},
  1716. +{ .name="liberation sans narrow",
  1717. + .stem_widths={on,10, 22, maxp,}
  1718. +},
  1719. +{ .name="liberation sans",
  1720. + .edge_detection={on, 11, 11, end},
  1721. + .stem_translating={on, 11, 32, end},
  1722. + .stem_translating_only={on, 10, 8, 8, 32, 9, 32, end},
  1723. + .stem_widths={on,10, 19, maxp,}
  1724. +},
  1725. +{ .name="lucida console",
  1726. + .always_use_100={on, 0, maxp, end}
  1727. +},
  1728. +{ .name="lucida grande",
  1729. + .stem_scaling={on, 13, 1, end},
  1730. + .stem_translating_only={on, 13, 24, 14, 24, 8, 16, 9, 16, end},
  1731. + .stem_widths={on, 10, 16, sw2pv, maxp},
  1732. +},
  1733. +{ .name="lucida sans unicode",
  1734. + .stem_translating_only={on, 13, 24, 14, 24, 8, 16, 9, 16, end},
  1735. + .stem_widths={on,10, 16, sw2pv, maxp,}
  1736. +},
  1737. +{ .name="luxi sans",
  1738. + .always_use_100={on, 13, 13, end},
  1739. + .stem_widths={on, 10, 17, sw2pv, maxp,}
  1740. +},
  1741. +{ .name="microsoft sans serif",
  1742. + .always_use_100={on, 0, maxp, end},
  1743. + .stem_translating_only={on, 10, 16, 8, 32, 9, 32, end}
  1744. +},
  1745. +{ .name="monaco",
  1746. + .always_use_100={on, 0, maxp, end}
  1747. +},
  1748. +{ .name="myriad pro",
  1749. + .stem_scaling={on, 14, 1, 17, 1, end},
  1750. + .stem_translating_only={on, 10, 16, 11, 0, 9, 16, end}
  1751. +},
  1752. +{ .name="nina",
  1753. + .stem_scaling={on, 11, 0, 12, 0, 13, 0, end}
  1754. +},
  1755. +{ .name="open sans",
  1756. + .stem_translating_only={on, 10, 16, 9, 16, end},
  1757. + .stem_widths={on, 10, 20, maxp,}
  1758. +},
  1759. +{ .name="optima",
  1760. + .brightness={on, 0, -20, end},
  1761. + .contrast={on, 0, 25, end},
  1762. + .stem_scaling={on, 17, 1, end},
  1763. + .stem_translating_only={on, 10, 0, 11, 0, 12, 0, end}
  1764. +},
  1765. +{ .name="palatino linotype",
  1766. + .edge_detection={on, 0, 100, end}
  1767. +},
  1768. +{ .name="pragmata",
  1769. + .always_use_100={on, 0, maxp, end}
  1770. +},
  1771. +{ .name="raleway",
  1772. + .stem_scaling={on, 15, 0, end}
  1773. +},
  1774. +{ .name="rokkitt",
  1775. + .stem_widths={on, 10, 21, maxp,}
  1776. +},
  1777. +{ .name="samba",
  1778. + .stem_scaling={on, 11, 0, end}
  1779. +},
  1780. +{ .name="segoe ui",
  1781. + .always_use_100={on, 11, 12, 14, 14, end},
  1782. + .stem_translating_only={on, 10, 0, 7, 32, 8, 16, 9, 24, end},
  1783. + .stem_widths={on, 10, 23, maxp,}
  1784. +},
  1785. +{ .name="tahoma",
  1786. + .always_use_100={on, 11, 11, 14, maxp, end},
  1787. + .edge_detection={on, 11, 11, end},
  1788. + .spacing={on, 10, 12, 18, 18, 30, end},
  1789. + .start={on, 14, 17, 30, 100, 100, end},
  1790. + .stem_translating={on, 11, 32, end},
  1791. + .stem_translating_only={on, 7, 32, 8, 32, 9, 32, end},
  1792. +},
  1793. +{ .name="times new roman",
  1794. + .always_use_100={on, 14, 14, 16, 16, end},
  1795. + .bearing_correction={0, 100, end},
  1796. + .stem_scaling={on, 17, 1, end},
  1797. + .stem_translating_only={on, 17, 8, end}
  1798. +},
  1799. +{ .name="trebuchet ms",
  1800. + .always_use_100={on, 13, 13, end},
  1801. + .stem_scaling={on, 13, 0, 17, 0, 20, 1, end},
  1802. + .stem_translating_only={on, 10, 16, 11, 0, 8, 32, 9, 32, end},
  1803. + .stem_widths={on, 10, 17, sw2pv, maxp,}
  1804. +},
  1805. +{ .name="ubuntu",
  1806. + .always_use_100={on, 12, 13, 15, 15, end}
  1807. +},
  1808. +{ .name="verdana",
  1809. + .always_use_100={on, 0, 14, 16, maxp, end},
  1810. + .stem_scaling={on, 12, 1, 15, 1, end},
  1811. + .stem_translating_only={on, 8, 16, 15, 16, 14, 32, 18, 32, 19, 24, end}
  1812. +},
  1813. +%%
  1814. +
  1815. +static const sa_rules_t*
  1816. +ftinf_rules( const char *name ){
  1817. + if( name ){
  1818. + enum {
  1819. + max_wlen=31
  1820. + };
  1821. + char buf[max_wlen+1];
  1822. + int len=strlen( name );
  1823. + if( len <= max_wlen ){
  1824. + int i;
  1825. + for( i=0; i<len; ++i )
  1826. + buf[i]=tolower( name[i] );
  1827. + buf[len]='\0';
  1828. + return _rules_get( buf, len );
  1829. + }
  1830. + }
  1831. + return NULL;
  1832. +}
  1833. +/*
  1834. + gperf --output-file=ftinf_rh.c ftinf_rh.gperf
  1835. +*/
  1836. diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/src/base/ftinf_sh.c a/src/base/ftinf_sh.c
  1837. --- b/src/base/ftinf_sh.c 1970-01-01 03:00:00.000000000 +0300
  1838. +++ a/src/base/ftinf_sh.c 2021-09-16 09:15:05.052379743 +0300
  1839. @@ -0,0 +1,463 @@
  1840. +/* ANSI-C code produced by gperf version 3.1 */
  1841. +/* Command-line: gperf --output-file=ftinf_sh.c ftinf_sh.gperf */
  1842. +/* Computed positions: -k'1,$' */
  1843. +
  1844. +#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
  1845. + && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
  1846. + && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
  1847. + && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
  1848. + && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
  1849. + && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
  1850. + && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
  1851. + && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
  1852. + && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
  1853. + && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
  1854. + && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
  1855. + && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
  1856. + && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
  1857. + && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
  1858. + && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
  1859. + && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
  1860. + && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
  1861. + && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
  1862. + && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
  1863. + && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
  1864. + && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
  1865. + && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
  1866. + && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
  1867. +/* The character set is not based on ISO-646. */
  1868. +#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>."
  1869. +#endif
  1870. +
  1871. +#line 9 "ftinf_sh.gperf"
  1872. +
  1873. +#include <ctype.h>
  1874. +static const struct ftinf_s* _settings_get( const char*str, unsigned len);
  1875. +/* maximum key range = 37, duplicates = 0 */
  1876. +
  1877. +#ifdef __GNUC__
  1878. +__inline
  1879. +#else
  1880. +#ifdef __cplusplus
  1881. +inline
  1882. +#endif
  1883. +#endif
  1884. +static unsigned int
  1885. +_settings_hash (register const char *str, register unsigned int len)
  1886. +{
  1887. + static const unsigned char asso_values[] =
  1888. + {
  1889. + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
  1890. + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
  1891. + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
  1892. + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
  1893. + 40, 40, 40, 40, 40, 40, 40, 40, 40, 13,
  1894. + 8, 30, 25, 20, 40, 10, 40, 40, 40, 40,
  1895. + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
  1896. + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
  1897. + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
  1898. + 40, 40, 40, 40, 40, 40, 40, 5, 40, 0,
  1899. + 0, 0, 40, 40, 10, 0, 40, 40, 15, 5,
  1900. + 10, 0, 10, 40, 40, 0, 0, 0, 0, 0,
  1901. + 0, 0, 40, 40, 40, 40, 40, 40, 40, 40,
  1902. + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
  1903. + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
  1904. + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
  1905. + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
  1906. + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
  1907. + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
  1908. + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
  1909. + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
  1910. + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
  1911. + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
  1912. + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
  1913. + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
  1914. + 40, 40, 40, 40, 40, 40
  1915. + };
  1916. + return len + asso_values[(unsigned char)str[len - 1]] + asso_values[(unsigned char)str[0]];
  1917. +}
  1918. +
  1919. +#ifdef __GNUC__
  1920. +__inline
  1921. +#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
  1922. +__attribute__ ((__gnu_inline__))
  1923. +#endif
  1924. +#endif
  1925. +const struct ftinf_s *
  1926. +_settings_get (register const char *str, register unsigned int len)
  1927. +{
  1928. + enum
  1929. + {
  1930. + TOTAL_KEYWORDS = 22,
  1931. + MIN_WORD_LENGTH = 3,
  1932. + MAX_WORD_LENGTH = 14,
  1933. + MIN_HASH_VALUE = 3,
  1934. + MAX_HASH_VALUE = 39
  1935. + };
  1936. +
  1937. + static const struct ftinf_s wordlist[] =
  1938. + {
  1939. +#line 76 "ftinf_sh.gperf"
  1940. +{ .name="osx",
  1941. + .autohint_horizontal_stem_darken_strength=10,
  1942. + .autohint_vertical_stem_darken_strength=25,
  1943. + .bold_embolden_x_value=16,
  1944. + .brightness=10,
  1945. + .contrast=20,
  1946. + .filter_params={on, 3, 32, 38, 32, 3},
  1947. + .gamma_correction={1000, 80},
  1948. + .global_embolden_y_value=8,
  1949. + .grayscale_filter_strength=25,
  1950. +},
  1951. +#line 37 "ftinf_sh.gperf"
  1952. +{ .name="ipad",
  1953. + .filter_params={on, 0, 0, 100, 0, 0},
  1954. + .gamma_correction={1000, 80},
  1955. + .grayscale_filter_strength=100
  1956. +},
  1957. +#line 114 "ftinf_sh.gperf"
  1958. +{ .name="shove",
  1959. + .autohint_horizontal_stem_darken_strength=10,
  1960. + .autohint_increase_glyph_heights=true,
  1961. + .autohint_snap_stem_height=100,
  1962. + .autohint_vertical_stem_darken_strength=25,
  1963. + .filter_params={on, 11, 22, 38, 22, 11},
  1964. + .gamma_correction={0, 100},
  1965. + .stem_alignment_strength=100,
  1966. + .stem_fitting_strength=100,
  1967. + .use_known_settings_on_selected_fonts=true,
  1968. + .use_various_tweaks=true
  1969. +},
  1970. +#line 126 "ftinf_sh.gperf"
  1971. +{ .name="ubuntu",
  1972. + .autohint_horizontal_stem_darken_strength=10,
  1973. + .autohint_vertical_stem_darken_strength=25,
  1974. + .brightness=-10,
  1975. + .contrast=15,
  1976. + .filter_params={on, 11, 22, 38, 22, 11},
  1977. + .gamma_correction={1000, 80},
  1978. + .use_various_tweaks=true
  1979. +},
  1980. +#line 27 "ftinf_sh.gperf"
  1981. +{ .name="classic",
  1982. + .autohint_increase_glyph_heights=true,
  1983. + .autohint_snap_stem_height=100,
  1984. + .filter_params={on, 6, 25, 38, 25, 6},
  1985. + .gamma_correction={0, 100},
  1986. + .use_various_tweaks=true
  1987. +},
  1988. +#line 34 "ftinf_sh.gperf"
  1989. +{ .name="disabled",
  1990. + .gamma_correction={0, 100},
  1991. +},
  1992. +#line 100 "ftinf_sh.gperf"
  1993. +{ .name="sharpened",
  1994. + .autohint_horizontal_stem_darken_strength=10,
  1995. + .autohint_increase_glyph_heights=true,
  1996. + .autohint_snap_stem_height=100,
  1997. + .autohint_vertical_stem_darken_strength=25,
  1998. + .filter_params={on, 11, 22, 38, 22, 11},
  1999. + .gamma_correction={0, 100},
  2000. + .stem_alignment_strength=25,
  2001. + .stem_fitting_strength=25,
  2002. + .stem_snapping_sliding_scale=40,
  2003. + .use_known_settings_on_selected_fonts=true,
  2004. + .use_various_tweaks=true,
  2005. + .windows_style_sharpening_strength=65
  2006. +},
  2007. +#line 42 "ftinf_sh.gperf"
  2008. +{ .name="infinality",
  2009. + .autohint_horizontal_stem_darken_strength=10,
  2010. + .autohint_increase_glyph_heights=true,
  2011. + .autohint_snap_stem_height=100,
  2012. + .autohint_vertical_stem_darken_strength=25,
  2013. + .filter_params={on, 11, 22, 38, 22, 11},
  2014. + .gamma_correction={0, 100},
  2015. + .stem_alignment_strength=25,
  2016. + .stem_fitting_strength=25,
  2017. + .stem_snapping_sliding_scale=40,
  2018. + .use_known_settings_on_selected_fonts=true,
  2019. + .use_various_tweaks=true,
  2020. + .windows_style_sharpening_strength=5
  2021. +},
  2022. +#line 15 "ftinf_sh.gperf"
  2023. +{ .name="custom",
  2024. + .autohint_horizontal_stem_darken_strength=10,
  2025. + .autohint_snap_stem_height=100,
  2026. + .autohint_vertical_stem_darken_strength=25,
  2027. + .filter_params={on, 8, 24, 48, 24, 8},
  2028. + .gamma_correction={0, 100},
  2029. + .stem_alignment_strength=75,
  2030. + .stem_fitting_strength=50,
  2031. + .stem_snapping_sliding_scale=30,
  2032. + .use_known_settings_on_selected_fonts=true,
  2033. + .use_various_tweaks=true
  2034. +},
  2035. +#line 180 "ftinf_sh.gperf"
  2036. +{ .name="vanilla",
  2037. + .filter_params={on, 6, 25, 38, 25, 6},
  2038. + .gamma_correction={0, 100},
  2039. +},
  2040. +#line 184 "ftinf_sh.gperf"
  2041. +{ .name="windows7light",
  2042. + .autohint_horizontal_stem_darken_strength=10,
  2043. + .autohint_snap_stem_height=100,
  2044. + .autohint_vertical_stem_darken_strength=25,
  2045. + .contrast=20,
  2046. + .filter_params={on, 20, 25, 38, 25, 05},
  2047. + .fringe_filter_strength=100,
  2048. + .gamma_correction={1000, 160},
  2049. + .stem_snapping_sliding_scale=30,
  2050. + .use_known_settings_on_selected_fonts=true,
  2051. + .use_various_tweaks=true,
  2052. + .windows_style_sharpening_strength=100
  2053. +},
  2054. +#line 226 "ftinf_sh.gperf"
  2055. +{ .name="windowsxplight",
  2056. + .autohint_horizontal_stem_darken_strength=10,
  2057. + .autohint_snap_stem_height=100,
  2058. + .autohint_vertical_stem_darken_strength=25,
  2059. + .brightness=20,
  2060. + .contrast=30,
  2061. + .filter_params={on, 6, 25, 44, 25, 6},
  2062. + .fringe_filter_strength=100,
  2063. + .gamma_correction={1000, 120},
  2064. + .stem_alignment_strength=15,
  2065. + .stem_fitting_strength=15,
  2066. + .stem_snapping_sliding_scale=30,
  2067. + .use_known_settings_on_selected_fonts=true,
  2068. + .use_various_tweaks=true,
  2069. + .windows_style_sharpening_strength=65
  2070. +},
  2071. +#line 64 "ftinf_sh.gperf"
  2072. +{ .name="nudge",
  2073. + .autohint_horizontal_stem_darken_strength=10,
  2074. + .autohint_increase_glyph_heights=true,
  2075. + .autohint_snap_stem_height=100,
  2076. + .autohint_vertical_stem_darken_strength=25,
  2077. + .filter_params={on, 11, 22, 38, 22, 11},
  2078. + .gamma_correction={0, 100},
  2079. + .stem_alignment_strength=25,
  2080. + .stem_fitting_strength=15,
  2081. + .stem_snapping_sliding_scale=30,
  2082. + .use_various_tweaks=true,
  2083. +},
  2084. +#line 144 "ftinf_sh.gperf"
  2085. +{ .name="ultimate2",
  2086. + .filter_params={on, 6, 22, 36, 22, 6},
  2087. + .fringe_filter_strength=25,
  2088. + .gamma_correction={0, 100},
  2089. + .stem_alignment_strength=15,
  2090. + .stem_fitting_strength=15,
  2091. + .use_various_tweaks=true,
  2092. + .windows_style_sharpening_strength=25
  2093. +},
  2094. +#line 197 "ftinf_sh.gperf"
  2095. +{ .name="windows7",
  2096. + .filter_params={on, 20, 25, 42, 25, 06},
  2097. + .fringe_filter_strength=100,
  2098. + .autohint_horizontal_stem_darken_strength=10,
  2099. + .autohint_vertical_stem_darken_strength=25,
  2100. + .windows_style_sharpening_strength=65,
  2101. + .gamma_correction={1000, 120},
  2102. + .brightness=10,
  2103. + .contrast=20,
  2104. + .use_various_tweaks=true,
  2105. + .autohint_snap_stem_height=100,
  2106. + .use_known_settings_on_selected_fonts=true,
  2107. +},
  2108. +#line 210 "ftinf_sh.gperf"
  2109. +{ .name="windowsxp",
  2110. + .autohint_horizontal_stem_darken_strength=10,
  2111. + .autohint_snap_stem_height=100,
  2112. + .autohint_vertical_stem_darken_strength=25,
  2113. + .brightness=10,
  2114. + .contrast=20,
  2115. + .filter_params={on, 6, 25, 44, 25, 6},
  2116. + .fringe_filter_strength=100,
  2117. + .gamma_correction={1000, 120},
  2118. + .stem_alignment_strength=15,
  2119. + .stem_fitting_strength=15,
  2120. + .stem_snapping_sliding_scale=30,
  2121. + .use_known_settings_on_selected_fonts=true,
  2122. + .use_various_tweaks=true,
  2123. + .windows_style_sharpening_strength=65
  2124. +},
  2125. +#line 56 "ftinf_sh.gperf"
  2126. +{ .name="linux",
  2127. + .autohint_horizontal_stem_darken_strength=10,
  2128. + .autohint_snap_stem_height=100,
  2129. + .autohint_vertical_stem_darken_strength=25,
  2130. + .filter_params={on, 6, 25, 44, 25, 6},
  2131. + .gamma_correction={0, 100},
  2132. + .use_various_tweaks=true
  2133. +},
  2134. +#line 135 "ftinf_sh.gperf"
  2135. +{ .name="ultimate1",
  2136. + .filter_params={on, 4, 22, 38, 22, 4},
  2137. + .fringe_filter_strength=25,
  2138. + .gamma_correction={0, 100},
  2139. + .stem_alignment_strength=15,
  2140. + .stem_fitting_strength=15,
  2141. + .use_various_tweaks=true,
  2142. + .windows_style_sharpening_strength=25
  2143. +},
  2144. +#line 87 "ftinf_sh.gperf"
  2145. +{ .name="push",
  2146. + .autohint_horizontal_stem_darken_strength=10,
  2147. + .autohint_increase_glyph_heights=true,
  2148. + .autohint_snap_stem_height=100,
  2149. + .autohint_vertical_stem_darken_strength=25,
  2150. + .filter_params={on, 11, 22, 38, 22, 11},
  2151. + .gamma_correction={0, 100},
  2152. + .stem_alignment_strength=75,
  2153. + .stem_fitting_strength=50,
  2154. + .stem_snapping_sliding_scale=30,
  2155. + .use_known_settings_on_selected_fonts=true,
  2156. + .use_various_tweaks=true
  2157. +},
  2158. +#line 171 "ftinf_sh.gperf"
  2159. +{ .name="ultimate5",
  2160. + .filter_params={on, 12, 28, 42, 28, 12},
  2161. + .fringe_filter_strength=25,
  2162. + .gamma_correction={0, 100},
  2163. + .stem_alignment_strength=15,
  2164. + .stem_fitting_strength=15,
  2165. + .use_various_tweaks=true,
  2166. + .windows_style_sharpening_strength=25
  2167. +},
  2168. +#line 162 "ftinf_sh.gperf"
  2169. +{ .name="ultimate4",
  2170. + .filter_params={on, 10, 25, 37, 25, 10},
  2171. + .fringe_filter_strength=25,
  2172. + .gamma_correction={0, 100},
  2173. + .stem_alignment_strength=15,
  2174. + .stem_fitting_strength=15,
  2175. + .use_various_tweaks=true,
  2176. + .windows_style_sharpening_strength=25
  2177. +},
  2178. +#line 153 "ftinf_sh.gperf"
  2179. +{ .name="ultimate3",
  2180. + .filter_params={on, 8, 24, 36, 24, 8},
  2181. + .fringe_filter_strength=25,
  2182. + .gamma_correction={0, 100},
  2183. + .stem_alignment_strength=15,
  2184. + .stem_fitting_strength=15,
  2185. + .use_various_tweaks=true,
  2186. + .windows_style_sharpening_strength=25
  2187. +}
  2188. + };
  2189. +
  2190. + if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
  2191. + {
  2192. + register int key = _settings_hash (str, len);
  2193. +
  2194. + if (key <= MAX_HASH_VALUE && key >= MIN_HASH_VALUE)
  2195. + {
  2196. + register const struct ftinf_s *resword;
  2197. +
  2198. + switch (key - 3)
  2199. + {
  2200. + case 0:
  2201. + resword = &wordlist[0];
  2202. + goto compare;
  2203. + case 1:
  2204. + resword = &wordlist[1];
  2205. + goto compare;
  2206. + case 2:
  2207. + resword = &wordlist[2];
  2208. + goto compare;
  2209. + case 3:
  2210. + resword = &wordlist[3];
  2211. + goto compare;
  2212. + case 4:
  2213. + resword = &wordlist[4];
  2214. + goto compare;
  2215. + case 5:
  2216. + resword = &wordlist[5];
  2217. + goto compare;
  2218. + case 6:
  2219. + resword = &wordlist[6];
  2220. + goto compare;
  2221. + case 7:
  2222. + resword = &wordlist[7];
  2223. + goto compare;
  2224. + case 8:
  2225. + resword = &wordlist[8];
  2226. + goto compare;
  2227. + case 9:
  2228. + resword = &wordlist[9];
  2229. + goto compare;
  2230. + case 10:
  2231. + resword = &wordlist[10];
  2232. + goto compare;
  2233. + case 11:
  2234. + resword = &wordlist[11];
  2235. + goto compare;
  2236. + case 12:
  2237. + resword = &wordlist[12];
  2238. + goto compare;
  2239. + case 14:
  2240. + resword = &wordlist[13];
  2241. + goto compare;
  2242. + case 15:
  2243. + resword = &wordlist[14];
  2244. + goto compare;
  2245. + case 16:
  2246. + resword = &wordlist[15];
  2247. + goto compare;
  2248. + case 17:
  2249. + resword = &wordlist[16];
  2250. + goto compare;
  2251. + case 19:
  2252. + resword = &wordlist[17];
  2253. + goto compare;
  2254. + case 21:
  2255. + resword = &wordlist[18];
  2256. + goto compare;
  2257. + case 26:
  2258. + resword = &wordlist[19];
  2259. + goto compare;
  2260. + case 31:
  2261. + resword = &wordlist[20];
  2262. + goto compare;
  2263. + case 36:
  2264. + resword = &wordlist[21];
  2265. + goto compare;
  2266. + }
  2267. + return 0;
  2268. + compare:
  2269. + {
  2270. + register const char *s = resword->name;
  2271. +
  2272. + if (*str == *s && !strcmp (str + 1, s + 1))
  2273. + return resword;
  2274. + }
  2275. + }
  2276. + }
  2277. + return 0;
  2278. +}
  2279. +#line 242 "ftinf_sh.gperf"
  2280. +
  2281. +
  2282. +static const ftinf_t*
  2283. +ftinf_settings( const char *name ){
  2284. + if( name ){
  2285. + enum {
  2286. + max_wlen=31
  2287. + };
  2288. + char buf[max_wlen+1];
  2289. + int len=strlen( name );
  2290. + if( len <= max_wlen ){
  2291. + int i;
  2292. + for( i=0; i<len; ++i )
  2293. + buf[i]=tolower( name[i] );
  2294. + buf[len]='\0';
  2295. + return _settings_get( buf, len );
  2296. + }
  2297. + }
  2298. + return NULL;
  2299. +}
  2300. +/*
  2301. + gperf --output-file=ftinf_sh.c ftinf_sh.gperf
  2302. +*/
  2303. diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/src/base/ftinf_sh.gperf a/src/base/ftinf_sh.gperf
  2304. --- b/src/base/ftinf_sh.gperf 1970-01-01 03:00:00.000000000 +0300
  2305. +++ a/src/base/ftinf_sh.gperf 2021-09-16 09:15:05.052379743 +0300
  2306. @@ -0,0 +1,264 @@
  2307. +%struct-type
  2308. +%define slot-name name
  2309. +%enum
  2310. +%switch=1
  2311. +%readonly-tables
  2312. +%omit-struct-type
  2313. +%define lookup-function-name _settings_get
  2314. +%define hash-function-name _settings_hash
  2315. +%{
  2316. +#include <ctype.h>
  2317. +static const struct ftinf_s* _settings_get( const char*str, unsigned len);
  2318. +%}
  2319. +struct ftinf_s;
  2320. +%%
  2321. +{ .name="custom",
  2322. + .autohint_horizontal_stem_darken_strength=10,
  2323. + .autohint_snap_stem_height=100,
  2324. + .autohint_vertical_stem_darken_strength=25,
  2325. + .filter_params={on, 8, 24, 48, 24, 8},
  2326. + .gamma_correction={0, 100},
  2327. + .stem_alignment_strength=75,
  2328. + .stem_fitting_strength=50,
  2329. + .stem_snapping_sliding_scale=30,
  2330. + .use_known_settings_on_selected_fonts=true,
  2331. + .use_various_tweaks=true
  2332. +},
  2333. +{ .name="classic",
  2334. + .autohint_increase_glyph_heights=true,
  2335. + .autohint_snap_stem_height=100,
  2336. + .filter_params={on, 6, 25, 38, 25, 6},
  2337. + .gamma_correction={0, 100},
  2338. + .use_various_tweaks=true
  2339. +},
  2340. +{ .name="disabled",
  2341. + .gamma_correction={0, 100},
  2342. +},
  2343. +{ .name="ipad",
  2344. + .filter_params={on, 0, 0, 100, 0, 0},
  2345. + .gamma_correction={1000, 80},
  2346. + .grayscale_filter_strength=100
  2347. +},
  2348. +{ .name="infinality",
  2349. + .autohint_horizontal_stem_darken_strength=10,
  2350. + .autohint_increase_glyph_heights=true,
  2351. + .autohint_snap_stem_height=100,
  2352. + .autohint_vertical_stem_darken_strength=25,
  2353. + .filter_params={on, 11, 22, 38, 22, 11},
  2354. + .gamma_correction={0, 100},
  2355. + .stem_alignment_strength=25,
  2356. + .stem_fitting_strength=25,
  2357. + .stem_snapping_sliding_scale=40,
  2358. + .use_known_settings_on_selected_fonts=true,
  2359. + .use_various_tweaks=true,
  2360. + .windows_style_sharpening_strength=5
  2361. +},
  2362. +{ .name="linux",
  2363. + .autohint_horizontal_stem_darken_strength=10,
  2364. + .autohint_snap_stem_height=100,
  2365. + .autohint_vertical_stem_darken_strength=25,
  2366. + .filter_params={on, 6, 25, 44, 25, 6},
  2367. + .gamma_correction={0, 100},
  2368. + .use_various_tweaks=true
  2369. +},
  2370. +{ .name="nudge",
  2371. + .autohint_horizontal_stem_darken_strength=10,
  2372. + .autohint_increase_glyph_heights=true,
  2373. + .autohint_snap_stem_height=100,
  2374. + .autohint_vertical_stem_darken_strength=25,
  2375. + .filter_params={on, 11, 22, 38, 22, 11},
  2376. + .gamma_correction={0, 100},
  2377. + .stem_alignment_strength=25,
  2378. + .stem_fitting_strength=15,
  2379. + .stem_snapping_sliding_scale=30,
  2380. + .use_various_tweaks=true,
  2381. +},
  2382. +{ .name="osx",
  2383. + .autohint_horizontal_stem_darken_strength=10,
  2384. + .autohint_vertical_stem_darken_strength=25,
  2385. + .bold_embolden_x_value=16,
  2386. + .brightness=10,
  2387. + .contrast=20,
  2388. + .filter_params={on, 3, 32, 38, 32, 3},
  2389. + .gamma_correction={1000, 80},
  2390. + .global_embolden_y_value=8,
  2391. + .grayscale_filter_strength=25,
  2392. +},
  2393. +{ .name="push",
  2394. + .autohint_horizontal_stem_darken_strength=10,
  2395. + .autohint_increase_glyph_heights=true,
  2396. + .autohint_snap_stem_height=100,
  2397. + .autohint_vertical_stem_darken_strength=25,
  2398. + .filter_params={on, 11, 22, 38, 22, 11},
  2399. + .gamma_correction={0, 100},
  2400. + .stem_alignment_strength=75,
  2401. + .stem_fitting_strength=50,
  2402. + .stem_snapping_sliding_scale=30,
  2403. + .use_known_settings_on_selected_fonts=true,
  2404. + .use_various_tweaks=true
  2405. +},
  2406. +{ .name="sharpened",
  2407. + .autohint_horizontal_stem_darken_strength=10,
  2408. + .autohint_increase_glyph_heights=true,
  2409. + .autohint_snap_stem_height=100,
  2410. + .autohint_vertical_stem_darken_strength=25,
  2411. + .filter_params={on, 11, 22, 38, 22, 11},
  2412. + .gamma_correction={0, 100},
  2413. + .stem_alignment_strength=25,
  2414. + .stem_fitting_strength=25,
  2415. + .stem_snapping_sliding_scale=40,
  2416. + .use_known_settings_on_selected_fonts=true,
  2417. + .use_various_tweaks=true,
  2418. + .windows_style_sharpening_strength=65
  2419. +},
  2420. +{ .name="shove",
  2421. + .autohint_horizontal_stem_darken_strength=10,
  2422. + .autohint_increase_glyph_heights=true,
  2423. + .autohint_snap_stem_height=100,
  2424. + .autohint_vertical_stem_darken_strength=25,
  2425. + .filter_params={on, 11, 22, 38, 22, 11},
  2426. + .gamma_correction={0, 100},
  2427. + .stem_alignment_strength=100,
  2428. + .stem_fitting_strength=100,
  2429. + .use_known_settings_on_selected_fonts=true,
  2430. + .use_various_tweaks=true
  2431. +},
  2432. +{ .name="ubuntu",
  2433. + .autohint_horizontal_stem_darken_strength=10,
  2434. + .autohint_vertical_stem_darken_strength=25,
  2435. + .brightness=-10,
  2436. + .contrast=15,
  2437. + .filter_params={on, 11, 22, 38, 22, 11},
  2438. + .gamma_correction={1000, 80},
  2439. + .use_various_tweaks=true
  2440. +},
  2441. +{ .name="ultimate1",
  2442. + .filter_params={on, 4, 22, 38, 22, 4},
  2443. + .fringe_filter_strength=25,
  2444. + .gamma_correction={0, 100},
  2445. + .stem_alignment_strength=15,
  2446. + .stem_fitting_strength=15,
  2447. + .use_various_tweaks=true,
  2448. + .windows_style_sharpening_strength=25
  2449. +},
  2450. +{ .name="ultimate2",
  2451. + .filter_params={on, 6, 22, 36, 22, 6},
  2452. + .fringe_filter_strength=25,
  2453. + .gamma_correction={0, 100},
  2454. + .stem_alignment_strength=15,
  2455. + .stem_fitting_strength=15,
  2456. + .use_various_tweaks=true,
  2457. + .windows_style_sharpening_strength=25
  2458. +},
  2459. +{ .name="ultimate3",
  2460. + .filter_params={on, 8, 24, 36, 24, 8},
  2461. + .fringe_filter_strength=25,
  2462. + .gamma_correction={0, 100},
  2463. + .stem_alignment_strength=15,
  2464. + .stem_fitting_strength=15,
  2465. + .use_various_tweaks=true,
  2466. + .windows_style_sharpening_strength=25
  2467. +},
  2468. +{ .name="ultimate4",
  2469. + .filter_params={on, 10, 25, 37, 25, 10},
  2470. + .fringe_filter_strength=25,
  2471. + .gamma_correction={0, 100},
  2472. + .stem_alignment_strength=15,
  2473. + .stem_fitting_strength=15,
  2474. + .use_various_tweaks=true,
  2475. + .windows_style_sharpening_strength=25
  2476. +},
  2477. +{ .name="ultimate5",
  2478. + .filter_params={on, 12, 28, 42, 28, 12},
  2479. + .fringe_filter_strength=25,
  2480. + .gamma_correction={0, 100},
  2481. + .stem_alignment_strength=15,
  2482. + .stem_fitting_strength=15,
  2483. + .use_various_tweaks=true,
  2484. + .windows_style_sharpening_strength=25
  2485. +},
  2486. +{ .name="vanilla",
  2487. + .filter_params={on, 6, 25, 38, 25, 6},
  2488. + .gamma_correction={0, 100},
  2489. +},
  2490. +{ .name="windows7light",
  2491. + .autohint_horizontal_stem_darken_strength=10,
  2492. + .autohint_snap_stem_height=100,
  2493. + .autohint_vertical_stem_darken_strength=25,
  2494. + .contrast=20,
  2495. + .filter_params={on, 20, 25, 38, 25, 05},
  2496. + .fringe_filter_strength=100,
  2497. + .gamma_correction={1000, 160},
  2498. + .stem_snapping_sliding_scale=30,
  2499. + .use_known_settings_on_selected_fonts=true,
  2500. + .use_various_tweaks=true,
  2501. + .windows_style_sharpening_strength=100
  2502. +},
  2503. +{ .name="windows7",
  2504. + .filter_params={on, 20, 25, 42, 25, 06},
  2505. + .fringe_filter_strength=100,
  2506. + .autohint_horizontal_stem_darken_strength=10,
  2507. + .autohint_vertical_stem_darken_strength=25,
  2508. + .windows_style_sharpening_strength=65,
  2509. + .gamma_correction={1000, 120},
  2510. + .brightness=10,
  2511. + .contrast=20,
  2512. + .use_various_tweaks=true,
  2513. + .autohint_snap_stem_height=100,
  2514. + .use_known_settings_on_selected_fonts=true,
  2515. +},
  2516. +{ .name="windowsxp",
  2517. + .autohint_horizontal_stem_darken_strength=10,
  2518. + .autohint_snap_stem_height=100,
  2519. + .autohint_vertical_stem_darken_strength=25,
  2520. + .brightness=10,
  2521. + .contrast=20,
  2522. + .filter_params={on, 6, 25, 44, 25, 6},
  2523. + .fringe_filter_strength=100,
  2524. + .gamma_correction={1000, 120},
  2525. + .stem_alignment_strength=15,
  2526. + .stem_fitting_strength=15,
  2527. + .stem_snapping_sliding_scale=30,
  2528. + .use_known_settings_on_selected_fonts=true,
  2529. + .use_various_tweaks=true,
  2530. + .windows_style_sharpening_strength=65
  2531. +},
  2532. +{ .name="windowsxplight",
  2533. + .autohint_horizontal_stem_darken_strength=10,
  2534. + .autohint_snap_stem_height=100,
  2535. + .autohint_vertical_stem_darken_strength=25,
  2536. + .brightness=20,
  2537. + .contrast=30,
  2538. + .filter_params={on, 6, 25, 44, 25, 6},
  2539. + .fringe_filter_strength=100,
  2540. + .gamma_correction={1000, 120},
  2541. + .stem_alignment_strength=15,
  2542. + .stem_fitting_strength=15,
  2543. + .stem_snapping_sliding_scale=30,
  2544. + .use_known_settings_on_selected_fonts=true,
  2545. + .use_various_tweaks=true,
  2546. + .windows_style_sharpening_strength=65
  2547. +},
  2548. +%%
  2549. +
  2550. +static const ftinf_t*
  2551. +ftinf_settings( const char *name ){
  2552. + if( name ){
  2553. + enum {
  2554. + max_wlen=31
  2555. + };
  2556. + char buf[max_wlen+1];
  2557. + int len=strlen( name );
  2558. + if( len <= max_wlen ){
  2559. + int i;
  2560. + for( i=0; i<len; ++i )
  2561. + buf[i]=tolower( name[i] );
  2562. + buf[len]='\0';
  2563. + return _settings_get( buf, len );
  2564. + }
  2565. + }
  2566. + return NULL;
  2567. +}
  2568. +/*
  2569. + gperf --output-file=ftinf_sh.c ftinf_sh.gperf
  2570. +*/
  2571. diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/src/base/ftinit.c a/src/base/ftinit.c
  2572. --- b/src/base/ftinit.c 2021-02-13 10:16:54.000000000 +0200
  2573. +++ a/src/base/ftinit.c 2021-09-16 09:15:05.052379743 +0300
  2574. @@ -43,6 +43,10 @@
  2575. #include <freetype/internal/ftdebug.h>
  2576. #include <freetype/ftmodapi.h>
  2577. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  2578. +#include "ftinf.h"
  2579. +#endif
  2580. +
  2581. /**************************************************************************
  2582. *
  2583. @@ -224,10 +228,14 @@
  2584. error = FT_New_Library( memory, alibrary );
  2585. if ( error )
  2586. FT_Done_Memory( memory );
  2587. - else
  2588. + else {
  2589. FT_Add_Default_Modules( *alibrary );
  2590. -
  2591. FT_Set_Default_Properties( *alibrary );
  2592. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  2593. + /* get Infinality settings */
  2594. + ftinf_env();
  2595. +#endif
  2596. + }
  2597. return error;
  2598. }
  2599. diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/src/base/ftlcdfil.c a/src/base/ftlcdfil.c
  2600. --- b/src/base/ftlcdfil.c 2021-07-05 06:41:53.000000000 +0300
  2601. +++ a/src/base/ftlcdfil.c 2021-09-16 09:15:05.052379743 +0300
  2602. @@ -17,11 +17,15 @@
  2603. #include <freetype/internal/ftdebug.h>
  2604. -
  2605. #include <freetype/ftlcdfil.h>
  2606. #include <freetype/ftimage.h>
  2607. #include <freetype/internal/ftobjs.h>
  2608. +#include <math.h>
  2609. +#include <string.h>
  2610. +#include <strings.h>
  2611. +#include "ftinf.h"
  2612. +
  2613. #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
  2614. @@ -76,13 +80,13 @@
  2615. /* FIR filter used by the default and light filters */
  2616. FT_BASE_DEF( void )
  2617. ft_lcd_filter_fir( FT_Bitmap* bitmap,
  2618. + FT_Render_Mode mode,
  2619. FT_LcdFiveTapFilter weights )
  2620. {
  2621. FT_UInt width = (FT_UInt)bitmap->width;
  2622. FT_UInt height = (FT_UInt)bitmap->rows;
  2623. FT_Int pitch = bitmap->pitch;
  2624. FT_Byte* origin = bitmap->buffer;
  2625. - FT_Byte mode = bitmap->pixel_mode;
  2626. /* take care of bitmap flow */
  2627. @@ -90,7 +94,7 @@
  2628. origin += pitch * (FT_Int)( height - 1 );
  2629. /* horizontal in-place FIR filter */
  2630. - if ( mode == FT_PIXEL_MODE_LCD && width >= 2 )
  2631. + if ( mode == FT_RENDER_MODE_LCD && width >= 2 )
  2632. {
  2633. FT_Byte* line = origin;
  2634. @@ -133,7 +137,7 @@
  2635. }
  2636. /* vertical in-place FIR filter */
  2637. - else if ( mode == FT_PIXEL_MODE_LCD_V && height >= 2 )
  2638. + else if ( mode == FT_RENDER_MODE_LCD_V && height >= 2 )
  2639. {
  2640. FT_Byte* column = origin;
  2641. @@ -182,13 +186,13 @@
  2642. /* intra-pixel filter used by the legacy filter */
  2643. static void
  2644. _ft_lcd_filter_legacy( FT_Bitmap* bitmap,
  2645. + FT_Render_Mode mode,
  2646. FT_Byte* weights )
  2647. {
  2648. FT_UInt width = (FT_UInt)bitmap->width;
  2649. FT_UInt height = (FT_UInt)bitmap->rows;
  2650. FT_Int pitch = bitmap->pitch;
  2651. FT_Byte* origin = bitmap->buffer;
  2652. - FT_Byte mode = bitmap->pixel_mode;
  2653. static const unsigned int filters[3][3] =
  2654. {
  2655. @@ -205,7 +209,7 @@
  2656. origin += pitch * (FT_Int)( height - 1 );
  2657. /* horizontal in-place intra-pixel filter */
  2658. - if ( mode == FT_PIXEL_MODE_LCD && width >= 3 )
  2659. + if ( mode == FT_RENDER_MODE_LCD && width >= 3 )
  2660. {
  2661. FT_Byte* line = origin;
  2662. @@ -242,7 +246,7 @@
  2663. }
  2664. }
  2665. }
  2666. - else if ( mode == FT_PIXEL_MODE_LCD_V && height >= 3 )
  2667. + else if ( mode == FT_RENDER_MODE_LCD_V && height >= 3 )
  2668. {
  2669. FT_Byte* column = origin;
  2670. @@ -298,6 +302,7 @@
  2671. ft_memcpy( library->lcd_weights, weights, FT_LCD_FILTER_FIVE_TAPS );
  2672. library->lcd_filter_func = ft_lcd_filter_fir;
  2673. + library->lcd_extra = 2;
  2674. return FT_Err_Ok;
  2675. }
  2676. @@ -309,11 +314,37 @@
  2677. FT_Library_SetLcdFilter( FT_Library library,
  2678. FT_LcdFilter filter )
  2679. {
  2680. - static const FT_LcdFiveTapFilter default_weights =
  2681. - { 0x08, 0x4d, 0x56, 0x4d, 0x08 };
  2682. static const FT_LcdFiveTapFilter light_weights =
  2683. { 0x00, 0x55, 0x56, 0x55, 0x00 };
  2684. +#ifndef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  2685. + static const FT_LcdFiveTapFilter default_weights =
  2686. + { 0x08, 0x4d, 0x56, 0x4d, 0x08 };
  2687. +#else
  2688. + FT_LcdFiveTapFilter default_weights;
  2689. + if( ftinf && ftinf->filter_params[0] )
  2690. + {
  2691. + const int *f=ftinf->filter_params;
  2692. + /* Assume we were given integers [0-100] get them to [0-255] */
  2693. + int val; /* 2611=2.55*1024 */
  2694. + val=(f[1]*2611+512)>>10; if( val > 255 ) val=255;
  2695. + default_weights[0] = (FT_Byte) val;
  2696. + val=(f[2]*2611+512)>>10; if( val > 255 ) val=255;
  2697. + default_weights[1] = (FT_Byte) val;
  2698. + val=(f[3]*2611+512)>>10; if( val > 255 ) val=255;
  2699. + default_weights[2] = (FT_Byte) val;
  2700. + val=(f[4]*2611+512)>>10; if( val > 255 ) val=255;
  2701. + default_weights[3] = (FT_Byte) val;
  2702. + val=(f[5]*2611+512)>>10; if( val > 255 ) val=255;
  2703. + default_weights[4] = (FT_Byte) val;
  2704. + } else {
  2705. + default_weights[0]=0x08;
  2706. + default_weights[1]=0x4d;
  2707. + default_weights[2]=0x56;
  2708. + default_weights[3]=0x4d;
  2709. + default_weights[4]=0x08;
  2710. + }
  2711. +#endif
  2712. if ( !library )
  2713. return FT_THROW( Invalid_Library_Handle );
  2714. @@ -322,6 +353,7 @@
  2715. {
  2716. case FT_LCD_FILTER_NONE:
  2717. library->lcd_filter_func = NULL;
  2718. + library->lcd_extra = 0;
  2719. break;
  2720. case FT_LCD_FILTER_DEFAULT:
  2721. @@ -329,6 +361,7 @@
  2722. default_weights,
  2723. FT_LCD_FILTER_FIVE_TAPS );
  2724. library->lcd_filter_func = ft_lcd_filter_fir;
  2725. + library->lcd_extra = 2;
  2726. break;
  2727. case FT_LCD_FILTER_LIGHT:
  2728. @@ -336,6 +369,7 @@
  2729. light_weights,
  2730. FT_LCD_FILTER_FIVE_TAPS );
  2731. library->lcd_filter_func = ft_lcd_filter_fir;
  2732. + library->lcd_extra = 2;
  2733. break;
  2734. #ifdef USE_LEGACY
  2735. @@ -343,6 +377,7 @@
  2736. case FT_LCD_FILTER_LEGACY:
  2737. case FT_LCD_FILTER_LEGACY1:
  2738. library->lcd_filter_func = _ft_lcd_filter_legacy;
  2739. + library->lcd_extra = 0;
  2740. break;
  2741. #endif
  2742. diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/src/base/ftobjs.c a/src/base/ftobjs.c
  2743. --- b/src/base/ftobjs.c 2021-07-15 13:09:04.000000000 +0300
  2744. +++ a/src/base/ftobjs.c 2021-09-16 09:15:05.053379751 +0300
  2745. @@ -45,7 +45,9 @@
  2746. #ifdef FT_CONFIG_OPTION_MAC_FONTS
  2747. #include "ftbase.h"
  2748. #endif
  2749. -
  2750. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  2751. +#include "ftinf.h"
  2752. +#endif
  2753. #ifdef FT_DEBUG_LEVEL_TRACE
  2754. @@ -99,6 +101,11 @@
  2755. #define GRID_FIT_METRICS
  2756. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  2757. +#include <strings.h>
  2758. +#include <stdlib.h>
  2759. +#include "../autofit/aflatin.h"
  2760. +#endif
  2761. /* forward declaration */
  2762. static FT_Error
  2763. @@ -777,6 +784,25 @@
  2764. ft_lookup_glyph_renderer( FT_GlyphSlot slot );
  2765. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  2766. + static void
  2767. + ft_glyphslot_enlarge_metrics( FT_GlyphSlot slot,
  2768. + FT_Render_Mode mode )
  2769. + {
  2770. + FT_Glyph_Metrics* metrics = &slot->metrics;
  2771. + FT_Pos enlarge_cbox = 0;
  2772. +
  2773. +
  2774. + /* enlarge for grayscale rendering */
  2775. + if ( mode == FT_RENDER_MODE_NORMAL )
  2776. + enlarge_cbox = 64;
  2777. +
  2778. + metrics->horiBearingX -= enlarge_cbox;
  2779. + metrics->width += 2 * enlarge_cbox;
  2780. + }
  2781. +#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */
  2782. +
  2783. +
  2784. #ifdef GRID_FIT_METRICS
  2785. static void
  2786. ft_glyphslot_grid_fit_metrics( FT_GlyphSlot slot,
  2787. @@ -843,8 +869,18 @@
  2788. FT_Bool autohint = FALSE;
  2789. FT_Module hinter;
  2790. TT_Face ttface = (TT_Face)face;
  2791. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  2792. + FT_Bool use_various_tweaks = FALSE;
  2793. + if( ftinf ) use_various_tweaks=ftinf->use_various_tweaks;
  2794. + /* Force autohint if no tt instructions */
  2795. + /* NOTE: NEEDS TO BE RUN LATER IN CODE???? */
  2796. + /*if ( use_various_tweaks &&
  2797. + ttface->num_locations &&
  2798. + ttface->max_profile.maxSizeOfInstructions == 0 )
  2799. + load_flags |= FT_LOAD_FORCE_AUTOHINT;*/
  2800. +#endif
  2801. if ( !face || !face->size || !face->glyph )
  2802. return FT_THROW( Invalid_Face_Handle );
  2803. @@ -946,6 +982,18 @@
  2804. {
  2805. FT_AutoHinter_Interface hinting;
  2806. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  2807. + if ( use_various_tweaks )
  2808. + {
  2809. + /* Force slight hinting over full hinting always */
  2810. + load_flags &= ~FT_LOAD_TARGET_LCD;
  2811. + load_flags &= ~FT_LOAD_TARGET_LCD_V;
  2812. + load_flags &= ~FT_LOAD_TARGET_MONO;
  2813. + load_flags &= ~FT_LOAD_TARGET_NORMAL;
  2814. + load_flags |= FT_LOAD_TARGET_LIGHT;
  2815. + /*printf("%d ", load_flags);*/
  2816. + }
  2817. +#endif
  2818. /* try to load embedded bitmaps first if available */
  2819. /* */
  2820. @@ -991,6 +1039,18 @@
  2821. if ( error )
  2822. goto Exit;
  2823. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  2824. + infinality_cur_width = 0;
  2825. +
  2826. + {
  2827. + /* fix for sdl_ttf */
  2828. + FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags );
  2829. +
  2830. + if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
  2831. + ft_glyphslot_enlarge_metrics( slot, mode );
  2832. + }
  2833. +#endif
  2834. +
  2835. if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
  2836. {
  2837. /* check that the loaded outline is correct */
  2838. @@ -5353,6 +5413,11 @@
  2839. /* That's ok now */
  2840. *alibrary = library;
  2841. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  2842. + /* get Infinality settings */
  2843. + ftinf_env();
  2844. +#endif
  2845. +
  2846. return FT_Err_Ok;
  2847. }
  2848. diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/src/base/ftoutln.c a/src/base/ftoutln.c
  2849. --- b/src/base/ftoutln.c 2021-02-13 10:16:54.000000000 +0200
  2850. +++ a/src/base/ftoutln.c 2021-09-16 09:15:05.053379751 +0300
  2851. @@ -22,6 +22,9 @@
  2852. #include <freetype/internal/ftdebug.h>
  2853. #include <freetype/fttrigon.h>
  2854. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  2855. +#include "ftinf.h"
  2856. +#endif
  2857. /**************************************************************************
  2858. *
  2859. @@ -907,8 +910,14 @@
  2860. {
  2861. FT_Vector* points;
  2862. FT_Int c, first, last;
  2863. - FT_Orientation orientation;
  2864. -
  2865. + FT_Int orientation;
  2866. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  2867. + FT_Bool use_various_tweaks = FALSE;
  2868. + if( ftinf ) use_various_tweaks=ftinf->use_various_tweaks;
  2869. +
  2870. + if ( use_various_tweaks )
  2871. + ystrength = FT_PIX_FLOOR ( ystrength );
  2872. +#endif
  2873. if ( !outline )
  2874. return FT_THROW( Invalid_Outline );
  2875. diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/src/base/ftsynth.c a/src/base/ftsynth.c
  2876. --- b/src/base/ftsynth.c 2021-02-13 10:16:54.000000000 +0200
  2877. +++ a/src/base/ftsynth.c 2021-09-16 09:15:05.053379751 +0300
  2878. @@ -22,6 +22,9 @@
  2879. #include <freetype/ftoutln.h>
  2880. #include <freetype/ftbitmap.h>
  2881. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  2882. +#include "ftinf.h"
  2883. +#endif
  2884. /**************************************************************************
  2885. *
  2886. @@ -92,7 +95,10 @@
  2887. FT_Face face;
  2888. FT_Error error;
  2889. FT_Pos xstr, ystr;
  2890. -
  2891. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  2892. + FT_Bool use_various_tweaks = FALSE;
  2893. + if( ftinf ) use_various_tweaks=ftinf->use_various_tweaks;
  2894. +#endif
  2895. if ( !slot )
  2896. return;
  2897. @@ -110,8 +116,16 @@
  2898. ystr = xstr;
  2899. if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
  2900. + {
  2901. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  2902. + if ( use_various_tweaks )
  2903. + (void)FT_Outline_EmboldenXY( &slot->outline,
  2904. + xstr,
  2905. + FT_PIX_FLOOR( ystr ) );
  2906. + else
  2907. +#endif
  2908. FT_Outline_EmboldenXY( &slot->outline, xstr, ystr );
  2909. -
  2910. + }
  2911. else /* slot->format == FT_GLYPH_FORMAT_BITMAP */
  2912. {
  2913. /* round to full pixels */
  2914. @@ -149,6 +163,9 @@
  2915. slot->metrics.width += xstr;
  2916. slot->metrics.height += ystr;
  2917. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  2918. + if ( !use_various_tweaks )
  2919. +#endif
  2920. slot->metrics.horiAdvance += xstr;
  2921. slot->metrics.vertAdvance += ystr;
  2922. slot->metrics.horiBearingY += ystr;
  2923. diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/src/base/rules.mk a/src/base/rules.mk
  2924. --- b/src/base/rules.mk 2021-02-13 10:16:54.000000000 +0200
  2925. +++ a/src/base/rules.mk 2021-09-16 09:15:05.053379751 +0300
  2926. @@ -44,6 +44,7 @@
  2927. $(BASE_DIR)/ftfntfmt.c \
  2928. $(BASE_DIR)/ftgloadr.c \
  2929. $(BASE_DIR)/fthash.c \
  2930. + $(BASE_DIR)/ftinf.c \
  2931. $(BASE_DIR)/ftlcdfil.c \
  2932. $(BASE_DIR)/ftobjs.c \
  2933. $(BASE_DIR)/ftoutln.c \
  2934. diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/src/cff/cffobjs.c a/src/cff/cffobjs.c
  2935. --- b/src/cff/cffobjs.c 2021-02-13 10:16:54.000000000 +0200
  2936. +++ a/src/cff/cffobjs.c 2021-09-16 09:15:05.053379751 +0300
  2937. @@ -42,6 +42,9 @@
  2938. #include <freetype/internal/psaux.h>
  2939. #include <freetype/internal/services/svcfftl.h>
  2940. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  2941. +#include "../base/ftinf.h"
  2942. +#endif
  2943. /**************************************************************************
  2944. *
  2945. @@ -1177,6 +1180,9 @@
  2946. driver->hinting_engine = FT_HINTING_ADOBE;
  2947. driver->no_stem_darkening = TRUE;
  2948. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  2949. + if(ftinf) driver->no_stem_darkening = !ftinf->stem_darkening_cff;
  2950. +#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */
  2951. driver->darken_params[0] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1;
  2952. driver->darken_params[1] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1;
  2953. diff -Nbur --exclude builds --exclude '*.orig' --exclude objs b/src/smooth/ftsmooth.c a/src/smooth/ftsmooth.c
  2954. --- b/src/smooth/ftsmooth.c 2021-02-13 10:16:54.000000000 +0200
  2955. +++ a/src/smooth/ftsmooth.c 2021-09-16 09:19:36.749340217 +0300
  2956. @@ -24,6 +24,28 @@
  2957. #include "ftsmerrs.h"
  2958. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  2959. +#include <math.h>
  2960. +#include FT_BITMAP_H
  2961. +#include <string.h>
  2962. +#include <strings.h>
  2963. +#include FT_OUTLINE_H
  2964. +#include "../base/ftinf.h"
  2965. +
  2966. +#define verbose FALSE
  2967. +#define STVALUES if (verbose) \
  2968. + printf ( "scale:%f translate:%ld ", *scale_value, *translate_value );
  2969. +#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */
  2970. +
  2971. + /* initialize renderer -- init its raster */
  2972. + static FT_Error
  2973. + ft_smooth_init( FT_Renderer render )
  2974. + {
  2975. + render->clazz->raster_class->raster_reset( render->raster, NULL, 0 );
  2976. +
  2977. + return 0;
  2978. + }
  2979. +
  2980. /* sets render-specific mode */
  2981. static FT_Error
  2982. @@ -76,367 +98,2440 @@
  2983. FT_Outline_Get_CBox( &slot->outline, cbox );
  2984. }
  2985. - typedef struct TOrigin_
  2986. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  2987. + static FT_Fixed FT_FixedFromFloat(float f)
  2988. {
  2989. - unsigned char* origin; /* pixmap origin at the bottom-left */
  2990. - int pitch; /* pitch to go down one row */
  2991. + short value = f;
  2992. + unsigned short fract = (f - value) * 0xFFFF;
  2993. - } TOrigin;
  2994. -#ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
  2995. + return (FT_Fixed)((long)value << 16 | (unsigned long)fract );
  2996. + }
  2997. - /* initialize renderer -- init its raster */
  2998. - static FT_Error
  2999. - ft_smooth_init( FT_Renderer render )
  3000. +
  3001. + /* ChromeOS sharpening algorithm */
  3002. + /* soften the sub-pixel anti-aliasing and sharpen */
  3003. + static void
  3004. + _ft_lcd_chromeos_sharpen( FT_Bitmap* bitmap,
  3005. + FT_Render_Mode mode,
  3006. + FT_Byte cutoff,
  3007. + double gamma_value )
  3008. + {
  3009. + static FT_Bool initialized_gamma = FALSE;
  3010. + static unsigned short gamma_ramp[256];
  3011. + FT_UInt width = (FT_UInt)bitmap->width;
  3012. + FT_UInt height = (FT_UInt)bitmap->rows;
  3013. + int ii;
  3014. +
  3015. + if ( !initialized_gamma )
  3016. + {
  3017. + initialized_gamma = TRUE;
  3018. + /* linear to voltage */
  3019. + for ( ii = 0; ii < 256; ii++ )
  3020. + {
  3021. + gamma_ramp[ii] = (unsigned char)
  3022. + ( pow( (double)ii / 255.0, gamma_value ) * 255.0f );
  3023. + if ( gamma_ramp[ii] < cutoff )
  3024. + gamma_ramp[ii] = 0;
  3025. + }
  3026. + }
  3027. +
  3028. + /* horizontal in-place sub-pixel sharpening filter */
  3029. + if ( mode == FT_RENDER_MODE_LCD )
  3030. {
  3031. - FT_Vector* sub = render->root.library->lcd_geometry;
  3032. + FT_Byte* line = bitmap->buffer;
  3033. - /* set up default subpixel geometry for striped RGB panels. */
  3034. - sub[0].x = -21;
  3035. - sub[0].y = 0;
  3036. - sub[1].x = 0;
  3037. - sub[1].y = 0;
  3038. - sub[2].x = 21;
  3039. - sub[2].y = 0;
  3040. + for ( ; height > 0; height--, line += bitmap->pitch )
  3041. + {
  3042. + FT_UInt xx;
  3043. - render->clazz->raster_class->raster_reset( render->raster, NULL, 0 );
  3044. - return 0;
  3045. + for ( xx = 0; xx < width; xx++ )
  3046. + line[xx] = gamma_ramp[line[xx]];
  3047. + }
  3048. + }
  3049. + }
  3050. +
  3051. + /* simple linear scale to handle various sliding values */
  3052. + float
  3053. + sliding_scale ( int min_value,
  3054. + int max_value,
  3055. + float min_amount,
  3056. + float max_amount,
  3057. + int cur_value )
  3058. + {
  3059. +
  3060. + float m = ( min_amount - max_amount ) / (float)( min_value - max_value );
  3061. + float result = ( ( (float)cur_value * m) + ( max_amount - max_value * m ) ) ;
  3062. +
  3063. + if ( min_amount < max_amount )
  3064. + {
  3065. + if ( result < min_amount )
  3066. + return min_amount;
  3067. + if ( result > max_amount )
  3068. + return max_amount;
  3069. + }
  3070. + else
  3071. + {
  3072. + if ( result < max_amount )
  3073. + return max_amount;
  3074. + if ( result > min_amount )
  3075. + return min_amount;
  3076. + }
  3077. +
  3078. + return result;
  3079. + }
  3080. +
  3081. +
  3082. + /* brightness and contrast adjustment on the bitmap */
  3083. + static FT_Bool
  3084. + _ft_bitmap_bc ( FT_Bitmap* bitmap,
  3085. + float brightness,
  3086. + float contrast )
  3087. + {
  3088. +
  3089. + FT_UInt width = (FT_UInt)bitmap->width;
  3090. + FT_UInt height = (FT_UInt)bitmap->rows;
  3091. + FT_Byte* line = bitmap->buffer;
  3092. + FT_UInt xx;
  3093. +
  3094. +
  3095. + if ( brightness == 0 && contrast == 0 )
  3096. + return FALSE;
  3097. +
  3098. + for ( height = (FT_UInt)bitmap->rows;
  3099. + height > 0;
  3100. + height--, line += bitmap->pitch )
  3101. + {
  3102. + for ( xx = 0; xx < width - 1; xx += 1 )
  3103. + {
  3104. + if ( line[xx] > 0)
  3105. + {
  3106. + float value = (float)( 255 - line[xx] ) / 256.0;
  3107. + FT_Int result = 0;
  3108. +
  3109. + if ( brightness < 0.0 )
  3110. + value = value * ( 1.0 + brightness );
  3111. + else
  3112. + value = value + ( ( 1.0 - value ) * brightness );
  3113. +
  3114. + value = ( value - 0.5 ) *
  3115. + ( tan ( ( contrast + 1.0 ) * 3.141592/4.0 ) ) + 0.5;
  3116. +
  3117. + result = (FT_Int)( 255.0 - value * 256.0 );
  3118. +
  3119. + if ( result < 0 )
  3120. + result = 0;
  3121. + if ( result > 255 )
  3122. + result = 255;
  3123. +
  3124. + line[xx] = result;
  3125. + }
  3126. + }
  3127. + }
  3128. + return TRUE;
  3129. }
  3130. - /* This function writes every third byte in direct rendering mode */
  3131. + /* Filter to mimic Windows-style sharpening */
  3132. + /* Determined via 100% experimentation. */
  3133. static void
  3134. - ft_smooth_lcd_spans( int y,
  3135. - int count,
  3136. - const FT_Span* spans,
  3137. - TOrigin* target )
  3138. + _ft_lcd_windows_sharpen( FT_Bitmap* bitmap,
  3139. + FT_Render_Mode mode,
  3140. + FT_UInt strength,
  3141. + FT_Library library )
  3142. + {
  3143. +
  3144. + FT_UInt width = (FT_UInt)bitmap->width;
  3145. + FT_UInt height = (FT_UInt)bitmap->rows;
  3146. + FT_Byte* new_line;
  3147. + FT_Byte* line = bitmap->buffer;
  3148. + FT_Bitmap new_bitmap;
  3149. +
  3150. +
  3151. + FT_Bitmap_Init( &new_bitmap );
  3152. + FT_Bitmap_Copy( library, bitmap, &new_bitmap );
  3153. + new_line = (&new_bitmap)->buffer;
  3154. +
  3155. + if (strength > 0)
  3156. + for (height = (FT_UInt)bitmap->rows;
  3157. + height > 0;
  3158. + height--, line += bitmap->pitch, new_line += bitmap->pitch )
  3159. + {
  3160. + FT_UInt xx, threshold = 128;
  3161. + FT_Byte* prevline = line - bitmap->pitch;
  3162. + FT_Byte* nextline = line + bitmap->pitch;
  3163. + FT_Byte* new_prevline = new_line - bitmap->pitch;
  3164. + FT_Byte* new_nextline = new_line + bitmap->pitch;
  3165. +
  3166. + for ( xx = 1; xx < width - 1; xx += 1 )
  3167. {
  3168. - unsigned char* dst_line = target->origin - y * target->pitch;
  3169. - unsigned char* dst;
  3170. - unsigned short w;
  3171. + /* subpixel grid sp11 sp21 sp31 */
  3172. + /* where sp22 is sp12 sp22 sp32 */
  3173. + /* current subpixel. sp13 sp23 sp33 */
  3174. +
  3175. + FT_Int prevtotal, nexttotal, lefttotal, righttotal, sidesdiff,
  3176. + prevdiff, nextdiff, sp11, sp21, sp31, sp12, sp22, sp32,
  3177. + sp13, sp23, sp33;
  3178. +
  3179. + sp12 = line [xx-1];
  3180. + sp22 = line [xx];
  3181. + sp32 = line [xx+1];
  3182. + if ( height == bitmap->rows )
  3183. + {
  3184. + prevtotal = sp11 = sp21 = sp31 = 0;
  3185. + prevdiff = sp22;
  3186. + lefttotal = sp12 + sp13;
  3187. + righttotal = sp32 + sp33;
  3188. + }
  3189. + else
  3190. + {
  3191. + prevtotal = prevline[xx-1] + prevline[xx] + prevline[xx+1];
  3192. + sp11 = prevline [xx-1];
  3193. + sp21 = prevline [xx];
  3194. + sp31 = prevline [xx+1];
  3195. + prevdiff = sp22 - sp21;
  3196. + lefttotal = sp11 + sp12 + sp13;
  3197. + righttotal = sp31 + sp32 + sp33;
  3198. + }
  3199. - for ( ; count--; spans++ )
  3200. - for ( dst = dst_line + spans->x * 3, w = spans->len; w--; dst += 3 )
  3201. - *dst = spans->coverage;
  3202. + if ( height == 1 )
  3203. + {
  3204. + nexttotal = sp13 = sp23 = sp33 = 0;
  3205. + nextdiff = sp22;
  3206. + lefttotal = sp11 + sp12;
  3207. + righttotal = sp31 + sp32;
  3208. + }
  3209. + else
  3210. + {
  3211. + nexttotal = nextline[xx-1] + nextline[xx] + nextline[xx+1];
  3212. + sp13 = nextline [xx-1];
  3213. + sp23 = nextline [xx];
  3214. + sp33 = nextline [xx+1];
  3215. + nextdiff = sp23 - sp22;
  3216. + lefttotal = sp11 + sp12 + sp13;
  3217. + righttotal = sp31 + sp32 + sp33;
  3218. }
  3219. + sidesdiff = lefttotal - righttotal;
  3220. - static FT_Error
  3221. - ft_smooth_raster_lcd( FT_Renderer render,
  3222. - FT_Outline* outline,
  3223. - FT_Bitmap* bitmap )
  3224. + if ( sidesdiff < 0 )
  3225. + sidesdiff *= -1;
  3226. +
  3227. + if ( prevdiff < 0 )
  3228. + prevdiff *= -1;
  3229. +
  3230. + if ( nextdiff < 0 )
  3231. + nextdiff *= -1;
  3232. +
  3233. + /* if the current pixel is less than threshold, and greater than 0 */
  3234. + if ( sp22 <= threshold && sp22 > 0 )
  3235. {
  3236. - FT_Error error = FT_Err_Ok;
  3237. - FT_Vector* sub = render->root.library->lcd_geometry;
  3238. - FT_Pos x, y;
  3239. + /* A pixel is horizontally isolated if: */
  3240. + /* 1: All upper adjecent pixels are >= threshold */
  3241. + if ( prevtotal >= nexttotal &&
  3242. + abs( sp11 - sp12 ) > 5 &&
  3243. + abs( sp21 - sp22 ) > 5 &&
  3244. + abs( sp31 - sp32 ) > 5 && /* not a vert stem end */
  3245. + sp11 >= threshold &&
  3246. + sp21 >= threshold &&
  3247. + sp31 >= threshold &&
  3248. + abs( sp23 - sp22 ) > 15 ) /* not on a vert stem */
  3249. + {
  3250. + /* darken upper adjacent subpixel; lighten current */
  3251. + if ( height != (FT_UInt)bitmap->rows )
  3252. + new_prevline[xx] += ( ( 255 - new_prevline[xx] )
  3253. + * strength ) / 100 ;
  3254. - FT_Raster_Params params;
  3255. - TOrigin target;
  3256. + new_line[xx] -= ( new_line[xx] * strength ) / 100;
  3257. + if ( height != 1 && height != (FT_UInt)bitmap->rows )
  3258. + if ( new_nextline[xx] > 155 + ( 100 - strength ) )
  3259. + new_prevline[xx] = 255;
  3260. - /* Render 3 separate coverage bitmaps, shifting the outline. */
  3261. - /* Set up direct rendering to record them on each third byte. */
  3262. - params.source = outline;
  3263. - params.flags = FT_RASTER_FLAG_AA | FT_RASTER_FLAG_DIRECT;
  3264. - params.gray_spans = (FT_SpanFunc)ft_smooth_lcd_spans;
  3265. - params.user = &target;
  3266. -
  3267. - params.clip_box.xMin = 0;
  3268. - params.clip_box.yMin = 0;
  3269. - params.clip_box.xMax = bitmap->width;
  3270. - params.clip_box.yMax = bitmap->rows;
  3271. -
  3272. - if ( bitmap->pitch < 0 )
  3273. - target.origin = bitmap->buffer;
  3274. - else
  3275. - target.origin = bitmap->buffer
  3276. - + ( bitmap->rows - 1 ) * (unsigned int)bitmap->pitch;
  3277. -
  3278. - target.pitch = bitmap->pitch;
  3279. -
  3280. - FT_Outline_Translate( outline,
  3281. - -sub[0].x,
  3282. - -sub[0].y );
  3283. - error = render->raster_render( render->raster, &params );
  3284. - x = sub[0].x;
  3285. - y = sub[0].y;
  3286. - if ( error )
  3287. - goto Exit;
  3288. + }
  3289. + else if ( nexttotal > prevtotal &&
  3290. + abs( sp13 - sp12 ) > 5 &&
  3291. + abs( sp23 - sp22 ) > 5 &&
  3292. + abs( sp33 - sp32 ) > 5 &&
  3293. + /* 2: All lower adjecent pixels are >= threshold */
  3294. + sp13 >= threshold &&
  3295. + sp23 >= threshold &&
  3296. + sp33 >= threshold &&
  3297. + abs( sp22 - sp21 ) > 15 )
  3298. + {
  3299. + /* darken lower adjacent subpixel; lighten current */
  3300. + if ( height != 1 )
  3301. + new_nextline[xx] += ( 255 - new_nextline[xx] ) * strength / 100;
  3302. - target.origin++;
  3303. - FT_Outline_Translate( outline,
  3304. - sub[0].x - sub[1].x,
  3305. - sub[0].y - sub[1].y );
  3306. - error = render->raster_render( render->raster, &params );
  3307. - x = sub[1].x;
  3308. - y = sub[1].y;
  3309. - if ( error )
  3310. - goto Exit;
  3311. + new_line[xx] -= ( new_line[xx] * strength ) / 100;
  3312. - target.origin++;
  3313. - FT_Outline_Translate( outline,
  3314. - sub[1].x - sub[2].x,
  3315. - sub[1].y - sub[2].y );
  3316. - error = render->raster_render( render->raster, &params );
  3317. - x = sub[2].x;
  3318. - y = sub[2].y;
  3319. + if ( height != 1 )
  3320. + if ( new_nextline[xx] > 155 + ( 100 - strength ) )
  3321. + new_nextline[xx] = 255;
  3322. - Exit:
  3323. - FT_Outline_Translate( outline, x, y );
  3324. + }
  3325. + }
  3326. + else if ( sp22 > threshold && sp22 < 255 )
  3327. + {
  3328. + if ( sp11 <= threshold &&
  3329. + abs( sp13 - sp12 ) > 5 &&
  3330. + abs( sp23 - sp22 ) > 5 &&
  3331. + abs( sp33 - sp32 ) > 5 &&
  3332. + sp21 <= threshold &&
  3333. + sp31 <= threshold &&
  3334. + prevtotal <= nexttotal &&
  3335. + abs( sp22 - sp21 ) > 15 )
  3336. + {
  3337. + /* bring this subpixel 1/3 of the way to 255 at 100% strength */
  3338. + new_line[xx] += ( strength * ( 255 - new_line[xx] ) ) / 100;
  3339. - return error;
  3340. + if ( height != (FT_UInt)bitmap->rows )
  3341. + new_prevline[xx] -= ( new_prevline[xx] * strength ) / 300;
  3342. }
  3343. + else if ( sp13 <= threshold &&
  3344. + abs( sp11 - sp12 ) > 5 &&
  3345. + abs( sp21 - sp22 ) > 5 &&
  3346. + abs( sp31 - sp32 ) > 5 &&
  3347. + sp23 <= threshold &&
  3348. + sp33 <= threshold &&
  3349. + nexttotal < prevtotal &&
  3350. + abs( sp23 - sp22 ) > 15 )
  3351. + {
  3352. + new_line[xx] += ( strength * ( 255 - new_line[xx] ) ) / 100;
  3353. + if ( height != 1 )
  3354. + new_nextline[xx] -= ( new_nextline[xx] * strength ) / 300;
  3355. + }
  3356. + }
  3357. + }
  3358. + }
  3359. + FT_Bitmap_Copy( library, &new_bitmap, bitmap);
  3360. + FT_Bitmap_Done( library, &new_bitmap );
  3361. + }
  3362. - static FT_Error
  3363. - ft_smooth_raster_lcdv( FT_Renderer render,
  3364. - FT_Outline* outline,
  3365. - FT_Bitmap* bitmap )
  3366. +
  3367. + static void
  3368. + _ft_lcd_darken_x ( FT_Bitmap* bitmap,
  3369. + FT_Render_Mode mode,
  3370. + FT_UInt strength,
  3371. + FT_Library library )
  3372. {
  3373. - FT_Error error = FT_Err_Ok;
  3374. - int pitch = bitmap->pitch;
  3375. - FT_Vector* sub = render->root.library->lcd_geometry;
  3376. - FT_Pos x, y;
  3377. - FT_Raster_Params params;
  3378. + FT_UInt width = (FT_UInt)bitmap->width;
  3379. + FT_UInt height = (FT_UInt)bitmap->rows;
  3380. + FT_Byte* new_line;
  3381. + FT_Byte* line = bitmap->buffer;
  3382. + FT_Bitmap new_bitmap;
  3383. + int factor1, factor2;
  3384. + int bias = 0;
  3385. + FT_Bitmap_Init( &new_bitmap );
  3386. - params.target = bitmap;
  3387. - params.source = outline;
  3388. - params.flags = FT_RASTER_FLAG_AA;
  3389. + FT_Bitmap_Copy( library, bitmap, &new_bitmap );
  3390. + new_line = (&new_bitmap)->buffer;
  3391. - /* Render 3 separate coverage bitmaps, shifting the outline. */
  3392. - /* Notice that the subpixel geometry vectors are rotated. */
  3393. - /* Triple the pitch to render on each third row. */
  3394. - bitmap->pitch *= 3;
  3395. - bitmap->rows /= 3;
  3396. -
  3397. - FT_Outline_Translate( outline,
  3398. - -sub[0].y,
  3399. - sub[0].x );
  3400. - error = render->raster_render( render->raster, &params );
  3401. - x = sub[0].y;
  3402. - y = -sub[0].x;
  3403. - if ( error )
  3404. - goto Exit;
  3405. + if ( strength > 0 )
  3406. + for ( height = (FT_UInt)bitmap->rows;
  3407. + height > 0;
  3408. + height--, line += bitmap->pitch, new_line += bitmap->pitch )
  3409. + {
  3410. + FT_UInt xx;
  3411. + FT_Byte* prevline = line - bitmap->pitch;
  3412. + FT_Byte* nextline = line + bitmap->pitch;
  3413. - bitmap->buffer += pitch;
  3414. - FT_Outline_Translate( outline,
  3415. - sub[0].y - sub[1].y,
  3416. - sub[1].x - sub[0].x );
  3417. - error = render->raster_render( render->raster, &params );
  3418. - x = sub[1].y;
  3419. - y = -sub[1].x;
  3420. - bitmap->buffer -= pitch;
  3421. - if ( error )
  3422. - goto Exit;
  3423. + for ( xx = 1; xx < width - 1; xx += 1 )
  3424. + {
  3425. + /* subpixel grid sp11 sp21 sp31 */
  3426. + /* where sp22 is sp12 sp22 sp32 */
  3427. + /* current subpixel. sp13 sp23 sp33 */
  3428. - bitmap->buffer += 2 * pitch;
  3429. - FT_Outline_Translate( outline,
  3430. - sub[1].y - sub[2].y,
  3431. - sub[2].x - sub[1].x );
  3432. - error = render->raster_render( render->raster, &params );
  3433. - x = sub[2].y;
  3434. - y = -sub[2].x;
  3435. - bitmap->buffer -= 2 * pitch;
  3436. + FT_Int sp21, sp12, sp22, sp32, sp23;
  3437. - Exit:
  3438. - FT_Outline_Translate( outline, x, y );
  3439. + sp12 = line [xx-1];
  3440. + sp22 = line [xx];
  3441. + sp32 = line [xx+1];
  3442. - bitmap->pitch /= 3;
  3443. - bitmap->rows *= 3;
  3444. + if ( height == bitmap->rows )
  3445. + sp21 = 0;
  3446. + else
  3447. + sp21 = prevline [xx];
  3448. +
  3449. + if ( height == 1 )
  3450. + sp23 = 0;
  3451. + else
  3452. + sp23 = nextline [xx];
  3453. +
  3454. + /* darken subpixel if neighbor above and below are much less than */
  3455. + /* safer but less effective */
  3456. + factor1 = 5;
  3457. + factor2 = 5;
  3458. +
  3459. + /* make matches in the middle of glyph slightly darker */
  3460. + /*if (height > 1 && height < (FT_UInt)bitmap->rows) bias = 1;*/
  3461. +
  3462. + if ( sp22 > factor1 * sp21 &&
  3463. + sp22 > factor1 * sp23 &&
  3464. + sp22 > factor2 &&
  3465. + sp12 > 16 &&
  3466. + sp32 > 16 )
  3467. + if ( new_line[xx] < ( strength * 255 ) / 100 )
  3468. + new_line[xx] = (strength * 255 ) / 100
  3469. + + bias * ( 255 - ( strength * 255 ) / 100 ) / 3;
  3470. - return error;
  3471. + }
  3472. + }
  3473. + FT_Bitmap_Copy( library, &new_bitmap, bitmap );
  3474. + FT_Bitmap_Done( library, &new_bitmap );
  3475. }
  3476. -#else /* FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
  3477. - /* initialize renderer -- init its raster */
  3478. - static FT_Error
  3479. - ft_smooth_init( FT_Renderer render )
  3480. + static void
  3481. + _ft_lcd_darken_y ( FT_Bitmap* bitmap,
  3482. + FT_Render_Mode mode,
  3483. + FT_UInt strength,
  3484. + FT_Library library )
  3485. {
  3486. - /* set up default LCD filtering */
  3487. - FT_Library_SetLcdFilter( render->root.library, FT_LCD_FILTER_DEFAULT );
  3488. - render->clazz->raster_class->raster_reset( render->raster, NULL, 0 );
  3489. + FT_UInt width = (FT_UInt)bitmap->width;
  3490. + FT_UInt height = (FT_UInt)bitmap->rows;
  3491. + FT_Byte* new_line;
  3492. + FT_Byte* line = bitmap->buffer;
  3493. + FT_Bitmap new_bitmap;
  3494. - return 0;
  3495. +
  3496. + FT_Bitmap_Init( &new_bitmap );
  3497. + FT_Bitmap_Copy( library, bitmap, &new_bitmap );
  3498. + new_line = (&new_bitmap)->buffer;
  3499. +
  3500. + if ( strength > 0 )
  3501. + for ( height = (FT_UInt)bitmap->rows;
  3502. + height > 0;
  3503. + height--, line += bitmap->pitch, new_line += bitmap->pitch )
  3504. + {
  3505. + FT_UInt xx;
  3506. +
  3507. +
  3508. + for ( xx = 1; xx < width - 1; xx += 1 )
  3509. + {
  3510. + if ( line[xx] > line[xx-1] && line[xx] > line[xx+1] )
  3511. + {
  3512. + if (new_line[xx] > 0)
  3513. + new_line[xx] += ( strength * ( 255 - new_line[xx] ) ) / 100;
  3514. + new_line[xx-1] += ( strength * ( 255 - line[xx-1] ) ) / 100;
  3515. + new_line[xx+1] += ( strength * ( 255 - line[xx+1] ) ) / 100;
  3516. + }
  3517. + }
  3518. + }
  3519. + FT_Bitmap_Copy( library, &new_bitmap, bitmap );
  3520. + FT_Bitmap_Done( library, &new_bitmap );
  3521. }
  3522. - static FT_Error
  3523. - ft_smooth_raster_lcd( FT_Renderer render,
  3524. - FT_Outline* outline,
  3525. - FT_Bitmap* bitmap )
  3526. + static void
  3527. + _ft_bitmap_cap ( FT_Bitmap* bitmap,
  3528. + FT_UInt strength,
  3529. + FT_Library library )
  3530. {
  3531. - FT_Error error = FT_Err_Ok;
  3532. - FT_Vector* points = outline->points;
  3533. - FT_Vector* points_end = FT_OFFSET( points, outline->n_points );
  3534. - FT_Vector* vec;
  3535. - FT_Raster_Params params;
  3536. + FT_UInt width = (FT_UInt)bitmap->width;
  3537. + FT_UInt height = (FT_UInt)bitmap->rows;
  3538. + FT_Byte* new_line;
  3539. + FT_Byte* line = bitmap->buffer;
  3540. + FT_UInt cur_value = 0;
  3541. + FT_Bitmap new_bitmap;
  3542. - params.target = bitmap;
  3543. - params.source = outline;
  3544. - params.flags = FT_RASTER_FLAG_AA;
  3545. + FT_Bitmap_Init( &new_bitmap );
  3546. + FT_Bitmap_Copy( library, bitmap, &new_bitmap );
  3547. + new_line = (&new_bitmap)->buffer;
  3548. - /* implode outline */
  3549. - for ( vec = points; vec < points_end; vec++ )
  3550. - vec->x *= 3;
  3551. + if ( strength > 0 )
  3552. + for ( height = (FT_UInt)bitmap->rows;
  3553. + height > 0;
  3554. + height--, line += bitmap->pitch, new_line += bitmap->pitch )
  3555. + {
  3556. + FT_UInt xx;
  3557. - /* render outline into the bitmap */
  3558. - error = render->raster_render( render->raster, &params );
  3559. - /* deflate outline */
  3560. - for ( vec = points; vec < points_end; vec++ )
  3561. - vec->x /= 3;
  3562. + for ( xx = 1; xx < width - 1; xx += 1 )
  3563. + {
  3564. + cur_value = ( new_line[xx-1] + new_line[xx] + new_line[xx+1] ) / 3;
  3565. + if ( cur_value > ( strength * 255 ) / 100 )
  3566. + {
  3567. + FT_UInt new_factor = ( strength * 255 ) / 100;
  3568. + new_line[xx] = ( new_line[xx] * new_factor ) / cur_value;
  3569. + new_line[xx+1] = ( new_line[xx+1] * new_factor ) / cur_value;
  3570. + new_line[xx-1] = ( new_line[xx-1] * new_factor ) / cur_value;
  3571. + }
  3572. + }
  3573. + }
  3574. + FT_Bitmap_Copy( library, &new_bitmap, bitmap );
  3575. + FT_Bitmap_Done( library, &new_bitmap );
  3576. + }
  3577. - return error;
  3578. + static int
  3579. + pseudo_gamma ( int val, float value )
  3580. + {
  3581. + return 256 * ( 1.0f - powf( ( 1.0f - val * (1.0f/256.0f) ), 1.0f / value ) );
  3582. }
  3583. +#if(0)
  3584. + static void
  3585. + _ft_bitmap_embolden ( FT_Bitmap* bitmap,
  3586. + FT_UInt strength,
  3587. + FT_Library library )
  3588. + {
  3589. - static FT_Error
  3590. - ft_smooth_raster_lcdv( FT_Renderer render,
  3591. - FT_Outline* outline,
  3592. - FT_Bitmap* bitmap )
  3593. + FT_UInt width = (FT_UInt)bitmap->width;
  3594. + FT_UInt height = (FT_UInt)bitmap->rows;
  3595. + FT_Byte* new_line;
  3596. + FT_Byte* line = bitmap->buffer;
  3597. + FT_Bitmap new_bitmap;
  3598. + FT_UInt xx;
  3599. +
  3600. +
  3601. + FT_Bitmap_Init(&new_bitmap);
  3602. + FT_Bitmap_Copy(library, bitmap, &new_bitmap);
  3603. + new_line = (&new_bitmap)->buffer;
  3604. +
  3605. + if ( strength > 0 )
  3606. + for ( height = (FT_UInt)bitmap->rows;
  3607. + height > 0;
  3608. + height--, line += bitmap->pitch, new_line += bitmap->pitch )
  3609. {
  3610. - FT_Error error = FT_Err_Ok;
  3611. - FT_Vector* points = outline->points;
  3612. - FT_Vector* points_end = FT_OFFSET( points, outline->n_points );
  3613. - FT_Vector* vec;
  3614. + for ( xx = 1; xx < width - 1; xx += 1 )
  3615. + {
  3616. + FT_Int new_value = 0;
  3617. - FT_Raster_Params params;
  3618. + new_value = ( strength * line [xx-1] ) / 100
  3619. + + pseudo_gamma( line [xx], .75 )
  3620. + + (strength * line [xx+1] ) / 100;
  3621. + if ( new_value > 255 )
  3622. + new_value = 255;
  3623. - params.target = bitmap;
  3624. - params.source = outline;
  3625. - params.flags = FT_RASTER_FLAG_AA;
  3626. + new_line[xx] = new_value;
  3627. + }
  3628. + }
  3629. + FT_Bitmap_Copy( library, &new_bitmap, bitmap );
  3630. + FT_Bitmap_Done( library, &new_bitmap );
  3631. + }
  3632. - /* implode outline */
  3633. - for ( vec = points; vec < points_end; vec++ )
  3634. - vec->y *= 3;
  3635. - /* render outline into the bitmap */
  3636. - error = render->raster_render( render->raster, &params );
  3637. - /* deflate outline */
  3638. - for ( vec = points; vec < points_end; vec++ )
  3639. - vec->y /= 3;
  3640. + static void
  3641. + _ft_bitmap_gamma ( FT_Bitmap* bitmap,
  3642. + float strength )
  3643. + {
  3644. - return error;
  3645. + FT_UInt width = (FT_UInt)bitmap->width;
  3646. + FT_UInt height = (FT_UInt)bitmap->rows;
  3647. + FT_Byte* line = bitmap->buffer;
  3648. + FT_UInt xx;
  3649. +
  3650. +
  3651. + if ( strength > 0 )
  3652. + for ( height = (FT_UInt)bitmap->rows;
  3653. + height > 0;
  3654. + height--, line += bitmap->pitch )
  3655. + {
  3656. +
  3657. + for ( xx = 1; xx < width - 1; xx += 1 )
  3658. + {
  3659. + if ( abs( line[xx-1] - line[xx] ) < 20 ||
  3660. + abs( line[xx+1] - line[xx] ) < 20 )
  3661. + line [xx] = pseudo_gamma( line [xx], strength ) ;
  3662. + }
  3663. + }
  3664. + }
  3665. +#endif
  3666. +
  3667. + /* Fringe filter */
  3668. + static void
  3669. + _ft_lcd_fringe_filter ( FT_Bitmap* bitmap,
  3670. + FT_Render_Mode mode,
  3671. + FT_UInt strength,
  3672. + FT_Library library )
  3673. + {
  3674. +
  3675. + FT_UInt width = (FT_UInt)bitmap->width;
  3676. + FT_UInt height = (FT_UInt)bitmap->rows;
  3677. + FT_Byte* new_line;
  3678. + FT_Byte* line = bitmap->buffer;
  3679. + FT_Bitmap new_bitmap;
  3680. +
  3681. +
  3682. + FT_Bitmap_Init(&new_bitmap);
  3683. +
  3684. + line = bitmap->buffer;
  3685. + FT_Bitmap_Copy( library, bitmap, &new_bitmap );
  3686. + new_line = (&new_bitmap)->buffer;
  3687. +
  3688. + for ( height = (FT_UInt)bitmap->rows;
  3689. + height > 0;
  3690. + height--, line += bitmap->pitch, new_line += bitmap->pitch )
  3691. + {
  3692. + /* Threshold set to 1/2 pixel intensity */
  3693. + FT_UInt xx, threshold = 128;
  3694. +
  3695. + /* Hack to make this work when bitmap is at first or last line */
  3696. + FT_Int fudge = bitmap->pitch * (height == (FT_UInt)bitmap->rows);
  3697. +
  3698. + FT_Byte* prevline = line - bitmap->pitch + fudge;
  3699. + FT_Byte* nextline = line + bitmap->pitch;
  3700. +
  3701. +
  3702. + for ( xx = 1; xx < width - 1; xx += 1 )
  3703. + {
  3704. + /* subpixel grid sp11 sp21 sp31 */
  3705. + /* where sp22 is sp12 sp22 sp32 */
  3706. + /* current subpixel. sp13 sp23 sp33 */
  3707. +
  3708. + FT_Int prevtotal, nexttotal, lefttotal, righttotal, sidesdiff,
  3709. + leftdiff, rightdiff, prevdiff, nextdiff, sp11, sp21, sp31,
  3710. + sp12, sp22, sp32, sp13, sp23, sp33;
  3711. +
  3712. + sp12 = line [xx-1];
  3713. + sp22 = line [xx];
  3714. + sp32 = line [xx+1];
  3715. +
  3716. + /* if at max height fake out some values */
  3717. + if ( height == (FT_UInt)bitmap->rows )
  3718. + {
  3719. + prevtotal = sp11 = sp21 = sp31 = 0;
  3720. + prevdiff = sp22;
  3721. + lefttotal = sp12 + sp13;
  3722. + righttotal = sp32 + sp33;
  3723. + }
  3724. + else
  3725. + {
  3726. + prevtotal = prevline[xx-1] + prevline[xx] + prevline[xx+1];
  3727. + sp11 = prevline [xx-1];
  3728. + sp21 = prevline [xx];
  3729. + sp31 = prevline [xx+1];
  3730. + prevdiff = sp22 - sp21;
  3731. + lefttotal = sp11 + sp12 + sp13;
  3732. + righttotal = sp31 + sp32 + sp33;
  3733. + }
  3734. +
  3735. + /* if at min height fake out some values */
  3736. + if ( height == 1 )
  3737. + {
  3738. + nexttotal = sp13 = sp23 = sp33 = 0;
  3739. + nextdiff = sp22;
  3740. + lefttotal = sp11 + sp12;
  3741. + righttotal = sp31 + sp32;
  3742. + }
  3743. + else
  3744. + {
  3745. + nexttotal = nextline[xx-1] + nextline[xx] + nextline[xx+1];
  3746. + sp13 = nextline [xx-1];
  3747. + sp23 = nextline [xx];
  3748. + sp33 = nextline [xx+1];
  3749. + nextdiff = sp23 - sp22;
  3750. + lefttotal = sp11 + sp12 + sp13;
  3751. + righttotal = sp31 + sp32 + sp33;
  3752. + }
  3753. +
  3754. + sidesdiff = lefttotal - righttotal;
  3755. + leftdiff = sp22 - sp12;
  3756. + rightdiff = sp32 - sp22;
  3757. +
  3758. + if ( sidesdiff < 0 )
  3759. + sidesdiff *= -1;
  3760. +
  3761. + if ( prevdiff < 0 )
  3762. + prevdiff *= -1;
  3763. +
  3764. + if ( nextdiff < 0 )
  3765. + nextdiff *= -1;
  3766. +
  3767. + if ( leftdiff < 0 )
  3768. + leftdiff *= -1;
  3769. +
  3770. + if ( rightdiff < 0 )
  3771. + rightdiff *= -1;
  3772. +
  3773. + /* if the current subpixel is less than threshold, and varies only
  3774. + slightly to left or right, lighten it */
  3775. + if ( sp22 <= threshold && sp22 > 0 &&
  3776. + ( leftdiff < 10 || rightdiff < 10 ) )
  3777. + {
  3778. + /* A pixel is horizontally isolated if: */
  3779. + /* 1: All upper adjecent subpixels are >= threshold and all lower
  3780. + adjacent ones are essentially white */
  3781. + if ( prevtotal >= nexttotal &&
  3782. + sp11 >= threshold &&
  3783. + sp21 >= threshold &&
  3784. + sp31 >= threshold &&
  3785. + sp13 < 2 &&
  3786. + sp23 < 2 &&
  3787. + sp33 < 2 )
  3788. +
  3789. + {
  3790. + new_line[xx] -= ( new_line[xx] * strength ) / 100;
  3791. +
  3792. + if ( leftdiff < 10 )
  3793. + /* OPPORTUNITY FOR IMPROVEMENT - keep going left until 255? */
  3794. + new_line[xx-1] -= ( new_line[xx-1] * strength ) / 200;
  3795. +
  3796. + if ( rightdiff < 10 )
  3797. + /* OPPORTUNITY FOR IMPROVEMENT */
  3798. + new_line[xx+1] -= ( new_line[xx+1] * strength ) / 200;
  3799. + }
  3800. + else if ( nexttotal > prevtotal &&
  3801. + /* 2: the inverse of above */
  3802. + sp13 >= threshold &&
  3803. + sp23 >= threshold &&
  3804. + sp33 >= threshold &&
  3805. + sp11 < 2 &&
  3806. + sp21 < 2 &&
  3807. + sp31 < 2 )
  3808. + {
  3809. + new_line[xx] -= ( new_line[xx] * strength ) / 100;
  3810. +
  3811. + if ( leftdiff < 10 )
  3812. + /* OPPORTUNITY FOR IMPROVEMENT - keep going left until 255? */
  3813. + new_line[xx-1] -= ( new_line[xx-1] * strength ) / 200;
  3814. +
  3815. + if ( rightdiff < 10 )
  3816. + /* OPPORTUNITY FOR IMPROVEMENT */
  3817. + new_line[xx+1] -= ( new_line[xx+1] * strength ) / 200;
  3818. + }
  3819. + }
  3820. + /* otherwise if the current subpixel is more than threshold, and varies
  3821. + slightly to left or right, darken it */
  3822. + else if ( sp22 > threshold &&
  3823. + sp22 < 255 &&
  3824. + ( leftdiff < 10 ||
  3825. + rightdiff < 10 ) )
  3826. + {
  3827. + if ( sp11 <= 2 &&
  3828. + sp21 <= 2 &&
  3829. + sp31 <= 2 &&
  3830. + sp13 >= threshold &&
  3831. + sp23 >= threshold &&
  3832. + sp33 >= threshold &&
  3833. + prevtotal < nexttotal )
  3834. + new_line[xx] += ( ( 255 - new_line[xx] ) * strength ) / 100;
  3835. +
  3836. + else if ( sp13 <= 2 &&
  3837. + sp23 <= 2 &&
  3838. + sp33 <= 2 &&
  3839. + nexttotal < prevtotal &&
  3840. + sp11 >= threshold &&
  3841. + sp21 >= threshold &&
  3842. + sp31 >= threshold )
  3843. + new_line[xx] += ( ( 255 - new_line[xx] ) * strength ) / 100;
  3844. +
  3845. + }
  3846. }
  3847. + }
  3848. + FT_Bitmap_Copy( library, &new_bitmap, bitmap );
  3849. + FT_Bitmap_Done( library, &new_bitmap );
  3850. + }
  3851. +
  3852. +
  3853. + /* Grayscale filter */
  3854. + static void
  3855. + _ft_lcd_grayscale_filter ( FT_Bitmap* bitmap,
  3856. + FT_Render_Mode mode,
  3857. + FT_UInt strength,
  3858. + FT_Library library )
  3859. + {
  3860. +
  3861. + FT_UInt width = (FT_UInt)bitmap->width;
  3862. + FT_UInt height = (FT_UInt)bitmap->rows;
  3863. + FT_Byte* line = bitmap->buffer;
  3864. +
  3865. +
  3866. + for ( height = (FT_UInt)bitmap->rows;
  3867. + height > 0;
  3868. + height--, line += bitmap->pitch )
  3869. + {
  3870. + FT_UInt xx;
  3871. -#endif /* FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
  3872. -/* Oversampling scale to be used in rendering overlaps */
  3873. -#define SCALE ( 1 << 2 )
  3874. + for ( xx = 0; xx < width - 1; xx += 3 )
  3875. + {
  3876. + FT_UInt total = line [xx] + line [xx + 1] + line [xx + 2];
  3877. + line[xx] = ( ( 100 - strength ) * line[xx]
  3878. + + strength * ( total / 3 ) ) / 100;
  3879. + line[xx+1] = ( ( 100 - strength ) * line[xx+1]
  3880. + + strength * ( total / 3 ) ) / 100;
  3881. + line[xx+2] = ( ( 100 - strength ) * line[xx+2]
  3882. + + strength * ( total / 3 ) ) / 100;
  3883. + }
  3884. + }
  3885. + }
  3886. +
  3887. +/*
  3888. + These need to be in sync with params inside ftinf.c
  3889. + (not ideal but perhaps better than making these public)
  3890. + */
  3891. +#define STEM_WIDTH_2_PPEM 18
  3892. +#define MAX_PPEM 100
  3893. +
  3894. + typedef struct Stem_Segment_
  3895. + {
  3896. + FT_Long x1;
  3897. + FT_Long x2;
  3898. + FT_Int y;
  3899. + } Stem_Segment;
  3900. +
  3901. + typedef struct Stem_Center_
  3902. + {
  3903. + FT_Long x;
  3904. + FT_Long y;
  3905. + FT_Long w;
  3906. + FT_Long x1;
  3907. + FT_Long x2;
  3908. + } Stem_Center;
  3909. +
  3910. + typedef struct Stem_
  3911. + {
  3912. + FT_Long center;
  3913. + FT_Long count;
  3914. + FT_Long rcount; /* used to count within a range in possible stems */
  3915. + FT_Long width;
  3916. + FT_Long height;
  3917. + FT_Short zone; /* 1 2 or 3 */
  3918. + FT_Bool generated;
  3919. + } Stem;
  3920. - /* This function averages inflated spans in direct rendering mode */
  3921. static void
  3922. - ft_smooth_overlap_spans( int y,
  3923. - int count,
  3924. - const FT_Span* spans,
  3925. - TOrigin* target )
  3926. + swap_stem ( Stem* s1, Stem* s2 )
  3927. {
  3928. - unsigned char* dst = target->origin - ( y / SCALE ) * target->pitch;
  3929. - unsigned short x;
  3930. - unsigned int cover, sum;
  3931. + Stem s;
  3932. + s.center = s1->center;
  3933. + s.count = s1->count;
  3934. + s.rcount = s1->rcount;
  3935. + s.width = s1->width;
  3936. + s.zone = s1->zone;
  3937. + s.generated = s1->generated;
  3938. +
  3939. + s1->center = s2->center;
  3940. + s1->count = s2->count;
  3941. + s1->rcount = s2->rcount;
  3942. + s1->width = s2->width;
  3943. + s1->zone = s2->zone;
  3944. + s1->generated = s2->generated;
  3945. +
  3946. + s2->center = s.center;
  3947. + s2->count = s.count;
  3948. + s2->rcount = s.rcount;
  3949. + s2->width = s.width;
  3950. + s2->zone = s.zone;
  3951. + s2->generated = s.generated;
  3952. + }
  3953. +
  3954. + /* Stem alignment for bitmaps; A hack with very nice results */
  3955. + /* Ideally this could be implemented on the outline, prior to
  3956. + * rasterization. Possible future enhancement is to use the
  3957. + * warper code to achieve this */
  3958. + static void
  3959. + _lcd_stem_align ( FT_Bitmap* bitmap,
  3960. + FT_Render_Mode mode,
  3961. + FT_GlyphSlot slot,
  3962. + FT_Long* translate_value,
  3963. + float* scale_value,
  3964. + FT_UInt alignment_strength,
  3965. + FT_UInt fitting_strength,
  3966. + float* embolden_value
  3967. + )
  3968. + {
  3969. + FT_UInt width = (FT_UInt)bitmap->width;
  3970. + FT_UInt height = (FT_UInt)bitmap->rows;
  3971. +
  3972. + Stem_Segment* segments;
  3973. + Stem_Segment* leftmost_segment;
  3974. + Stem_Segment* rightmost_segment;
  3975. + Stem_Segment* leftmost_segment_not_extrema;
  3976. + Stem_Segment* rightmost_segment_not_extrema;
  3977. + Stem* stems;
  3978. + Stem* possible_stems;
  3979. + Stem* leftmost_stem;
  3980. + Stem* rightmost_stem;
  3981. + Stem_Data* known_stem_values;
  3982. + Stem_Center* centers;
  3983. + FT_Long leftmost_point = width * 256;
  3984. + FT_Long rightmost_point = 0;
  3985. + FT_Long leftmost_point_not_extrema = width * 256;
  3986. + FT_Long rightmost_point_not_extrema = 0;
  3987. + FT_Long num_segments = 0;
  3988. + FT_Long num_centers = 0;
  3989. + FT_Long *stem_centers;
  3990. + FT_UInt h;
  3991. + FT_ULong valid_stems = 0, valid_possible_stems = 0;
  3992. + FT_Long center, stem_matches, stem_matches_ledge;
  3993. + FT_Long stem_matches_redge, next_center, last_matching_center;
  3994. + FT_Long last_matching_ledge, last_matching_redge, this_center;
  3995. + FT_Int max_strength;
  3996. + FT_Byte* line = bitmap->buffer;
  3997. + FT_UInt current_value = 0;
  3998. + FT_UInt xx;
  3999. + FT_Long linearHoriAdvance = slot->linearHoriAdvance >> 10;
  4000. +
  4001. + FT_Int m_horiBearingX = slot->metrics.horiBearingX;
  4002. + FT_Int m_horiAdvance = slot->metrics.horiAdvance;
  4003. + FT_Int m_width = slot->metrics.width;
  4004. + FT_Pos one_pixel = 768;
  4005. + FT_Pos one_third_pixel = 256;
  4006. + FT_Int columns_per_pixel = 3;
  4007. + /*FT_Int extra_columns = 6;*/
  4008. +
  4009. + /* on / off flags for testing different features */
  4010. + FT_Bool strategy_translate_using_closest_stem = TRUE;
  4011. + FT_Bool strategy_scale_to_closest_centers = FALSE;
  4012. + FT_Bool strategy_scale_to_closest_centers_up_only = FALSE;
  4013. + FT_Bool strategy_always_use_distance_ceiling = FALSE;
  4014. + FT_Bool strategy_auto_change_center_offset = TRUE;
  4015. + FT_Bool strategy_use_m_control = FALSE;
  4016. + FT_Bool strategy_correct_out_of_bounds_outlines = FALSE;
  4017. + FT_Bool strategy_also_use_edge_detection_for_stems = FALSE;
  4018. + FT_Bool strategy_use_strengths = TRUE;
  4019. + FT_Bool strategy_synthesize_stems = FALSE;
  4020. + FT_Bool strategy_bearing_correction = TRUE;
  4021. + FT_Bool strategy_use_d_correction = TRUE;
  4022. + FT_Bool strategy_fit_to_width = FALSE;
  4023. + /*FT_Bool strategy_center_glyph = FALSE;*/
  4024. +
  4025. + const FT_Int MIN_PPEM = 7;
  4026. + /*const FT_Int MAX_PPEM = 100;*/
  4027. + const FT_Int MAX_STEMS = 3;
  4028. + FT_Int ppem = 0;
  4029. +
  4030. + Stem_Data stem_data;
  4031. +
  4032. + /* reset to default */
  4033. + *scale_value = 1.0;
  4034. +
  4035. + /* Simply return in odd cases where these don't seem to be set */
  4036. + /* Flash and some pdf viewers will crash otherwise */
  4037. + if ( !slot->face ||
  4038. + !slot->face->size ||
  4039. + !slot->face->size->metrics.x_ppem )
  4040. + return;
  4041. +
  4042. + if ( slot->face->size->metrics.x_ppem > MAX_PPEM )
  4043. + return;
  4044. +
  4045. + if ( slot->face->size->metrics.x_ppem < MIN_PPEM )
  4046. + return;
  4047. +
  4048. + if ( !FT_IS_SCALABLE( slot->face ) )
  4049. + return;
  4050. +
  4051. + ppem = slot->face->size->metrics.x_ppem;
  4052. +
  4053. + if ( ppem < 9 )
  4054. + return;
  4055. + if ( ppem > 20 )
  4056. + strategy_use_m_control = TRUE;
  4057. +
  4058. + /* only perform alignment on styles we know, that aren't bold or italic */
  4059. + /* perhaps detection could be added on those that are not set? */
  4060. + /* Require certain ppems for narrow and light fonts */
  4061. + if( slot->face->style_name )
  4062. + {
  4063. + if ( strcasestr( slot->face->style_name, "Italic" ) ||
  4064. + strcasestr( slot->face->style_name, "Oblique" ) ||
  4065. + strcasestr( slot->face->style_name, "Script" ) ||
  4066. + strcasestr( slot->face->style_name, "Handwriting" ) ||
  4067. + strcasestr( slot->face->style_name, "Bold" ) ||
  4068. + strcasestr( slot->face->style_name, "Black" ) ||
  4069. + ( ( strcasestr( slot->face->style_name, "Extra Thin" ) ||
  4070. + strcasestr( slot->face->style_name, "Extra Light" ) ) &&
  4071. + ppem < 10 ) ||
  4072. + ( strcasestr( slot->face->style_name, "Thin" )
  4073. + && ppem < 10 ) ||
  4074. + ( strcasestr( slot->face->style_name, "Light" )
  4075. + && ppem < 10 ) ||
  4076. + ( strcasestr( slot->face->style_name, "Narrow" )
  4077. + && ppem < 15 ) ||
  4078. + ( strcasestr( slot->face->style_name, "Condensed" )
  4079. + && ppem < 20 ) )
  4080. + return;
  4081. + }
  4082. +
  4083. + if( slot->face->family_name )
  4084. + {
  4085. + if ( strcasestr( slot->face->family_name, "Italic" ) ||
  4086. + strcasestr( slot->face->family_name, "Oblique" ) ||
  4087. + strcasestr( slot->face->family_name, "Script" ) ||
  4088. + strcasestr( slot->face->family_name, "Handwriting" ) ||
  4089. + strcasestr( slot->face->family_name, "Bold" ) ||
  4090. + strcasestr( slot->face->family_name, "Black" ) ||
  4091. + ( ( strcasestr( slot->face->family_name, "Extra Thin" ) ||
  4092. + strcasestr( slot->face->family_name, "Extra Light" ) ) &&
  4093. + ppem < 10 ) ||
  4094. + ( strcasestr( slot->face->family_name, "Thin" )
  4095. + && ppem < 10 ) ||
  4096. + ( strcasestr( slot->face->family_name, "Light" )
  4097. + && ppem < 10 ) ||
  4098. + ( strcasestr( slot->face->family_name, "Narrow" )
  4099. + && ppem < 15 ) ||
  4100. + ( strcasestr( slot->face->family_name, "Condensed" )
  4101. + && ppem < 20 ) )
  4102. + return;
  4103. + }
  4104. + else if ( slot->face->style_flags )
  4105. + {
  4106. + if ( slot->face->style_flags & FT_STYLE_FLAG_ITALIC ||
  4107. + slot->face->style_flags & FT_STYLE_FLAG_BOLD ||
  4108. + FT_IS_TRICKY( slot->face ) )
  4109. + return;
  4110. + }
  4111. + else return;
  4112. +
  4113. + if ( mode != FT_RENDER_MODE_LCD )
  4114. + {
  4115. + columns_per_pixel = 1;
  4116. + one_pixel = 256;
  4117. + one_third_pixel = 85;
  4118. + /*extra_columns = 0;*/
  4119. + /* until this can be figured out just return */
  4120. + /* There are issues with missing glyphs */
  4121. + return;
  4122. + }
  4123. +
  4124. + known_stem_values=&stem_data;
  4125. + if ( ftinf && ftinf->use_known_settings_on_selected_fonts )
  4126. + {
  4127. + ftinf_fill_stem_values( known_stem_values, slot->face->family_name, ppem, TRUE );
  4128. + /* translate value may be set for < 10 */
  4129. + if (known_stem_values->stem_translating_only > -1024 )
  4130. + {
  4131. + *translate_value = known_stem_values->stem_translating_only;
  4132. + return;
  4133. + }
  4134. + if( known_stem_values->bearing_correction == FALSE )
  4135. + strategy_bearing_correction = FALSE;
  4136. + } else
  4137. + ftinf_fill_stem_values( known_stem_values, slot->face->family_name, ppem, FALSE );
  4138. +
  4139. + if ( known_stem_values->use_100 ||
  4140. + known_stem_values->m >= 0 )
  4141. + {
  4142. + alignment_strength = fitting_strength = 100;
  4143. + strategy_use_m_control = TRUE;
  4144. + }
  4145. +
  4146. + if ( known_stem_values->edge_detection )
  4147. + strategy_also_use_edge_detection_for_stems = TRUE;
  4148. +
  4149. + /* Allocate */
  4150. + segments = NULL;
  4151. + leftmost_segment = (Stem_Segment*) malloc( 4*sizeof ( Stem_Segment ) );
  4152. + leftmost_segment_not_extrema = leftmost_segment+1;
  4153. + rightmost_segment = leftmost_segment+2;
  4154. + rightmost_segment_not_extrema = leftmost_segment+3;
  4155. +
  4156. + stems = (Stem*) malloc ( (2*MAX_STEMS+2) * sizeof ( Stem ) );
  4157. + possible_stems = stems+MAX_STEMS;
  4158. + leftmost_stem = possible_stems+MAX_STEMS;
  4159. + rightmost_stem = leftmost_stem + 1;
  4160. + centers = NULL;
  4161. +
  4162. + if ( verbose )
  4163. + printf("\n");
  4164. +
  4165. + /* Initialize */
  4166. + stem_centers=(FT_Long*)calloc( width * 256, sizeof(stem_centers[0]) );
  4167. +
  4168. + rightmost_segment->x1 = 0;
  4169. + rightmost_segment->x2 = 0;
  4170. + rightmost_segment->y = 0;
  4171. + leftmost_segment->x1 = 99999999;
  4172. + leftmost_segment->x2 = 0;
  4173. + leftmost_segment->y = 0;
  4174. +
  4175. + rightmost_segment_not_extrema->x1 = 0;
  4176. + rightmost_segment_not_extrema->x2 = 0;
  4177. + rightmost_segment_not_extrema->y = 0;
  4178. + leftmost_segment_not_extrema->x1 = 99999999;
  4179. + leftmost_segment_not_extrema->x2 = 0;
  4180. + leftmost_segment_not_extrema->y = 0;
  4181. +
  4182. + /* Locate stem centers for later processing */
  4183. + for ( h = (FT_UInt)bitmap->rows; h > 0; h--, line += bitmap->pitch )
  4184. + {
  4185. + current_value = 0;
  4186. + /* Calculate various sums and stem widths of glyph */
  4187. + for ( xx = 0; xx < width; xx += 1 )
  4188. + {
  4189. + /* Reallocate (in blocks of 64) */
  4190. + if( num_segments % 64 == 0 )
  4191. + segments = (Stem_Segment*) realloc
  4192. + ( segments, ( num_segments + 64 ) * sizeof ( Stem_Segment ) );
  4193. +
  4194. + /* if line is white, and now has color, it's the start of a stem */
  4195. + if ( current_value == 0 && line[xx] > 0 )
  4196. + {
  4197. + /* start of stem */
  4198. + segments[num_segments].x1 = 256 * xx + ( 255 - line[xx] );
  4199. + segments[num_segments].y = h;
  4200. + }
  4201. +
  4202. + /* otherwise, if it's currently black and the new value is 0,
  4203. + it's the end of a stem */
  4204. + else if ( ( current_value > 0 && line[xx] == 0 ) ||
  4205. + ( current_value > 0 && xx == width - 1 ) )
  4206. + {
  4207. + FT_Long stem_center_x;
  4208. + segments[num_segments].x2 = 256 * ( xx - 1 ) + line[xx-1];
  4209. +
  4210. + if ( xx == width - 1 )
  4211. + segments[num_segments].x2 += line[xx];
  4212. +
  4213. + /*stem center is average of start and end of stem */
  4214. + stem_center_x = ( segments[num_segments].x2
  4215. + + segments[num_segments].x1 ) / 2;
  4216. +
  4217. + /* Reallocate (in blocks of 32) */
  4218. + if( num_centers % 32 == 0 )
  4219. + centers = (Stem_Center*) realloc
  4220. + ( centers, ( num_centers + 32 ) * sizeof ( Stem_Center ) );
  4221. + centers[num_centers].x = stem_center_x;
  4222. + centers[num_centers].y = h;
  4223. + centers[num_centers].x1 = segments[num_segments].x1;
  4224. + centers[num_centers].x2 = segments[num_segments].x2;
  4225. +
  4226. + num_centers++;
  4227. +
  4228. + stem_centers[stem_center_x] += 1;
  4229. +
  4230. + /* Find left and rightmost points for later calculations */
  4231. + /* OR - Favor ones that aren't on the top or bottom if */
  4232. + /* possible to prevent v and w from getting caught later */
  4233. + if ( segments[num_segments].x1 < leftmost_segment->x1 ||
  4234. + ( segments[num_segments].y > 1 &&
  4235. + segments[num_segments].y < height &&
  4236. + segments[num_segments].x1 == leftmost_segment->x1 ) )
  4237. + {
  4238. + leftmost_segment->x1 = segments[num_segments].x1;
  4239. + leftmost_segment->x2 = segments[num_segments].x2;
  4240. + leftmost_segment->y = h;
  4241. + }
  4242. + if ( segments[num_segments].x2 > rightmost_segment->x2 ||
  4243. + ( segments[num_segments].y > 1 &&
  4244. + segments[num_segments].y < height &&
  4245. + segments[num_segments].x1 == rightmost_segment->x1 ) )
  4246. + {
  4247. + rightmost_segment->x1 = segments[num_segments].x1;
  4248. + rightmost_segment->x2 = segments[num_segments].x2;
  4249. + rightmost_segment->y = h;
  4250. + }
  4251. +
  4252. + if ( segments[num_segments].x1
  4253. + < leftmost_segment_not_extrema->x1 ||
  4254. + ( segments[num_segments].y > 1 &&
  4255. + segments[num_segments].y < height &&
  4256. + segments[num_segments].x1
  4257. + == leftmost_segment_not_extrema->x1 &&
  4258. + h < (FT_UInt)bitmap->rows && h > 0 ) )
  4259. + {
  4260. + leftmost_segment_not_extrema->x1 = segments[num_segments].x1;
  4261. + leftmost_segment_not_extrema->x2 = segments[num_segments].x2;
  4262. + leftmost_segment_not_extrema->y = h;
  4263. + }
  4264. + if ( segments[num_segments].x2
  4265. + > rightmost_segment_not_extrema->x2 ||
  4266. + ( segments[num_segments].y > 1 &&
  4267. + segments[num_segments].y < height &&
  4268. + segments[num_segments].x1
  4269. + == rightmost_segment_not_extrema->x1 &&
  4270. + h < (FT_UInt)bitmap->rows && h > 0 ) )
  4271. + {
  4272. + rightmost_segment_not_extrema->x1 = segments[num_segments].x1;
  4273. + rightmost_segment_not_extrema->x2 = segments[num_segments].x2;
  4274. + rightmost_segment_not_extrema->y = h;
  4275. + }
  4276. +
  4277. + if ( segments[num_segments].x1 < leftmost_point )
  4278. + leftmost_point = segments[num_segments].x1;
  4279. +
  4280. + if ( segments[num_segments].x2 > rightmost_point )
  4281. + rightmost_point = segments[num_segments].x2;
  4282. +
  4283. + if ( segments[num_segments].x1 < leftmost_point_not_extrema &&
  4284. + h < (FT_UInt)bitmap->rows && h > 0 )
  4285. + leftmost_point_not_extrema = segments[num_segments].x1;
  4286. +
  4287. + if ( segments[num_segments].x2 > rightmost_point_not_extrema &&
  4288. + h < (FT_UInt)bitmap->rows && h > 0 )
  4289. + rightmost_point_not_extrema = segments[num_segments].x2;
  4290. +
  4291. + num_segments++;
  4292. + }
  4293. + /* else - other conditions - need some error checking here */
  4294. + current_value = line[xx];
  4295. + }
  4296. + }
  4297. +
  4298. + /* initialize */
  4299. + for ( xx = 0; xx < MAX_STEMS; xx +=1 )
  4300. + {
  4301. + stems[xx].center = 0;
  4302. + stems[xx].count = 0;
  4303. + stems[xx].width = 0;
  4304. + stems[xx].height = 0;
  4305. + possible_stems[xx].center = 0;
  4306. + possible_stems[xx].count = 0;
  4307. + possible_stems[xx].width = 0;
  4308. + possible_stems[xx].height = 0;
  4309. + }
  4310. +
  4311. + valid_stems = 0;
  4312. + valid_possible_stems = 0;
  4313. +
  4314. + /* Determine which centers belong to stems */
  4315. + center = 0;
  4316. +
  4317. + while ( center < num_centers )
  4318. + {
  4319. + /* slope at within which to consider a point part of a stem */
  4320. + /*const FT_UInt slope = 1;
  4321. + const FT_UInt topslope = (256 * 3) / 10; */
  4322. +
  4323. + /* 10 to 20 with 4 matches seems good, */
  4324. + /* but 1 or 2 with 3 stems needs to somehow get included */
  4325. + FT_Int deviation1 = 5;
  4326. + FT_Int deviation2=-1, requirement1 = 4, stem_match_requirement = 3;
  4327. + FT_Int center_difference_in_height;
  4328. + FT_Int center_difference_in_width, valid_center_average;
  4329. + FT_Int smallest_width_ledge, smallest_width_redge;
  4330. + FT_Int x1_difference_in_width, x2_difference_in_width;
  4331. + FT_Bool no_gap_found = FALSE;
  4332. + FT_Bool no_gap_found_ledge = FALSE;
  4333. + FT_Bool no_gap_found_redge = FALSE;
  4334. + FT_Bool stem_detected = FALSE;
  4335. + FT_Int set_width_to, set_center_to;
  4336. +
  4337. + /* seems to not do damage */
  4338. + /* May not be effective */
  4339. + requirement1 = height / 4;
  4340. + if ( requirement1 < 5 )
  4341. + requirement1 = 5;
  4342. + deviation1 = 20;
  4343. + deviation2 = 20;
  4344. +
  4345. + if ( columns_per_pixel == 1 )
  4346. + deviation1 = deviation2 = 10;
  4347. +
  4348. + if ( (FT_Int)bitmap->rows <= 6 )
  4349. + deviation1 = 25;
  4350. +
  4351. + if ( (FT_Int)bitmap->rows <= 6 )
  4352. + deviation2 = 25;
  4353. +
  4354. + if ( columns_per_pixel == 1 &&
  4355. + (FT_Int)bitmap->rows <= 6 )
  4356. + deviation1 = deviation2 = 12;
  4357. +
  4358. + valid_center_average = 0;
  4359. +
  4360. + no_gap_found = no_gap_found_ledge = no_gap_found_redge = FALSE;
  4361. + stem_detected = FALSE;
  4362. +
  4363. + if ( ppem < 11 )
  4364. + requirement1 = 4;
  4365. +
  4366. + if ( ppem > 18 )
  4367. + {
  4368. + stem_match_requirement = height / 4;
  4369. + if ( stem_match_requirement < 3 )
  4370. + stem_match_requirement = 3;
  4371. + }
  4372. +
  4373. + smallest_width_ledge = smallest_width_redge = width * 256;
  4374. + stem_matches = 0;
  4375. + stem_matches_ledge = 0;
  4376. + stem_matches_redge = 0;
  4377. + last_matching_center = -1;
  4378. + last_matching_ledge = -1;
  4379. + last_matching_redge = -1;
  4380. +
  4381. + /* set currently looked at center to center value */
  4382. + this_center = center;
  4383. + next_center = 0;
  4384. +
  4385. + /* For each center, compare with all other centers to see if others */
  4386. + /* match the properties of this one */
  4387. + while ( next_center < num_centers )
  4388. + {
  4389. +
  4390. + /* calculate differences */
  4391. + center_difference_in_width = abs ( centers[this_center].x
  4392. + - centers[next_center].x );
  4393. + center_difference_in_height = abs ( centers[this_center].y
  4394. + - centers[next_center].y );
  4395. + x1_difference_in_width = abs ( centers[this_center].x1
  4396. + - centers[next_center].x1 );
  4397. + x2_difference_in_width = abs ( centers[this_center].x2
  4398. + - centers[next_center].x2 );
  4399. +
  4400. +
  4401. + /* property - stem center points that align */
  4402. + /* if the center is within range, the center is less than */
  4403. + /* 1/2 the height away, and at least one edge is also within range */
  4404. + if ( center_difference_in_width
  4405. + < center_difference_in_height * deviation1 &&
  4406. + center_difference_in_height
  4407. + <= (FT_Int)bitmap->rows / 2 &&
  4408. + /* prevents w from getting caught ---- but also kills m */
  4409. + ( x1_difference_in_width
  4410. + < center_difference_in_height * deviation2 ||
  4411. + x2_difference_in_width
  4412. + < center_difference_in_height * deviation2 ) )
  4413. + {
  4414. + stem_matches += 1;
  4415. + valid_center_average += centers[next_center].x;
  4416. +
  4417. + /* try to find where the matching centers are far apart */
  4418. + if ( last_matching_center >= 0 &&
  4419. + abs( centers[last_matching_center].y
  4420. + - centers[next_center].y ) >= (FT_Int)bitmap->rows / 2 )
  4421. +
  4422. + /* try to find where matching centers are next to each other */
  4423. + if ( last_matching_center >= 0 &&
  4424. + abs( centers[last_matching_center].y
  4425. + - centers[next_center].y ) == 1 )
  4426. + no_gap_found = TRUE;
  4427. +
  4428. + last_matching_center = next_center;
  4429. + }
  4430. +
  4431. + if ( strategy_also_use_edge_detection_for_stems )
  4432. + {
  4433. + /* property - stem left edge points that align */
  4434. + /* if the center is within range, */
  4435. + /* the center is less than 1/2 the height away */
  4436. + if ( x1_difference_in_width
  4437. + < center_difference_in_height * deviation1 &&
  4438. + center_difference_in_height <= (FT_Int)bitmap->rows / 2 )
  4439. + {
  4440. + stem_matches_ledge += 1;
  4441. + /* may not need for edges */
  4442. + /*valid_center_average += centers[next_center].x; */
  4443. +
  4444. + if ( centers[next_center].x2 - centers[next_center].x1
  4445. + < smallest_width_ledge )
  4446. + smallest_width_ledge = centers[next_center].x2
  4447. + - centers[next_center].x1;
  4448. +
  4449. + /* try to find where the matching centers are far apart */
  4450. + if ( last_matching_ledge >= 0 &&
  4451. + abs( centers[last_matching_ledge].y
  4452. + - centers[next_center].y)
  4453. + >= (FT_Int)bitmap->rows / 2 )
  4454. +
  4455. + /* try to find where matching centers are next to each other */
  4456. + if ( last_matching_ledge >= 0 &&
  4457. + abs( centers[last_matching_ledge].y
  4458. + - centers[next_center].y ) == 1 )
  4459. + no_gap_found_ledge = TRUE;
  4460. + last_matching_ledge = next_center;
  4461. + }
  4462. + }
  4463. +
  4464. + if ( strategy_also_use_edge_detection_for_stems )
  4465. + {
  4466. + /* property - stem right edge points that align */
  4467. + /* if the center is within range, the center is less than 1/2 */
  4468. + /* the height away */
  4469. + if ( x2_difference_in_width
  4470. + < center_difference_in_height * deviation1 &&
  4471. + center_difference_in_height
  4472. + <= (FT_Int)bitmap->rows / 2 )
  4473. + {
  4474. + stem_matches_redge += 1;
  4475. + /* may not need for edges */
  4476. + /*valid_center_average += centers[next_center].x; */
  4477. +
  4478. + if ( centers[next_center].x2 - centers[next_center].x1
  4479. + < smallest_width_redge )
  4480. + smallest_width_redge = centers[next_center].x2
  4481. + - centers[next_center].x1;
  4482. +
  4483. + /* try to find where the matching centers are far apart */
  4484. + if ( last_matching_redge >= 0 &&
  4485. + abs( centers[last_matching_redge].y
  4486. + - centers[next_center].y ) >= (FT_Int)bitmap->rows / 2 )
  4487. +
  4488. + /* try to find where matching centers are next to each other */
  4489. + if ( last_matching_redge >= 0 &&
  4490. + abs( centers[last_matching_redge].y
  4491. + - centers[next_center].y ) == 1 )
  4492. + no_gap_found_redge = TRUE;
  4493. +
  4494. + last_matching_redge = next_center;
  4495. + }
  4496. + }
  4497. +
  4498. + next_center++;
  4499. + }
  4500. +
  4501. + if ( stem_matches > 0 )
  4502. + valid_center_average /= stem_matches;
  4503. +
  4504. + if ( ( stem_matches >= stem_match_requirement ||
  4505. + ( ( (FT_Int)bitmap->rows <= 6 || ppem < 11 ) &&
  4506. + stem_matches >= 2 &&
  4507. + abs ( valid_center_average
  4508. + - centers[center].x) < deviation1 /2 ) ||
  4509. + /* try to catch tightly aligned stuff where the matching centers */
  4510. + /* are next to each other only */
  4511. + ( stem_matches == 2 &&
  4512. + abs( valid_center_average
  4513. + - centers[center].x) <= deviation1 /2 &&
  4514. + no_gap_found &&
  4515. + ppem < 18 ) ) &&
  4516. + /* catches things like times 16 u but gets a lot of w's too */
  4517. + /* stem width is less than 1/3 of the bitmap width, */
  4518. + /* or bitmap_width is small */
  4519. + ( centers[center].x2 - centers[center].x1
  4520. + < (m_horiAdvance * 12) / 2 ||
  4521. + m_horiAdvance * 12 <= columns_per_pixel * one_pixel ) )
  4522. + {
  4523. + stem_detected = TRUE;
  4524. + set_width_to = centers[center].x2 - centers[center].x1;
  4525. + set_center_to = centers[center].x;
  4526. + }
  4527. +
  4528. + /* see if edges found anything */
  4529. + if ( strategy_also_use_edge_detection_for_stems && !stem_detected )
  4530. + {
  4531. + /* Require no gap for edges */
  4532. + /* stem width less than 1/3 bitmap width, or bitmap_width is small */
  4533. + /* The stem occurs on the left side of glyph only */
  4534. + if ( ( stem_matches_ledge >= stem_match_requirement &&
  4535. + no_gap_found_ledge ) &&
  4536. + ( centers[center].x2 - centers[center].x1
  4537. + < ( m_horiAdvance * 12 ) / 2 ||
  4538. + m_horiAdvance * 12 <= columns_per_pixel * one_pixel ) &&
  4539. + centers[center].x < ( m_horiAdvance * 12 ) / 2 )
  4540. + {
  4541. + stem_detected = TRUE;
  4542. + set_width_to = smallest_width_ledge;
  4543. + set_center_to = centers[center].x1 + set_width_to / 2;
  4544. + stem_matches = stem_matches_ledge;
  4545. + }
  4546. + /* Require no gap for edges */
  4547. + /* stem width is less than 1/3 bitmap width, or bitmap_width is small */
  4548. + /* The stem occurs on the right side of glyph only */
  4549. + else if ( ( stem_matches_redge >= stem_match_requirement &&
  4550. + no_gap_found_redge ) &&
  4551. + ( centers[center].x2 - centers[center].x1
  4552. + < ( m_horiAdvance * 12 ) / 2 ||
  4553. + m_horiAdvance * 12 <= columns_per_pixel * one_pixel ) &&
  4554. + centers[center].x > (m_horiAdvance * 12) / 2 )
  4555. + {
  4556. + stem_detected = TRUE;
  4557. + set_width_to = smallest_width_redge;
  4558. + set_center_to = centers[center].x2 - set_width_to / 2;
  4559. + stem_matches = stem_matches_redge;
  4560. + }
  4561. + }
  4562. +
  4563. +
  4564. + /*store and/or replace highest occurrences with 3 or more centers */
  4565. + /* because this matched, it will become the top dog regardless */
  4566. + if ( stem_detected && (stem_matches > possible_stems[0].height) )
  4567. + {
  4568. + /* if this is the first stem just go ahead */
  4569. + if ( valid_possible_stems == 0 )
  4570. + {
  4571. + valid_possible_stems = 1;
  4572. + possible_stems[0].center = set_center_to;
  4573. + possible_stems[0].count = stem_matches;
  4574. + possible_stems[0].width = set_width_to;
  4575. + possible_stems[0].height = stem_matches;
  4576. + }
  4577. +
  4578. + /* otherwise, if there is already a stem */
  4579. + else if ( valid_possible_stems == 1 )
  4580. + {
  4581. + /* if stem is within range of existing one, replace existing one */
  4582. +
  4583. + /* if the stem isn't within the range of this one swap it with */
  4584. + /* next one first */
  4585. + if ( abs ( set_center_to - possible_stems[0].center )
  4586. + >= one_pixel * 2 )
  4587. + {
  4588. + swap_stem ( &possible_stems[0], &possible_stems[1] );
  4589. + valid_possible_stems = 2;
  4590. + }
  4591. + possible_stems[0].center = set_center_to;
  4592. + possible_stems[0].count = stem_matches;
  4593. + possible_stems[0].width = set_width_to;
  4594. + possible_stems[0].height = stem_matches;
  4595. + }
  4596. +
  4597. + /* otherwise if there are already 2 stems */
  4598. + else if ( valid_possible_stems >= 2 )
  4599. + {
  4600. + /* if the stem is within the range of existing one, replace */
  4601. + /* existing one */
  4602. + if ( abs ( set_center_to - possible_stems[0].center )
  4603. + <= one_pixel * 2 )
  4604. + {
  4605. + possible_stems[0].center = set_center_to;
  4606. + possible_stems[0].count = stem_matches;
  4607. + possible_stems[0].width = set_width_to;
  4608. + possible_stems[0].height = stem_matches;
  4609. + }
  4610. + /* if the stem isn't within the range of this one */
  4611. + else
  4612. + {
  4613. + /* see if within range of next one and swap if so and proceed */
  4614. + /* overwriting it */
  4615. + if ( abs ( set_center_to - possible_stems[1].center )
  4616. + <= one_pixel * 2 )
  4617. + swap_stem ( &possible_stems[0], &possible_stems[1] );
  4618. +
  4619. + /* otherwise see if in range of third one */
  4620. + else if ( abs ( set_center_to - possible_stems[2].center )
  4621. + <= one_pixel * 2 )
  4622. + swap_stem ( &possible_stems[0], &possible_stems[2] );
  4623. +
  4624. + /* otherwise this is the new top dog, so demote everything */
  4625. + else
  4626. + {
  4627. + swap_stem ( &possible_stems[1], &possible_stems[2] );
  4628. + swap_stem ( &possible_stems[0], &possible_stems[1] );
  4629. + valid_possible_stems += 1;
  4630. + }
  4631. + possible_stems[0].center = set_center_to;
  4632. + possible_stems[0].count = stem_matches;
  4633. + possible_stems[0].width = set_width_to;
  4634. + possible_stems[0].height = stem_matches;
  4635. + }
  4636. + }
  4637. + }
  4638. + else if ( stem_matches > possible_stems[1].height &&
  4639. + set_center_to != 0 )
  4640. + {
  4641. - /* When accumulating the oversampled spans we need to assure that */
  4642. - /* fully covered pixels are equal to 255 and do not overflow. */
  4643. - /* It is important that the SCALE is a power of 2, each subpixel */
  4644. - /* cover can also reach a power of 2 after rounding, and the total */
  4645. - /* is clamped to 255 when it adds up to 256. */
  4646. - for ( ; count--; spans++ )
  4647. + /* make sure it doesn't match the first stem */
  4648. + if ( abs ( set_center_to - possible_stems[0].center ) >= one_pixel * 2 )
  4649. {
  4650. - cover = ( spans->coverage + SCALE * SCALE / 2 ) / ( SCALE * SCALE );
  4651. - for ( x = 0; x < spans->len; x++ )
  4652. +
  4653. + /* if this is the second stem */
  4654. + if ( valid_possible_stems == 1 )
  4655. + valid_possible_stems = 2;
  4656. +
  4657. + /* otherwise if there is already a stem here */
  4658. + else if ( valid_possible_stems >= 2 )
  4659. + {
  4660. + /* if it doesn't match the second stem, proceed to swap out */
  4661. + /* with the third. if it does, replace it */
  4662. + if ( abs ( set_center_to - possible_stems[1].center )
  4663. + >= one_pixel * 2 )
  4664. {
  4665. - sum = dst[( spans->x + x ) / SCALE] + cover;
  4666. - dst[( spans->x + x ) / SCALE] = (unsigned char)( sum - ( sum >> 8 ) );
  4667. + swap_stem ( &possible_stems[1], &possible_stems[2] );
  4668. + valid_possible_stems +=1;
  4669. }
  4670. }
  4671. + possible_stems[1].center = set_center_to;
  4672. + possible_stems[1].count = stem_matches;
  4673. + possible_stems[1].width = set_width_to;
  4674. + possible_stems[1].height = stem_matches;
  4675. + }
  4676. }
  4677. + else if ( stem_matches > possible_stems[2].height &&
  4678. + set_center_to != 0 )
  4679. + {
  4680. + /* if it doesn't match the first or second one */
  4681. + if ( abs( set_center_to - possible_stems[0].center) >= one_pixel * 2 &&
  4682. + abs( set_center_to - possible_stems[1].center) >= one_pixel * 2 )
  4683. + {
  4684. + if ( valid_possible_stems == 2 )
  4685. + valid_possible_stems += 1;
  4686. - static FT_Error
  4687. - ft_smooth_raster_overlap( FT_Renderer render,
  4688. - FT_Outline* outline,
  4689. - FT_Bitmap* bitmap )
  4690. + possible_stems[2].center = set_center_to;
  4691. + possible_stems[2].count = stem_matches;
  4692. + possible_stems[2].width = set_width_to;
  4693. + possible_stems[1].height = stem_matches;
  4694. + }
  4695. + }
  4696. +
  4697. + if ( valid_possible_stems > 3 )
  4698. + valid_possible_stems = 3;
  4699. +
  4700. + center++;
  4701. + }
  4702. +
  4703. + /* promote to stem */
  4704. + if ( valid_possible_stems > 0 )
  4705. {
  4706. - FT_Error error = FT_Err_Ok;
  4707. - FT_Vector* points = outline->points;
  4708. - FT_Vector* points_end = FT_OFFSET( points, outline->n_points );
  4709. - FT_Vector* vec;
  4710. + stems[0].center = possible_stems[0].center;
  4711. + stems[0].count = possible_stems[0].count;
  4712. + stems[0].width = possible_stems[0].width;
  4713. + stems[0].height = possible_stems[0].height;
  4714. + stems[0].generated = FALSE;
  4715. + valid_stems++;
  4716. + }
  4717. - FT_Raster_Params params;
  4718. - TOrigin target;
  4719. + if ( valid_stems == 1 &&
  4720. + valid_possible_stems > 1 )
  4721. + {
  4722. + stems[1].center = possible_stems[1].center;
  4723. + stems[1].count = possible_stems[1].count;
  4724. + stems[1].width = possible_stems[1].width;
  4725. + stems[1].height = possible_stems[1].height;
  4726. + stems[1].generated = FALSE;
  4727. + valid_stems++;
  4728. + }
  4729. + if ( valid_stems == 2 &&
  4730. + valid_possible_stems > 2 &&
  4731. + possible_stems[2].center != 0 )
  4732. + {
  4733. + stems[2].center = possible_stems[2].center;
  4734. + stems[2].count = possible_stems[2].count;
  4735. + stems[2].width = possible_stems[2].width;
  4736. + stems[2].height = possible_stems[2].height;
  4737. + stems[2].generated = FALSE;
  4738. + valid_stems++;
  4739. + }
  4740. - /* Reject outlines that are too wide for 16-bit FT_Span. */
  4741. - /* Other limits are applied upstream with the same error code. */
  4742. - if ( bitmap->width * SCALE > 0x7FFF )
  4743. - return FT_THROW( Raster_Overflow );
  4744. + /* sort stems in x direction */
  4745. + if ( valid_stems == 3 )
  4746. + {
  4747. + if ( stems[0].center > stems[1].center )
  4748. + swap_stem ( &stems[0], &stems[1] );
  4749. - /* Set up direct rendering to average oversampled spans. */
  4750. - params.source = outline;
  4751. - params.flags = FT_RASTER_FLAG_AA | FT_RASTER_FLAG_DIRECT;
  4752. - params.gray_spans = (FT_SpanFunc)ft_smooth_overlap_spans;
  4753. - params.user = &target;
  4754. + if ( stems[0].center > stems[2].center )
  4755. + swap_stem ( &stems[1], &stems[2] );
  4756. +
  4757. + if ( stems[1].center > stems[2].center )
  4758. + swap_stem ( &stems[1], &stems[2] );
  4759. +
  4760. + if ( stems[0].center > stems[1].center )
  4761. + swap_stem ( &stems[0], &stems[1] );
  4762. +
  4763. + /* only look at first and last stem for now */
  4764. + swap_stem ( &stems[1], &stems[2] );
  4765. + }
  4766. +
  4767. + /* synthesize stems - Works, but needs work */
  4768. + if ( ( strategy_synthesize_stems ||
  4769. + known_stem_values->synth_stems ) &&
  4770. + valid_stems == 0 &&
  4771. + ppem > 10 )
  4772. + {
  4773. + /* if the leftmost segment's leftmost point is the same as the glyph's */
  4774. + /* leftmost point, and it is of reasonable width, and is not on the */
  4775. + /* top or bottom of the bitmap */
  4776. + if ( leftmost_segment_not_extrema->x1
  4777. + == leftmost_point_not_extrema &&
  4778. + abs ( leftmost_segment_not_extrema->x2
  4779. + - leftmost_segment_not_extrema->x1 )
  4780. + < ( rightmost_point_not_extrema
  4781. + - leftmost_point_not_extrema ) / 3 &&
  4782. + leftmost_segment_not_extrema->y < height &&
  4783. + leftmost_segment_not_extrema->y > 1 )
  4784. + {
  4785. + stems[valid_stems].center = ( leftmost_segment_not_extrema->x2
  4786. + + leftmost_segment_not_extrema->x1 ) / 2;
  4787. + stems[valid_stems].width = leftmost_segment_not_extrema->x2
  4788. + - leftmost_segment_not_extrema->x1;
  4789. + stems[valid_stems].generated = TRUE;
  4790. + valid_stems += 1;
  4791. + }
  4792. +
  4793. +
  4794. + if ( rightmost_segment_not_extrema->x2
  4795. + == rightmost_point_not_extrema &&
  4796. + abs ( rightmost_segment_not_extrema->x2
  4797. + - rightmost_segment_not_extrema->x1 )
  4798. + < ( rightmost_point_not_extrema
  4799. + - leftmost_point_not_extrema ) / 3 &&
  4800. + rightmost_segment_not_extrema->y < height &&
  4801. + rightmost_segment_not_extrema->y > 1 )
  4802. + {
  4803. + stems[valid_stems].center = ( rightmost_segment_not_extrema->x2
  4804. + + rightmost_segment_not_extrema->x1 ) / 2;
  4805. + stems[valid_stems].width = rightmost_segment_not_extrema->x2
  4806. + - rightmost_segment_not_extrema->x1;
  4807. + stems[valid_stems].generated = TRUE;
  4808. + valid_stems += 1;
  4809. + }
  4810. +
  4811. + }
  4812. +
  4813. + /* sort stems in x direction */
  4814. + if ( valid_stems > 1 && stems[0].center > stems[1].center )
  4815. + swap_stem ( &stems[0], &stems[1] );
  4816. +
  4817. + if ( valid_stems == 0 && known_stem_values->stem_translating != 0 )
  4818. + {
  4819. + *translate_value += known_stem_values->stem_translating;
  4820. +
  4821. + if ( strategy_use_strengths )
  4822. + {
  4823. + /* consider 1/2 pixel the max when strength is at 100%,
  4824. + unless translate is already greater than that */
  4825. + FT_Int strength_cutoff = 32;
  4826. +
  4827. +
  4828. + if ( abs ( *translate_value ) > strength_cutoff)
  4829. + strength_cutoff = *translate_value;
  4830. +
  4831. + max_strength = ( strength_cutoff * alignment_strength ) / 100;
  4832. +
  4833. + if ( *translate_value < -max_strength )
  4834. + *translate_value = -max_strength;
  4835. + else if ( *translate_value > max_strength )
  4836. + *translate_value = max_strength;
  4837. + }
  4838. + }
  4839. + else
  4840. + /* Start snapping */
  4841. + {
  4842. + FT_Int center_offset;
  4843. + FT_Int modulus;
  4844. + FT_Int delta, delta2;
  4845. + FT_Long stem_distance = 1, new_distance = 1;
  4846. + FT_Int distance_floor, distance_ceiling;
  4847. + FT_Int translate_value2 = 0;
  4848. + FT_Int main_stem = 0;
  4849. + FT_Int lbearing = m_horiBearingX * 12;
  4850. + FT_Int bitmap_stem_location = stems[0].center;
  4851. + FT_Int advance_stem_location = bitmap_stem_location
  4852. + + lbearing - one_pixel;
  4853. + FT_Int advance_width = m_horiAdvance * 12;
  4854. + FT_Int original_advance_width = 12 * ( slot->linearHoriAdvance >> 10 );
  4855. + FT_Int glyph_width = rightmost_point - leftmost_point;
  4856. + FT_Int stem_width = stems[0].width;
  4857. + FT_Int advance_leftmost_location = leftmost_point
  4858. + + lbearing - one_pixel;
  4859. + FT_Int advance_rightmost_location = rightmost_point
  4860. + + lbearing - one_pixel;
  4861. +
  4862. +#define proposed_transformed_point(point) \
  4863. + point * (float)(new_distance) / (float)(stem_distance) \
  4864. + + *translate_value * 12 - ( stems[main_stem].center * (float)(new_distance) \
  4865. + / (float)(stem_distance) - stems[main_stem].center)
  4866. +
  4867. +#define proposed_translated_point(point) point + *translate_value * 12
  4868. - params.clip_box.xMin = 0;
  4869. - params.clip_box.yMin = 0;
  4870. - params.clip_box.xMax = bitmap->width * SCALE;
  4871. - params.clip_box.yMax = bitmap->rows * SCALE;
  4872. + center_offset = one_pixel / 2; /* half pixel */
  4873. + modulus = one_pixel; /* whole pixel */
  4874. - if ( bitmap->pitch < 0 )
  4875. - target.origin = bitmap->buffer;
  4876. + /* Determine center_offset via known values */
  4877. + if ( known_stem_values->stem_width >= 0 )
  4878. + {
  4879. + if ( known_stem_values->stem_width % 2 == 0 )
  4880. + center_offset = 0;
  4881. else
  4882. - target.origin = bitmap->buffer
  4883. - + ( bitmap->rows - 1 ) * (unsigned int)bitmap->pitch;
  4884. + center_offset = one_pixel / 2;
  4885. + }
  4886. + /* otherwise do intelligent guessing, if set */
  4887. + else if ( strategy_auto_change_center_offset &&
  4888. + ppem >= STEM_WIDTH_2_PPEM &&
  4889. + stems[0].width < one_pixel * 1.45 )
  4890. + center_offset = one_pixel / 2;
  4891. + else if ( strategy_auto_change_center_offset &&
  4892. + ppem >= STEM_WIDTH_2_PPEM &&
  4893. + stems[0].width >= one_pixel * 1.45 &&
  4894. + stems[0].width < one_pixel * 2.6 )
  4895. + center_offset = 0;
  4896. + else if ( strategy_auto_change_center_offset &&
  4897. + ppem >= STEM_WIDTH_2_PPEM &&
  4898. + stems[0].width >= one_pixel * 2.6 &&
  4899. + stems[0].width < one_pixel * 3.6 )
  4900. + center_offset = one_pixel / 2;
  4901. + else if ( strategy_auto_change_center_offset &&
  4902. + ppem >= STEM_WIDTH_2_PPEM )
  4903. + center_offset =
  4904. + ( one_pixel
  4905. + * ( ( ( (int)( stems[0].width + one_pixel / 2 ) )
  4906. + / one_pixel ) % 2 ) ) / 2;
  4907. +
  4908. + /* Snap to closest translate and scale values by default */
  4909. + if ( valid_stems >= 1 )
  4910. + {
  4911. + /* closest snapping point for stem 0 */
  4912. + delta = ( stems[0].center + center_offset ) % modulus;
  4913. +
  4914. + if ( delta < modulus / 2 )
  4915. + /* snap left */
  4916. + *translate_value = -delta / ( columns_per_pixel * 4 );
  4917. + else
  4918. + /* snap right */
  4919. + *translate_value = ( modulus - delta ) / ( columns_per_pixel * 4 );
  4920. + }
  4921. - target.pitch = bitmap->pitch;
  4922. + if ( strategy_use_d_correction )
  4923. + {
  4924. + /* if the only stem is in the last 1/3 of glyph width, the advance */
  4925. + /* is 6 pixels, the ppem 11, and doing so doesn't violate bitmap , */
  4926. + /* boundaries force it to snap right */
  4927. + if ( valid_stems == 1 &&
  4928. + advance_stem_location > (advance_width * 2) / 3 &&
  4929. + advance_width == 6 * one_pixel &&
  4930. + rightmost_point + modulus - delta
  4931. + <= ( width - (columns_per_pixel * 2) / 3) * 256 &&
  4932. + ppem == 11 )
  4933. + *translate_value = ( modulus - delta ) / ( columns_per_pixel * 4 );
  4934. + }
  4935. - /* inflate outline */
  4936. - for ( vec = points; vec < points_end; vec++ )
  4937. + if ( strategy_use_strengths )
  4938. {
  4939. - vec->x *= SCALE;
  4940. - vec->y *= SCALE;
  4941. + /* consider 1/2 pixel the max when strength is at 100%,
  4942. + unless translate is already greater than that */
  4943. + FT_Int strength_cutoff = 32;
  4944. + if ( abs ( *translate_value ) > strength_cutoff )
  4945. + strength_cutoff = *translate_value;
  4946. +
  4947. + max_strength = ( strength_cutoff * alignment_strength ) / 100;
  4948. +
  4949. + if ( *translate_value < -max_strength )
  4950. + *translate_value = -max_strength;
  4951. + else if ( *translate_value > max_strength )
  4952. + *translate_value = max_strength;
  4953. }
  4954. - /* render outline into the bitmap */
  4955. - error = render->raster_render( render->raster, &params );
  4956. + /* If 2 stems is detected, scale distance
  4957. + between in order to land on pixels */
  4958. + if ( valid_stems >= 2 )
  4959. + {
  4960. + stem_distance = abs ( stems[1].center - stems[0].center );
  4961. - /* deflate outline */
  4962. - for ( vec = points; vec < points_end; vec++ )
  4963. + delta = stem_distance % modulus;
  4964. + new_distance = stem_distance - delta;
  4965. +
  4966. + distance_floor = stem_distance - delta;
  4967. + distance_ceiling = stem_distance + ( modulus - delta );
  4968. +
  4969. + if ( delta < modulus / 2 )
  4970. + new_distance = distance_floor;
  4971. + else
  4972. + new_distance = distance_ceiling;
  4973. +
  4974. + if ( columns_per_pixel == 3 &&
  4975. + valid_stems == 3 &&
  4976. + strategy_use_m_control &&
  4977. + ( width - 2 * columns_per_pixel ) > 6 * columns_per_pixel &&
  4978. + ppem > 8 &&
  4979. + ( advance_stem_location - advance_leftmost_location )
  4980. + < stems[main_stem].width * 2 )
  4981. + {
  4982. + /* Possibly use 2 only when compatible widths is on? */
  4983. + FT_Int mod_factor = 2;
  4984. +
  4985. + if ( verbose )
  4986. + printf ( "USING M CONTROL ");
  4987. +
  4988. + distance_floor = stem_distance
  4989. + - stem_distance % ( modulus * mod_factor ) ;
  4990. + distance_ceiling = distance_floor + modulus * mod_factor;
  4991. +
  4992. + new_distance = distance_ceiling;
  4993. +
  4994. + /* force certain ideal situations */
  4995. + /* these 2 are mostly safe to do */
  4996. + if ( distance_ceiling
  4997. + + one_pixel * columns_per_pixel == advance_width &&
  4998. + stem_width < one_pixel * 1.25 )
  4999. + new_distance = distance_ceiling;
  5000. + /* NEED TO FIGURE OUT A WAY TO DETERMINE WHETHER
  5001. + THAT NUDGE IS UP OR DOWN */
  5002. + else if ( stem_distance + one_pixel * 2.6 >= advance_width &&
  5003. + stem_width < one_pixel * 1.25 )
  5004. + new_distance = distance_ceiling;
  5005. +
  5006. + if ( proposed_transformed_point ( leftmost_point )
  5007. + < one_third_pixel * 2 ||
  5008. + proposed_transformed_point ( rightmost_point )
  5009. + > ( width -2 ) * one_third_pixel )
  5010. + new_distance = distance_floor;
  5011. +
  5012. + /* NEED TO IGNORE SERIF Ms HERE */
  5013. + /* perhaps check bitmap boundaries instead??? */
  5014. + if ( strategy_bearing_correction && new_distance == distance_ceiling )
  5015. + {
  5016. + /* Correct if bearings are made substantially worse
  5017. + (more than 1/3 a pixel beyond advance) */
  5018. + if ( proposed_transformed_point( advance_rightmost_location )
  5019. + > advance_width + one_third_pixel &&
  5020. + proposed_transformed_point( advance_rightmost_location )
  5021. + > advance_rightmost_location &&
  5022. + -proposed_transformed_point( advance_leftmost_location )
  5023. + < advance_rightmost_location - advance_width )
  5024. + new_distance = distance_floor;
  5025. + }
  5026. +
  5027. + if ( known_stem_values->m >= 0 )
  5028. {
  5029. - vec->x /= SCALE;
  5030. - vec->y /= SCALE;
  5031. + if ( known_stem_values->m == 0 )
  5032. + new_distance = distance_floor;
  5033. + else
  5034. + new_distance = distance_ceiling;
  5035. }
  5036. - return error;
  5037. + if ( ( rightmost_point - leftmost_point) -
  5038. + ( ( rightmost_point * *scale_value)
  5039. + - ( leftmost_point * *scale_value ) ) >= one_pixel * 1.5 )
  5040. + {
  5041. + *scale_value = 1.0;
  5042. + *translate_value = 0;
  5043. + goto Exit;
  5044. + }
  5045. +
  5046. + }
  5047. + else if ( columns_per_pixel == 1 &&
  5048. + valid_stems == 3 &&
  5049. + strategy_use_m_control && valid_stems == 3 &&
  5050. + width >= 6 * columns_per_pixel &&
  5051. + ppem > 8 &&
  5052. + ( advance_stem_location - advance_leftmost_location )
  5053. + < stems[main_stem].width * 2 )
  5054. + {
  5055. + /* Possibly use 2 only when compatible widths is on? */
  5056. + FT_Int mod_factor = 2;
  5057. +
  5058. + if ( verbose )
  5059. + printf ("USING M CONTROL ");
  5060. + distance_floor = stem_distance - stem_distance
  5061. + % ( modulus * mod_factor) ;
  5062. + distance_ceiling = distance_floor + modulus * mod_factor;
  5063. +
  5064. + new_distance = distance_ceiling;
  5065. +
  5066. + /* force certain ideal situations */
  5067. + /* these 2 are mostly safe to do */
  5068. + if ( distance_ceiling
  5069. + + one_pixel * columns_per_pixel == advance_width &&
  5070. + stem_width < one_pixel * 1.25 )
  5071. + new_distance = distance_ceiling;
  5072. + /* NEED TO FIGURE OUT A WAY TO DETERMINE WHETHER
  5073. + THAT NUDGE IS UP OR DOWN */
  5074. + else if ( stem_distance + one_pixel * 2.6 >= advance_width &&
  5075. + stem_width < one_pixel * 1.25 )
  5076. + new_distance = distance_ceiling;
  5077. +
  5078. + if ( proposed_transformed_point( leftmost_point ) < 0 ||
  5079. + proposed_transformed_point( rightmost_point )
  5080. + > width * one_pixel - 2 * one_third_pixel )
  5081. + new_distance = distance_floor;
  5082. +
  5083. + /* NEED TO IGNORE SERIF Ms HERE */
  5084. + /* perhaps check bitmap boundaries instead??? */
  5085. + if ( strategy_bearing_correction && new_distance == distance_ceiling )
  5086. + {
  5087. + /* Correct if bearings are made substantially worse
  5088. + (more than 1/3 a pixel beyond advance) */
  5089. + if ( proposed_transformed_point( advance_rightmost_location )
  5090. + > advance_width + one_third_pixel &&
  5091. + proposed_transformed_point( advance_rightmost_location )
  5092. + > advance_rightmost_location &&
  5093. + -proposed_transformed_point( advance_leftmost_location )
  5094. + < advance_rightmost_location - advance_width )
  5095. + new_distance = distance_floor;
  5096. + }
  5097. +
  5098. + if ( known_stem_values->m >= 0 )
  5099. + {
  5100. + if ( known_stem_values->m == 0 )
  5101. + new_distance = distance_floor;
  5102. + else
  5103. + new_distance = distance_ceiling;
  5104. + }
  5105. +
  5106. +
  5107. + if ( ( rightmost_point - leftmost_point )
  5108. + - ( ( rightmost_point * *scale_value )
  5109. + - ( leftmost_point * *scale_value ) ) >= one_pixel * 1.5 )
  5110. + {
  5111. + *scale_value = 1.0;
  5112. + *translate_value = 0;
  5113. + goto Exit;
  5114. + }
  5115. +
  5116. + }
  5117. + else
  5118. + {
  5119. + if ( strategy_fit_to_width )
  5120. + new_distance = advance_width - 3 * one_pixel;
  5121. + else if ( known_stem_values->stem_scaling >= 0 )
  5122. + {
  5123. + if ( known_stem_values->stem_scaling > 0 )
  5124. + new_distance = distance_ceiling;
  5125. + else
  5126. + new_distance = distance_floor;
  5127. +
  5128. + /* enforce advance width boundaries */
  5129. + /* TOO RESTRICTIVE ON SERIF FONTS */
  5130. + if ( proposed_transformed_point( advance_rightmost_location )
  5131. + >= advance_width ||
  5132. + proposed_transformed_point( advance_leftmost_location )
  5133. + <= 0 )
  5134. + new_distance = distance_floor;
  5135. +
  5136. + /* enforce literal bitmap boundaries if no translate room */
  5137. + if ( ( proposed_transformed_point(rightmost_point) >= width * 256
  5138. + || proposed_transformed_point(leftmost_point ) <= one_pixel )
  5139. + && new_distance + one_pixel * 3 > advance_width )
  5140. + new_distance = distance_floor;
  5141. +
  5142. + }
  5143. + else if ( strategy_translate_using_closest_stem )
  5144. + {
  5145. + /* closest snapping point for stem 1 */
  5146. + delta2 = ( stems[1].center + center_offset ) % modulus;
  5147. +
  5148. + if ( delta2 < modulus / 2 )
  5149. + /* snap left */
  5150. + translate_value2 = -delta2 / ( columns_per_pixel * 4 );
  5151. + else
  5152. + /* snap right */
  5153. + translate_value2 = ( modulus - delta2 )
  5154. + / ( columns_per_pixel * 4 );
  5155. +
  5156. + if ( abs ( translate_value2 ) < abs ( *translate_value ) )
  5157. + {
  5158. + *translate_value = translate_value2;
  5159. + main_stem = 1;
  5160. + }
  5161. +
  5162. + }
  5163. + else if ( strategy_scale_to_closest_centers )
  5164. + {
  5165. + /* closest snapping point for stem 0 */
  5166. + delta = ( stems[0].center + center_offset ) % modulus;
  5167. + delta2 = ( stems[1].center + center_offset ) % modulus;
  5168. +
  5169. + if ( delta < modulus / 2 )
  5170. + /* stretch left */
  5171. + new_distance = delta + stem_distance;
  5172. + else
  5173. + /* stretch right */
  5174. + new_distance = delta - modulus + stem_distance;
  5175. +
  5176. + if ( delta2 < modulus / 2 )
  5177. + new_distance -= delta2; /* stretch left */
  5178. + else
  5179. + new_distance += modulus - delta2; /* stretch right */
  5180. +
  5181. + }
  5182. + else if ( strategy_scale_to_closest_centers_up_only )
  5183. + {
  5184. + FT_Int net_change = 0;
  5185. +
  5186. + /* closest snapping point for stem 0 */
  5187. + delta = ( stems[0].center + center_offset ) % modulus;
  5188. + delta2 = ( stems[1].center + center_offset ) % modulus;
  5189. +
  5190. + if ( delta < modulus / 2 )
  5191. + net_change = delta; /* stretch left */
  5192. + else
  5193. + net_change = -( modulus - delta ); /* stretch right */
  5194. +
  5195. + if ( delta2 < modulus / 2 )
  5196. + net_change -= delta2; /* stretch left */
  5197. + else
  5198. + net_change += modulus - delta2; /* stretch right */
  5199. +
  5200. + if ( net_change > 0 &&
  5201. + proposed_transformed_point( advance_rightmost_location )
  5202. + < advance_width &&
  5203. + proposed_transformed_point( advance_leftmost_location ) > 0 )
  5204. + new_distance = distance_ceiling;
  5205. + }
  5206. +
  5207. + else if ( strategy_always_use_distance_ceiling )
  5208. + {
  5209. + if ( proposed_transformed_point( advance_rightmost_location )
  5210. + < advance_width &&
  5211. + proposed_transformed_point( advance_leftmost_location ) > 0 )
  5212. + new_distance = distance_ceiling;
  5213. + }
  5214. + }
  5215. +
  5216. + if ( strategy_use_strengths )
  5217. + {
  5218. + FT_Int strength_cutoff = center_offset;
  5219. +
  5220. +
  5221. + delta2 = new_distance - stem_distance;
  5222. +
  5223. + if ( abs ( delta2 ) > strength_cutoff )
  5224. + strength_cutoff = delta2;
  5225. +
  5226. + max_strength = ( strength_cutoff * fitting_strength ) / 100;
  5227. +
  5228. + if ( delta2 < -max_strength )
  5229. + new_distance = stem_distance - max_strength;
  5230. + else if ( delta2 > max_strength )
  5231. + new_distance = stem_distance + max_strength;
  5232. + }
  5233. +
  5234. + *scale_value = (float)( new_distance ) / (float)( stem_distance );
  5235. + *translate_value = *translate_value
  5236. + - ( (float)( stems[main_stem].center * (float)new_distance )
  5237. + / (float)stem_distance - stems[main_stem].center ) / 12;
  5238. +
  5239. + if ( valid_stems == 2 )
  5240. + *embolden_value = ( 64.0 / *scale_value - 64.0 );
  5241. +
  5242. + if ( valid_stems == 3 )
  5243. + *embolden_value = ( 64.0 / *scale_value - 64.0 ) / 1.5;
  5244. + }
  5245. +
  5246. + if ( verbose )
  5247. + printf ( "%lu stems:", valid_stems );
  5248. +
  5249. + if ( valid_stems == 1 && verbose )
  5250. + printf ( "1 stem: bitmapwidth:%d glyphwidth:%f glyph_width:%f center:%f bearing:%f advance:%f lhadvance:%f stemwidth:%f %d %d",
  5251. + (width - 6) / columns_per_pixel,
  5252. + (float)m_width / 64.0,
  5253. + (float)glyph_width / (float)one_pixel,
  5254. + (float)( (float)advance_stem_location ) / (float)one_pixel,
  5255. + (float)m_horiBearingX / 64.0,
  5256. + (float)m_horiAdvance / 64.0,
  5257. + (float)linearHoriAdvance / 64.0,
  5258. + (float)stems[0].width / (float)one_pixel,
  5259. + advance_width, original_advance_width );
  5260. + else if ( valid_stems >= 2 && verbose )
  5261. + printf ( "%lu stems: bitmapwidth:%d center1:%f center2:%f difference:%f bearing:%f advance:%f advstemloc:%f ",
  5262. + valid_stems,
  5263. + (width - 6) / columns_per_pixel,
  5264. + ( (float)advance_stem_location ) / (float)one_pixel,
  5265. + ( (float)advance_stem_location
  5266. + + (float)abs ( stems[1].center
  5267. + - stems[0].center) ) / (float)one_pixel,
  5268. + ( (float)abs ( stems[1].center
  5269. + - stems[0].center ) ) / (float)one_pixel,
  5270. + (float)m_horiBearingX / 64.0,
  5271. + (float)m_horiAdvance / 64.0,
  5272. + (float)advance_stem_location / (float)one_pixel );
  5273. +
  5274. + if ( strategy_bearing_correction )
  5275. + {
  5276. + /* Correct if negative bearings are made substantially worse */
  5277. + /* (more than 1/3 a pixel) */
  5278. + if ( proposed_transformed_point( advance_rightmost_location )
  5279. + > advance_width &&
  5280. + proposed_transformed_point( advance_rightmost_location )
  5281. + > advance_rightmost_location &&
  5282. + -proposed_transformed_point( advance_leftmost_location )
  5283. + < advance_rightmost_location - advance_width &&
  5284. + *translate_value
  5285. + > one_third_pixel / ( columns_per_pixel * 4 ) )
  5286. + {
  5287. + *translate_value -=64 ;
  5288. + if ( verbose )
  5289. + printf ( "TRANSLATING -64 " );
  5290. + }
  5291. + }
  5292. + goto Exit;
  5293. + }
  5294. +
  5295. + Exit:
  5296. +
  5297. +#define transformed_point( point ) point * *scale_value + *translate_value * 12
  5298. +
  5299. + if ( strategy_correct_out_of_bounds_outlines )
  5300. + {
  5301. + /* Correct if outside bitmap */
  5302. + if ( transformed_point( rightmost_point )
  5303. + >= width * 256 - 2 * one_third_pixel &&
  5304. + transformed_point( leftmost_point )
  5305. + > one_pixel + 2 * one_third_pixel )
  5306. + *translate_value -=64 ;
  5307. + else if ( transformed_point( leftmost_point )
  5308. + <= one_pixel / 2 &&
  5309. + transformed_point( rightmost_point )
  5310. + <= width * 256 - ( one_pixel + one_pixel / 2 ) )
  5311. + *translate_value += 64;
  5312. + }
  5313. +
  5314. + STVALUES
  5315. + free ( centers );
  5316. + free ( segments );
  5317. + free ( stem_centers );
  5318. + free ( stems );
  5319. + free ( leftmost_segment );
  5320. }
  5321. -#undef SCALE
  5322. + /* Gamma correction */
  5323. + static void
  5324. + _ft_lcd_gamma_correction_correction ( FT_Bitmap* bitmap,
  5325. + FT_Render_Mode mode,
  5326. + FT_GlyphSlot slot,
  5327. + float gamma_correction_lt,
  5328. + float gamma_correction_value )
  5329. + {
  5330. + if ( gamma_correction_value != 1.0 )
  5331. + {
  5332. + FT_UInt width = (FT_UInt)bitmap->width;
  5333. + FT_UInt height = (FT_UInt)bitmap->rows;
  5334. + FT_Byte* line = bitmap->buffer;
  5335. + float ppem = (float)slot->face->size->metrics.x_ppem;
  5336. +
  5337. +
  5338. + if ( !slot->face || !slot->face->size ) return;
  5339. +
  5340. + if ( ppem >= 5 )
  5341. + for ( height = (FT_UInt)bitmap->rows;
  5342. + height > 0;
  5343. + height--, line += bitmap->pitch )
  5344. + {
  5345. + FT_UInt xx;
  5346. +
  5347. +
  5348. + for ( xx = 0; xx < width; xx += 1 )
  5349. + {
  5350. + /*normal*/
  5351. + /*line[xx] = pseudo_gamma ( line[xx], gamma_correction_value );*/
  5352. +
  5353. + /* sloped */
  5354. + /*line[xx] = pseudo_gamma ( line[xx], gamma_correction_value - 5
  5355. + * (1-gamma_correction_value)/(gamma_correction_lt -5)
  5356. + + ((1-gamma_correction_value)/(gamma_correction_lt -5)) * ppem );*/
  5357. +
  5358. + /* 1/3-sloped */
  5359. + line[xx] = pseudo_gamma ( line[xx], gamma_correction_value - 5
  5360. + * ( ( 1 - gamma_correction_value )
  5361. + / ( 3 * ( gamma_correction_lt -5 ) ) )
  5362. + + ( ( 1 - gamma_correction_value )
  5363. + / ( 3 * ( gamma_correction_lt -5) ) ) * ppem );
  5364. + }
  5365. + }
  5366. + }
  5367. + }
  5368. +
  5369. +#endif
  5370. +
  5371. + /* convert a slot's glyph image into a bitmap */
  5372. static FT_Error
  5373. - ft_smooth_render( FT_Renderer render,
  5374. + ft_smooth_render_generic( FT_Renderer render,
  5375. FT_GlyphSlot slot,
  5376. FT_Render_Mode mode,
  5377. - const FT_Vector* origin )
  5378. + const FT_Vector* origin,
  5379. + FT_Render_Mode required_mode )
  5380. {
  5381. - FT_Error error = FT_Err_Ok;
  5382. - FT_Outline* outline = &slot->outline;
  5383. + FT_Error error;
  5384. + FT_Outline* outline = NULL;
  5385. + FT_Outline* outline_orig = NULL;
  5386. + FT_BBox cbox;
  5387. + FT_Pos width, height, pitch, ppem;
  5388. +#ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
  5389. + FT_Pos height_org, width_org;
  5390. +#endif
  5391. FT_Bitmap* bitmap = &slot->bitmap;
  5392. FT_Memory memory = render->root.memory;
  5393. + FT_Int hmul = ( mode == FT_RENDER_MODE_LCD );
  5394. + FT_Int vmul = ( mode == FT_RENDER_MODE_LCD_V );
  5395. FT_Pos x_shift = 0;
  5396. FT_Pos y_shift = 0;
  5397. + FT_Pos x_left, y_top;
  5398. +
  5399. + FT_Raster_Params params;
  5400. +
  5401. + FT_Bool have_translated_origin = FALSE;
  5402. + FT_Bool have_outline_shifted = FALSE;
  5403. + FT_Bool have_buffer = FALSE;
  5404. +
  5405. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  5406. + FT_Matrix scaleMat;
  5407. + FT_Long translate_value = 0;
  5408. + float scale_value = 1.0;
  5409. + FT_Int align_called = 0;
  5410. +
  5411. +
  5412. + int chromeos_style_sharpening_strength = 0;
  5413. + int alignment_strength = 0;
  5414. + int fitting_strength = 0;
  5415. + int fringe_filter_strength = 0;
  5416. + int grayscale_filter_strength = 0;
  5417. +
  5418. + int autohint_horizontal_stem_darken_strength = 0;
  5419. + int autohint_vertical_stem_darken_strength = 0;
  5420. +
  5421. + int windows_style_sharpening_strength = 0;
  5422. + float gamma_correction_value = 1;
  5423. + float gamma_correction_lt = 0;
  5424. +
  5425. + FT_Int brightness_value = 0.0;
  5426. + FT_Int contrast_value = 0.0;
  5427. +
  5428. + FT_Int snapping_sliding_scale_value = 0;
  5429. +
  5430. + FT_Int global_embolden_x_value = 0;
  5431. + FT_Int global_embolden_y_value = 0;
  5432. +
  5433. + FT_Int bold_embolden_x_value = 0;
  5434. + FT_Int bold_embolden_y_value = 0;
  5435. +
  5436. + FT_Byte chromeos_cutoff;
  5437. + double chromeos_gamma_value;
  5438. +
  5439. + float embolden_value = 0.0;
  5440. + FT_Bool autohinted = FALSE;
  5441. + FT_Bool use_various_tweaks = FALSE;
  5442. + FT_Pos cur_width = infinality_cur_width;
  5443. +
  5444. + const FT_Int MIN_PPEM = 1;
  5445. + /*const FT_Int MAX_PPEM = 100; */
  5446. +
  5447. + FT_Bool use_known_settings_on_selected_fonts;
  5448. +
  5449. + if ( slot->face &&
  5450. + slot->face->size &&
  5451. + slot->face->size->metrics.x_ppem )
  5452. + ppem = slot->face->size->metrics.x_ppem;
  5453. + else
  5454. + ppem = 0;
  5455. +
  5456. + if ( cur_width )
  5457. + {
  5458. + autohinted = TRUE;
  5459. + }
  5460. + if( ftinf ){
  5461. + const float *f=ftinf->gamma_correction;
  5462. +
  5463. + use_known_settings_on_selected_fonts=ftinf->use_known_settings_on_selected_fonts;
  5464. + use_various_tweaks=ftinf->use_various_tweaks;
  5465. + snapping_sliding_scale_value=ftinf->stem_snapping_sliding_scale;
  5466. +
  5467. + alignment_strength=ftinf->stem_alignment_strength;
  5468. + if ( snapping_sliding_scale_value != 0 )
  5469. + alignment_strength = sliding_scale(10, snapping_sliding_scale_value, alignment_strength, 100, ppem);
  5470. +
  5471. + fitting_strength=ftinf->stem_fitting_strength;
  5472. + if ( snapping_sliding_scale_value != 0 )
  5473. + fitting_strength = sliding_scale(10, snapping_sliding_scale_value, fitting_strength, 100, ppem);
  5474. +
  5475. + chromeos_style_sharpening_strength=ftinf->chromeos_style_sharpening_strength;
  5476. +
  5477. + if ( ppem > 10 )
  5478. + chromeos_style_sharpening_strength =
  5479. + ( chromeos_style_sharpening_strength * ppem ) / 10;
  5480. +
  5481. + if ( chromeos_style_sharpening_strength > 100 )
  5482. + chromeos_style_sharpening_strength = 100;
  5483. +
  5484. + brightness_value=ftinf->brightness;
  5485. + contrast_value=ftinf->contrast;
  5486. +
  5487. + windows_style_sharpening_strength=ftinf->windows_style_sharpening_strength;
  5488. +
  5489. + /* Decrease effect slightly to have a more linear increase in sharpness */
  5490. + windows_style_sharpening_strength =
  5491. + ( ( windows_style_sharpening_strength
  5492. + * windows_style_sharpening_strength ) / 100
  5493. + + windows_style_sharpening_strength ) / 2;
  5494. + gamma_correction_lt = f[0];
  5495. + gamma_correction_value = f[1] / 100.0f;
  5496. +
  5497. + fringe_filter_strength=ftinf->fringe_filter_strength;
  5498. + grayscale_filter_strength=ftinf->grayscale_filter_strength;
  5499. +
  5500. + autohint_horizontal_stem_darken_strength=ftinf->autohint_horizontal_stem_darken_strength;
  5501. + autohint_vertical_stem_darken_strength=ftinf->autohint_vertical_stem_darken_strength;
  5502. +
  5503. + global_embolden_x_value=ftinf->global_embolden_x_value;
  5504. + global_embolden_y_value=ftinf->global_embolden_y_value;
  5505. +
  5506. + bold_embolden_x_value=ftinf->bold_embolden_x_value;
  5507. + bold_embolden_y_value=ftinf->bold_embolden_y_value;
  5508. + } else {
  5509. + use_known_settings_on_selected_fonts=FALSE;
  5510. + }
  5511. +
  5512. + /* set gamma value to 1 if out of range */
  5513. + if ( slot->face &&
  5514. + slot->face->size &&
  5515. + slot->face->size->metrics.x_ppem )
  5516. + {
  5517. + if ( slot->face->size->metrics.x_ppem >= gamma_correction_lt )
  5518. + gamma_correction_value = 1;
  5519. + }
  5520. + else
  5521. + gamma_correction_value = 1;
  5522. +
  5523. + if( use_various_tweaks &&
  5524. + slot->face &&
  5525. + slot->face->style_name )
  5526. + {
  5527. + /* needs to also check for artifical italics */
  5528. + if ( strcasestr(slot->face->style_name, "Italic" ) ||
  5529. + strcasestr(slot->face->style_name, "Oblique" ) )
  5530. + {
  5531. + windows_style_sharpening_strength = 0;
  5532. + chromeos_style_sharpening_strength = 0;
  5533. + }
  5534. + }
  5535. +
  5536. + /*if (fitting_strength == 100) scale_value = 1.1;*/
  5537. +
  5538. +#endif
  5539. +
  5540. +#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
  5541. +
  5542. + FT_Int lcd_extra = 0;
  5543. + FT_LcdFiveTapFilter lcd_weights = { 0 };
  5544. + FT_Bool have_custom_weight = FALSE;
  5545. + FT_Bitmap_LcdFilterFunc lcd_filter_func = NULL;
  5546. +
  5547. +
  5548. + if ( slot->face )
  5549. + {
  5550. + FT_Char i;
  5551. +
  5552. +
  5553. + for ( i = 0; i < FT_LCD_FILTER_FIVE_TAPS; i++ )
  5554. + if ( slot->face->internal->lcd_weights[i] != 0 )
  5555. + {
  5556. + have_custom_weight = TRUE;
  5557. + break;
  5558. + }
  5559. + }
  5560. +
  5561. + /*
  5562. + * The LCD filter can be set library-wide and per-face. Face overrides
  5563. + * library. If the face filter weights are all zero (the default), it
  5564. + * means that the library default should be used.
  5565. + */
  5566. + if ( have_custom_weight )
  5567. + {
  5568. + /*
  5569. + * A per-font filter is set. It always uses the default 5-tap
  5570. + * in-place FIR filter that needs 2 extra pixels.
  5571. + */
  5572. + ft_memcpy( lcd_weights,
  5573. + slot->face->internal->lcd_weights,
  5574. + FT_LCD_FILTER_FIVE_TAPS );
  5575. + lcd_filter_func = ft_lcd_filter_fir;
  5576. + lcd_extra = 2;
  5577. + }
  5578. + else
  5579. + {
  5580. + /*
  5581. + * The face's lcd_weights is {0, 0, 0, 0, 0}, meaning `use library
  5582. + * default'. If the library is set to use no LCD filtering
  5583. + * (lcd_filter_func == NULL), `lcd_filter_func' here is also set to
  5584. + * NULL and the tests further below pass over the filtering process.
  5585. + */
  5586. + ft_memcpy( lcd_weights,
  5587. + slot->library->lcd_weights,
  5588. + FT_LCD_FILTER_FIVE_TAPS );
  5589. + lcd_filter_func = slot->library->lcd_filter_func;
  5590. + lcd_extra = slot->library->lcd_extra;
  5591. + }
  5592. +
  5593. +#endif /*FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
  5594. /* check glyph image format */
  5595. if ( slot->format != render->glyph_format )
  5596. @@ -446,15 +2541,134 @@
  5597. }
  5598. /* check mode */
  5599. - if ( mode != FT_RENDER_MODE_NORMAL &&
  5600. - mode != FT_RENDER_MODE_LIGHT &&
  5601. - mode != FT_RENDER_MODE_LCD &&
  5602. - mode != FT_RENDER_MODE_LCD_V )
  5603. + if ( mode != required_mode )
  5604. {
  5605. error = FT_THROW( Cannot_Render_Glyph );
  5606. goto Exit;
  5607. }
  5608. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  5609. +RERENDER:
  5610. + if ( align_called == 1 )
  5611. + {
  5612. + scaleMat.xx = FT_FixedFromFloat(scale_value);
  5613. + scaleMat.xy = 0;
  5614. + scaleMat.yx = 0;
  5615. + scaleMat.yy = ( 1 << 16 );
  5616. +
  5617. + FT_Outline_Copy(outline_orig, outline);
  5618. +
  5619. + if ( scale_value != 1.0 )
  5620. + FT_Outline_Transform( outline, &scaleMat );
  5621. +
  5622. + FT_Outline_Translate( outline, translate_value, 0 );
  5623. +
  5624. + FT_Outline_EmboldenXY( outline, embolden_value, 0 );
  5625. + }
  5626. + else
  5627. + {
  5628. +#endif
  5629. + outline = &slot->outline;
  5630. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  5631. + /* Need to get this PRIOR to embolden, otherwise bad things happen */
  5632. + FT_Outline_Get_CBox( outline, &cbox );
  5633. +
  5634. + /* Various hacks that need to be turned into a new rule set */
  5635. + /*if ( !autohinted
  5636. + && use_known_settings_on_selected_fonts
  5637. + && mode == FT_RENDER_MODE_LCD
  5638. + && slot->face->family_name
  5639. + && slot->face->style_name
  5640. + && ( strcasestr(slot->face->family_name, "Courier New" )
  5641. + && ( strcasestr(slot->face->style_name, "Regular" )
  5642. + || strcasestr(slot->face->style_name, "Italic" ) ) ) )
  5643. + FT_Outline_Embolden( outline, 24 );*/
  5644. +
  5645. + if ( slot->face )
  5646. + {
  5647. + if ( !autohinted &&
  5648. + use_known_settings_on_selected_fonts &&
  5649. + mode == FT_RENDER_MODE_LCD &&
  5650. + slot->face->family_name &&
  5651. + slot->face->style_name &&
  5652. + strcasestr( slot->face->family_name, "Times New Roman" ) &&
  5653. + strcasestr( slot->face->style_name, "Italic" ) )
  5654. + FT_Outline_EmboldenXY( outline, 12, 0 );
  5655. +
  5656. + if ( use_known_settings_on_selected_fonts &&
  5657. + autohinted &&
  5658. + mode == FT_RENDER_MODE_LCD &&
  5659. + slot->face->family_name &&
  5660. + slot->face->style_name &&
  5661. + strcasestr(slot->face->family_name, "FreeSerif" ) &&
  5662. + strcasestr(slot->face->style_name, "Italic" ) )
  5663. + FT_Outline_EmboldenXY( outline, 8, 0 );
  5664. +
  5665. + if ( global_embolden_x_value != 0 || global_embolden_y_value != 0 )
  5666. + FT_Outline_EmboldenXY( outline,
  5667. + global_embolden_x_value,
  5668. + global_embolden_y_value );
  5669. +
  5670. + if ( ( bold_embolden_x_value != 0 || bold_embolden_y_value != 0 ) &&
  5671. + ( slot->face->style_name &&
  5672. + ( strcasestr(slot->face->style_name, "Bold" ) ||
  5673. + strcasestr(slot->face->style_name, "Black" ) ||
  5674. + ( slot->face->style_flags &&
  5675. + slot->face->style_flags & FT_STYLE_FLAG_BOLD ) ) ) )
  5676. + FT_Outline_EmboldenXY( outline,
  5677. + bold_embolden_x_value,
  5678. + bold_embolden_y_value );
  5679. + }
  5680. +
  5681. + FT_Outline_Copy( outline, outline_orig );
  5682. + }
  5683. +
  5684. + /* translate the outline to the new origin if needed */
  5685. + if ( align_called == 0 )
  5686. + {
  5687. + FT_Pos enlarge_cbox = 0;
  5688. +
  5689. + /* enlarge for grayscale rendering */
  5690. + if ( mode == FT_RENDER_MODE_NORMAL )
  5691. + enlarge_cbox = 64;
  5692. +
  5693. + if ( origin )
  5694. + {
  5695. + FT_Outline_Translate( outline, origin->x, origin->y );
  5696. + have_translated_origin = TRUE;
  5697. + }
  5698. +
  5699. + /* compute the control box, and grid fit it */
  5700. + /*FT_Outline_Get_CBox( outline, &cbox );*/
  5701. +
  5702. + cbox.xMin = FT_PIX_FLOOR( cbox.xMin - enlarge_cbox );
  5703. + cbox.yMin = FT_PIX_FLOOR( cbox.yMin );
  5704. + cbox.xMax = FT_PIX_CEIL( cbox.xMax + enlarge_cbox );
  5705. + cbox.yMax = FT_PIX_CEIL( cbox.yMax );
  5706. +#else
  5707. + if ( origin )
  5708. + {
  5709. + FT_Outline_Translate( outline, origin->x, origin->y );
  5710. + have_translated_origin = TRUE;
  5711. + }
  5712. +
  5713. + /* compute the control box, and grid fit it */
  5714. + FT_Outline_Get_CBox( outline, &cbox );
  5715. +
  5716. + cbox.xMin = FT_PIX_FLOOR( cbox.xMin );
  5717. + cbox.yMin = FT_PIX_FLOOR( cbox.yMin );
  5718. + cbox.xMax = FT_PIX_CEIL( cbox.xMax );
  5719. + cbox.yMax = FT_PIX_CEIL( cbox.yMax );
  5720. +#endif
  5721. +
  5722. + width = (FT_ULong)( cbox.xMax - cbox.xMin ) >> 6;
  5723. + height = (FT_ULong)( cbox.yMax - cbox.yMin ) >> 6;
  5724. +
  5725. +#ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
  5726. + width_org = width;
  5727. + height_org = height;
  5728. +#endif
  5729. +
  5730. /* release old bitmap buffer */
  5731. if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
  5732. {
  5733. @@ -462,109 +2676,427 @@
  5734. slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
  5735. }
  5736. - if ( ft_glyphslot_preset_bitmap( slot, mode, origin ) )
  5737. + /* allocate new one */
  5738. + pitch = width;
  5739. + if ( hmul )
  5740. {
  5741. - error = FT_THROW( Raster_Overflow );
  5742. - goto Exit;
  5743. + width = width * 3;
  5744. + pitch = FT_PAD_CEIL( width, 4 );
  5745. }
  5746. - if ( !bitmap->rows || !bitmap->pitch )
  5747. - goto Exit;
  5748. + if ( vmul )
  5749. + height *= 3;
  5750. - /* allocate new one */
  5751. - if ( FT_ALLOC_MULT( bitmap->buffer, bitmap->rows, bitmap->pitch ) )
  5752. - goto Exit;
  5753. + x_shift = cbox.xMin;
  5754. + y_shift = cbox.yMin;
  5755. + x_left = cbox.xMin >> 6;
  5756. + y_top = cbox.yMax >> 6;
  5757. - slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
  5758. +#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
  5759. + if ( lcd_filter_func )
  5760. + {
  5761. + if ( hmul )
  5762. + {
  5763. + x_shift -= 64 * ( lcd_extra >> 1 );
  5764. + x_left -= lcd_extra >> 1;
  5765. + width += 3 * lcd_extra;
  5766. + pitch = FT_PAD_CEIL( width, 4 );
  5767. + }
  5768. - x_shift = 64 * -slot->bitmap_left;
  5769. - y_shift = 64 * -slot->bitmap_top;
  5770. - if ( bitmap->pixel_mode == FT_PIXEL_MODE_LCD_V )
  5771. - y_shift += 64 * (FT_Int)bitmap->rows / 3;
  5772. - else
  5773. - y_shift += 64 * (FT_Int)bitmap->rows;
  5774. + if ( vmul )
  5775. + {
  5776. + y_shift -= 64 * ( lcd_extra >> 1 );
  5777. + y_top += lcd_extra >> 1;
  5778. + height += 3 * lcd_extra;
  5779. + }
  5780. + }
  5781. +#endif
  5782. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  5783. + }
  5784. +#endif
  5785. - if ( origin )
  5786. +
  5787. + /* Required check is (pitch * height < FT_ULONG_MAX), */
  5788. + /* but we care realistic cases only. Always pitch <= width. */
  5789. + if ( width > 0x7FFF || height > 0x7FFF )
  5790. {
  5791. - x_shift += origin->x;
  5792. - y_shift += origin->y;
  5793. + FT_ERROR(( "ft_smooth_render_generic: glyph too large: %u x %u\n",
  5794. + width, height ));
  5795. + error = FT_THROW( Raster_Overflow );
  5796. + goto Exit;
  5797. }
  5798. - /* translate outline to render it into the bitmap */
  5799. - if ( x_shift || y_shift )
  5800. - FT_Outline_Translate( outline, x_shift, y_shift );
  5801. + bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
  5802. + bitmap->num_grays = 256;
  5803. + bitmap->width = (unsigned int)width;
  5804. + bitmap->rows = (unsigned int)height;
  5805. + bitmap->pitch = pitch;
  5806. - if ( mode == FT_RENDER_MODE_NORMAL ||
  5807. - mode == FT_RENDER_MODE_LIGHT )
  5808. + /* translate outline to render it into the bitmap */
  5809. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  5810. + if ( align_called == 0 )
  5811. {
  5812. - if ( outline->flags & FT_OUTLINE_OVERLAP )
  5813. - error = ft_smooth_raster_overlap( render, outline, bitmap );
  5814. - else
  5815. +#endif
  5816. + FT_Outline_Translate( outline, -x_shift, -y_shift );
  5817. + have_outline_shifted = TRUE;
  5818. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  5819. + }
  5820. +#endif
  5821. + /* release old bitmap buffer */
  5822. + if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
  5823. {
  5824. - FT_Raster_Params params;
  5825. + FT_FREE( bitmap->buffer );
  5826. + slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
  5827. + }
  5828. + if ( FT_ALLOC( bitmap->buffer, (FT_ULong)( pitch * height ) ) )
  5829. + goto Exit;
  5830. + else
  5831. + have_buffer = TRUE;
  5832. + slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
  5833. +
  5834. + /* set up parameters */
  5835. params.target = bitmap;
  5836. params.source = outline;
  5837. params.flags = FT_RASTER_FLAG_AA;
  5838. - error = render->raster_render( render->raster, &params );
  5839. - }
  5840. - }
  5841. - else
  5842. +#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
  5843. +
  5844. + /* implode outline if needed */
  5845. {
  5846. - if ( mode == FT_RENDER_MODE_LCD )
  5847. - error = ft_smooth_raster_lcd ( render, outline, bitmap );
  5848. - else if ( mode == FT_RENDER_MODE_LCD_V )
  5849. - error = ft_smooth_raster_lcdv( render, outline, bitmap );
  5850. + FT_Vector* points = outline->points;
  5851. + FT_Vector* points_end = FT_OFFSET( points, outline->n_points );
  5852. + FT_Vector* vec;
  5853. -#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
  5854. - /* finally apply filtering */
  5855. + if ( hmul )
  5856. + for ( vec = points; vec < points_end; vec++ )
  5857. + vec->x *= 3;
  5858. +
  5859. + if ( vmul )
  5860. + for ( vec = points; vec < points_end; vec++ )
  5861. + vec->y *= 3;
  5862. + }
  5863. +
  5864. + /* render outline into the bitmap */
  5865. + error = render->raster_render( render->raster, &params );
  5866. +
  5867. + /* deflate outline if needed */
  5868. {
  5869. - FT_Byte* lcd_weights;
  5870. - FT_Bitmap_LcdFilterFunc lcd_filter_func;
  5871. + FT_Vector* points = outline->points;
  5872. + FT_Vector* points_end = FT_OFFSET( points, outline->n_points );
  5873. + FT_Vector* vec;
  5874. +
  5875. +
  5876. + if ( hmul )
  5877. + for ( vec = points; vec < points_end; vec++ )
  5878. + vec->x /= 3;
  5879. +
  5880. + if ( vmul )
  5881. + for ( vec = points; vec < points_end; vec++ )
  5882. + vec->y /= 3;
  5883. + }
  5884. +
  5885. + if ( error )
  5886. + goto Exit;
  5887. +#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
  5888. + if ( ppem <= MAX_PPEM && ppem >= MIN_PPEM )
  5889. + {
  5890. + if ( align_called == 0 && cur_width / ppem < 10 &&
  5891. + ( alignment_strength > 0 || fitting_strength > 0 ) )
  5892. + _lcd_stem_align ( bitmap,
  5893. + mode,
  5894. + slot,
  5895. + &translate_value,
  5896. + &scale_value,
  5897. + alignment_strength,
  5898. + fitting_strength,
  5899. + &embolden_value );
  5900. - /* Per-face LCD filtering takes priority if set up. */
  5901. - if ( slot->face && slot->face->internal->lcd_filter_func )
  5902. + if ( align_called == 0 &&
  5903. + ( translate_value != 0 || scale_value != 1.0 ) )
  5904. {
  5905. - lcd_weights = slot->face->internal->lcd_weights;
  5906. - lcd_filter_func = slot->face->internal->lcd_filter_func;
  5907. + align_called = 1;
  5908. + goto RERENDER;
  5909. }
  5910. - else
  5911. +
  5912. + if ( mode == FT_RENDER_MODE_LCD )
  5913. {
  5914. - lcd_weights = slot->library->lcd_weights;
  5915. - lcd_filter_func = slot->library->lcd_filter_func;
  5916. +
  5917. + if ( fringe_filter_strength > 0 /*&& autohinted*/ )
  5918. + _ft_lcd_fringe_filter( bitmap,
  5919. + mode,
  5920. + fringe_filter_strength,
  5921. + slot->library );
  5922. +
  5923. + /*if ( autohinted)
  5924. + _ft_lcd_stem_end_filter( bitmap, mode, 100, slot->library );*/
  5925. +
  5926. + if ( gamma_correction_lt > 0 && gamma_correction_value != 1.0 )
  5927. + _ft_lcd_gamma_correction_correction( bitmap,
  5928. + mode,
  5929. + slot,
  5930. + gamma_correction_lt,
  5931. + gamma_correction_value );
  5932. +
  5933. + chromeos_cutoff = (FT_Byte)( 0.5 * 255.0 )
  5934. + * ( chromeos_style_sharpening_strength / 100.0 );
  5935. + chromeos_gamma_value = 1;
  5936. +
  5937. + if ( chromeos_style_sharpening_strength > 0 )
  5938. + _ft_lcd_chromeos_sharpen( bitmap,
  5939. + mode,
  5940. + chromeos_cutoff,
  5941. + chromeos_gamma_value );
  5942. +
  5943. + if ( ppem > 8 )
  5944. + if ( windows_style_sharpening_strength > 0 )
  5945. + _ft_lcd_windows_sharpen( bitmap,
  5946. + mode,
  5947. + windows_style_sharpening_strength,
  5948. + slot->library );
  5949. +
  5950. + if ( autohinted &&
  5951. + ( cur_width * 100 ) / 64
  5952. + > autohint_horizontal_stem_darken_strength &&
  5953. + autohint_horizontal_stem_darken_strength != 0 )
  5954. + autohint_horizontal_stem_darken_strength = ( cur_width * 100 ) / 64;
  5955. +
  5956. + if ( autohint_horizontal_stem_darken_strength > 100)
  5957. + autohint_horizontal_stem_darken_strength = 100;
  5958. +
  5959. + /* only do on autohinted fonts */
  5960. + /* Necessary to do on some non-thin fonts, which is why it is outside */
  5961. + /* of the below conditional */
  5962. + if ( autohint_horizontal_stem_darken_strength > 0 && autohinted )
  5963. + _ft_lcd_darken_x ( bitmap,
  5964. + mode,
  5965. + autohint_horizontal_stem_darken_strength,
  5966. + slot->library );
  5967. +
  5968. + /* Enhance thin fonts */
  5969. + if ( autohinted )
  5970. + {
  5971. + /* if forcibly set use that, otherwise make a good estimate */
  5972. + float contrast, brightness;
  5973. + ftinf_get_bc( slot->face->family_name, ppem, &brightness, &contrast);
  5974. + if ( slot->face && !_ft_bitmap_bc ( bitmap, brightness, contrast ) )
  5975. + {
  5976. + FT_Bool is_fixed_name = FALSE;
  5977. +
  5978. + if ( slot->face->family_name &&
  5979. + strcasestr(slot->face->family_name, "Mono" ) )
  5980. + is_fixed_name = TRUE;
  5981. +
  5982. + /* Darken vertical stems */
  5983. + _ft_lcd_darken_y ( bitmap,
  5984. + mode,
  5985. + autohint_vertical_stem_darken_strength,
  5986. + slot->library );
  5987. +
  5988. + /* Adjust brightness / contrast automatically based on stem width */
  5989. + if ( cur_width != 0 && cur_width < 30 )
  5990. + cur_width = 30;
  5991. +
  5992. + if ( cur_width >= 30 && cur_width <= 60 )
  5993. + {
  5994. + float ppem_factor = sliding_scale ( 5, 11, 0.0, 1.0, ppem );
  5995. + float brightness_factor = sliding_scale ( 30, 52, -.3, 0.0,
  5996. + cur_width );
  5997. + float contrast_factor = sliding_scale ( 30, 52, .45, 0.0,
  5998. + cur_width );
  5999. + _ft_bitmap_bc ( bitmap,
  6000. + ppem_factor * brightness_factor,
  6001. + ppem_factor * contrast_factor );
  6002. +
  6003. + /* Only cap variable width thin-stemmed fonts */
  6004. + if ( !FT_IS_FIXED_WIDTH( slot->face ) && !is_fixed_name )
  6005. + _ft_bitmap_cap ( bitmap,
  6006. + ( cur_width * 150 ) / 64,
  6007. + slot->library );
  6008. }
  6009. + }
  6010. + }
  6011. +
  6012. if ( lcd_filter_func )
  6013. - lcd_filter_func( bitmap, lcd_weights );
  6014. + lcd_filter_func( bitmap, mode, lcd_weights );
  6015. +
  6016. + if ( grayscale_filter_strength > 0 )
  6017. + _ft_lcd_grayscale_filter( bitmap,
  6018. + mode,
  6019. + grayscale_filter_strength,
  6020. + slot->library );
  6021. +
  6022. }
  6023. -#endif /* FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
  6024. + /* Global values */
  6025. + if ( brightness_value != 0 || contrast_value != 0 )
  6026. + _ft_bitmap_bc ( bitmap,
  6027. + (float)brightness_value / 300.0,
  6028. + (float)contrast_value / 300.0);
  6029. + FT_Outline_Done( slot->library, outline_orig );
  6030. }
  6031. + else if ( mode == FT_RENDER_MODE_LCD &&
  6032. + lcd_filter_func )
  6033. + lcd_filter_func( bitmap, mode, lcd_weights );
  6034. +#else
  6035. + if ( lcd_filter_func )
  6036. + lcd_filter_func( bitmap, mode, lcd_weights );
  6037. +#endif /* FT_CONFIG_OPTION_INFINALITY_PATCHSET */
  6038. - Exit:
  6039. - if ( !error )
  6040. +#else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
  6041. +
  6042. + /* render outline into bitmap */
  6043. + error = render->raster_render( render->raster, &params );
  6044. + if ( error )
  6045. + goto Exit;
  6046. +
  6047. + /* expand it horizontally */
  6048. + if ( hmul )
  6049. {
  6050. - /* everything is fine; the glyph is now officially a bitmap */
  6051. - slot->format = FT_GLYPH_FORMAT_BITMAP;
  6052. + FT_Byte* line = bitmap->buffer;
  6053. + FT_UInt hh;
  6054. +
  6055. +
  6056. + for ( hh = height_org; hh > 0; hh--, line += pitch )
  6057. + {
  6058. + FT_UInt xx;
  6059. + FT_Byte* end = line + width;
  6060. +
  6061. +
  6062. + for ( xx = width_org; xx > 0; xx-- )
  6063. + {
  6064. + FT_UInt pixel = line[xx-1];
  6065. +
  6066. +
  6067. + end[-3] = (FT_Byte)pixel;
  6068. + end[-2] = (FT_Byte)pixel;
  6069. + end[-1] = (FT_Byte)pixel;
  6070. + end -= 3;
  6071. + }
  6072. + }
  6073. + }
  6074. +
  6075. + /* expand it vertically */
  6076. + if ( vmul )
  6077. + {
  6078. + FT_Byte* read = bitmap->buffer + ( height - height_org ) * pitch;
  6079. + FT_Byte* write = bitmap->buffer;
  6080. + FT_UInt hh;
  6081. +
  6082. +
  6083. + for ( hh = height_org; hh > 0; hh-- )
  6084. + {
  6085. + ft_memcpy( write, read, pitch );
  6086. + write += pitch;
  6087. +
  6088. + ft_memcpy( write, read, pitch );
  6089. + write += pitch;
  6090. +
  6091. + ft_memcpy( write, read, pitch );
  6092. + write += pitch;
  6093. + read += pitch;
  6094. + }
  6095. }
  6096. - else if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
  6097. +
  6098. +#endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
  6099. +
  6100. + /*
  6101. + * XXX: on 16bit system, we return an error for huge bitmap
  6102. + * to prevent an overflow.
  6103. + */
  6104. + if ( x_left > FT_INT_MAX || y_top > FT_INT_MAX )
  6105. + {
  6106. + error = FT_THROW( Invalid_Pixel_Size );
  6107. + goto Exit;
  6108. + }
  6109. +
  6110. + slot->format = FT_GLYPH_FORMAT_BITMAP;
  6111. + slot->bitmap_left = (FT_Int)x_left;
  6112. + slot->bitmap_top = (FT_Int)y_top;
  6113. +
  6114. + /* everything is fine; don't deallocate buffer */
  6115. + have_buffer = FALSE;
  6116. +
  6117. + error = FT_Err_Ok;
  6118. +
  6119. + Exit:
  6120. + if ( have_outline_shifted )
  6121. + FT_Outline_Translate( outline, x_shift, y_shift );
  6122. + if ( have_translated_origin )
  6123. + FT_Outline_Translate( outline, -origin->x, -origin->y );
  6124. + if ( have_buffer )
  6125. {
  6126. FT_FREE( bitmap->buffer );
  6127. slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
  6128. }
  6129. - if ( x_shift || y_shift )
  6130. - FT_Outline_Translate( outline, -x_shift, -y_shift );
  6131. + return error;
  6132. + }
  6133. +
  6134. +
  6135. +
  6136. + /* convert a slot's glyph image into a horizontal LCD bitmap */
  6137. + static FT_Error
  6138. + ft_smooth_render_lcd( FT_Renderer render,
  6139. + FT_GlyphSlot slot,
  6140. + FT_Render_Mode mode,
  6141. + const FT_Vector* origin )
  6142. + {
  6143. + FT_Error error;
  6144. +
  6145. + error = ft_smooth_render_generic( render, slot, mode, origin,
  6146. + FT_RENDER_MODE_LCD );
  6147. + if ( !error )
  6148. + slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD;
  6149. return error;
  6150. }
  6151. + /* convert a slot's glyph image into a vertical LCD bitmap */
  6152. + static FT_Error
  6153. + ft_smooth_render_lcd_v( FT_Renderer render,
  6154. + FT_GlyphSlot slot,
  6155. + FT_Render_Mode mode,
  6156. + const FT_Vector* origin )
  6157. + {
  6158. + FT_Error error;
  6159. +
  6160. + error = ft_smooth_render_generic( render, slot, mode, origin,
  6161. + FT_RENDER_MODE_LCD_V );
  6162. + if ( !error )
  6163. + slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD_V;
  6164. +
  6165. + return error;
  6166. + }
  6167. +
  6168. +
  6169. +
  6170. + /* convert a slot's glyph image into a bitmap */
  6171. + static FT_Error
  6172. + ft_smooth_render( FT_Renderer render,
  6173. + FT_GlyphSlot slot,
  6174. + FT_Render_Mode mode,
  6175. + const FT_Vector* origin )
  6176. + {
  6177. + switch (mode) {
  6178. + case FT_RENDER_MODE_LIGHT:
  6179. + case FT_RENDER_MODE_NORMAL:
  6180. + return ft_smooth_render_generic( render, slot, mode, origin,
  6181. + FT_RENDER_MODE_NORMAL );
  6182. + case FT_RENDER_MODE_LCD:
  6183. + return ft_smooth_render_lcd( render, slot, mode, origin);
  6184. + case FT_RENDER_MODE_LCD_V:
  6185. + return ft_smooth_render_lcd_v( render, slot, mode, origin);
  6186. + }
  6187. + }
  6188. +
  6189. +
  6190. FT_DEFINE_RENDERER(
  6191. ft_smooth_renderer_class,