imstb_truetype.h 195 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086
  1. // [DEAR IMGUI]
  2. // This is a slightly modified version of stb_truetype.h 1.26.
  3. // Mostly fixing for compiler and static analyzer warnings.
  4. // Grep for [DEAR IMGUI] to find the changes.
  5. // stb_truetype.h - v1.26 - public domain
  6. // authored from 2009-2021 by Sean Barrett / RAD Game Tools
  7. //
  8. // =======================================================================
  9. //
  10. // NO SECURITY GUARANTEE -- DO NOT USE THIS ON UNTRUSTED FONT FILES
  11. //
  12. // This library does no range checking of the offsets found in the file,
  13. // meaning an attacker can use it to read arbitrary memory.
  14. //
  15. // =======================================================================
  16. //
  17. // This library processes TrueType files:
  18. // parse files
  19. // extract glyph metrics
  20. // extract glyph shapes
  21. // render glyphs to one-channel bitmaps with antialiasing (box filter)
  22. // render glyphs to one-channel SDF bitmaps (signed-distance field/function)
  23. //
  24. // Todo:
  25. // non-MS cmaps
  26. // crashproof on bad data
  27. // hinting? (no longer patented)
  28. // cleartype-style AA?
  29. // optimize: use simple memory allocator for intermediates
  30. // optimize: build edge-list directly from curves
  31. // optimize: rasterize directly from curves?
  32. //
  33. // ADDITIONAL CONTRIBUTORS
  34. //
  35. // Mikko Mononen: compound shape support, more cmap formats
  36. // Tor Andersson: kerning, subpixel rendering
  37. // Dougall Johnson: OpenType / Type 2 font handling
  38. // Daniel Ribeiro Maciel: basic GPOS-based kerning
  39. //
  40. // Misc other:
  41. // Ryan Gordon
  42. // Simon Glass
  43. // github:IntellectualKitty
  44. // Imanol Celaya
  45. // Daniel Ribeiro Maciel
  46. //
  47. // Bug/warning reports/fixes:
  48. // "Zer" on mollyrocket Fabian "ryg" Giesen github:NiLuJe
  49. // Cass Everitt Martins Mozeiko github:aloucks
  50. // stoiko (Haemimont Games) Cap Petschulat github:oyvindjam
  51. // Brian Hook Omar Cornut github:vassvik
  52. // Walter van Niftrik Ryan Griege
  53. // David Gow Peter LaValle
  54. // David Given Sergey Popov
  55. // Ivan-Assen Ivanov Giumo X. Clanjor
  56. // Anthony Pesch Higor Euripedes
  57. // Johan Duparc Thomas Fields
  58. // Hou Qiming Derek Vinyard
  59. // Rob Loach Cort Stratton
  60. // Kenney Phillis Jr. Brian Costabile
  61. // Ken Voskuil (kaesve)
  62. //
  63. // VERSION HISTORY
  64. //
  65. // 1.26 (2021-08-28) fix broken rasterizer
  66. // 1.25 (2021-07-11) many fixes
  67. // 1.24 (2020-02-05) fix warning
  68. // 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS)
  69. // 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined
  70. // 1.21 (2019-02-25) fix warning
  71. // 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics()
  72. // 1.19 (2018-02-11) GPOS kerning, STBTT_fmod
  73. // 1.18 (2018-01-29) add missing function
  74. // 1.17 (2017-07-23) make more arguments const; doc fix
  75. // 1.16 (2017-07-12) SDF support
  76. // 1.15 (2017-03-03) make more arguments const
  77. // 1.14 (2017-01-16) num-fonts-in-TTC function
  78. // 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts
  79. // 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual
  80. // 1.11 (2016-04-02) fix unused-variable warning
  81. // 1.10 (2016-04-02) user-defined fabs(); rare memory leak; remove duplicate typedef
  82. // 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use allocation userdata properly
  83. // 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges
  84. // 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints;
  85. // variant PackFontRanges to pack and render in separate phases;
  86. // fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?);
  87. // fixed an assert() bug in the new rasterizer
  88. // replace assert() with STBTT_assert() in new rasterizer
  89. //
  90. // Full history can be found at the end of this file.
  91. //
  92. // LICENSE
  93. //
  94. // See end of file for license information.
  95. //
  96. // USAGE
  97. //
  98. // Include this file in whatever places need to refer to it. In ONE C/C++
  99. // file, write:
  100. // #define STB_TRUETYPE_IMPLEMENTATION
  101. // before the #include of this file. This expands out the actual
  102. // implementation into that C/C++ file.
  103. //
  104. // To make the implementation private to the file that generates the implementation,
  105. // #define STBTT_STATIC
  106. //
  107. // Simple 3D API (don't ship this, but it's fine for tools and quick start)
  108. // stbtt_BakeFontBitmap() -- bake a font to a bitmap for use as texture
  109. // stbtt_GetBakedQuad() -- compute quad to draw for a given char
  110. //
  111. // Improved 3D API (more shippable):
  112. // #include "stb_rect_pack.h" -- optional, but you really want it
  113. // stbtt_PackBegin()
  114. // stbtt_PackSetOversampling() -- for improved quality on small fonts
  115. // stbtt_PackFontRanges() -- pack and renders
  116. // stbtt_PackEnd()
  117. // stbtt_GetPackedQuad()
  118. //
  119. // "Load" a font file from a memory buffer (you have to keep the buffer loaded)
  120. // stbtt_InitFont()
  121. // stbtt_GetFontOffsetForIndex() -- indexing for TTC font collections
  122. // stbtt_GetNumberOfFonts() -- number of fonts for TTC font collections
  123. //
  124. // Render a unicode codepoint to a bitmap
  125. // stbtt_GetCodepointBitmap() -- allocates and returns a bitmap
  126. // stbtt_MakeCodepointBitmap() -- renders into bitmap you provide
  127. // stbtt_GetCodepointBitmapBox() -- how big the bitmap must be
  128. //
  129. // Character advance/positioning
  130. // stbtt_GetCodepointHMetrics()
  131. // stbtt_GetFontVMetrics()
  132. // stbtt_GetFontVMetricsOS2()
  133. // stbtt_GetCodepointKernAdvance()
  134. //
  135. // Starting with version 1.06, the rasterizer was replaced with a new,
  136. // faster and generally-more-precise rasterizer. The new rasterizer more
  137. // accurately measures pixel coverage for anti-aliasing, except in the case
  138. // where multiple shapes overlap, in which case it overestimates the AA pixel
  139. // coverage. Thus, anti-aliasing of intersecting shapes may look wrong. If
  140. // this turns out to be a problem, you can re-enable the old rasterizer with
  141. // #define STBTT_RASTERIZER_VERSION 1
  142. // which will incur about a 15% speed hit.
  143. //
  144. // ADDITIONAL DOCUMENTATION
  145. //
  146. // Immediately after this block comment are a series of sample programs.
  147. //
  148. // After the sample programs is the "header file" section. This section
  149. // includes documentation for each API function.
  150. //
  151. // Some important concepts to understand to use this library:
  152. //
  153. // Codepoint
  154. // Characters are defined by unicode codepoints, e.g. 65 is
  155. // uppercase A, 231 is lowercase c with a cedilla, 0x7e30 is
  156. // the hiragana for "ma".
  157. //
  158. // Glyph
  159. // A visual character shape (every codepoint is rendered as
  160. // some glyph)
  161. //
  162. // Glyph index
  163. // A font-specific integer ID representing a glyph
  164. //
  165. // Baseline
  166. // Glyph shapes are defined relative to a baseline, which is the
  167. // bottom of uppercase characters. Characters extend both above
  168. // and below the baseline.
  169. //
  170. // Current Point
  171. // As you draw text to the screen, you keep track of a "current point"
  172. // which is the origin of each character. The current point's vertical
  173. // position is the baseline. Even "baked fonts" use this model.
  174. //
  175. // Vertical Font Metrics
  176. // The vertical qualities of the font, used to vertically position
  177. // and space the characters. See docs for stbtt_GetFontVMetrics.
  178. //
  179. // Font Size in Pixels or Points
  180. // The preferred interface for specifying font sizes in stb_truetype
  181. // is to specify how tall the font's vertical extent should be in pixels.
  182. // If that sounds good enough, skip the next paragraph.
  183. //
  184. // Most font APIs instead use "points", which are a common typographic
  185. // measurement for describing font size, defined as 72 points per inch.
  186. // stb_truetype provides a point API for compatibility. However, true
  187. // "per inch" conventions don't make much sense on computer displays
  188. // since different monitors have different number of pixels per
  189. // inch. For example, Windows traditionally uses a convention that
  190. // there are 96 pixels per inch, thus making 'inch' measurements have
  191. // nothing to do with inches, and thus effectively defining a point to
  192. // be 1.333 pixels. Additionally, the TrueType font data provides
  193. // an explicit scale factor to scale a given font's glyphs to points,
  194. // but the author has observed that this scale factor is often wrong
  195. // for non-commercial fonts, thus making fonts scaled in points
  196. // according to the TrueType spec incoherently sized in practice.
  197. //
  198. // DETAILED USAGE:
  199. //
  200. // Scale:
  201. // Select how high you want the font to be, in points or pixels.
  202. // Call ScaleForPixelHeight or ScaleForMappingEmToPixels to compute
  203. // a scale factor SF that will be used by all other functions.
  204. //
  205. // Baseline:
  206. // You need to select a y-coordinate that is the baseline of where
  207. // your text will appear. Call GetFontBoundingBox to get the baseline-relative
  208. // bounding box for all characters. SF*-y0 will be the distance in pixels
  209. // that the worst-case character could extend above the baseline, so if
  210. // you want the top edge of characters to appear at the top of the
  211. // screen where y=0, then you would set the baseline to SF*-y0.
  212. //
  213. // Current point:
  214. // Set the current point where the first character will appear. The
  215. // first character could extend left of the current point; this is font
  216. // dependent. You can either choose a current point that is the leftmost
  217. // point and hope, or add some padding, or check the bounding box or
  218. // left-side-bearing of the first character to be displayed and set
  219. // the current point based on that.
  220. //
  221. // Displaying a character:
  222. // Compute the bounding box of the character. It will contain signed values
  223. // relative to <current_point, baseline>. I.e. if it returns x0,y0,x1,y1,
  224. // then the character should be displayed in the rectangle from
  225. // <current_point+SF*x0, baseline+SF*y0> to <current_point+SF*x1,baseline+SF*y1).
  226. //
  227. // Advancing for the next character:
  228. // Call GlyphHMetrics, and compute 'current_point += SF * advance'.
  229. //
  230. //
  231. // ADVANCED USAGE
  232. //
  233. // Quality:
  234. //
  235. // - Use the functions with Subpixel at the end to allow your characters
  236. // to have subpixel positioning. Since the font is anti-aliased, not
  237. // hinted, this is very import for quality. (This is not possible with
  238. // baked fonts.)
  239. //
  240. // - Kerning is now supported, and if you're supporting subpixel rendering
  241. // then kerning is worth using to give your text a polished look.
  242. //
  243. // Performance:
  244. //
  245. // - Convert Unicode codepoints to glyph indexes and operate on the glyphs;
  246. // if you don't do this, stb_truetype is forced to do the conversion on
  247. // every call.
  248. //
  249. // - There are a lot of memory allocations. We should modify it to take
  250. // a temp buffer and allocate from the temp buffer (without freeing),
  251. // should help performance a lot.
  252. //
  253. // NOTES
  254. //
  255. // The system uses the raw data found in the .ttf file without changing it
  256. // and without building auxiliary data structures. This is a bit inefficient
  257. // on little-endian systems (the data is big-endian), but assuming you're
  258. // caching the bitmaps or glyph shapes this shouldn't be a big deal.
  259. //
  260. // It appears to be very hard to programmatically determine what font a
  261. // given file is in a general way. I provide an API for this, but I don't
  262. // recommend it.
  263. //
  264. //
  265. // PERFORMANCE MEASUREMENTS FOR 1.06:
  266. //
  267. // 32-bit 64-bit
  268. // Previous release: 8.83 s 7.68 s
  269. // Pool allocations: 7.72 s 6.34 s
  270. // Inline sort : 6.54 s 5.65 s
  271. // New rasterizer : 5.63 s 5.00 s
  272. //////////////////////////////////////////////////////////////////////////////
  273. //////////////////////////////////////////////////////////////////////////////
  274. ////
  275. //// SAMPLE PROGRAMS
  276. ////
  277. //
  278. // Incomplete text-in-3d-api example, which draws quads properly aligned to be lossless.
  279. // See "tests/truetype_demo_win32.c" for a complete version.
  280. #if 0
  281. #define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
  282. #include "stb_truetype.h"
  283. unsigned char ttf_buffer[1<<20];
  284. unsigned char temp_bitmap[512*512];
  285. stbtt_bakedchar cdata[96]; // ASCII 32..126 is 95 glyphs
  286. GLuint ftex;
  287. void my_stbtt_initfont(void)
  288. {
  289. fread(ttf_buffer, 1, 1<<20, fopen("c:/windows/fonts/times.ttf", "rb"));
  290. stbtt_BakeFontBitmap(ttf_buffer,0, 32.0, temp_bitmap,512,512, 32,96, cdata); // no guarantee this fits!
  291. // can free ttf_buffer at this point
  292. glGenTextures(1, &ftex);
  293. glBindTexture(GL_TEXTURE_2D, ftex);
  294. glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 512,512, 0, GL_ALPHA, GL_UNSIGNED_BYTE, temp_bitmap);
  295. // can free temp_bitmap at this point
  296. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  297. }
  298. void my_stbtt_print(float x, float y, char *text)
  299. {
  300. // assume orthographic projection with units = screen pixels, origin at top left
  301. glEnable(GL_BLEND);
  302. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  303. glEnable(GL_TEXTURE_2D);
  304. glBindTexture(GL_TEXTURE_2D, ftex);
  305. glBegin(GL_QUADS);
  306. while (*text) {
  307. if (*text >= 32 && *text < 128) {
  308. stbtt_aligned_quad q;
  309. stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);//1=opengl & d3d10+,0=d3d9
  310. glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y0);
  311. glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y0);
  312. glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y1);
  313. glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y1);
  314. }
  315. ++text;
  316. }
  317. glEnd();
  318. }
  319. #endif
  320. //
  321. //
  322. //////////////////////////////////////////////////////////////////////////////
  323. //
  324. // Complete program (this compiles): get a single bitmap, print as ASCII art
  325. //
  326. #if 0
  327. #include <stdio.h>
  328. #define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
  329. #include "stb_truetype.h"
  330. char ttf_buffer[1<<25];
  331. int main(int argc, char **argv)
  332. {
  333. stbtt_fontinfo font;
  334. unsigned char *bitmap;
  335. int w,h,i,j,c = (argc > 1 ? atoi(argv[1]) : 'a'), s = (argc > 2 ? atoi(argv[2]) : 20);
  336. fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/windows/fonts/arialbd.ttf", "rb"));
  337. stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0));
  338. bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, s), c, &w, &h, 0,0);
  339. for (j=0; j < h; ++j) {
  340. for (i=0; i < w; ++i)
  341. putchar(" .:ioVM@"[bitmap[j*w+i]>>5]);
  342. putchar('\n');
  343. }
  344. return 0;
  345. }
  346. #endif
  347. //
  348. // Output:
  349. //
  350. // .ii.
  351. // @@@@@@.
  352. // V@Mio@@o
  353. // :i. V@V
  354. // :oM@@M
  355. // :@@@MM@M
  356. // @@o o@M
  357. // :@@. M@M
  358. // @@@o@@@@
  359. // :M@@V:@@.
  360. //
  361. //////////////////////////////////////////////////////////////////////////////
  362. //
  363. // Complete program: print "Hello World!" banner, with bugs
  364. //
  365. #if 0
  366. char buffer[24<<20];
  367. unsigned char screen[20][79];
  368. int main(int arg, char **argv)
  369. {
  370. stbtt_fontinfo font;
  371. int i,j,ascent,baseline,ch=0;
  372. float scale, xpos=2; // leave a little padding in case the character extends left
  373. char *text = "Heljo World!"; // intentionally misspelled to show 'lj' brokenness
  374. fread(buffer, 1, 1000000, fopen("c:/windows/fonts/arialbd.ttf", "rb"));
  375. stbtt_InitFont(&font, buffer, 0);
  376. scale = stbtt_ScaleForPixelHeight(&font, 15);
  377. stbtt_GetFontVMetrics(&font, &ascent,0,0);
  378. baseline = (int) (ascent*scale);
  379. while (text[ch]) {
  380. int advance,lsb,x0,y0,x1,y1;
  381. float x_shift = xpos - (float) floor(xpos);
  382. stbtt_GetCodepointHMetrics(&font, text[ch], &advance, &lsb);
  383. stbtt_GetCodepointBitmapBoxSubpixel(&font, text[ch], scale,scale,x_shift,0, &x0,&y0,&x1,&y1);
  384. stbtt_MakeCodepointBitmapSubpixel(&font, &screen[baseline + y0][(int) xpos + x0], x1-x0,y1-y0, 79, scale,scale,x_shift,0, text[ch]);
  385. // note that this stomps the old data, so where character boxes overlap (e.g. 'lj') it's wrong
  386. // because this API is really for baking character bitmaps into textures. if you want to render
  387. // a sequence of characters, you really need to render each bitmap to a temp buffer, then
  388. // "alpha blend" that into the working buffer
  389. xpos += (advance * scale);
  390. if (text[ch+1])
  391. xpos += scale*stbtt_GetCodepointKernAdvance(&font, text[ch],text[ch+1]);
  392. ++ch;
  393. }
  394. for (j=0; j < 20; ++j) {
  395. for (i=0; i < 78; ++i)
  396. putchar(" .:ioVM@"[screen[j][i]>>5]);
  397. putchar('\n');
  398. }
  399. return 0;
  400. }
  401. #endif
  402. //////////////////////////////////////////////////////////////////////////////
  403. //////////////////////////////////////////////////////////////////////////////
  404. ////
  405. //// INTEGRATION WITH YOUR CODEBASE
  406. ////
  407. //// The following sections allow you to supply alternate definitions
  408. //// of C library functions used by stb_truetype, e.g. if you don't
  409. //// link with the C runtime library.
  410. #ifdef STB_TRUETYPE_IMPLEMENTATION
  411. // #define your own (u)stbtt_int8/16/32 before including to override this
  412. #ifndef stbtt_uint8
  413. typedef unsigned char stbtt_uint8;
  414. typedef signed char stbtt_int8;
  415. typedef unsigned short stbtt_uint16;
  416. typedef signed short stbtt_int16;
  417. typedef unsigned int stbtt_uint32;
  418. typedef signed int stbtt_int32;
  419. #endif
  420. typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1];
  421. typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1];
  422. // e.g. #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h
  423. #ifndef STBTT_ifloor
  424. #include <math.h>
  425. #define STBTT_ifloor(x) ((int) floor(x))
  426. #define STBTT_iceil(x) ((int) ceil(x))
  427. #endif
  428. #ifndef STBTT_sqrt
  429. #include <math.h>
  430. #define STBTT_sqrt(x) sqrt(x)
  431. #define STBTT_pow(x,y) pow(x,y)
  432. #endif
  433. #ifndef STBTT_fmod
  434. #include <math.h>
  435. #define STBTT_fmod(x,y) fmod(x,y)
  436. #endif
  437. #ifndef STBTT_cos
  438. #include <math.h>
  439. #define STBTT_cos(x) cos(x)
  440. #define STBTT_acos(x) acos(x)
  441. #endif
  442. #ifndef STBTT_fabs
  443. #include <math.h>
  444. #define STBTT_fabs(x) fabs(x)
  445. #endif
  446. // #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h
  447. #ifndef STBTT_malloc
  448. #include <stdlib.h>
  449. #define STBTT_malloc(x,u) ((void)(u),malloc(x))
  450. #define STBTT_free(x,u) ((void)(u),free(x))
  451. #endif
  452. #ifndef STBTT_assert
  453. #include <assert.h>
  454. #define STBTT_assert(x) assert(x)
  455. #endif
  456. #ifndef STBTT_strlen
  457. #include <string.h>
  458. #define STBTT_strlen(x) strlen(x)
  459. #endif
  460. #ifndef STBTT_memcpy
  461. #include <string.h>
  462. #define STBTT_memcpy memcpy
  463. #define STBTT_memset memset
  464. #endif
  465. #endif
  466. ///////////////////////////////////////////////////////////////////////////////
  467. ///////////////////////////////////////////////////////////////////////////////
  468. ////
  469. //// INTERFACE
  470. ////
  471. ////
  472. #ifndef __STB_INCLUDE_STB_TRUETYPE_H__
  473. #define __STB_INCLUDE_STB_TRUETYPE_H__
  474. #ifdef STBTT_STATIC
  475. #define STBTT_DEF static
  476. #else
  477. #define STBTT_DEF extern
  478. #endif
  479. #ifdef __cplusplus
  480. extern "C" {
  481. #endif
  482. // private structure
  483. typedef struct
  484. {
  485. unsigned char *data;
  486. int cursor;
  487. int size;
  488. } stbtt__buf;
  489. //////////////////////////////////////////////////////////////////////////////
  490. //
  491. // TEXTURE BAKING API
  492. //
  493. // If you use this API, you only have to call two functions ever.
  494. //
  495. typedef struct
  496. {
  497. unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap
  498. float xoff,yoff,xadvance;
  499. } stbtt_bakedchar;
  500. STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf)
  501. float pixel_height, // height of font in pixels
  502. unsigned char *pixels, int pw, int ph, // bitmap to be filled in
  503. int first_char, int num_chars, // characters to bake
  504. stbtt_bakedchar *chardata); // you allocate this, it's num_chars long
  505. // if return is positive, the first unused row of the bitmap
  506. // if return is negative, returns the negative of the number of characters that fit
  507. // if return is 0, no characters fit and no rows were used
  508. // This uses a very crappy packing.
  509. typedef struct
  510. {
  511. float x0,y0,s0,t0; // top-left
  512. float x1,y1,s1,t1; // bottom-right
  513. } stbtt_aligned_quad;
  514. STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, // same data as above
  515. int char_index, // character to display
  516. float *xpos, float *ypos, // pointers to current position in screen pixel space
  517. stbtt_aligned_quad *q, // output: quad to draw
  518. int opengl_fillrule); // true if opengl fill rule; false if DX9 or earlier
  519. // Call GetBakedQuad with char_index = 'character - first_char', and it
  520. // creates the quad you need to draw and advances the current position.
  521. //
  522. // The coordinate system used assumes y increases downwards.
  523. //
  524. // Characters will extend both above and below the current position;
  525. // see discussion of "BASELINE" above.
  526. //
  527. // It's inefficient; you might want to c&p it and optimize it.
  528. STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap);
  529. // Query the font vertical metrics without having to create a font first.
  530. //////////////////////////////////////////////////////////////////////////////
  531. //
  532. // NEW TEXTURE BAKING API
  533. //
  534. // This provides options for packing multiple fonts into one atlas, not
  535. // perfectly but better than nothing.
  536. typedef struct
  537. {
  538. unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap
  539. float xoff,yoff,xadvance;
  540. float xoff2,yoff2;
  541. } stbtt_packedchar;
  542. typedef struct stbtt_pack_context stbtt_pack_context;
  543. typedef struct stbtt_fontinfo stbtt_fontinfo;
  544. #ifndef STB_RECT_PACK_VERSION
  545. typedef struct stbrp_rect stbrp_rect;
  546. #endif
  547. STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int width, int height, int stride_in_bytes, int padding, void *alloc_context);
  548. // Initializes a packing context stored in the passed-in stbtt_pack_context.
  549. // Future calls using this context will pack characters into the bitmap passed
  550. // in here: a 1-channel bitmap that is width * height. stride_in_bytes is
  551. // the distance from one row to the next (or 0 to mean they are packed tightly
  552. // together). "padding" is the amount of padding to leave between each
  553. // character (normally you want '1' for bitmaps you'll use as textures with
  554. // bilinear filtering).
  555. //
  556. // Returns 0 on failure, 1 on success.
  557. STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc);
  558. // Cleans up the packing context and frees all memory.
  559. #define STBTT_POINT_SIZE(x) (-(x))
  560. STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size,
  561. int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range);
  562. // Creates character bitmaps from the font_index'th font found in fontdata (use
  563. // font_index=0 if you don't know what that is). It creates num_chars_in_range
  564. // bitmaps for characters with unicode values starting at first_unicode_char_in_range
  565. // and increasing. Data for how to render them is stored in chardata_for_range;
  566. // pass these to stbtt_GetPackedQuad to get back renderable quads.
  567. //
  568. // font_size is the full height of the character from ascender to descender,
  569. // as computed by stbtt_ScaleForPixelHeight. To use a point size as computed
  570. // by stbtt_ScaleForMappingEmToPixels, wrap the point size in STBTT_POINT_SIZE()
  571. // and pass that result as 'font_size':
  572. // ..., 20 , ... // font max minus min y is 20 pixels tall
  573. // ..., STBTT_POINT_SIZE(20), ... // 'M' is 20 pixels tall
  574. typedef struct
  575. {
  576. float font_size;
  577. int first_unicode_codepoint_in_range; // if non-zero, then the chars are continuous, and this is the first codepoint
  578. int *array_of_unicode_codepoints; // if non-zero, then this is an array of unicode codepoints
  579. int num_chars;
  580. stbtt_packedchar *chardata_for_range; // output
  581. unsigned char h_oversample, v_oversample; // don't set these, they're used internally
  582. } stbtt_pack_range;
  583. STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges);
  584. // Creates character bitmaps from multiple ranges of characters stored in
  585. // ranges. This will usually create a better-packed bitmap than multiple
  586. // calls to stbtt_PackFontRange. Note that you can call this multiple
  587. // times within a single PackBegin/PackEnd.
  588. STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample);
  589. // Oversampling a font increases the quality by allowing higher-quality subpixel
  590. // positioning, and is especially valuable at smaller text sizes.
  591. //
  592. // This function sets the amount of oversampling for all following calls to
  593. // stbtt_PackFontRange(s) or stbtt_PackFontRangesGatherRects for a given
  594. // pack context. The default (no oversampling) is achieved by h_oversample=1
  595. // and v_oversample=1. The total number of pixels required is
  596. // h_oversample*v_oversample larger than the default; for example, 2x2
  597. // oversampling requires 4x the storage of 1x1. For best results, render
  598. // oversampled textures with bilinear filtering. Look at the readme in
  599. // stb/tests/oversample for information about oversampled fonts
  600. //
  601. // To use with PackFontRangesGather etc., you must set it before calls
  602. // call to PackFontRangesGatherRects.
  603. STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip);
  604. // If skip != 0, this tells stb_truetype to skip any codepoints for which
  605. // there is no corresponding glyph. If skip=0, which is the default, then
  606. // codepoints without a glyph recived the font's "missing character" glyph,
  607. // typically an empty box by convention.
  608. STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above
  609. int char_index, // character to display
  610. float *xpos, float *ypos, // pointers to current position in screen pixel space
  611. stbtt_aligned_quad *q, // output: quad to draw
  612. int align_to_integer);
  613. STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects);
  614. STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects);
  615. STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects);
  616. // Calling these functions in sequence is roughly equivalent to calling
  617. // stbtt_PackFontRanges(). If you more control over the packing of multiple
  618. // fonts, or if you want to pack custom data into a font texture, take a look
  619. // at the source to of stbtt_PackFontRanges() and create a custom version
  620. // using these functions, e.g. call GatherRects multiple times,
  621. // building up a single array of rects, then call PackRects once,
  622. // then call RenderIntoRects repeatedly. This may result in a
  623. // better packing than calling PackFontRanges multiple times
  624. // (or it may not).
  625. // this is an opaque structure that you shouldn't mess with which holds
  626. // all the context needed from PackBegin to PackEnd.
  627. struct stbtt_pack_context {
  628. void *user_allocator_context;
  629. void *pack_info;
  630. int width;
  631. int height;
  632. int stride_in_bytes;
  633. int padding;
  634. int skip_missing;
  635. unsigned int h_oversample, v_oversample;
  636. unsigned char *pixels;
  637. void *nodes;
  638. };
  639. //////////////////////////////////////////////////////////////////////////////
  640. //
  641. // FONT LOADING
  642. //
  643. //
  644. STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data);
  645. // This function will determine the number of fonts in a font file. TrueType
  646. // collection (.ttc) files may contain multiple fonts, while TrueType font
  647. // (.ttf) files only contain one font. The number of fonts can be used for
  648. // indexing with the previous function where the index is between zero and one
  649. // less than the total fonts. If an error occurs, -1 is returned.
  650. STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index);
  651. // Each .ttf/.ttc file may have more than one font. Each font has a sequential
  652. // index number starting from 0. Call this function to get the font offset for
  653. // a given index; it returns -1 if the index is out of range. A regular .ttf
  654. // file will only define one font and it always be at offset 0, so it will
  655. // return '0' for index 0, and -1 for all other indices.
  656. // The following structure is defined publicly so you can declare one on
  657. // the stack or as a global or etc, but you should treat it as opaque.
  658. struct stbtt_fontinfo
  659. {
  660. void * userdata;
  661. unsigned char * data; // pointer to .ttf file
  662. int fontstart; // offset of start of font
  663. int numGlyphs; // number of glyphs, needed for range checking
  664. int loca,head,glyf,hhea,hmtx,kern,gpos,svg; // table locations as offset from start of .ttf
  665. int index_map; // a cmap mapping for our chosen character encoding
  666. int indexToLocFormat; // format needed to map from glyph index to glyph
  667. stbtt__buf cff; // cff font data
  668. stbtt__buf charstrings; // the charstring index
  669. stbtt__buf gsubrs; // global charstring subroutines index
  670. stbtt__buf subrs; // private charstring subroutines index
  671. stbtt__buf fontdicts; // array of font dicts
  672. stbtt__buf fdselect; // map from glyph to fontdict
  673. };
  674. STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset);
  675. // Given an offset into the file that defines a font, this function builds
  676. // the necessary cached info for the rest of the system. You must allocate
  677. // the stbtt_fontinfo yourself, and stbtt_InitFont will fill it out. You don't
  678. // need to do anything special to free it, because the contents are pure
  679. // value data with no additional data structures. Returns 0 on failure.
  680. //////////////////////////////////////////////////////////////////////////////
  681. //
  682. // CHARACTER TO GLYPH-INDEX CONVERSIOn
  683. STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint);
  684. // If you're going to perform multiple operations on the same character
  685. // and you want a speed-up, call this function with the character you're
  686. // going to process, then use glyph-based functions instead of the
  687. // codepoint-based functions.
  688. // Returns 0 if the character codepoint is not defined in the font.
  689. //////////////////////////////////////////////////////////////////////////////
  690. //
  691. // CHARACTER PROPERTIES
  692. //
  693. STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels);
  694. // computes a scale factor to produce a font whose "height" is 'pixels' tall.
  695. // Height is measured as the distance from the highest ascender to the lowest
  696. // descender; in other words, it's equivalent to calling stbtt_GetFontVMetrics
  697. // and computing:
  698. // scale = pixels / (ascent - descent)
  699. // so if you prefer to measure height by the ascent only, use a similar calculation.
  700. STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels);
  701. // computes a scale factor to produce a font whose EM size is mapped to
  702. // 'pixels' tall. This is probably what traditional APIs compute, but
  703. // I'm not positive.
  704. STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap);
  705. // ascent is the coordinate above the baseline the font extends; descent
  706. // is the coordinate below the baseline the font extends (i.e. it is typically negative)
  707. // lineGap is the spacing between one row's descent and the next row's ascent...
  708. // so you should advance the vertical position by "*ascent - *descent + *lineGap"
  709. // these are expressed in unscaled coordinates, so you must multiply by
  710. // the scale factor for a given size
  711. STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap);
  712. // analogous to GetFontVMetrics, but returns the "typographic" values from the OS/2
  713. // table (specific to MS/Windows TTF files).
  714. //
  715. // Returns 1 on success (table present), 0 on failure.
  716. STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1);
  717. // the bounding box around all possible characters
  718. STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing);
  719. // leftSideBearing is the offset from the current horizontal position to the left edge of the character
  720. // advanceWidth is the offset from the current horizontal position to the next horizontal position
  721. // these are expressed in unscaled coordinates
  722. STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2);
  723. // an additional amount to add to the 'advance' value between ch1 and ch2
  724. STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1);
  725. // Gets the bounding box of the visible part of the glyph, in unscaled coordinates
  726. STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing);
  727. STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2);
  728. STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1);
  729. // as above, but takes one or more glyph indices for greater efficiency
  730. typedef struct stbtt_kerningentry
  731. {
  732. int glyph1; // use stbtt_FindGlyphIndex
  733. int glyph2;
  734. int advance;
  735. } stbtt_kerningentry;
  736. STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info);
  737. STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length);
  738. // Retrieves a complete list of all of the kerning pairs provided by the font
  739. // stbtt_GetKerningTable never writes more than table_length entries and returns how many entries it did write.
  740. // The table will be sorted by (a.glyph1 == b.glyph1)?(a.glyph2 < b.glyph2):(a.glyph1 < b.glyph1)
  741. //////////////////////////////////////////////////////////////////////////////
  742. //
  743. // GLYPH SHAPES (you probably don't need these, but they have to go before
  744. // the bitmaps for C declaration-order reasons)
  745. //
  746. #ifndef STBTT_vmove // you can predefine these to use different values (but why?)
  747. enum {
  748. STBTT_vmove=1,
  749. STBTT_vline,
  750. STBTT_vcurve,
  751. STBTT_vcubic
  752. };
  753. #endif
  754. #ifndef stbtt_vertex // you can predefine this to use different values
  755. // (we share this with other code at RAD)
  756. #define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file
  757. typedef struct
  758. {
  759. stbtt_vertex_type x,y,cx,cy,cx1,cy1;
  760. unsigned char type,padding;
  761. } stbtt_vertex;
  762. #endif
  763. STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index);
  764. // returns non-zero if nothing is drawn for this glyph
  765. STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices);
  766. STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices);
  767. // returns # of vertices and fills *vertices with the pointer to them
  768. // these are expressed in "unscaled" coordinates
  769. //
  770. // The shape is a series of contours. Each one starts with
  771. // a STBTT_moveto, then consists of a series of mixed
  772. // STBTT_lineto and STBTT_curveto segments. A lineto
  773. // draws a line from previous endpoint to its x,y; a curveto
  774. // draws a quadratic bezier from previous endpoint to
  775. // its x,y, using cx,cy as the bezier control point.
  776. STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices);
  777. // frees the data allocated above
  778. STBTT_DEF unsigned char *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl);
  779. STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg);
  780. STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg);
  781. // fills svg with the character's SVG data.
  782. // returns data size or 0 if SVG not found.
  783. //////////////////////////////////////////////////////////////////////////////
  784. //
  785. // BITMAP RENDERING
  786. //
  787. STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata);
  788. // frees the bitmap allocated below
  789. STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff);
  790. // allocates a large-enough single-channel 8bpp bitmap and renders the
  791. // specified character/glyph at the specified scale into it, with
  792. // antialiasing. 0 is no coverage (transparent), 255 is fully covered (opaque).
  793. // *width & *height are filled out with the width & height of the bitmap,
  794. // which is stored left-to-right, top-to-bottom.
  795. //
  796. // xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap
  797. STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff);
  798. // the same as stbtt_GetCodepoitnBitmap, but you can specify a subpixel
  799. // shift for the character
  800. STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint);
  801. // the same as stbtt_GetCodepointBitmap, but you pass in storage for the bitmap
  802. // in the form of 'output', with row spacing of 'out_stride' bytes. the bitmap
  803. // is clipped to out_w/out_h bytes. Call stbtt_GetCodepointBitmapBox to get the
  804. // width and height and positioning info for it first.
  805. STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint);
  806. // same as stbtt_MakeCodepointBitmap, but you can specify a subpixel
  807. // shift for the character
  808. STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint);
  809. // same as stbtt_MakeCodepointBitmapSubpixel, but prefiltering
  810. // is performed (see stbtt_PackSetOversampling)
  811. STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1);
  812. // get the bbox of the bitmap centered around the glyph origin; so the
  813. // bitmap width is ix1-ix0, height is iy1-iy0, and location to place
  814. // the bitmap top left is (leftSideBearing*scale,iy0).
  815. // (Note that the bitmap uses y-increases-down, but the shape uses
  816. // y-increases-up, so CodepointBitmapBox and CodepointBox are inverted.)
  817. STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1);
  818. // same as stbtt_GetCodepointBitmapBox, but you can specify a subpixel
  819. // shift for the character
  820. // the following functions are equivalent to the above functions, but operate
  821. // on glyph indices instead of Unicode codepoints (for efficiency)
  822. STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff);
  823. STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff);
  824. STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph);
  825. STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph);
  826. STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int glyph);
  827. STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1);
  828. STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1);
  829. // @TODO: don't expose this structure
  830. typedef struct
  831. {
  832. int w,h,stride;
  833. unsigned char *pixels;
  834. } stbtt__bitmap;
  835. // rasterize a shape with quadratic beziers into a bitmap
  836. STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, // 1-channel bitmap to draw into
  837. float flatness_in_pixels, // allowable error of curve in pixels
  838. stbtt_vertex *vertices, // array of vertices defining shape
  839. int num_verts, // number of vertices in above array
  840. float scale_x, float scale_y, // scale applied to input vertices
  841. float shift_x, float shift_y, // translation applied to input vertices
  842. int x_off, int y_off, // another translation applied to input
  843. int invert, // if non-zero, vertically flip shape
  844. void *userdata); // context for to STBTT_MALLOC
  845. //////////////////////////////////////////////////////////////////////////////
  846. //
  847. // Signed Distance Function (or Field) rendering
  848. STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata);
  849. // frees the SDF bitmap allocated below
  850. STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff);
  851. STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff);
  852. // These functions compute a discretized SDF field for a single character, suitable for storing
  853. // in a single-channel texture, sampling with bilinear filtering, and testing against
  854. // larger than some threshold to produce scalable fonts.
  855. // info -- the font
  856. // scale -- controls the size of the resulting SDF bitmap, same as it would be creating a regular bitmap
  857. // glyph/codepoint -- the character to generate the SDF for
  858. // padding -- extra "pixels" around the character which are filled with the distance to the character (not 0),
  859. // which allows effects like bit outlines
  860. // onedge_value -- value 0-255 to test the SDF against to reconstruct the character (i.e. the isocontour of the character)
  861. // pixel_dist_scale -- what value the SDF should increase by when moving one SDF "pixel" away from the edge (on the 0..255 scale)
  862. // if positive, > onedge_value is inside; if negative, < onedge_value is inside
  863. // width,height -- output height & width of the SDF bitmap (including padding)
  864. // xoff,yoff -- output origin of the character
  865. // return value -- a 2D array of bytes 0..255, width*height in size
  866. //
  867. // pixel_dist_scale & onedge_value are a scale & bias that allows you to make
  868. // optimal use of the limited 0..255 for your application, trading off precision
  869. // and special effects. SDF values outside the range 0..255 are clamped to 0..255.
  870. //
  871. // Example:
  872. // scale = stbtt_ScaleForPixelHeight(22)
  873. // padding = 5
  874. // onedge_value = 180
  875. // pixel_dist_scale = 180/5.0 = 36.0
  876. //
  877. // This will create an SDF bitmap in which the character is about 22 pixels
  878. // high but the whole bitmap is about 22+5+5=32 pixels high. To produce a filled
  879. // shape, sample the SDF at each pixel and fill the pixel if the SDF value
  880. // is greater than or equal to 180/255. (You'll actually want to antialias,
  881. // which is beyond the scope of this example.) Additionally, you can compute
  882. // offset outlines (e.g. to stroke the character border inside & outside,
  883. // or only outside). For example, to fill outside the character up to 3 SDF
  884. // pixels, you would compare against (180-36.0*3)/255 = 72/255. The above
  885. // choice of variables maps a range from 5 pixels outside the shape to
  886. // 2 pixels inside the shape to 0..255; this is intended primarily for apply
  887. // outside effects only (the interior range is needed to allow proper
  888. // antialiasing of the font at *smaller* sizes)
  889. //
  890. // The function computes the SDF analytically at each SDF pixel, not by e.g.
  891. // building a higher-res bitmap and approximating it. In theory the quality
  892. // should be as high as possible for an SDF of this size & representation, but
  893. // unclear if this is true in practice (perhaps building a higher-res bitmap
  894. // and computing from that can allow drop-out prevention).
  895. //
  896. // The algorithm has not been optimized at all, so expect it to be slow
  897. // if computing lots of characters or very large sizes.
  898. //////////////////////////////////////////////////////////////////////////////
  899. //
  900. // Finding the right font...
  901. //
  902. // You should really just solve this offline, keep your own tables
  903. // of what font is what, and don't try to get it out of the .ttf file.
  904. // That's because getting it out of the .ttf file is really hard, because
  905. // the names in the file can appear in many possible encodings, in many
  906. // possible languages, and e.g. if you need a case-insensitive comparison,
  907. // the details of that depend on the encoding & language in a complex way
  908. // (actually underspecified in truetype, but also gigantic).
  909. //
  910. // But you can use the provided functions in two possible ways:
  911. // stbtt_FindMatchingFont() will use *case-sensitive* comparisons on
  912. // unicode-encoded names to try to find the font you want;
  913. // you can run this before calling stbtt_InitFont()
  914. //
  915. // stbtt_GetFontNameString() lets you get any of the various strings
  916. // from the file yourself and do your own comparisons on them.
  917. // You have to have called stbtt_InitFont() first.
  918. STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags);
  919. // returns the offset (not index) of the font that matches, or -1 if none
  920. // if you use STBTT_MACSTYLE_DONTCARE, use a font name like "Arial Bold".
  921. // if you use any other flag, use a font name like "Arial"; this checks
  922. // the 'macStyle' header field; i don't know if fonts set this consistently
  923. #define STBTT_MACSTYLE_DONTCARE 0
  924. #define STBTT_MACSTYLE_BOLD 1
  925. #define STBTT_MACSTYLE_ITALIC 2
  926. #define STBTT_MACSTYLE_UNDERSCORE 4
  927. #define STBTT_MACSTYLE_NONE 8 // <= not same as 0, this makes us check the bitfield is 0
  928. STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2);
  929. // returns 1/0 whether the first string interpreted as utf8 is identical to
  930. // the second string interpreted as big-endian utf16... useful for strings from next func
  931. STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID);
  932. // returns the string (which may be big-endian double byte, e.g. for unicode)
  933. // and puts the length in bytes in *length.
  934. //
  935. // some of the values for the IDs are below; for more see the truetype spec:
  936. // http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html
  937. // http://www.microsoft.com/typography/otspec/name.htm
  938. enum { // platformID
  939. STBTT_PLATFORM_ID_UNICODE =0,
  940. STBTT_PLATFORM_ID_MAC =1,
  941. STBTT_PLATFORM_ID_ISO =2,
  942. STBTT_PLATFORM_ID_MICROSOFT =3
  943. };
  944. enum { // encodingID for STBTT_PLATFORM_ID_UNICODE
  945. STBTT_UNICODE_EID_UNICODE_1_0 =0,
  946. STBTT_UNICODE_EID_UNICODE_1_1 =1,
  947. STBTT_UNICODE_EID_ISO_10646 =2,
  948. STBTT_UNICODE_EID_UNICODE_2_0_BMP=3,
  949. STBTT_UNICODE_EID_UNICODE_2_0_FULL=4
  950. };
  951. enum { // encodingID for STBTT_PLATFORM_ID_MICROSOFT
  952. STBTT_MS_EID_SYMBOL =0,
  953. STBTT_MS_EID_UNICODE_BMP =1,
  954. STBTT_MS_EID_SHIFTJIS =2,
  955. STBTT_MS_EID_UNICODE_FULL =10
  956. };
  957. enum { // encodingID for STBTT_PLATFORM_ID_MAC; same as Script Manager codes
  958. STBTT_MAC_EID_ROMAN =0, STBTT_MAC_EID_ARABIC =4,
  959. STBTT_MAC_EID_JAPANESE =1, STBTT_MAC_EID_HEBREW =5,
  960. STBTT_MAC_EID_CHINESE_TRAD =2, STBTT_MAC_EID_GREEK =6,
  961. STBTT_MAC_EID_KOREAN =3, STBTT_MAC_EID_RUSSIAN =7
  962. };
  963. enum { // languageID for STBTT_PLATFORM_ID_MICROSOFT; same as LCID...
  964. // problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs
  965. STBTT_MS_LANG_ENGLISH =0x0409, STBTT_MS_LANG_ITALIAN =0x0410,
  966. STBTT_MS_LANG_CHINESE =0x0804, STBTT_MS_LANG_JAPANESE =0x0411,
  967. STBTT_MS_LANG_DUTCH =0x0413, STBTT_MS_LANG_KOREAN =0x0412,
  968. STBTT_MS_LANG_FRENCH =0x040c, STBTT_MS_LANG_RUSSIAN =0x0419,
  969. STBTT_MS_LANG_GERMAN =0x0407, STBTT_MS_LANG_SPANISH =0x0409,
  970. STBTT_MS_LANG_HEBREW =0x040d, STBTT_MS_LANG_SWEDISH =0x041D
  971. };
  972. enum { // languageID for STBTT_PLATFORM_ID_MAC
  973. STBTT_MAC_LANG_ENGLISH =0 , STBTT_MAC_LANG_JAPANESE =11,
  974. STBTT_MAC_LANG_ARABIC =12, STBTT_MAC_LANG_KOREAN =23,
  975. STBTT_MAC_LANG_DUTCH =4 , STBTT_MAC_LANG_RUSSIAN =32,
  976. STBTT_MAC_LANG_FRENCH =1 , STBTT_MAC_LANG_SPANISH =6 ,
  977. STBTT_MAC_LANG_GERMAN =2 , STBTT_MAC_LANG_SWEDISH =5 ,
  978. STBTT_MAC_LANG_HEBREW =10, STBTT_MAC_LANG_CHINESE_SIMPLIFIED =33,
  979. STBTT_MAC_LANG_ITALIAN =3 , STBTT_MAC_LANG_CHINESE_TRAD =19
  980. };
  981. #ifdef __cplusplus
  982. }
  983. #endif
  984. #endif // __STB_INCLUDE_STB_TRUETYPE_H__
  985. ///////////////////////////////////////////////////////////////////////////////
  986. ///////////////////////////////////////////////////////////////////////////////
  987. ////
  988. //// IMPLEMENTATION
  989. ////
  990. ////
  991. #ifdef STB_TRUETYPE_IMPLEMENTATION
  992. #ifndef STBTT_MAX_OVERSAMPLE
  993. #define STBTT_MAX_OVERSAMPLE 8
  994. #endif
  995. #if STBTT_MAX_OVERSAMPLE > 255
  996. #error "STBTT_MAX_OVERSAMPLE cannot be > 255"
  997. #endif
  998. typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE-1)) == 0 ? 1 : -1];
  999. #ifndef STBTT_RASTERIZER_VERSION
  1000. #define STBTT_RASTERIZER_VERSION 2
  1001. #endif
  1002. #ifdef _MSC_VER
  1003. #define STBTT__NOTUSED(v) (void)(v)
  1004. #else
  1005. #define STBTT__NOTUSED(v) (void)sizeof(v)
  1006. #endif
  1007. //////////////////////////////////////////////////////////////////////////
  1008. //
  1009. // stbtt__buf helpers to parse data from file
  1010. //
  1011. static stbtt_uint8 stbtt__buf_get8(stbtt__buf *b)
  1012. {
  1013. if (b->cursor >= b->size)
  1014. return 0;
  1015. return b->data[b->cursor++];
  1016. }
  1017. static stbtt_uint8 stbtt__buf_peek8(stbtt__buf *b)
  1018. {
  1019. if (b->cursor >= b->size)
  1020. return 0;
  1021. return b->data[b->cursor];
  1022. }
  1023. static void stbtt__buf_seek(stbtt__buf *b, int o)
  1024. {
  1025. STBTT_assert(!(o > b->size || o < 0));
  1026. b->cursor = (o > b->size || o < 0) ? b->size : o;
  1027. }
  1028. static void stbtt__buf_skip(stbtt__buf *b, int o)
  1029. {
  1030. stbtt__buf_seek(b, b->cursor + o);
  1031. }
  1032. static stbtt_uint32 stbtt__buf_get(stbtt__buf *b, int n)
  1033. {
  1034. stbtt_uint32 v = 0;
  1035. int i;
  1036. STBTT_assert(n >= 1 && n <= 4);
  1037. for (i = 0; i < n; i++)
  1038. v = (v << 8) | stbtt__buf_get8(b);
  1039. return v;
  1040. }
  1041. static stbtt__buf stbtt__new_buf(const void *p, size_t size)
  1042. {
  1043. stbtt__buf r;
  1044. STBTT_assert(size < 0x40000000);
  1045. r.data = (stbtt_uint8*) p;
  1046. r.size = (int) size;
  1047. r.cursor = 0;
  1048. return r;
  1049. }
  1050. #define stbtt__buf_get16(b) stbtt__buf_get((b), 2)
  1051. #define stbtt__buf_get32(b) stbtt__buf_get((b), 4)
  1052. static stbtt__buf stbtt__buf_range(const stbtt__buf *b, int o, int s)
  1053. {
  1054. stbtt__buf r = stbtt__new_buf(NULL, 0);
  1055. if (o < 0 || s < 0 || o > b->size || s > b->size - o) return r;
  1056. r.data = b->data + o;
  1057. r.size = s;
  1058. return r;
  1059. }
  1060. static stbtt__buf stbtt__cff_get_index(stbtt__buf *b)
  1061. {
  1062. int count, start, offsize;
  1063. start = b->cursor;
  1064. count = stbtt__buf_get16(b);
  1065. if (count) {
  1066. offsize = stbtt__buf_get8(b);
  1067. STBTT_assert(offsize >= 1 && offsize <= 4);
  1068. stbtt__buf_skip(b, offsize * count);
  1069. stbtt__buf_skip(b, stbtt__buf_get(b, offsize) - 1);
  1070. }
  1071. return stbtt__buf_range(b, start, b->cursor - start);
  1072. }
  1073. static stbtt_uint32 stbtt__cff_int(stbtt__buf *b)
  1074. {
  1075. int b0 = stbtt__buf_get8(b);
  1076. if (b0 >= 32 && b0 <= 246) return b0 - 139;
  1077. else if (b0 >= 247 && b0 <= 250) return (b0 - 247)*256 + stbtt__buf_get8(b) + 108;
  1078. else if (b0 >= 251 && b0 <= 254) return -(b0 - 251)*256 - stbtt__buf_get8(b) - 108;
  1079. else if (b0 == 28) return stbtt__buf_get16(b);
  1080. else if (b0 == 29) return stbtt__buf_get32(b);
  1081. STBTT_assert(0);
  1082. return 0;
  1083. }
  1084. static void stbtt__cff_skip_operand(stbtt__buf *b) {
  1085. int v, b0 = stbtt__buf_peek8(b);
  1086. STBTT_assert(b0 >= 28);
  1087. if (b0 == 30) {
  1088. stbtt__buf_skip(b, 1);
  1089. while (b->cursor < b->size) {
  1090. v = stbtt__buf_get8(b);
  1091. if ((v & 0xF) == 0xF || (v >> 4) == 0xF)
  1092. break;
  1093. }
  1094. } else {
  1095. stbtt__cff_int(b);
  1096. }
  1097. }
  1098. static stbtt__buf stbtt__dict_get(stbtt__buf *b, int key)
  1099. {
  1100. stbtt__buf_seek(b, 0);
  1101. while (b->cursor < b->size) {
  1102. int start = b->cursor, end, op;
  1103. while (stbtt__buf_peek8(b) >= 28)
  1104. stbtt__cff_skip_operand(b);
  1105. end = b->cursor;
  1106. op = stbtt__buf_get8(b);
  1107. if (op == 12) op = stbtt__buf_get8(b) | 0x100;
  1108. if (op == key) return stbtt__buf_range(b, start, end-start);
  1109. }
  1110. return stbtt__buf_range(b, 0, 0);
  1111. }
  1112. static void stbtt__dict_get_ints(stbtt__buf *b, int key, int outcount, stbtt_uint32 *out)
  1113. {
  1114. int i;
  1115. stbtt__buf operands = stbtt__dict_get(b, key);
  1116. for (i = 0; i < outcount && operands.cursor < operands.size; i++)
  1117. out[i] = stbtt__cff_int(&operands);
  1118. }
  1119. static int stbtt__cff_index_count(stbtt__buf *b)
  1120. {
  1121. stbtt__buf_seek(b, 0);
  1122. return stbtt__buf_get16(b);
  1123. }
  1124. static stbtt__buf stbtt__cff_index_get(stbtt__buf b, int i)
  1125. {
  1126. int count, offsize, start, end;
  1127. stbtt__buf_seek(&b, 0);
  1128. count = stbtt__buf_get16(&b);
  1129. offsize = stbtt__buf_get8(&b);
  1130. STBTT_assert(i >= 0 && i < count);
  1131. STBTT_assert(offsize >= 1 && offsize <= 4);
  1132. stbtt__buf_skip(&b, i*offsize);
  1133. start = stbtt__buf_get(&b, offsize);
  1134. end = stbtt__buf_get(&b, offsize);
  1135. return stbtt__buf_range(&b, 2+(count+1)*offsize+start, end - start);
  1136. }
  1137. //////////////////////////////////////////////////////////////////////////
  1138. //
  1139. // accessors to parse data from file
  1140. //
  1141. // on platforms that don't allow misaligned reads, if we want to allow
  1142. // truetype fonts that aren't padded to alignment, define ALLOW_UNALIGNED_TRUETYPE
  1143. #define ttBYTE(p) (* (stbtt_uint8 *) (p))
  1144. #define ttCHAR(p) (* (stbtt_int8 *) (p))
  1145. #define ttFixed(p) ttLONG(p)
  1146. static stbtt_uint16 ttUSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; }
  1147. static stbtt_int16 ttSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; }
  1148. static stbtt_uint32 ttULONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }
  1149. static stbtt_int32 ttLONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }
  1150. #define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3))
  1151. #define stbtt_tag(p,str) stbtt_tag4(p,str[0],str[1],str[2],str[3])
  1152. static int stbtt__isfont(stbtt_uint8 *font)
  1153. {
  1154. // check the version number
  1155. if (stbtt_tag4(font, '1',0,0,0)) return 1; // TrueType 1
  1156. if (stbtt_tag(font, "typ1")) return 1; // TrueType with type 1 font -- we don't support this!
  1157. if (stbtt_tag(font, "OTTO")) return 1; // OpenType with CFF
  1158. if (stbtt_tag4(font, 0,1,0,0)) return 1; // OpenType 1.0
  1159. if (stbtt_tag(font, "true")) return 1; // Apple specification for TrueType fonts
  1160. return 0;
  1161. }
  1162. // @OPTIMIZE: binary search
  1163. static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, const char *tag)
  1164. {
  1165. stbtt_int32 num_tables = ttUSHORT(data+fontstart+4);
  1166. stbtt_uint32 tabledir = fontstart + 12;
  1167. stbtt_int32 i;
  1168. for (i=0; i < num_tables; ++i) {
  1169. stbtt_uint32 loc = tabledir + 16*i;
  1170. if (stbtt_tag(data+loc+0, tag))
  1171. return ttULONG(data+loc+8);
  1172. }
  1173. return 0;
  1174. }
  1175. static int stbtt_GetFontOffsetForIndex_internal(unsigned char *font_collection, int index)
  1176. {
  1177. // if it's just a font, there's only one valid index
  1178. if (stbtt__isfont(font_collection))
  1179. return index == 0 ? 0 : -1;
  1180. // check if it's a TTC
  1181. if (stbtt_tag(font_collection, "ttcf")) {
  1182. // version 1?
  1183. if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) {
  1184. stbtt_int32 n = ttLONG(font_collection+8);
  1185. if (index >= n)
  1186. return -1;
  1187. return ttULONG(font_collection+12+index*4);
  1188. }
  1189. }
  1190. return -1;
  1191. }
  1192. static int stbtt_GetNumberOfFonts_internal(unsigned char *font_collection)
  1193. {
  1194. // if it's just a font, there's only one valid font
  1195. if (stbtt__isfont(font_collection))
  1196. return 1;
  1197. // check if it's a TTC
  1198. if (stbtt_tag(font_collection, "ttcf")) {
  1199. // version 1?
  1200. if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) {
  1201. return ttLONG(font_collection+8);
  1202. }
  1203. }
  1204. return 0;
  1205. }
  1206. static stbtt__buf stbtt__get_subrs(stbtt__buf cff, stbtt__buf fontdict)
  1207. {
  1208. stbtt_uint32 subrsoff = 0, private_loc[2] = { 0, 0 };
  1209. stbtt__buf pdict;
  1210. stbtt__dict_get_ints(&fontdict, 18, 2, private_loc);
  1211. if (!private_loc[1] || !private_loc[0]) return stbtt__new_buf(NULL, 0);
  1212. pdict = stbtt__buf_range(&cff, private_loc[1], private_loc[0]);
  1213. stbtt__dict_get_ints(&pdict, 19, 1, &subrsoff);
  1214. if (!subrsoff) return stbtt__new_buf(NULL, 0);
  1215. stbtt__buf_seek(&cff, private_loc[1]+subrsoff);
  1216. return stbtt__cff_get_index(&cff);
  1217. }
  1218. // since most people won't use this, find this table the first time it's needed
  1219. static int stbtt__get_svg(stbtt_fontinfo *info)
  1220. {
  1221. stbtt_uint32 t;
  1222. if (info->svg < 0) {
  1223. t = stbtt__find_table(info->data, info->fontstart, "SVG ");
  1224. if (t) {
  1225. stbtt_uint32 offset = ttULONG(info->data + t + 2);
  1226. info->svg = t + offset;
  1227. } else {
  1228. info->svg = 0;
  1229. }
  1230. }
  1231. return info->svg;
  1232. }
  1233. static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart)
  1234. {
  1235. stbtt_uint32 cmap, t;
  1236. stbtt_int32 i,numTables;
  1237. info->data = data;
  1238. info->fontstart = fontstart;
  1239. info->cff = stbtt__new_buf(NULL, 0);
  1240. cmap = stbtt__find_table(data, fontstart, "cmap"); // required
  1241. info->loca = stbtt__find_table(data, fontstart, "loca"); // required
  1242. info->head = stbtt__find_table(data, fontstart, "head"); // required
  1243. info->glyf = stbtt__find_table(data, fontstart, "glyf"); // required
  1244. info->hhea = stbtt__find_table(data, fontstart, "hhea"); // required
  1245. info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); // required
  1246. info->kern = stbtt__find_table(data, fontstart, "kern"); // not required
  1247. info->gpos = stbtt__find_table(data, fontstart, "GPOS"); // not required
  1248. if (!cmap || !info->head || !info->hhea || !info->hmtx)
  1249. return 0;
  1250. if (info->glyf) {
  1251. // required for truetype
  1252. if (!info->loca) return 0;
  1253. } else {
  1254. // initialization for CFF / Type2 fonts (OTF)
  1255. stbtt__buf b, topdict, topdictidx;
  1256. stbtt_uint32 cstype = 2, charstrings = 0, fdarrayoff = 0, fdselectoff = 0;
  1257. stbtt_uint32 cff;
  1258. cff = stbtt__find_table(data, fontstart, "CFF ");
  1259. if (!cff) return 0;
  1260. info->fontdicts = stbtt__new_buf(NULL, 0);
  1261. info->fdselect = stbtt__new_buf(NULL, 0);
  1262. // @TODO this should use size from table (not 512MB)
  1263. info->cff = stbtt__new_buf(data+cff, 512*1024*1024);
  1264. b = info->cff;
  1265. // read the header
  1266. stbtt__buf_skip(&b, 2);
  1267. stbtt__buf_seek(&b, stbtt__buf_get8(&b)); // hdrsize
  1268. // @TODO the name INDEX could list multiple fonts,
  1269. // but we just use the first one.
  1270. stbtt__cff_get_index(&b); // name INDEX
  1271. topdictidx = stbtt__cff_get_index(&b);
  1272. topdict = stbtt__cff_index_get(topdictidx, 0);
  1273. stbtt__cff_get_index(&b); // string INDEX
  1274. info->gsubrs = stbtt__cff_get_index(&b);
  1275. stbtt__dict_get_ints(&topdict, 17, 1, &charstrings);
  1276. stbtt__dict_get_ints(&topdict, 0x100 | 6, 1, &cstype);
  1277. stbtt__dict_get_ints(&topdict, 0x100 | 36, 1, &fdarrayoff);
  1278. stbtt__dict_get_ints(&topdict, 0x100 | 37, 1, &fdselectoff);
  1279. info->subrs = stbtt__get_subrs(b, topdict);
  1280. // we only support Type 2 charstrings
  1281. if (cstype != 2) return 0;
  1282. if (charstrings == 0) return 0;
  1283. if (fdarrayoff) {
  1284. // looks like a CID font
  1285. if (!fdselectoff) return 0;
  1286. stbtt__buf_seek(&b, fdarrayoff);
  1287. info->fontdicts = stbtt__cff_get_index(&b);
  1288. info->fdselect = stbtt__buf_range(&b, fdselectoff, b.size-fdselectoff);
  1289. }
  1290. stbtt__buf_seek(&b, charstrings);
  1291. info->charstrings = stbtt__cff_get_index(&b);
  1292. }
  1293. t = stbtt__find_table(data, fontstart, "maxp");
  1294. if (t)
  1295. info->numGlyphs = ttUSHORT(data+t+4);
  1296. else
  1297. info->numGlyphs = 0xffff;
  1298. info->svg = -1;
  1299. // find a cmap encoding table we understand *now* to avoid searching
  1300. // later. (todo: could make this installable)
  1301. // the same regardless of glyph.
  1302. numTables = ttUSHORT(data + cmap + 2);
  1303. info->index_map = 0;
  1304. for (i=0; i < numTables; ++i) {
  1305. stbtt_uint32 encoding_record = cmap + 4 + 8 * i;
  1306. // find an encoding we understand:
  1307. switch(ttUSHORT(data+encoding_record)) {
  1308. case STBTT_PLATFORM_ID_MICROSOFT:
  1309. switch (ttUSHORT(data+encoding_record+2)) {
  1310. case STBTT_MS_EID_UNICODE_BMP:
  1311. case STBTT_MS_EID_UNICODE_FULL:
  1312. // MS/Unicode
  1313. info->index_map = cmap + ttULONG(data+encoding_record+4);
  1314. break;
  1315. }
  1316. break;
  1317. case STBTT_PLATFORM_ID_UNICODE:
  1318. // Mac/iOS has these
  1319. // all the encodingIDs are unicode, so we don't bother to check it
  1320. info->index_map = cmap + ttULONG(data+encoding_record+4);
  1321. break;
  1322. }
  1323. }
  1324. if (info->index_map == 0)
  1325. return 0;
  1326. info->indexToLocFormat = ttUSHORT(data+info->head + 50);
  1327. return 1;
  1328. }
  1329. STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint)
  1330. {
  1331. stbtt_uint8 *data = info->data;
  1332. stbtt_uint32 index_map = info->index_map;
  1333. stbtt_uint16 format = ttUSHORT(data + index_map + 0);
  1334. if (format == 0) { // apple byte encoding
  1335. stbtt_int32 bytes = ttUSHORT(data + index_map + 2);
  1336. if (unicode_codepoint < bytes-6)
  1337. return ttBYTE(data + index_map + 6 + unicode_codepoint);
  1338. return 0;
  1339. } else if (format == 6) {
  1340. stbtt_uint32 first = ttUSHORT(data + index_map + 6);
  1341. stbtt_uint32 count = ttUSHORT(data + index_map + 8);
  1342. if ((stbtt_uint32) unicode_codepoint >= first && (stbtt_uint32) unicode_codepoint < first+count)
  1343. return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first)*2);
  1344. return 0;
  1345. } else if (format == 2) {
  1346. STBTT_assert(0); // @TODO: high-byte mapping for japanese/chinese/korean
  1347. return 0;
  1348. } else if (format == 4) { // standard mapping for windows fonts: binary search collection of ranges
  1349. stbtt_uint16 segcount = ttUSHORT(data+index_map+6) >> 1;
  1350. stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1;
  1351. stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10);
  1352. stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1;
  1353. // do a binary search of the segments
  1354. stbtt_uint32 endCount = index_map + 14;
  1355. stbtt_uint32 search = endCount;
  1356. if (unicode_codepoint > 0xffff)
  1357. return 0;
  1358. // they lie from endCount .. endCount + segCount
  1359. // but searchRange is the nearest power of two, so...
  1360. if (unicode_codepoint >= ttUSHORT(data + search + rangeShift*2))
  1361. search += rangeShift*2;
  1362. // now decrement to bias correctly to find smallest
  1363. search -= 2;
  1364. while (entrySelector) {
  1365. stbtt_uint16 end;
  1366. searchRange >>= 1;
  1367. end = ttUSHORT(data + search + searchRange*2);
  1368. if (unicode_codepoint > end)
  1369. search += searchRange*2;
  1370. --entrySelector;
  1371. }
  1372. search += 2;
  1373. {
  1374. stbtt_uint16 offset, start, last;
  1375. stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1);
  1376. start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);
  1377. last = ttUSHORT(data + endCount + 2*item);
  1378. if (unicode_codepoint < start || unicode_codepoint > last)
  1379. return 0;
  1380. offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item);
  1381. if (offset == 0)
  1382. return (stbtt_uint16) (unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item));
  1383. return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item);
  1384. }
  1385. } else if (format == 12 || format == 13) {
  1386. stbtt_uint32 ngroups = ttULONG(data+index_map+12);
  1387. stbtt_int32 low,high;
  1388. low = 0; high = (stbtt_int32)ngroups;
  1389. // Binary search the right group.
  1390. while (low < high) {
  1391. stbtt_int32 mid = low + ((high-low) >> 1); // rounds down, so low <= mid < high
  1392. stbtt_uint32 start_char = ttULONG(data+index_map+16+mid*12);
  1393. stbtt_uint32 end_char = ttULONG(data+index_map+16+mid*12+4);
  1394. if ((stbtt_uint32) unicode_codepoint < start_char)
  1395. high = mid;
  1396. else if ((stbtt_uint32) unicode_codepoint > end_char)
  1397. low = mid+1;
  1398. else {
  1399. stbtt_uint32 start_glyph = ttULONG(data+index_map+16+mid*12+8);
  1400. if (format == 12)
  1401. return start_glyph + unicode_codepoint-start_char;
  1402. else // format == 13
  1403. return start_glyph;
  1404. }
  1405. }
  1406. return 0; // not found
  1407. }
  1408. // @TODO
  1409. STBTT_assert(0);
  1410. return 0;
  1411. }
  1412. STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices)
  1413. {
  1414. return stbtt_GetGlyphShape(info, stbtt_FindGlyphIndex(info, unicode_codepoint), vertices);
  1415. }
  1416. static void stbtt_setvertex(stbtt_vertex *v, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy)
  1417. {
  1418. v->type = type;
  1419. v->x = (stbtt_int16) x;
  1420. v->y = (stbtt_int16) y;
  1421. v->cx = (stbtt_int16) cx;
  1422. v->cy = (stbtt_int16) cy;
  1423. }
  1424. static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index)
  1425. {
  1426. int g1,g2;
  1427. STBTT_assert(!info->cff.size);
  1428. if (glyph_index >= info->numGlyphs) return -1; // glyph index out of range
  1429. if (info->indexToLocFormat >= 2) return -1; // unknown index->glyph map format
  1430. if (info->indexToLocFormat == 0) {
  1431. g1 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2) * 2;
  1432. g2 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2;
  1433. } else {
  1434. g1 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4);
  1435. g2 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4 + 4);
  1436. }
  1437. return g1==g2 ? -1 : g1; // if length is 0, return -1
  1438. }
  1439. static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1);
  1440. STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1)
  1441. {
  1442. if (info->cff.size) {
  1443. stbtt__GetGlyphInfoT2(info, glyph_index, x0, y0, x1, y1);
  1444. } else {
  1445. int g = stbtt__GetGlyfOffset(info, glyph_index);
  1446. if (g < 0) return 0;
  1447. if (x0) *x0 = ttSHORT(info->data + g + 2);
  1448. if (y0) *y0 = ttSHORT(info->data + g + 4);
  1449. if (x1) *x1 = ttSHORT(info->data + g + 6);
  1450. if (y1) *y1 = ttSHORT(info->data + g + 8);
  1451. }
  1452. return 1;
  1453. }
  1454. STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1)
  1455. {
  1456. return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info,codepoint), x0,y0,x1,y1);
  1457. }
  1458. STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index)
  1459. {
  1460. stbtt_int16 numberOfContours;
  1461. int g;
  1462. if (info->cff.size)
  1463. return stbtt__GetGlyphInfoT2(info, glyph_index, NULL, NULL, NULL, NULL) == 0;
  1464. g = stbtt__GetGlyfOffset(info, glyph_index);
  1465. if (g < 0) return 1;
  1466. numberOfContours = ttSHORT(info->data + g);
  1467. return numberOfContours == 0;
  1468. }
  1469. static int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, int was_off, int start_off,
  1470. stbtt_int32 sx, stbtt_int32 sy, stbtt_int32 scx, stbtt_int32 scy, stbtt_int32 cx, stbtt_int32 cy)
  1471. {
  1472. if (start_off) {
  1473. if (was_off)
  1474. stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy);
  1475. stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, sx,sy,scx,scy);
  1476. } else {
  1477. if (was_off)
  1478. stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve,sx,sy,cx,cy);
  1479. else
  1480. stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0);
  1481. }
  1482. return num_vertices;
  1483. }
  1484. static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
  1485. {
  1486. stbtt_int16 numberOfContours;
  1487. stbtt_uint8 *endPtsOfContours;
  1488. stbtt_uint8 *data = info->data;
  1489. stbtt_vertex *vertices=0;
  1490. int num_vertices=0;
  1491. int g = stbtt__GetGlyfOffset(info, glyph_index);
  1492. *pvertices = NULL;
  1493. if (g < 0) return 0;
  1494. numberOfContours = ttSHORT(data + g);
  1495. if (numberOfContours > 0) {
  1496. stbtt_uint8 flags=0,flagcount;
  1497. stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0;
  1498. stbtt_int32 x,y,cx,cy,sx,sy, scx,scy;
  1499. stbtt_uint8 *points;
  1500. endPtsOfContours = (data + g + 10);
  1501. ins = ttUSHORT(data + g + 10 + numberOfContours * 2);
  1502. points = data + g + 10 + numberOfContours * 2 + 2 + ins;
  1503. n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2);
  1504. m = n + 2*numberOfContours; // a loose bound on how many vertices we might need
  1505. vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]), info->userdata);
  1506. if (vertices == 0)
  1507. return 0;
  1508. next_move = 0;
  1509. flagcount=0;
  1510. // in first pass, we load uninterpreted data into the allocated array
  1511. // above, shifted to the end of the array so we won't overwrite it when
  1512. // we create our final data starting from the front
  1513. off = m - n; // starting offset for uninterpreted data, regardless of how m ends up being calculated
  1514. // first load flags
  1515. for (i=0; i < n; ++i) {
  1516. if (flagcount == 0) {
  1517. flags = *points++;
  1518. if (flags & 8)
  1519. flagcount = *points++;
  1520. } else
  1521. --flagcount;
  1522. vertices[off+i].type = flags;
  1523. }
  1524. // now load x coordinates
  1525. x=0;
  1526. for (i=0; i < n; ++i) {
  1527. flags = vertices[off+i].type;
  1528. if (flags & 2) {
  1529. stbtt_int16 dx = *points++;
  1530. x += (flags & 16) ? dx : -dx; // ???
  1531. } else {
  1532. if (!(flags & 16)) {
  1533. x = x + (stbtt_int16) (points[0]*256 + points[1]);
  1534. points += 2;
  1535. }
  1536. }
  1537. vertices[off+i].x = (stbtt_int16) x;
  1538. }
  1539. // now load y coordinates
  1540. y=0;
  1541. for (i=0; i < n; ++i) {
  1542. flags = vertices[off+i].type;
  1543. if (flags & 4) {
  1544. stbtt_int16 dy = *points++;
  1545. y += (flags & 32) ? dy : -dy; // ???
  1546. } else {
  1547. if (!(flags & 32)) {
  1548. y = y + (stbtt_int16) (points[0]*256 + points[1]);
  1549. points += 2;
  1550. }
  1551. }
  1552. vertices[off+i].y = (stbtt_int16) y;
  1553. }
  1554. // now convert them to our format
  1555. num_vertices=0;
  1556. sx = sy = cx = cy = scx = scy = 0;
  1557. for (i=0; i < n; ++i) {
  1558. flags = vertices[off+i].type;
  1559. x = (stbtt_int16) vertices[off+i].x;
  1560. y = (stbtt_int16) vertices[off+i].y;
  1561. if (next_move == i) {
  1562. if (i != 0)
  1563. num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
  1564. // now start the new one
  1565. start_off = !(flags & 1);
  1566. if (start_off) {
  1567. // if we start off with an off-curve point, then when we need to find a point on the curve
  1568. // where we can start, and we need to save some state for when we wraparound.
  1569. scx = x;
  1570. scy = y;
  1571. if (!(vertices[off+i+1].type & 1)) {
  1572. // next point is also a curve point, so interpolate an on-point curve
  1573. sx = (x + (stbtt_int32) vertices[off+i+1].x) >> 1;
  1574. sy = (y + (stbtt_int32) vertices[off+i+1].y) >> 1;
  1575. } else {
  1576. // otherwise just use the next point as our start point
  1577. sx = (stbtt_int32) vertices[off+i+1].x;
  1578. sy = (stbtt_int32) vertices[off+i+1].y;
  1579. ++i; // we're using point i+1 as the starting point, so skip it
  1580. }
  1581. } else {
  1582. sx = x;
  1583. sy = y;
  1584. }
  1585. stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove,sx,sy,0,0);
  1586. was_off = 0;
  1587. next_move = 1 + ttUSHORT(endPtsOfContours+j*2);
  1588. ++j;
  1589. } else {
  1590. if (!(flags & 1)) { // if it's a curve
  1591. if (was_off) // two off-curve control points in a row means interpolate an on-curve midpoint
  1592. stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy);
  1593. cx = x;
  1594. cy = y;
  1595. was_off = 1;
  1596. } else {
  1597. if (was_off)
  1598. stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, x,y, cx, cy);
  1599. else
  1600. stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, x,y,0,0);
  1601. was_off = 0;
  1602. }
  1603. }
  1604. }
  1605. num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
  1606. } else if (numberOfContours < 0) {
  1607. // Compound shapes.
  1608. int more = 1;
  1609. stbtt_uint8 *comp = data + g + 10;
  1610. num_vertices = 0;
  1611. vertices = 0;
  1612. while (more) {
  1613. stbtt_uint16 flags, gidx;
  1614. int comp_num_verts = 0, i;
  1615. stbtt_vertex *comp_verts = 0, *tmp = 0;
  1616. float mtx[6] = {1,0,0,1,0,0}, m, n;
  1617. flags = ttSHORT(comp); comp+=2;
  1618. gidx = ttSHORT(comp); comp+=2;
  1619. if (flags & 2) { // XY values
  1620. if (flags & 1) { // shorts
  1621. mtx[4] = ttSHORT(comp); comp+=2;
  1622. mtx[5] = ttSHORT(comp); comp+=2;
  1623. } else {
  1624. mtx[4] = ttCHAR(comp); comp+=1;
  1625. mtx[5] = ttCHAR(comp); comp+=1;
  1626. }
  1627. }
  1628. else {
  1629. // @TODO handle matching point
  1630. STBTT_assert(0);
  1631. }
  1632. if (flags & (1<<3)) { // WE_HAVE_A_SCALE
  1633. mtx[0] = mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
  1634. mtx[1] = mtx[2] = 0;
  1635. } else if (flags & (1<<6)) { // WE_HAVE_AN_X_AND_YSCALE
  1636. mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;
  1637. mtx[1] = mtx[2] = 0;
  1638. mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
  1639. } else if (flags & (1<<7)) { // WE_HAVE_A_TWO_BY_TWO
  1640. mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;
  1641. mtx[1] = ttSHORT(comp)/16384.0f; comp+=2;
  1642. mtx[2] = ttSHORT(comp)/16384.0f; comp+=2;
  1643. mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
  1644. }
  1645. // Find transformation scales.
  1646. m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]);
  1647. n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]);
  1648. // Get indexed glyph.
  1649. comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts);
  1650. if (comp_num_verts > 0) {
  1651. // Transform vertices.
  1652. for (i = 0; i < comp_num_verts; ++i) {
  1653. stbtt_vertex* v = &comp_verts[i];
  1654. stbtt_vertex_type x,y;
  1655. x=v->x; y=v->y;
  1656. v->x = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
  1657. v->y = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
  1658. x=v->cx; y=v->cy;
  1659. v->cx = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
  1660. v->cy = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
  1661. }
  1662. // Append vertices.
  1663. tmp = (stbtt_vertex*)STBTT_malloc((num_vertices+comp_num_verts)*sizeof(stbtt_vertex), info->userdata);
  1664. if (!tmp) {
  1665. if (vertices) STBTT_free(vertices, info->userdata);
  1666. if (comp_verts) STBTT_free(comp_verts, info->userdata);
  1667. return 0;
  1668. }
  1669. if (num_vertices > 0 && vertices) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex));
  1670. STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex));
  1671. if (vertices) STBTT_free(vertices, info->userdata);
  1672. vertices = tmp;
  1673. STBTT_free(comp_verts, info->userdata);
  1674. num_vertices += comp_num_verts;
  1675. }
  1676. // More components ?
  1677. more = flags & (1<<5);
  1678. }
  1679. } else {
  1680. // numberOfCounters == 0, do nothing
  1681. }
  1682. *pvertices = vertices;
  1683. return num_vertices;
  1684. }
  1685. typedef struct
  1686. {
  1687. int bounds;
  1688. int started;
  1689. float first_x, first_y;
  1690. float x, y;
  1691. stbtt_int32 min_x, max_x, min_y, max_y;
  1692. stbtt_vertex *pvertices;
  1693. int num_vertices;
  1694. } stbtt__csctx;
  1695. #define STBTT__CSCTX_INIT(bounds) {bounds,0, 0,0, 0,0, 0,0,0,0, NULL, 0}
  1696. static void stbtt__track_vertex(stbtt__csctx *c, stbtt_int32 x, stbtt_int32 y)
  1697. {
  1698. if (x > c->max_x || !c->started) c->max_x = x;
  1699. if (y > c->max_y || !c->started) c->max_y = y;
  1700. if (x < c->min_x || !c->started) c->min_x = x;
  1701. if (y < c->min_y || !c->started) c->min_y = y;
  1702. c->started = 1;
  1703. }
  1704. static void stbtt__csctx_v(stbtt__csctx *c, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy, stbtt_int32 cx1, stbtt_int32 cy1)
  1705. {
  1706. if (c->bounds) {
  1707. stbtt__track_vertex(c, x, y);
  1708. if (type == STBTT_vcubic) {
  1709. stbtt__track_vertex(c, cx, cy);
  1710. stbtt__track_vertex(c, cx1, cy1);
  1711. }
  1712. } else {
  1713. stbtt_setvertex(&c->pvertices[c->num_vertices], type, x, y, cx, cy);
  1714. c->pvertices[c->num_vertices].cx1 = (stbtt_int16) cx1;
  1715. c->pvertices[c->num_vertices].cy1 = (stbtt_int16) cy1;
  1716. }
  1717. c->num_vertices++;
  1718. }
  1719. static void stbtt__csctx_close_shape(stbtt__csctx *ctx)
  1720. {
  1721. if (ctx->first_x != ctx->x || ctx->first_y != ctx->y)
  1722. stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->first_x, (int)ctx->first_y, 0, 0, 0, 0);
  1723. }
  1724. static void stbtt__csctx_rmove_to(stbtt__csctx *ctx, float dx, float dy)
  1725. {
  1726. stbtt__csctx_close_shape(ctx);
  1727. ctx->first_x = ctx->x = ctx->x + dx;
  1728. ctx->first_y = ctx->y = ctx->y + dy;
  1729. stbtt__csctx_v(ctx, STBTT_vmove, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0);
  1730. }
  1731. static void stbtt__csctx_rline_to(stbtt__csctx *ctx, float dx, float dy)
  1732. {
  1733. ctx->x += dx;
  1734. ctx->y += dy;
  1735. stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0);
  1736. }
  1737. static void stbtt__csctx_rccurve_to(stbtt__csctx *ctx, float dx1, float dy1, float dx2, float dy2, float dx3, float dy3)
  1738. {
  1739. float cx1 = ctx->x + dx1;
  1740. float cy1 = ctx->y + dy1;
  1741. float cx2 = cx1 + dx2;
  1742. float cy2 = cy1 + dy2;
  1743. ctx->x = cx2 + dx3;
  1744. ctx->y = cy2 + dy3;
  1745. stbtt__csctx_v(ctx, STBTT_vcubic, (int)ctx->x, (int)ctx->y, (int)cx1, (int)cy1, (int)cx2, (int)cy2);
  1746. }
  1747. static stbtt__buf stbtt__get_subr(stbtt__buf idx, int n)
  1748. {
  1749. int count = stbtt__cff_index_count(&idx);
  1750. int bias = 107;
  1751. if (count >= 33900)
  1752. bias = 32768;
  1753. else if (count >= 1240)
  1754. bias = 1131;
  1755. n += bias;
  1756. if (n < 0 || n >= count)
  1757. return stbtt__new_buf(NULL, 0);
  1758. return stbtt__cff_index_get(idx, n);
  1759. }
  1760. static stbtt__buf stbtt__cid_get_glyph_subrs(const stbtt_fontinfo *info, int glyph_index)
  1761. {
  1762. stbtt__buf fdselect = info->fdselect;
  1763. int nranges, start, end, v, fmt, fdselector = -1, i;
  1764. stbtt__buf_seek(&fdselect, 0);
  1765. fmt = stbtt__buf_get8(&fdselect);
  1766. if (fmt == 0) {
  1767. // untested
  1768. stbtt__buf_skip(&fdselect, glyph_index);
  1769. fdselector = stbtt__buf_get8(&fdselect);
  1770. } else if (fmt == 3) {
  1771. nranges = stbtt__buf_get16(&fdselect);
  1772. start = stbtt__buf_get16(&fdselect);
  1773. for (i = 0; i < nranges; i++) {
  1774. v = stbtt__buf_get8(&fdselect);
  1775. end = stbtt__buf_get16(&fdselect);
  1776. if (glyph_index >= start && glyph_index < end) {
  1777. fdselector = v;
  1778. break;
  1779. }
  1780. start = end;
  1781. }
  1782. }
  1783. if (fdselector == -1) return stbtt__new_buf(NULL, 0); // [DEAR IMGUI] fixed, see #6007 and nothings/stb#1422
  1784. return stbtt__get_subrs(info->cff, stbtt__cff_index_get(info->fontdicts, fdselector));
  1785. }
  1786. static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, stbtt__csctx *c)
  1787. {
  1788. int in_header = 1, maskbits = 0, subr_stack_height = 0, sp = 0, v, i, b0;
  1789. int has_subrs = 0, clear_stack;
  1790. float s[48];
  1791. stbtt__buf subr_stack[10], subrs = info->subrs, b;
  1792. float f;
  1793. #define STBTT__CSERR(s) (0)
  1794. // this currently ignores the initial width value, which isn't needed if we have hmtx
  1795. b = stbtt__cff_index_get(info->charstrings, glyph_index);
  1796. while (b.cursor < b.size) {
  1797. i = 0;
  1798. clear_stack = 1;
  1799. b0 = stbtt__buf_get8(&b);
  1800. switch (b0) {
  1801. // @TODO implement hinting
  1802. case 0x13: // hintmask
  1803. case 0x14: // cntrmask
  1804. if (in_header)
  1805. maskbits += (sp / 2); // implicit "vstem"
  1806. in_header = 0;
  1807. stbtt__buf_skip(&b, (maskbits + 7) / 8);
  1808. break;
  1809. case 0x01: // hstem
  1810. case 0x03: // vstem
  1811. case 0x12: // hstemhm
  1812. case 0x17: // vstemhm
  1813. maskbits += (sp / 2);
  1814. break;
  1815. case 0x15: // rmoveto
  1816. in_header = 0;
  1817. if (sp < 2) return STBTT__CSERR("rmoveto stack");
  1818. stbtt__csctx_rmove_to(c, s[sp-2], s[sp-1]);
  1819. break;
  1820. case 0x04: // vmoveto
  1821. in_header = 0;
  1822. if (sp < 1) return STBTT__CSERR("vmoveto stack");
  1823. stbtt__csctx_rmove_to(c, 0, s[sp-1]);
  1824. break;
  1825. case 0x16: // hmoveto
  1826. in_header = 0;
  1827. if (sp < 1) return STBTT__CSERR("hmoveto stack");
  1828. stbtt__csctx_rmove_to(c, s[sp-1], 0);
  1829. break;
  1830. case 0x05: // rlineto
  1831. if (sp < 2) return STBTT__CSERR("rlineto stack");
  1832. for (; i + 1 < sp; i += 2)
  1833. stbtt__csctx_rline_to(c, s[i], s[i+1]);
  1834. break;
  1835. // hlineto/vlineto and vhcurveto/hvcurveto alternate horizontal and vertical
  1836. // starting from a different place.
  1837. case 0x07: // vlineto
  1838. if (sp < 1) return STBTT__CSERR("vlineto stack");
  1839. goto vlineto;
  1840. case 0x06: // hlineto
  1841. if (sp < 1) return STBTT__CSERR("hlineto stack");
  1842. for (;;) {
  1843. if (i >= sp) break;
  1844. stbtt__csctx_rline_to(c, s[i], 0);
  1845. i++;
  1846. vlineto:
  1847. if (i >= sp) break;
  1848. stbtt__csctx_rline_to(c, 0, s[i]);
  1849. i++;
  1850. }
  1851. break;
  1852. case 0x1F: // hvcurveto
  1853. if (sp < 4) return STBTT__CSERR("hvcurveto stack");
  1854. goto hvcurveto;
  1855. case 0x1E: // vhcurveto
  1856. if (sp < 4) return STBTT__CSERR("vhcurveto stack");
  1857. for (;;) {
  1858. if (i + 3 >= sp) break;
  1859. stbtt__csctx_rccurve_to(c, 0, s[i], s[i+1], s[i+2], s[i+3], (sp - i == 5) ? s[i + 4] : 0.0f);
  1860. i += 4;
  1861. hvcurveto:
  1862. if (i + 3 >= sp) break;
  1863. stbtt__csctx_rccurve_to(c, s[i], 0, s[i+1], s[i+2], (sp - i == 5) ? s[i+4] : 0.0f, s[i+3]);
  1864. i += 4;
  1865. }
  1866. break;
  1867. case 0x08: // rrcurveto
  1868. if (sp < 6) return STBTT__CSERR("rcurveline stack");
  1869. for (; i + 5 < sp; i += 6)
  1870. stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);
  1871. break;
  1872. case 0x18: // rcurveline
  1873. if (sp < 8) return STBTT__CSERR("rcurveline stack");
  1874. for (; i + 5 < sp - 2; i += 6)
  1875. stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);
  1876. if (i + 1 >= sp) return STBTT__CSERR("rcurveline stack");
  1877. stbtt__csctx_rline_to(c, s[i], s[i+1]);
  1878. break;
  1879. case 0x19: // rlinecurve
  1880. if (sp < 8) return STBTT__CSERR("rlinecurve stack");
  1881. for (; i + 1 < sp - 6; i += 2)
  1882. stbtt__csctx_rline_to(c, s[i], s[i+1]);
  1883. if (i + 5 >= sp) return STBTT__CSERR("rlinecurve stack");
  1884. stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);
  1885. break;
  1886. case 0x1A: // vvcurveto
  1887. case 0x1B: // hhcurveto
  1888. if (sp < 4) return STBTT__CSERR("(vv|hh)curveto stack");
  1889. f = 0.0;
  1890. if (sp & 1) { f = s[i]; i++; }
  1891. for (; i + 3 < sp; i += 4) {
  1892. if (b0 == 0x1B)
  1893. stbtt__csctx_rccurve_to(c, s[i], f, s[i+1], s[i+2], s[i+3], 0.0);
  1894. else
  1895. stbtt__csctx_rccurve_to(c, f, s[i], s[i+1], s[i+2], 0.0, s[i+3]);
  1896. f = 0.0;
  1897. }
  1898. break;
  1899. case 0x0A: // callsubr
  1900. if (!has_subrs) {
  1901. if (info->fdselect.size)
  1902. subrs = stbtt__cid_get_glyph_subrs(info, glyph_index);
  1903. has_subrs = 1;
  1904. }
  1905. // FALLTHROUGH
  1906. case 0x1D: // callgsubr
  1907. if (sp < 1) return STBTT__CSERR("call(g|)subr stack");
  1908. v = (int) s[--sp];
  1909. if (subr_stack_height >= 10) return STBTT__CSERR("recursion limit");
  1910. subr_stack[subr_stack_height++] = b;
  1911. b = stbtt__get_subr(b0 == 0x0A ? subrs : info->gsubrs, v);
  1912. if (b.size == 0) return STBTT__CSERR("subr not found");
  1913. b.cursor = 0;
  1914. clear_stack = 0;
  1915. break;
  1916. case 0x0B: // return
  1917. if (subr_stack_height <= 0) return STBTT__CSERR("return outside subr");
  1918. b = subr_stack[--subr_stack_height];
  1919. clear_stack = 0;
  1920. break;
  1921. case 0x0E: // endchar
  1922. stbtt__csctx_close_shape(c);
  1923. return 1;
  1924. case 0x0C: { // two-byte escape
  1925. float dx1, dx2, dx3, dx4, dx5, dx6, dy1, dy2, dy3, dy4, dy5, dy6;
  1926. float dx, dy;
  1927. int b1 = stbtt__buf_get8(&b);
  1928. switch (b1) {
  1929. // @TODO These "flex" implementations ignore the flex-depth and resolution,
  1930. // and always draw beziers.
  1931. case 0x22: // hflex
  1932. if (sp < 7) return STBTT__CSERR("hflex stack");
  1933. dx1 = s[0];
  1934. dx2 = s[1];
  1935. dy2 = s[2];
  1936. dx3 = s[3];
  1937. dx4 = s[4];
  1938. dx5 = s[5];
  1939. dx6 = s[6];
  1940. stbtt__csctx_rccurve_to(c, dx1, 0, dx2, dy2, dx3, 0);
  1941. stbtt__csctx_rccurve_to(c, dx4, 0, dx5, -dy2, dx6, 0);
  1942. break;
  1943. case 0x23: // flex
  1944. if (sp < 13) return STBTT__CSERR("flex stack");
  1945. dx1 = s[0];
  1946. dy1 = s[1];
  1947. dx2 = s[2];
  1948. dy2 = s[3];
  1949. dx3 = s[4];
  1950. dy3 = s[5];
  1951. dx4 = s[6];
  1952. dy4 = s[7];
  1953. dx5 = s[8];
  1954. dy5 = s[9];
  1955. dx6 = s[10];
  1956. dy6 = s[11];
  1957. //fd is s[12]
  1958. stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3);
  1959. stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6);
  1960. break;
  1961. case 0x24: // hflex1
  1962. if (sp < 9) return STBTT__CSERR("hflex1 stack");
  1963. dx1 = s[0];
  1964. dy1 = s[1];
  1965. dx2 = s[2];
  1966. dy2 = s[3];
  1967. dx3 = s[4];
  1968. dx4 = s[5];
  1969. dx5 = s[6];
  1970. dy5 = s[7];
  1971. dx6 = s[8];
  1972. stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, 0);
  1973. stbtt__csctx_rccurve_to(c, dx4, 0, dx5, dy5, dx6, -(dy1+dy2+dy5));
  1974. break;
  1975. case 0x25: // flex1
  1976. if (sp < 11) return STBTT__CSERR("flex1 stack");
  1977. dx1 = s[0];
  1978. dy1 = s[1];
  1979. dx2 = s[2];
  1980. dy2 = s[3];
  1981. dx3 = s[4];
  1982. dy3 = s[5];
  1983. dx4 = s[6];
  1984. dy4 = s[7];
  1985. dx5 = s[8];
  1986. dy5 = s[9];
  1987. dx6 = dy6 = s[10];
  1988. dx = dx1+dx2+dx3+dx4+dx5;
  1989. dy = dy1+dy2+dy3+dy4+dy5;
  1990. if (STBTT_fabs(dx) > STBTT_fabs(dy))
  1991. dy6 = -dy;
  1992. else
  1993. dx6 = -dx;
  1994. stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3);
  1995. stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6);
  1996. break;
  1997. default:
  1998. return STBTT__CSERR("unimplemented");
  1999. }
  2000. } break;
  2001. default:
  2002. if (b0 != 255 && b0 != 28 && b0 < 32)
  2003. return STBTT__CSERR("reserved operator");
  2004. // push immediate
  2005. if (b0 == 255) {
  2006. f = (float)(stbtt_int32)stbtt__buf_get32(&b) / 0x10000;
  2007. } else {
  2008. stbtt__buf_skip(&b, -1);
  2009. f = (float)(stbtt_int16)stbtt__cff_int(&b);
  2010. }
  2011. if (sp >= 48) return STBTT__CSERR("push stack overflow");
  2012. s[sp++] = f;
  2013. clear_stack = 0;
  2014. break;
  2015. }
  2016. if (clear_stack) sp = 0;
  2017. }
  2018. return STBTT__CSERR("no endchar");
  2019. #undef STBTT__CSERR
  2020. }
  2021. static int stbtt__GetGlyphShapeT2(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
  2022. {
  2023. // runs the charstring twice, once to count and once to output (to avoid realloc)
  2024. stbtt__csctx count_ctx = STBTT__CSCTX_INIT(1);
  2025. stbtt__csctx output_ctx = STBTT__CSCTX_INIT(0);
  2026. if (stbtt__run_charstring(info, glyph_index, &count_ctx)) {
  2027. *pvertices = (stbtt_vertex*)STBTT_malloc(count_ctx.num_vertices*sizeof(stbtt_vertex), info->userdata);
  2028. output_ctx.pvertices = *pvertices;
  2029. if (stbtt__run_charstring(info, glyph_index, &output_ctx)) {
  2030. STBTT_assert(output_ctx.num_vertices == count_ctx.num_vertices);
  2031. return output_ctx.num_vertices;
  2032. }
  2033. }
  2034. *pvertices = NULL;
  2035. return 0;
  2036. }
  2037. static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1)
  2038. {
  2039. stbtt__csctx c = STBTT__CSCTX_INIT(1);
  2040. int r = stbtt__run_charstring(info, glyph_index, &c);
  2041. if (x0) *x0 = r ? c.min_x : 0;
  2042. if (y0) *y0 = r ? c.min_y : 0;
  2043. if (x1) *x1 = r ? c.max_x : 0;
  2044. if (y1) *y1 = r ? c.max_y : 0;
  2045. return r ? c.num_vertices : 0;
  2046. }
  2047. STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
  2048. {
  2049. if (!info->cff.size)
  2050. return stbtt__GetGlyphShapeTT(info, glyph_index, pvertices);
  2051. else
  2052. return stbtt__GetGlyphShapeT2(info, glyph_index, pvertices);
  2053. }
  2054. STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing)
  2055. {
  2056. stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data+info->hhea + 34);
  2057. if (glyph_index < numOfLongHorMetrics) {
  2058. if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*glyph_index);
  2059. if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*glyph_index + 2);
  2060. } else {
  2061. if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1));
  2062. if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics));
  2063. }
  2064. }
  2065. STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info)
  2066. {
  2067. stbtt_uint8 *data = info->data + info->kern;
  2068. // we only look at the first table. it must be 'horizontal' and format 0.
  2069. if (!info->kern)
  2070. return 0;
  2071. if (ttUSHORT(data+2) < 1) // number of tables, need at least 1
  2072. return 0;
  2073. if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format
  2074. return 0;
  2075. return ttUSHORT(data+10);
  2076. }
  2077. STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length)
  2078. {
  2079. stbtt_uint8 *data = info->data + info->kern;
  2080. int k, length;
  2081. // we only look at the first table. it must be 'horizontal' and format 0.
  2082. if (!info->kern)
  2083. return 0;
  2084. if (ttUSHORT(data+2) < 1) // number of tables, need at least 1
  2085. return 0;
  2086. if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format
  2087. return 0;
  2088. length = ttUSHORT(data+10);
  2089. if (table_length < length)
  2090. length = table_length;
  2091. for (k = 0; k < length; k++)
  2092. {
  2093. table[k].glyph1 = ttUSHORT(data+18+(k*6));
  2094. table[k].glyph2 = ttUSHORT(data+20+(k*6));
  2095. table[k].advance = ttSHORT(data+22+(k*6));
  2096. }
  2097. return length;
  2098. }
  2099. static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
  2100. {
  2101. stbtt_uint8 *data = info->data + info->kern;
  2102. stbtt_uint32 needle, straw;
  2103. int l, r, m;
  2104. // we only look at the first table. it must be 'horizontal' and format 0.
  2105. if (!info->kern)
  2106. return 0;
  2107. if (ttUSHORT(data+2) < 1) // number of tables, need at least 1
  2108. return 0;
  2109. if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format
  2110. return 0;
  2111. l = 0;
  2112. r = ttUSHORT(data+10) - 1;
  2113. needle = glyph1 << 16 | glyph2;
  2114. while (l <= r) {
  2115. m = (l + r) >> 1;
  2116. straw = ttULONG(data+18+(m*6)); // note: unaligned read
  2117. if (needle < straw)
  2118. r = m - 1;
  2119. else if (needle > straw)
  2120. l = m + 1;
  2121. else
  2122. return ttSHORT(data+22+(m*6));
  2123. }
  2124. return 0;
  2125. }
  2126. static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph)
  2127. {
  2128. stbtt_uint16 coverageFormat = ttUSHORT(coverageTable);
  2129. switch (coverageFormat) {
  2130. case 1: {
  2131. stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2);
  2132. // Binary search.
  2133. stbtt_int32 l=0, r=glyphCount-1, m;
  2134. int straw, needle=glyph;
  2135. while (l <= r) {
  2136. stbtt_uint8 *glyphArray = coverageTable + 4;
  2137. stbtt_uint16 glyphID;
  2138. m = (l + r) >> 1;
  2139. glyphID = ttUSHORT(glyphArray + 2 * m);
  2140. straw = glyphID;
  2141. if (needle < straw)
  2142. r = m - 1;
  2143. else if (needle > straw)
  2144. l = m + 1;
  2145. else {
  2146. return m;
  2147. }
  2148. }
  2149. break;
  2150. }
  2151. case 2: {
  2152. stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2);
  2153. stbtt_uint8 *rangeArray = coverageTable + 4;
  2154. // Binary search.
  2155. stbtt_int32 l=0, r=rangeCount-1, m;
  2156. int strawStart, strawEnd, needle=glyph;
  2157. while (l <= r) {
  2158. stbtt_uint8 *rangeRecord;
  2159. m = (l + r) >> 1;
  2160. rangeRecord = rangeArray + 6 * m;
  2161. strawStart = ttUSHORT(rangeRecord);
  2162. strawEnd = ttUSHORT(rangeRecord + 2);
  2163. if (needle < strawStart)
  2164. r = m - 1;
  2165. else if (needle > strawEnd)
  2166. l = m + 1;
  2167. else {
  2168. stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4);
  2169. return startCoverageIndex + glyph - strawStart;
  2170. }
  2171. }
  2172. break;
  2173. }
  2174. default: return -1; // unsupported
  2175. }
  2176. return -1;
  2177. }
  2178. static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph)
  2179. {
  2180. stbtt_uint16 classDefFormat = ttUSHORT(classDefTable);
  2181. switch (classDefFormat)
  2182. {
  2183. case 1: {
  2184. stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2);
  2185. stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4);
  2186. stbtt_uint8 *classDef1ValueArray = classDefTable + 6;
  2187. if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount)
  2188. return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID));
  2189. break;
  2190. }
  2191. case 2: {
  2192. stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2);
  2193. stbtt_uint8 *classRangeRecords = classDefTable + 4;
  2194. // Binary search.
  2195. stbtt_int32 l=0, r=classRangeCount-1, m;
  2196. int strawStart, strawEnd, needle=glyph;
  2197. while (l <= r) {
  2198. stbtt_uint8 *classRangeRecord;
  2199. m = (l + r) >> 1;
  2200. classRangeRecord = classRangeRecords + 6 * m;
  2201. strawStart = ttUSHORT(classRangeRecord);
  2202. strawEnd = ttUSHORT(classRangeRecord + 2);
  2203. if (needle < strawStart)
  2204. r = m - 1;
  2205. else if (needle > strawEnd)
  2206. l = m + 1;
  2207. else
  2208. return (stbtt_int32)ttUSHORT(classRangeRecord + 4);
  2209. }
  2210. break;
  2211. }
  2212. default:
  2213. return -1; // Unsupported definition type, return an error.
  2214. }
  2215. // "All glyphs not assigned to a class fall into class 0". (OpenType spec)
  2216. return 0;
  2217. }
  2218. // Define to STBTT_assert(x) if you want to break on unimplemented formats.
  2219. #define STBTT_GPOS_TODO_assert(x)
  2220. static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
  2221. {
  2222. stbtt_uint16 lookupListOffset;
  2223. stbtt_uint8 *lookupList;
  2224. stbtt_uint16 lookupCount;
  2225. stbtt_uint8 *data;
  2226. stbtt_int32 i, sti;
  2227. if (!info->gpos) return 0;
  2228. data = info->data + info->gpos;
  2229. if (ttUSHORT(data+0) != 1) return 0; // Major version 1
  2230. if (ttUSHORT(data+2) != 0) return 0; // Minor version 0
  2231. lookupListOffset = ttUSHORT(data+8);
  2232. lookupList = data + lookupListOffset;
  2233. lookupCount = ttUSHORT(lookupList);
  2234. for (i=0; i<lookupCount; ++i) {
  2235. stbtt_uint16 lookupOffset = ttUSHORT(lookupList + 2 + 2 * i);
  2236. stbtt_uint8 *lookupTable = lookupList + lookupOffset;
  2237. stbtt_uint16 lookupType = ttUSHORT(lookupTable);
  2238. stbtt_uint16 subTableCount = ttUSHORT(lookupTable + 4);
  2239. stbtt_uint8 *subTableOffsets = lookupTable + 6;
  2240. if (lookupType != 2) // Pair Adjustment Positioning Subtable
  2241. continue;
  2242. for (sti=0; sti<subTableCount; sti++) {
  2243. stbtt_uint16 subtableOffset = ttUSHORT(subTableOffsets + 2 * sti);
  2244. stbtt_uint8 *table = lookupTable + subtableOffset;
  2245. stbtt_uint16 posFormat = ttUSHORT(table);
  2246. stbtt_uint16 coverageOffset = ttUSHORT(table + 2);
  2247. stbtt_int32 coverageIndex = stbtt__GetCoverageIndex(table + coverageOffset, glyph1);
  2248. if (coverageIndex == -1) continue;
  2249. switch (posFormat) {
  2250. case 1: {
  2251. stbtt_int32 l, r, m;
  2252. int straw, needle;
  2253. stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
  2254. stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
  2255. if (valueFormat1 == 4 && valueFormat2 == 0) { // Support more formats?
  2256. stbtt_int32 valueRecordPairSizeInBytes = 2;
  2257. stbtt_uint16 pairSetCount = ttUSHORT(table + 8);
  2258. stbtt_uint16 pairPosOffset = ttUSHORT(table + 10 + 2 * coverageIndex);
  2259. stbtt_uint8 *pairValueTable = table + pairPosOffset;
  2260. stbtt_uint16 pairValueCount = ttUSHORT(pairValueTable);
  2261. stbtt_uint8 *pairValueArray = pairValueTable + 2;
  2262. if (coverageIndex >= pairSetCount) return 0;
  2263. needle=glyph2;
  2264. r=pairValueCount-1;
  2265. l=0;
  2266. // Binary search.
  2267. while (l <= r) {
  2268. stbtt_uint16 secondGlyph;
  2269. stbtt_uint8 *pairValue;
  2270. m = (l + r) >> 1;
  2271. pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m;
  2272. secondGlyph = ttUSHORT(pairValue);
  2273. straw = secondGlyph;
  2274. if (needle < straw)
  2275. r = m - 1;
  2276. else if (needle > straw)
  2277. l = m + 1;
  2278. else {
  2279. stbtt_int16 xAdvance = ttSHORT(pairValue + 2);
  2280. return xAdvance;
  2281. }
  2282. }
  2283. } else
  2284. return 0;
  2285. break;
  2286. }
  2287. case 2: {
  2288. stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
  2289. stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
  2290. if (valueFormat1 == 4 && valueFormat2 == 0) { // Support more formats?
  2291. stbtt_uint16 classDef1Offset = ttUSHORT(table + 8);
  2292. stbtt_uint16 classDef2Offset = ttUSHORT(table + 10);
  2293. int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1);
  2294. int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2);
  2295. stbtt_uint16 class1Count = ttUSHORT(table + 12);
  2296. stbtt_uint16 class2Count = ttUSHORT(table + 14);
  2297. stbtt_uint8 *class1Records, *class2Records;
  2298. stbtt_int16 xAdvance;
  2299. if (glyph1class < 0 || glyph1class >= class1Count) return 0; // malformed
  2300. if (glyph2class < 0 || glyph2class >= class2Count) return 0; // malformed
  2301. class1Records = table + 16;
  2302. class2Records = class1Records + 2 * (glyph1class * class2Count);
  2303. xAdvance = ttSHORT(class2Records + 2 * glyph2class);
  2304. return xAdvance;
  2305. } else
  2306. return 0;
  2307. break;
  2308. }
  2309. default:
  2310. return 0; // Unsupported position format
  2311. }
  2312. }
  2313. }
  2314. return 0;
  2315. }
  2316. STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int g2)
  2317. {
  2318. int xAdvance = 0;
  2319. if (info->gpos)
  2320. xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2);
  2321. else if (info->kern)
  2322. xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2);
  2323. return xAdvance;
  2324. }
  2325. STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2)
  2326. {
  2327. if (!info->kern && !info->gpos) // if no kerning table, don't waste time looking up both codepoint->glyphs
  2328. return 0;
  2329. return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2));
  2330. }
  2331. STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing)
  2332. {
  2333. stbtt_GetGlyphHMetrics(info, stbtt_FindGlyphIndex(info,codepoint), advanceWidth, leftSideBearing);
  2334. }
  2335. STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap)
  2336. {
  2337. if (ascent ) *ascent = ttSHORT(info->data+info->hhea + 4);
  2338. if (descent) *descent = ttSHORT(info->data+info->hhea + 6);
  2339. if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8);
  2340. }
  2341. STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap)
  2342. {
  2343. int tab = stbtt__find_table(info->data, info->fontstart, "OS/2");
  2344. if (!tab)
  2345. return 0;
  2346. if (typoAscent ) *typoAscent = ttSHORT(info->data+tab + 68);
  2347. if (typoDescent) *typoDescent = ttSHORT(info->data+tab + 70);
  2348. if (typoLineGap) *typoLineGap = ttSHORT(info->data+tab + 72);
  2349. return 1;
  2350. }
  2351. STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1)
  2352. {
  2353. *x0 = ttSHORT(info->data + info->head + 36);
  2354. *y0 = ttSHORT(info->data + info->head + 38);
  2355. *x1 = ttSHORT(info->data + info->head + 40);
  2356. *y1 = ttSHORT(info->data + info->head + 42);
  2357. }
  2358. STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float height)
  2359. {
  2360. int fheight = ttSHORT(info->data + info->hhea + 4) - ttSHORT(info->data + info->hhea + 6);
  2361. return (float) height / fheight;
  2362. }
  2363. STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels)
  2364. {
  2365. int unitsPerEm = ttUSHORT(info->data + info->head + 18);
  2366. return pixels / unitsPerEm;
  2367. }
  2368. STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v)
  2369. {
  2370. STBTT_free(v, info->userdata);
  2371. }
  2372. STBTT_DEF stbtt_uint8 *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl)
  2373. {
  2374. int i;
  2375. stbtt_uint8 *data = info->data;
  2376. stbtt_uint8 *svg_doc_list = data + stbtt__get_svg((stbtt_fontinfo *) info);
  2377. int numEntries = ttUSHORT(svg_doc_list);
  2378. stbtt_uint8 *svg_docs = svg_doc_list + 2;
  2379. for(i=0; i<numEntries; i++) {
  2380. stbtt_uint8 *svg_doc = svg_docs + (12 * i);
  2381. if ((gl >= ttUSHORT(svg_doc)) && (gl <= ttUSHORT(svg_doc + 2)))
  2382. return svg_doc;
  2383. }
  2384. return 0;
  2385. }
  2386. STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg)
  2387. {
  2388. stbtt_uint8 *data = info->data;
  2389. stbtt_uint8 *svg_doc;
  2390. if (info->svg == 0)
  2391. return 0;
  2392. svg_doc = stbtt_FindSVGDoc(info, gl);
  2393. if (svg_doc != NULL) {
  2394. *svg = (char *) data + info->svg + ttULONG(svg_doc + 4);
  2395. return ttULONG(svg_doc + 8);
  2396. } else {
  2397. return 0;
  2398. }
  2399. }
  2400. STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg)
  2401. {
  2402. return stbtt_GetGlyphSVG(info, stbtt_FindGlyphIndex(info, unicode_codepoint), svg);
  2403. }
  2404. //////////////////////////////////////////////////////////////////////////////
  2405. //
  2406. // antialiasing software rasterizer
  2407. //
  2408. STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1)
  2409. {
  2410. int x0=0,y0=0,x1,y1; // =0 suppresses compiler warning
  2411. if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) {
  2412. // e.g. space character
  2413. if (ix0) *ix0 = 0;
  2414. if (iy0) *iy0 = 0;
  2415. if (ix1) *ix1 = 0;
  2416. if (iy1) *iy1 = 0;
  2417. } else {
  2418. // move to integral bboxes (treating pixels as little squares, what pixels get touched)?
  2419. if (ix0) *ix0 = STBTT_ifloor( x0 * scale_x + shift_x);
  2420. if (iy0) *iy0 = STBTT_ifloor(-y1 * scale_y + shift_y);
  2421. if (ix1) *ix1 = STBTT_iceil ( x1 * scale_x + shift_x);
  2422. if (iy1) *iy1 = STBTT_iceil (-y0 * scale_y + shift_y);
  2423. }
  2424. }
  2425. STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
  2426. {
  2427. stbtt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1);
  2428. }
  2429. STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1)
  2430. {
  2431. stbtt_GetGlyphBitmapBoxSubpixel(font, stbtt_FindGlyphIndex(font,codepoint), scale_x, scale_y,shift_x,shift_y, ix0,iy0,ix1,iy1);
  2432. }
  2433. STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
  2434. {
  2435. stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y,0.0f,0.0f, ix0,iy0,ix1,iy1);
  2436. }
  2437. //////////////////////////////////////////////////////////////////////////////
  2438. //
  2439. // Rasterizer
  2440. typedef struct stbtt__hheap_chunk
  2441. {
  2442. struct stbtt__hheap_chunk *next;
  2443. } stbtt__hheap_chunk;
  2444. typedef struct stbtt__hheap
  2445. {
  2446. struct stbtt__hheap_chunk *head;
  2447. void *first_free;
  2448. int num_remaining_in_head_chunk;
  2449. } stbtt__hheap;
  2450. static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata)
  2451. {
  2452. if (hh->first_free) {
  2453. void *p = hh->first_free;
  2454. hh->first_free = * (void **) p;
  2455. return p;
  2456. } else {
  2457. if (hh->num_remaining_in_head_chunk == 0) {
  2458. int count = (size < 32 ? 2000 : size < 128 ? 800 : 100);
  2459. stbtt__hheap_chunk *c = (stbtt__hheap_chunk *) STBTT_malloc(sizeof(stbtt__hheap_chunk) + size * count, userdata);
  2460. if (c == NULL)
  2461. return NULL;
  2462. c->next = hh->head;
  2463. hh->head = c;
  2464. hh->num_remaining_in_head_chunk = count;
  2465. }
  2466. --hh->num_remaining_in_head_chunk;
  2467. return (char *) (hh->head) + sizeof(stbtt__hheap_chunk) + size * hh->num_remaining_in_head_chunk;
  2468. }
  2469. }
  2470. static void stbtt__hheap_free(stbtt__hheap *hh, void *p)
  2471. {
  2472. *(void **) p = hh->first_free;
  2473. hh->first_free = p;
  2474. }
  2475. static void stbtt__hheap_cleanup(stbtt__hheap *hh, void *userdata)
  2476. {
  2477. stbtt__hheap_chunk *c = hh->head;
  2478. while (c) {
  2479. stbtt__hheap_chunk *n = c->next;
  2480. STBTT_free(c, userdata);
  2481. c = n;
  2482. }
  2483. }
  2484. typedef struct stbtt__edge {
  2485. float x0,y0, x1,y1;
  2486. int invert;
  2487. } stbtt__edge;
  2488. typedef struct stbtt__active_edge
  2489. {
  2490. struct stbtt__active_edge *next;
  2491. #if STBTT_RASTERIZER_VERSION==1
  2492. int x,dx;
  2493. float ey;
  2494. int direction;
  2495. #elif STBTT_RASTERIZER_VERSION==2
  2496. float fx,fdx,fdy;
  2497. float direction;
  2498. float sy;
  2499. float ey;
  2500. #else
  2501. #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
  2502. #endif
  2503. } stbtt__active_edge;
  2504. #if STBTT_RASTERIZER_VERSION == 1
  2505. #define STBTT_FIXSHIFT 10
  2506. #define STBTT_FIX (1 << STBTT_FIXSHIFT)
  2507. #define STBTT_FIXMASK (STBTT_FIX-1)
  2508. static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata)
  2509. {
  2510. stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);
  2511. float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
  2512. STBTT_assert(z != NULL);
  2513. if (!z) return z;
  2514. // round dx down to avoid overshooting
  2515. if (dxdy < 0)
  2516. z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy);
  2517. else
  2518. z->dx = STBTT_ifloor(STBTT_FIX * dxdy);
  2519. z->x = STBTT_ifloor(STBTT_FIX * e->x0 + z->dx * (start_point - e->y0)); // use z->dx so when we offset later it's by the same amount
  2520. z->x -= off_x * STBTT_FIX;
  2521. z->ey = e->y1;
  2522. z->next = 0;
  2523. z->direction = e->invert ? 1 : -1;
  2524. return z;
  2525. }
  2526. #elif STBTT_RASTERIZER_VERSION == 2
  2527. static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata)
  2528. {
  2529. stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);
  2530. float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
  2531. STBTT_assert(z != NULL);
  2532. //STBTT_assert(e->y0 <= start_point);
  2533. if (!z) return z;
  2534. z->fdx = dxdy;
  2535. z->fdy = dxdy != 0.0f ? (1.0f/dxdy) : 0.0f;
  2536. z->fx = e->x0 + dxdy * (start_point - e->y0);
  2537. z->fx -= off_x;
  2538. z->direction = e->invert ? 1.0f : -1.0f;
  2539. z->sy = e->y0;
  2540. z->ey = e->y1;
  2541. z->next = 0;
  2542. return z;
  2543. }
  2544. #else
  2545. #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
  2546. #endif
  2547. #if STBTT_RASTERIZER_VERSION == 1
  2548. // note: this routine clips fills that extend off the edges... ideally this
  2549. // wouldn't happen, but it could happen if the truetype glyph bounding boxes
  2550. // are wrong, or if the user supplies a too-small bitmap
  2551. static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__active_edge *e, int max_weight)
  2552. {
  2553. // non-zero winding fill
  2554. int x0=0, w=0;
  2555. while (e) {
  2556. if (w == 0) {
  2557. // if we're currently at zero, we need to record the edge start point
  2558. x0 = e->x; w += e->direction;
  2559. } else {
  2560. int x1 = e->x; w += e->direction;
  2561. // if we went to zero, we need to draw
  2562. if (w == 0) {
  2563. int i = x0 >> STBTT_FIXSHIFT;
  2564. int j = x1 >> STBTT_FIXSHIFT;
  2565. if (i < len && j >= 0) {
  2566. if (i == j) {
  2567. // x0,x1 are the same pixel, so compute combined coverage
  2568. scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> STBTT_FIXSHIFT);
  2569. } else {
  2570. if (i >= 0) // add antialiasing for x0
  2571. scanline[i] = scanline[i] + (stbtt_uint8) (((STBTT_FIX - (x0 & STBTT_FIXMASK)) * max_weight) >> STBTT_FIXSHIFT);
  2572. else
  2573. i = -1; // clip
  2574. if (j < len) // add antialiasing for x1
  2575. scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & STBTT_FIXMASK) * max_weight) >> STBTT_FIXSHIFT);
  2576. else
  2577. j = len; // clip
  2578. for (++i; i < j; ++i) // fill pixels between x0 and x1
  2579. scanline[i] = scanline[i] + (stbtt_uint8) max_weight;
  2580. }
  2581. }
  2582. }
  2583. }
  2584. e = e->next;
  2585. }
  2586. }
  2587. static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata)
  2588. {
  2589. stbtt__hheap hh = { 0, 0, 0 };
  2590. stbtt__active_edge *active = NULL;
  2591. int y,j=0;
  2592. int max_weight = (255 / vsubsample); // weight per vertical scanline
  2593. int s; // vertical subsample index
  2594. unsigned char scanline_data[512], *scanline;
  2595. if (result->w > 512)
  2596. scanline = (unsigned char *) STBTT_malloc(result->w, userdata);
  2597. else
  2598. scanline = scanline_data;
  2599. y = off_y * vsubsample;
  2600. e[n].y0 = (off_y + result->h) * (float) vsubsample + 1;
  2601. while (j < result->h) {
  2602. STBTT_memset(scanline, 0, result->w);
  2603. for (s=0; s < vsubsample; ++s) {
  2604. // find center of pixel for this scanline
  2605. float scan_y = y + 0.5f;
  2606. stbtt__active_edge **step = &active;
  2607. // update all active edges;
  2608. // remove all active edges that terminate before the center of this scanline
  2609. while (*step) {
  2610. stbtt__active_edge * z = *step;
  2611. if (z->ey <= scan_y) {
  2612. *step = z->next; // delete from list
  2613. STBTT_assert(z->direction);
  2614. z->direction = 0;
  2615. stbtt__hheap_free(&hh, z);
  2616. } else {
  2617. z->x += z->dx; // advance to position for current scanline
  2618. step = &((*step)->next); // advance through list
  2619. }
  2620. }
  2621. // resort the list if needed
  2622. for(;;) {
  2623. int changed=0;
  2624. step = &active;
  2625. while (*step && (*step)->next) {
  2626. if ((*step)->x > (*step)->next->x) {
  2627. stbtt__active_edge *t = *step;
  2628. stbtt__active_edge *q = t->next;
  2629. t->next = q->next;
  2630. q->next = t;
  2631. *step = q;
  2632. changed = 1;
  2633. }
  2634. step = &(*step)->next;
  2635. }
  2636. if (!changed) break;
  2637. }
  2638. // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline
  2639. while (e->y0 <= scan_y) {
  2640. if (e->y1 > scan_y) {
  2641. stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y, userdata);
  2642. if (z != NULL) {
  2643. // find insertion point
  2644. if (active == NULL)
  2645. active = z;
  2646. else if (z->x < active->x) {
  2647. // insert at front
  2648. z->next = active;
  2649. active = z;
  2650. } else {
  2651. // find thing to insert AFTER
  2652. stbtt__active_edge *p = active;
  2653. while (p->next && p->next->x < z->x)
  2654. p = p->next;
  2655. // at this point, p->next->x is NOT < z->x
  2656. z->next = p->next;
  2657. p->next = z;
  2658. }
  2659. }
  2660. }
  2661. ++e;
  2662. }
  2663. // now process all active edges in XOR fashion
  2664. if (active)
  2665. stbtt__fill_active_edges(scanline, result->w, active, max_weight);
  2666. ++y;
  2667. }
  2668. STBTT_memcpy(result->pixels + j * result->stride, scanline, result->w);
  2669. ++j;
  2670. }
  2671. stbtt__hheap_cleanup(&hh, userdata);
  2672. if (scanline != scanline_data)
  2673. STBTT_free(scanline, userdata);
  2674. }
  2675. #elif STBTT_RASTERIZER_VERSION == 2
  2676. // the edge passed in here does not cross the vertical line at x or the vertical line at x+1
  2677. // (i.e. it has already been clipped to those)
  2678. static void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edge *e, float x0, float y0, float x1, float y1)
  2679. {
  2680. if (y0 == y1) return;
  2681. STBTT_assert(y0 < y1);
  2682. STBTT_assert(e->sy <= e->ey);
  2683. if (y0 > e->ey) return;
  2684. if (y1 < e->sy) return;
  2685. if (y0 < e->sy) {
  2686. x0 += (x1-x0) * (e->sy - y0) / (y1-y0);
  2687. y0 = e->sy;
  2688. }
  2689. if (y1 > e->ey) {
  2690. x1 += (x1-x0) * (e->ey - y1) / (y1-y0);
  2691. y1 = e->ey;
  2692. }
  2693. if (x0 == x)
  2694. STBTT_assert(x1 <= x+1);
  2695. else if (x0 == x+1)
  2696. STBTT_assert(x1 >= x);
  2697. else if (x0 <= x)
  2698. STBTT_assert(x1 <= x);
  2699. else if (x0 >= x+1)
  2700. STBTT_assert(x1 >= x+1);
  2701. else
  2702. STBTT_assert(x1 >= x && x1 <= x+1);
  2703. if (x0 <= x && x1 <= x)
  2704. scanline[x] += e->direction * (y1-y0);
  2705. else if (x0 >= x+1 && x1 >= x+1)
  2706. ;
  2707. else {
  2708. STBTT_assert(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1);
  2709. scanline[x] += e->direction * (y1-y0) * (1-((x0-x)+(x1-x))/2); // coverage = 1 - average x position
  2710. }
  2711. }
  2712. static float stbtt__sized_trapezoid_area(float height, float top_width, float bottom_width)
  2713. {
  2714. STBTT_assert(top_width >= 0);
  2715. STBTT_assert(bottom_width >= 0);
  2716. return (top_width + bottom_width) / 2.0f * height;
  2717. }
  2718. static float stbtt__position_trapezoid_area(float height, float tx0, float tx1, float bx0, float bx1)
  2719. {
  2720. return stbtt__sized_trapezoid_area(height, tx1 - tx0, bx1 - bx0);
  2721. }
  2722. static float stbtt__sized_triangle_area(float height, float width)
  2723. {
  2724. return height * width / 2;
  2725. }
  2726. static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top)
  2727. {
  2728. float y_bottom = y_top+1;
  2729. while (e) {
  2730. // brute force every pixel
  2731. // compute intersection points with top & bottom
  2732. STBTT_assert(e->ey >= y_top);
  2733. if (e->fdx == 0) {
  2734. float x0 = e->fx;
  2735. if (x0 < len) {
  2736. if (x0 >= 0) {
  2737. stbtt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom);
  2738. stbtt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom);
  2739. } else {
  2740. stbtt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom);
  2741. }
  2742. }
  2743. } else {
  2744. float x0 = e->fx;
  2745. float dx = e->fdx;
  2746. float xb = x0 + dx;
  2747. float x_top, x_bottom;
  2748. float sy0,sy1;
  2749. float dy = e->fdy;
  2750. STBTT_assert(e->sy <= y_bottom && e->ey >= y_top);
  2751. // compute endpoints of line segment clipped to this scanline (if the
  2752. // line segment starts on this scanline. x0 is the intersection of the
  2753. // line with y_top, but that may be off the line segment.
  2754. if (e->sy > y_top) {
  2755. x_top = x0 + dx * (e->sy - y_top);
  2756. sy0 = e->sy;
  2757. } else {
  2758. x_top = x0;
  2759. sy0 = y_top;
  2760. }
  2761. if (e->ey < y_bottom) {
  2762. x_bottom = x0 + dx * (e->ey - y_top);
  2763. sy1 = e->ey;
  2764. } else {
  2765. x_bottom = xb;
  2766. sy1 = y_bottom;
  2767. }
  2768. if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) {
  2769. // from here on, we don't have to range check x values
  2770. if ((int) x_top == (int) x_bottom) {
  2771. float height;
  2772. // simple case, only spans one pixel
  2773. int x = (int) x_top;
  2774. height = (sy1 - sy0) * e->direction;
  2775. STBTT_assert(x >= 0 && x < len);
  2776. scanline[x] += stbtt__position_trapezoid_area(height, x_top, x+1.0f, x_bottom, x+1.0f);
  2777. scanline_fill[x] += height; // everything right of this pixel is filled
  2778. } else {
  2779. int x,x1,x2;
  2780. float y_crossing, y_final, step, sign, area;
  2781. // covers 2+ pixels
  2782. if (x_top > x_bottom) {
  2783. // flip scanline vertically; signed area is the same
  2784. float t;
  2785. sy0 = y_bottom - (sy0 - y_top);
  2786. sy1 = y_bottom - (sy1 - y_top);
  2787. t = sy0, sy0 = sy1, sy1 = t;
  2788. t = x_bottom, x_bottom = x_top, x_top = t;
  2789. dx = -dx;
  2790. dy = -dy;
  2791. t = x0, x0 = xb, xb = t;
  2792. }
  2793. STBTT_assert(dy >= 0);
  2794. STBTT_assert(dx >= 0);
  2795. x1 = (int) x_top;
  2796. x2 = (int) x_bottom;
  2797. // compute intersection with y axis at x1+1
  2798. y_crossing = y_top + dy * (x1+1 - x0);
  2799. // compute intersection with y axis at x2
  2800. y_final = y_top + dy * (x2 - x0);
  2801. // x1 x_top x2 x_bottom
  2802. // y_top +------|-----+------------+------------+--------|---+------------+
  2803. // | | | | | |
  2804. // | | | | | |
  2805. // sy0 | Txxxxx|............|............|............|............|
  2806. // y_crossing | *xxxxx.......|............|............|............|
  2807. // | | xxxxx..|............|............|............|
  2808. // | | /- xx*xxxx........|............|............|
  2809. // | | dy < | xxxxxx..|............|............|
  2810. // y_final | | \- | xx*xxx.........|............|
  2811. // sy1 | | | | xxxxxB...|............|
  2812. // | | | | | |
  2813. // | | | | | |
  2814. // y_bottom +------------+------------+------------+------------+------------+
  2815. //
  2816. // goal is to measure the area covered by '.' in each pixel
  2817. // if x2 is right at the right edge of x1, y_crossing can blow up, github #1057
  2818. // @TODO: maybe test against sy1 rather than y_bottom?
  2819. if (y_crossing > y_bottom)
  2820. y_crossing = y_bottom;
  2821. sign = e->direction;
  2822. // area of the rectangle covered from sy0..y_crossing
  2823. area = sign * (y_crossing-sy0);
  2824. // area of the triangle (x_top,sy0), (x1+1,sy0), (x1+1,y_crossing)
  2825. scanline[x1] += stbtt__sized_triangle_area(area, x1+1 - x_top);
  2826. // check if final y_crossing is blown up; no test case for this
  2827. if (y_final > y_bottom) {
  2828. int denom = (x2 - (x1+1));
  2829. y_final = y_bottom;
  2830. if (denom != 0) { // [DEAR IMGUI] Avoid div by zero (https://github.com/nothings/stb/issues/1316)
  2831. dy = (y_final - y_crossing ) / denom; // if denom=0, y_final = y_crossing, so y_final <= y_bottom
  2832. }
  2833. }
  2834. // in second pixel, area covered by line segment found in first pixel
  2835. // is always a rectangle 1 wide * the height of that line segment; this
  2836. // is exactly what the variable 'area' stores. it also gets a contribution
  2837. // from the line segment within it. the THIRD pixel will get the first
  2838. // pixel's rectangle contribution, the second pixel's rectangle contribution,
  2839. // and its own contribution. the 'own contribution' is the same in every pixel except
  2840. // the leftmost and rightmost, a trapezoid that slides down in each pixel.
  2841. // the second pixel's contribution to the third pixel will be the
  2842. // rectangle 1 wide times the height change in the second pixel, which is dy.
  2843. step = sign * dy * 1; // dy is dy/dx, change in y for every 1 change in x,
  2844. // which multiplied by 1-pixel-width is how much pixel area changes for each step in x
  2845. // so the area advances by 'step' every time
  2846. for (x = x1+1; x < x2; ++x) {
  2847. scanline[x] += area + step/2; // area of trapezoid is 1*step/2
  2848. area += step;
  2849. }
  2850. STBTT_assert(STBTT_fabs(area) <= 1.01f); // accumulated error from area += step unless we round step down
  2851. STBTT_assert(sy1 > y_final-0.01f);
  2852. // area covered in the last pixel is the rectangle from all the pixels to the left,
  2853. // plus the trapezoid filled by the line segment in this pixel all the way to the right edge
  2854. scanline[x2] += area + sign * stbtt__position_trapezoid_area(sy1-y_final, (float) x2, x2+1.0f, x_bottom, x2+1.0f);
  2855. // the rest of the line is filled based on the total height of the line segment in this pixel
  2856. scanline_fill[x2] += sign * (sy1-sy0);
  2857. }
  2858. } else {
  2859. // if edge goes outside of box we're drawing, we require
  2860. // clipping logic. since this does not match the intended use
  2861. // of this library, we use a different, very slow brute
  2862. // force implementation
  2863. // note though that this does happen some of the time because
  2864. // x_top and x_bottom can be extrapolated at the top & bottom of
  2865. // the shape and actually lie outside the bounding box
  2866. int x;
  2867. for (x=0; x < len; ++x) {
  2868. // cases:
  2869. //
  2870. // there can be up to two intersections with the pixel. any intersection
  2871. // with left or right edges can be handled by splitting into two (or three)
  2872. // regions. intersections with top & bottom do not necessitate case-wise logic.
  2873. //
  2874. // the old way of doing this found the intersections with the left & right edges,
  2875. // then used some simple logic to produce up to three segments in sorted order
  2876. // from top-to-bottom. however, this had a problem: if an x edge was epsilon
  2877. // across the x border, then the corresponding y position might not be distinct
  2878. // from the other y segment, and it might ignored as an empty segment. to avoid
  2879. // that, we need to explicitly produce segments based on x positions.
  2880. // rename variables to clearly-defined pairs
  2881. float y0 = y_top;
  2882. float x1 = (float) (x);
  2883. float x2 = (float) (x+1);
  2884. float x3 = xb;
  2885. float y3 = y_bottom;
  2886. // x = e->x + e->dx * (y-y_top)
  2887. // (y-y_top) = (x - e->x) / e->dx
  2888. // y = (x - e->x) / e->dx + y_top
  2889. float y1 = (x - x0) / dx + y_top;
  2890. float y2 = (x+1 - x0) / dx + y_top;
  2891. if (x0 < x1 && x3 > x2) { // three segments descending down-right
  2892. stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
  2893. stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x2,y2);
  2894. stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
  2895. } else if (x3 < x1 && x0 > x2) { // three segments descending down-left
  2896. stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);
  2897. stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x1,y1);
  2898. stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);
  2899. } else if (x0 < x1 && x3 > x1) { // two segments across x, down-right
  2900. stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
  2901. stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);
  2902. } else if (x3 < x1 && x0 > x1) { // two segments across x, down-left
  2903. stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
  2904. stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);
  2905. } else if (x0 < x2 && x3 > x2) { // two segments across x+1, down-right
  2906. stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);
  2907. stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
  2908. } else if (x3 < x2 && x0 > x2) { // two segments across x+1, down-left
  2909. stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);
  2910. stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
  2911. } else { // one segment
  2912. stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x3,y3);
  2913. }
  2914. }
  2915. }
  2916. }
  2917. e = e->next;
  2918. }
  2919. }
  2920. // directly AA rasterize edges w/o supersampling
  2921. static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata)
  2922. {
  2923. stbtt__hheap hh = { 0, 0, 0 };
  2924. stbtt__active_edge *active = NULL;
  2925. int y,j=0, i;
  2926. float scanline_data[129], *scanline, *scanline2;
  2927. STBTT__NOTUSED(vsubsample);
  2928. if (result->w > 64)
  2929. scanline = (float *) STBTT_malloc((result->w*2+1) * sizeof(float), userdata);
  2930. else
  2931. scanline = scanline_data;
  2932. scanline2 = scanline + result->w;
  2933. y = off_y;
  2934. e[n].y0 = (float) (off_y + result->h) + 1;
  2935. while (j < result->h) {
  2936. // find center of pixel for this scanline
  2937. float scan_y_top = y + 0.0f;
  2938. float scan_y_bottom = y + 1.0f;
  2939. stbtt__active_edge **step = &active;
  2940. STBTT_memset(scanline , 0, result->w*sizeof(scanline[0]));
  2941. STBTT_memset(scanline2, 0, (result->w+1)*sizeof(scanline[0]));
  2942. // update all active edges;
  2943. // remove all active edges that terminate before the top of this scanline
  2944. while (*step) {
  2945. stbtt__active_edge * z = *step;
  2946. if (z->ey <= scan_y_top) {
  2947. *step = z->next; // delete from list
  2948. STBTT_assert(z->direction);
  2949. z->direction = 0;
  2950. stbtt__hheap_free(&hh, z);
  2951. } else {
  2952. step = &((*step)->next); // advance through list
  2953. }
  2954. }
  2955. // insert all edges that start before the bottom of this scanline
  2956. while (e->y0 <= scan_y_bottom) {
  2957. if (e->y0 != e->y1) {
  2958. stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata);
  2959. if (z != NULL) {
  2960. if (j == 0 && off_y != 0) {
  2961. if (z->ey < scan_y_top) {
  2962. // this can happen due to subpixel positioning and some kind of fp rounding error i think
  2963. z->ey = scan_y_top;
  2964. }
  2965. }
  2966. STBTT_assert(z->ey >= scan_y_top); // if we get really unlucky a tiny bit of an edge can be out of bounds
  2967. // insert at front
  2968. z->next = active;
  2969. active = z;
  2970. }
  2971. }
  2972. ++e;
  2973. }
  2974. // now process all active edges
  2975. if (active)
  2976. stbtt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top);
  2977. {
  2978. float sum = 0;
  2979. for (i=0; i < result->w; ++i) {
  2980. float k;
  2981. int m;
  2982. sum += scanline2[i];
  2983. k = scanline[i] + sum;
  2984. k = (float) STBTT_fabs(k)*255 + 0.5f;
  2985. m = (int) k;
  2986. if (m > 255) m = 255;
  2987. result->pixels[j*result->stride + i] = (unsigned char) m;
  2988. }
  2989. }
  2990. // advance all the edges
  2991. step = &active;
  2992. while (*step) {
  2993. stbtt__active_edge *z = *step;
  2994. z->fx += z->fdx; // advance to position for current scanline
  2995. step = &((*step)->next); // advance through list
  2996. }
  2997. ++y;
  2998. ++j;
  2999. }
  3000. stbtt__hheap_cleanup(&hh, userdata);
  3001. if (scanline != scanline_data)
  3002. STBTT_free(scanline, userdata);
  3003. }
  3004. #else
  3005. #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
  3006. #endif
  3007. #define STBTT__COMPARE(a,b) ((a)->y0 < (b)->y0)
  3008. static void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n)
  3009. {
  3010. int i,j;
  3011. for (i=1; i < n; ++i) {
  3012. stbtt__edge t = p[i], *a = &t;
  3013. j = i;
  3014. while (j > 0) {
  3015. stbtt__edge *b = &p[j-1];
  3016. int c = STBTT__COMPARE(a,b);
  3017. if (!c) break;
  3018. p[j] = p[j-1];
  3019. --j;
  3020. }
  3021. if (i != j)
  3022. p[j] = t;
  3023. }
  3024. }
  3025. static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n)
  3026. {
  3027. /* threshold for transitioning to insertion sort */
  3028. while (n > 12) {
  3029. stbtt__edge t;
  3030. int c01,c12,c,m,i,j;
  3031. /* compute median of three */
  3032. m = n >> 1;
  3033. c01 = STBTT__COMPARE(&p[0],&p[m]);
  3034. c12 = STBTT__COMPARE(&p[m],&p[n-1]);
  3035. /* if 0 >= mid >= end, or 0 < mid < end, then use mid */
  3036. if (c01 != c12) {
  3037. /* otherwise, we'll need to swap something else to middle */
  3038. int z;
  3039. c = STBTT__COMPARE(&p[0],&p[n-1]);
  3040. /* 0>mid && mid<n: 0>n => n; 0<n => 0 */
  3041. /* 0<mid && mid>n: 0>n => 0; 0<n => n */
  3042. z = (c == c12) ? 0 : n-1;
  3043. t = p[z];
  3044. p[z] = p[m];
  3045. p[m] = t;
  3046. }
  3047. /* now p[m] is the median-of-three */
  3048. /* swap it to the beginning so it won't move around */
  3049. t = p[0];
  3050. p[0] = p[m];
  3051. p[m] = t;
  3052. /* partition loop */
  3053. i=1;
  3054. j=n-1;
  3055. for(;;) {
  3056. /* handling of equality is crucial here */
  3057. /* for sentinels & efficiency with duplicates */
  3058. for (;;++i) {
  3059. if (!STBTT__COMPARE(&p[i], &p[0])) break;
  3060. }
  3061. for (;;--j) {
  3062. if (!STBTT__COMPARE(&p[0], &p[j])) break;
  3063. }
  3064. /* make sure we haven't crossed */
  3065. if (i >= j) break;
  3066. t = p[i];
  3067. p[i] = p[j];
  3068. p[j] = t;
  3069. ++i;
  3070. --j;
  3071. }
  3072. /* recurse on smaller side, iterate on larger */
  3073. if (j < (n-i)) {
  3074. stbtt__sort_edges_quicksort(p,j);
  3075. p = p+i;
  3076. n = n-i;
  3077. } else {
  3078. stbtt__sort_edges_quicksort(p+i, n-i);
  3079. n = j;
  3080. }
  3081. }
  3082. }
  3083. static void stbtt__sort_edges(stbtt__edge *p, int n)
  3084. {
  3085. stbtt__sort_edges_quicksort(p, n);
  3086. stbtt__sort_edges_ins_sort(p, n);
  3087. }
  3088. typedef struct
  3089. {
  3090. float x,y;
  3091. } stbtt__point;
  3092. static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x, float scale_y, float shift_x, float shift_y, int off_x, int off_y, int invert, void *userdata)
  3093. {
  3094. float y_scale_inv = invert ? -scale_y : scale_y;
  3095. stbtt__edge *e;
  3096. int n,i,j,k,m;
  3097. #if STBTT_RASTERIZER_VERSION == 1
  3098. int vsubsample = result->h < 8 ? 15 : 5;
  3099. #elif STBTT_RASTERIZER_VERSION == 2
  3100. int vsubsample = 1;
  3101. #else
  3102. #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
  3103. #endif
  3104. // vsubsample should divide 255 evenly; otherwise we won't reach full opacity
  3105. // now we have to blow out the windings into explicit edge lists
  3106. n = 0;
  3107. for (i=0; i < windings; ++i)
  3108. n += wcount[i];
  3109. e = (stbtt__edge *) STBTT_malloc(sizeof(*e) * (n+1), userdata); // add an extra one as a sentinel
  3110. if (e == 0) return;
  3111. n = 0;
  3112. m=0;
  3113. for (i=0; i < windings; ++i) {
  3114. stbtt__point *p = pts + m;
  3115. m += wcount[i];
  3116. j = wcount[i]-1;
  3117. for (k=0; k < wcount[i]; j=k++) {
  3118. int a=k,b=j;
  3119. // skip the edge if horizontal
  3120. if (p[j].y == p[k].y)
  3121. continue;
  3122. // add edge from j to k to the list
  3123. e[n].invert = 0;
  3124. if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) {
  3125. e[n].invert = 1;
  3126. a=j,b=k;
  3127. }
  3128. e[n].x0 = p[a].x * scale_x + shift_x;
  3129. e[n].y0 = (p[a].y * y_scale_inv + shift_y) * vsubsample;
  3130. e[n].x1 = p[b].x * scale_x + shift_x;
  3131. e[n].y1 = (p[b].y * y_scale_inv + shift_y) * vsubsample;
  3132. ++n;
  3133. }
  3134. }
  3135. // now sort the edges by their highest point (should snap to integer, and then by x)
  3136. //STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare);
  3137. stbtt__sort_edges(e, n);
  3138. // now, traverse the scanlines and find the intersections on each scanline, use xor winding rule
  3139. stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata);
  3140. STBTT_free(e, userdata);
  3141. }
  3142. static void stbtt__add_point(stbtt__point *points, int n, float x, float y)
  3143. {
  3144. if (!points) return; // during first pass, it's unallocated
  3145. points[n].x = x;
  3146. points[n].y = y;
  3147. }
  3148. // tessellate until threshold p is happy... @TODO warped to compensate for non-linear stretching
  3149. static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float objspace_flatness_squared, int n)
  3150. {
  3151. // midpoint
  3152. float mx = (x0 + 2*x1 + x2)/4;
  3153. float my = (y0 + 2*y1 + y2)/4;
  3154. // versus directly drawn line
  3155. float dx = (x0+x2)/2 - mx;
  3156. float dy = (y0+y2)/2 - my;
  3157. if (n > 16) // 65536 segments on one curve better be enough!
  3158. return 1;
  3159. if (dx*dx+dy*dy > objspace_flatness_squared) { // half-pixel error allowed... need to be smaller if AA
  3160. stbtt__tesselate_curve(points, num_points, x0,y0, (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1);
  3161. stbtt__tesselate_curve(points, num_points, mx,my, (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1);
  3162. } else {
  3163. stbtt__add_point(points, *num_points,x2,y2);
  3164. *num_points = *num_points+1;
  3165. }
  3166. return 1;
  3167. }
  3168. static void stbtt__tesselate_cubic(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float objspace_flatness_squared, int n)
  3169. {
  3170. // @TODO this "flatness" calculation is just made-up nonsense that seems to work well enough
  3171. float dx0 = x1-x0;
  3172. float dy0 = y1-y0;
  3173. float dx1 = x2-x1;
  3174. float dy1 = y2-y1;
  3175. float dx2 = x3-x2;
  3176. float dy2 = y3-y2;
  3177. float dx = x3-x0;
  3178. float dy = y3-y0;
  3179. float longlen = (float) (STBTT_sqrt(dx0*dx0+dy0*dy0)+STBTT_sqrt(dx1*dx1+dy1*dy1)+STBTT_sqrt(dx2*dx2+dy2*dy2));
  3180. float shortlen = (float) STBTT_sqrt(dx*dx+dy*dy);
  3181. float flatness_squared = longlen*longlen-shortlen*shortlen;
  3182. if (n > 16) // 65536 segments on one curve better be enough!
  3183. return;
  3184. if (flatness_squared > objspace_flatness_squared) {
  3185. float x01 = (x0+x1)/2;
  3186. float y01 = (y0+y1)/2;
  3187. float x12 = (x1+x2)/2;
  3188. float y12 = (y1+y2)/2;
  3189. float x23 = (x2+x3)/2;
  3190. float y23 = (y2+y3)/2;
  3191. float xa = (x01+x12)/2;
  3192. float ya = (y01+y12)/2;
  3193. float xb = (x12+x23)/2;
  3194. float yb = (y12+y23)/2;
  3195. float mx = (xa+xb)/2;
  3196. float my = (ya+yb)/2;
  3197. stbtt__tesselate_cubic(points, num_points, x0,y0, x01,y01, xa,ya, mx,my, objspace_flatness_squared,n+1);
  3198. stbtt__tesselate_cubic(points, num_points, mx,my, xb,yb, x23,y23, x3,y3, objspace_flatness_squared,n+1);
  3199. } else {
  3200. stbtt__add_point(points, *num_points,x3,y3);
  3201. *num_points = *num_points+1;
  3202. }
  3203. }
  3204. // returns number of contours
  3205. static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata)
  3206. {
  3207. stbtt__point *points=0;
  3208. int num_points=0;
  3209. float objspace_flatness_squared = objspace_flatness * objspace_flatness;
  3210. int i,n=0,start=0, pass;
  3211. // count how many "moves" there are to get the contour count
  3212. for (i=0; i < num_verts; ++i)
  3213. if (vertices[i].type == STBTT_vmove)
  3214. ++n;
  3215. *num_contours = n;
  3216. if (n == 0) return 0;
  3217. *contour_lengths = (int *) STBTT_malloc(sizeof(**contour_lengths) * n, userdata);
  3218. if (*contour_lengths == 0) {
  3219. *num_contours = 0;
  3220. return 0;
  3221. }
  3222. // make two passes through the points so we don't need to realloc
  3223. for (pass=0; pass < 2; ++pass) {
  3224. float x=0,y=0;
  3225. if (pass == 1) {
  3226. points = (stbtt__point *) STBTT_malloc(num_points * sizeof(points[0]), userdata);
  3227. if (points == NULL) goto error;
  3228. }
  3229. num_points = 0;
  3230. n= -1;
  3231. for (i=0; i < num_verts; ++i) {
  3232. switch (vertices[i].type) {
  3233. case STBTT_vmove:
  3234. // start the next contour
  3235. if (n >= 0)
  3236. (*contour_lengths)[n] = num_points - start;
  3237. ++n;
  3238. start = num_points;
  3239. x = vertices[i].x, y = vertices[i].y;
  3240. stbtt__add_point(points, num_points++, x,y);
  3241. break;
  3242. case STBTT_vline:
  3243. x = vertices[i].x, y = vertices[i].y;
  3244. stbtt__add_point(points, num_points++, x, y);
  3245. break;
  3246. case STBTT_vcurve:
  3247. stbtt__tesselate_curve(points, &num_points, x,y,
  3248. vertices[i].cx, vertices[i].cy,
  3249. vertices[i].x, vertices[i].y,
  3250. objspace_flatness_squared, 0);
  3251. x = vertices[i].x, y = vertices[i].y;
  3252. break;
  3253. case STBTT_vcubic:
  3254. stbtt__tesselate_cubic(points, &num_points, x,y,
  3255. vertices[i].cx, vertices[i].cy,
  3256. vertices[i].cx1, vertices[i].cy1,
  3257. vertices[i].x, vertices[i].y,
  3258. objspace_flatness_squared, 0);
  3259. x = vertices[i].x, y = vertices[i].y;
  3260. break;
  3261. }
  3262. }
  3263. (*contour_lengths)[n] = num_points - start;
  3264. }
  3265. return points;
  3266. error:
  3267. STBTT_free(points, userdata);
  3268. STBTT_free(*contour_lengths, userdata);
  3269. *contour_lengths = 0;
  3270. *num_contours = 0;
  3271. return NULL;
  3272. }
  3273. STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata)
  3274. {
  3275. float scale = scale_x > scale_y ? scale_y : scale_x;
  3276. int winding_count = 0;
  3277. int *winding_lengths = NULL;
  3278. stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata);
  3279. if (windings) {
  3280. stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata);
  3281. STBTT_free(winding_lengths, userdata);
  3282. STBTT_free(windings, userdata);
  3283. }
  3284. }
  3285. STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata)
  3286. {
  3287. STBTT_free(bitmap, userdata);
  3288. }
  3289. STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff)
  3290. {
  3291. int ix0,iy0,ix1,iy1;
  3292. stbtt__bitmap gbm;
  3293. stbtt_vertex *vertices;
  3294. int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
  3295. if (scale_x == 0) scale_x = scale_y;
  3296. if (scale_y == 0) {
  3297. if (scale_x == 0) {
  3298. STBTT_free(vertices, info->userdata);
  3299. return NULL;
  3300. }
  3301. scale_y = scale_x;
  3302. }
  3303. stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,&ix1,&iy1);
  3304. // now we get the size
  3305. gbm.w = (ix1 - ix0);
  3306. gbm.h = (iy1 - iy0);
  3307. gbm.pixels = NULL; // in case we error
  3308. if (width ) *width = gbm.w;
  3309. if (height) *height = gbm.h;
  3310. if (xoff ) *xoff = ix0;
  3311. if (yoff ) *yoff = iy0;
  3312. if (gbm.w && gbm.h) {
  3313. gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata);
  3314. if (gbm.pixels) {
  3315. gbm.stride = gbm.w;
  3316. stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, iy0, 1, info->userdata);
  3317. }
  3318. }
  3319. STBTT_free(vertices, info->userdata);
  3320. return gbm.pixels;
  3321. }
  3322. STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff)
  3323. {
  3324. return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y, 0.0f, 0.0f, glyph, width, height, xoff, yoff);
  3325. }
  3326. STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph)
  3327. {
  3328. int ix0,iy0;
  3329. stbtt_vertex *vertices;
  3330. int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
  3331. stbtt__bitmap gbm;
  3332. stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0);
  3333. gbm.pixels = output;
  3334. gbm.w = out_w;
  3335. gbm.h = out_h;
  3336. gbm.stride = out_stride;
  3337. if (gbm.w && gbm.h)
  3338. stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0,iy0, 1, info->userdata);
  3339. STBTT_free(vertices, info->userdata);
  3340. }
  3341. STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph)
  3342. {
  3343. stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, glyph);
  3344. }
  3345. STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff)
  3346. {
  3347. return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff);
  3348. }
  3349. STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint)
  3350. {
  3351. stbtt_MakeGlyphBitmapSubpixelPrefilter(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, oversample_x, oversample_y, sub_x, sub_y, stbtt_FindGlyphIndex(info,codepoint));
  3352. }
  3353. STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint)
  3354. {
  3355. stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info,codepoint));
  3356. }
  3357. STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff)
  3358. {
  3359. return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, codepoint, width,height,xoff,yoff);
  3360. }
  3361. STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint)
  3362. {
  3363. stbtt_MakeCodepointBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, codepoint);
  3364. }
  3365. //////////////////////////////////////////////////////////////////////////////
  3366. //
  3367. // bitmap baking
  3368. //
  3369. // This is SUPER-CRAPPY packing to keep source code small
  3370. static int stbtt_BakeFontBitmap_internal(unsigned char *data, int offset, // font location (use offset=0 for plain .ttf)
  3371. float pixel_height, // height of font in pixels
  3372. unsigned char *pixels, int pw, int ph, // bitmap to be filled in
  3373. int first_char, int num_chars, // characters to bake
  3374. stbtt_bakedchar *chardata)
  3375. {
  3376. float scale;
  3377. int x,y,bottom_y, i;
  3378. stbtt_fontinfo f;
  3379. f.userdata = NULL;
  3380. if (!stbtt_InitFont(&f, data, offset))
  3381. return -1;
  3382. STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels
  3383. x=y=1;
  3384. bottom_y = 1;
  3385. scale = stbtt_ScaleForPixelHeight(&f, pixel_height);
  3386. for (i=0; i < num_chars; ++i) {
  3387. int advance, lsb, x0,y0,x1,y1,gw,gh;
  3388. int g = stbtt_FindGlyphIndex(&f, first_char + i);
  3389. stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb);
  3390. stbtt_GetGlyphBitmapBox(&f, g, scale,scale, &x0,&y0,&x1,&y1);
  3391. gw = x1-x0;
  3392. gh = y1-y0;
  3393. if (x + gw + 1 >= pw)
  3394. y = bottom_y, x = 1; // advance to next row
  3395. if (y + gh + 1 >= ph) // check if it fits vertically AFTER potentially moving to next row
  3396. return -i;
  3397. STBTT_assert(x+gw < pw);
  3398. STBTT_assert(y+gh < ph);
  3399. stbtt_MakeGlyphBitmap(&f, pixels+x+y*pw, gw,gh,pw, scale,scale, g);
  3400. chardata[i].x0 = (stbtt_int16) x;
  3401. chardata[i].y0 = (stbtt_int16) y;
  3402. chardata[i].x1 = (stbtt_int16) (x + gw);
  3403. chardata[i].y1 = (stbtt_int16) (y + gh);
  3404. chardata[i].xadvance = scale * advance;
  3405. chardata[i].xoff = (float) x0;
  3406. chardata[i].yoff = (float) y0;
  3407. x = x + gw + 1;
  3408. if (y+gh+1 > bottom_y)
  3409. bottom_y = y+gh+1;
  3410. }
  3411. return bottom_y;
  3412. }
  3413. STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule)
  3414. {
  3415. float d3d_bias = opengl_fillrule ? 0 : -0.5f;
  3416. float ipw = 1.0f / pw, iph = 1.0f / ph;
  3417. const stbtt_bakedchar *b = chardata + char_index;
  3418. int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5f);
  3419. int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5f);
  3420. q->x0 = round_x + d3d_bias;
  3421. q->y0 = round_y + d3d_bias;
  3422. q->x1 = round_x + b->x1 - b->x0 + d3d_bias;
  3423. q->y1 = round_y + b->y1 - b->y0 + d3d_bias;
  3424. q->s0 = b->x0 * ipw;
  3425. q->t0 = b->y0 * iph;
  3426. q->s1 = b->x1 * ipw;
  3427. q->t1 = b->y1 * iph;
  3428. *xpos += b->xadvance;
  3429. }
  3430. //////////////////////////////////////////////////////////////////////////////
  3431. //
  3432. // rectangle packing replacement routines if you don't have stb_rect_pack.h
  3433. //
  3434. #ifndef STB_RECT_PACK_VERSION
  3435. typedef int stbrp_coord;
  3436. ////////////////////////////////////////////////////////////////////////////////////
  3437. // //
  3438. // //
  3439. // COMPILER WARNING ?!?!? //
  3440. // //
  3441. // //
  3442. // if you get a compile warning due to these symbols being defined more than //
  3443. // once, move #include "stb_rect_pack.h" before #include "stb_truetype.h" //
  3444. // //
  3445. ////////////////////////////////////////////////////////////////////////////////////
  3446. typedef struct
  3447. {
  3448. int width,height;
  3449. int x,y,bottom_y;
  3450. } stbrp_context;
  3451. typedef struct
  3452. {
  3453. unsigned char x;
  3454. } stbrp_node;
  3455. struct stbrp_rect
  3456. {
  3457. stbrp_coord x,y;
  3458. int id,w,h,was_packed;
  3459. };
  3460. static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *nodes, int num_nodes)
  3461. {
  3462. con->width = pw;
  3463. con->height = ph;
  3464. con->x = 0;
  3465. con->y = 0;
  3466. con->bottom_y = 0;
  3467. STBTT__NOTUSED(nodes);
  3468. STBTT__NOTUSED(num_nodes);
  3469. }
  3470. static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rects)
  3471. {
  3472. int i;
  3473. for (i=0; i < num_rects; ++i) {
  3474. if (con->x + rects[i].w > con->width) {
  3475. con->x = 0;
  3476. con->y = con->bottom_y;
  3477. }
  3478. if (con->y + rects[i].h > con->height)
  3479. break;
  3480. rects[i].x = con->x;
  3481. rects[i].y = con->y;
  3482. rects[i].was_packed = 1;
  3483. con->x += rects[i].w;
  3484. if (con->y + rects[i].h > con->bottom_y)
  3485. con->bottom_y = con->y + rects[i].h;
  3486. }
  3487. for ( ; i < num_rects; ++i)
  3488. rects[i].was_packed = 0;
  3489. }
  3490. #endif
  3491. //////////////////////////////////////////////////////////////////////////////
  3492. //
  3493. // bitmap baking
  3494. //
  3495. // This is SUPER-AWESOME (tm Ryan Gordon) packing using stb_rect_pack.h. If
  3496. // stb_rect_pack.h isn't available, it uses the BakeFontBitmap strategy.
  3497. STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int pw, int ph, int stride_in_bytes, int padding, void *alloc_context)
  3498. {
  3499. stbrp_context *context = (stbrp_context *) STBTT_malloc(sizeof(*context) ,alloc_context);
  3500. int num_nodes = pw - padding;
  3501. stbrp_node *nodes = (stbrp_node *) STBTT_malloc(sizeof(*nodes ) * num_nodes,alloc_context);
  3502. if (context == NULL || nodes == NULL) {
  3503. if (context != NULL) STBTT_free(context, alloc_context);
  3504. if (nodes != NULL) STBTT_free(nodes , alloc_context);
  3505. return 0;
  3506. }
  3507. spc->user_allocator_context = alloc_context;
  3508. spc->width = pw;
  3509. spc->height = ph;
  3510. spc->pixels = pixels;
  3511. spc->pack_info = context;
  3512. spc->nodes = nodes;
  3513. spc->padding = padding;
  3514. spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw;
  3515. spc->h_oversample = 1;
  3516. spc->v_oversample = 1;
  3517. spc->skip_missing = 0;
  3518. stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes);
  3519. if (pixels)
  3520. STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels
  3521. return 1;
  3522. }
  3523. STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc)
  3524. {
  3525. STBTT_free(spc->nodes , spc->user_allocator_context);
  3526. STBTT_free(spc->pack_info, spc->user_allocator_context);
  3527. }
  3528. STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample)
  3529. {
  3530. STBTT_assert(h_oversample <= STBTT_MAX_OVERSAMPLE);
  3531. STBTT_assert(v_oversample <= STBTT_MAX_OVERSAMPLE);
  3532. if (h_oversample <= STBTT_MAX_OVERSAMPLE)
  3533. spc->h_oversample = h_oversample;
  3534. if (v_oversample <= STBTT_MAX_OVERSAMPLE)
  3535. spc->v_oversample = v_oversample;
  3536. }
  3537. STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip)
  3538. {
  3539. spc->skip_missing = skip;
  3540. }
  3541. #define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1)
  3542. static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width)
  3543. {
  3544. unsigned char buffer[STBTT_MAX_OVERSAMPLE];
  3545. int safe_w = w - kernel_width;
  3546. int j;
  3547. STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze
  3548. for (j=0; j < h; ++j) {
  3549. int i;
  3550. unsigned int total;
  3551. STBTT_memset(buffer, 0, kernel_width);
  3552. total = 0;
  3553. // make kernel_width a constant in common cases so compiler can optimize out the divide
  3554. switch (kernel_width) {
  3555. case 2:
  3556. for (i=0; i <= safe_w; ++i) {
  3557. total += pixels[i] - buffer[i & STBTT__OVER_MASK];
  3558. buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
  3559. pixels[i] = (unsigned char) (total / 2);
  3560. }
  3561. break;
  3562. case 3:
  3563. for (i=0; i <= safe_w; ++i) {
  3564. total += pixels[i] - buffer[i & STBTT__OVER_MASK];
  3565. buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
  3566. pixels[i] = (unsigned char) (total / 3);
  3567. }
  3568. break;
  3569. case 4:
  3570. for (i=0; i <= safe_w; ++i) {
  3571. total += pixels[i] - buffer[i & STBTT__OVER_MASK];
  3572. buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
  3573. pixels[i] = (unsigned char) (total / 4);
  3574. }
  3575. break;
  3576. case 5:
  3577. for (i=0; i <= safe_w; ++i) {
  3578. total += pixels[i] - buffer[i & STBTT__OVER_MASK];
  3579. buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
  3580. pixels[i] = (unsigned char) (total / 5);
  3581. }
  3582. break;
  3583. default:
  3584. for (i=0; i <= safe_w; ++i) {
  3585. total += pixels[i] - buffer[i & STBTT__OVER_MASK];
  3586. buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
  3587. pixels[i] = (unsigned char) (total / kernel_width);
  3588. }
  3589. break;
  3590. }
  3591. for (; i < w; ++i) {
  3592. STBTT_assert(pixels[i] == 0);
  3593. total -= buffer[i & STBTT__OVER_MASK];
  3594. pixels[i] = (unsigned char) (total / kernel_width);
  3595. }
  3596. pixels += stride_in_bytes;
  3597. }
  3598. }
  3599. static void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width)
  3600. {
  3601. unsigned char buffer[STBTT_MAX_OVERSAMPLE];
  3602. int safe_h = h - kernel_width;
  3603. int j;
  3604. STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze
  3605. for (j=0; j < w; ++j) {
  3606. int i;
  3607. unsigned int total;
  3608. STBTT_memset(buffer, 0, kernel_width);
  3609. total = 0;
  3610. // make kernel_width a constant in common cases so compiler can optimize out the divide
  3611. switch (kernel_width) {
  3612. case 2:
  3613. for (i=0; i <= safe_h; ++i) {
  3614. total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
  3615. buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
  3616. pixels[i*stride_in_bytes] = (unsigned char) (total / 2);
  3617. }
  3618. break;
  3619. case 3:
  3620. for (i=0; i <= safe_h; ++i) {
  3621. total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
  3622. buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
  3623. pixels[i*stride_in_bytes] = (unsigned char) (total / 3);
  3624. }
  3625. break;
  3626. case 4:
  3627. for (i=0; i <= safe_h; ++i) {
  3628. total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
  3629. buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
  3630. pixels[i*stride_in_bytes] = (unsigned char) (total / 4);
  3631. }
  3632. break;
  3633. case 5:
  3634. for (i=0; i <= safe_h; ++i) {
  3635. total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
  3636. buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
  3637. pixels[i*stride_in_bytes] = (unsigned char) (total / 5);
  3638. }
  3639. break;
  3640. default:
  3641. for (i=0; i <= safe_h; ++i) {
  3642. total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
  3643. buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
  3644. pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width);
  3645. }
  3646. break;
  3647. }
  3648. for (; i < h; ++i) {
  3649. STBTT_assert(pixels[i*stride_in_bytes] == 0);
  3650. total -= buffer[i & STBTT__OVER_MASK];
  3651. pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width);
  3652. }
  3653. pixels += 1;
  3654. }
  3655. }
  3656. static float stbtt__oversample_shift(int oversample)
  3657. {
  3658. if (!oversample)
  3659. return 0.0f;
  3660. // The prefilter is a box filter of width "oversample",
  3661. // which shifts phase by (oversample - 1)/2 pixels in
  3662. // oversampled space. We want to shift in the opposite
  3663. // direction to counter this.
  3664. return (float)-(oversample - 1) / (2.0f * (float)oversample);
  3665. }
  3666. // rects array must be big enough to accommodate all characters in the given ranges
  3667. STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
  3668. {
  3669. int i,j,k;
  3670. int missing_glyph_added = 0;
  3671. k=0;
  3672. for (i=0; i < num_ranges; ++i) {
  3673. float fh = ranges[i].font_size;
  3674. float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh);
  3675. ranges[i].h_oversample = (unsigned char) spc->h_oversample;
  3676. ranges[i].v_oversample = (unsigned char) spc->v_oversample;
  3677. for (j=0; j < ranges[i].num_chars; ++j) {
  3678. int x0,y0,x1,y1;
  3679. int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
  3680. int glyph = stbtt_FindGlyphIndex(info, codepoint);
  3681. if (glyph == 0 && (spc->skip_missing || missing_glyph_added)) {
  3682. rects[k].w = rects[k].h = 0;
  3683. } else {
  3684. stbtt_GetGlyphBitmapBoxSubpixel(info,glyph,
  3685. scale * spc->h_oversample,
  3686. scale * spc->v_oversample,
  3687. 0,0,
  3688. &x0,&y0,&x1,&y1);
  3689. rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1);
  3690. rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1);
  3691. if (glyph == 0)
  3692. missing_glyph_added = 1;
  3693. }
  3694. ++k;
  3695. }
  3696. }
  3697. return k;
  3698. }
  3699. STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int prefilter_x, int prefilter_y, float *sub_x, float *sub_y, int glyph)
  3700. {
  3701. stbtt_MakeGlyphBitmapSubpixel(info,
  3702. output,
  3703. out_w - (prefilter_x - 1),
  3704. out_h - (prefilter_y - 1),
  3705. out_stride,
  3706. scale_x,
  3707. scale_y,
  3708. shift_x,
  3709. shift_y,
  3710. glyph);
  3711. if (prefilter_x > 1)
  3712. stbtt__h_prefilter(output, out_w, out_h, out_stride, prefilter_x);
  3713. if (prefilter_y > 1)
  3714. stbtt__v_prefilter(output, out_w, out_h, out_stride, prefilter_y);
  3715. *sub_x = stbtt__oversample_shift(prefilter_x);
  3716. *sub_y = stbtt__oversample_shift(prefilter_y);
  3717. }
  3718. // rects array must be big enough to accommodate all characters in the given ranges
  3719. STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
  3720. {
  3721. int i,j,k, missing_glyph = -1, return_value = 1;
  3722. // save current values
  3723. int old_h_over = spc->h_oversample;
  3724. int old_v_over = spc->v_oversample;
  3725. k = 0;
  3726. for (i=0; i < num_ranges; ++i) {
  3727. float fh = ranges[i].font_size;
  3728. float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh);
  3729. float recip_h,recip_v,sub_x,sub_y;
  3730. spc->h_oversample = ranges[i].h_oversample;
  3731. spc->v_oversample = ranges[i].v_oversample;
  3732. recip_h = 1.0f / spc->h_oversample;
  3733. recip_v = 1.0f / spc->v_oversample;
  3734. sub_x = stbtt__oversample_shift(spc->h_oversample);
  3735. sub_y = stbtt__oversample_shift(spc->v_oversample);
  3736. for (j=0; j < ranges[i].num_chars; ++j) {
  3737. stbrp_rect *r = &rects[k];
  3738. if (r->was_packed && r->w != 0 && r->h != 0) {
  3739. stbtt_packedchar *bc = &ranges[i].chardata_for_range[j];
  3740. int advance, lsb, x0,y0,x1,y1;
  3741. int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
  3742. int glyph = stbtt_FindGlyphIndex(info, codepoint);
  3743. stbrp_coord pad = (stbrp_coord) spc->padding;
  3744. // pad on left and top
  3745. r->x += pad;
  3746. r->y += pad;
  3747. r->w -= pad;
  3748. r->h -= pad;
  3749. stbtt_GetGlyphHMetrics(info, glyph, &advance, &lsb);
  3750. stbtt_GetGlyphBitmapBox(info, glyph,
  3751. scale * spc->h_oversample,
  3752. scale * spc->v_oversample,
  3753. &x0,&y0,&x1,&y1);
  3754. stbtt_MakeGlyphBitmapSubpixel(info,
  3755. spc->pixels + r->x + r->y*spc->stride_in_bytes,
  3756. r->w - spc->h_oversample+1,
  3757. r->h - spc->v_oversample+1,
  3758. spc->stride_in_bytes,
  3759. scale * spc->h_oversample,
  3760. scale * spc->v_oversample,
  3761. 0,0,
  3762. glyph);
  3763. if (spc->h_oversample > 1)
  3764. stbtt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
  3765. r->w, r->h, spc->stride_in_bytes,
  3766. spc->h_oversample);
  3767. if (spc->v_oversample > 1)
  3768. stbtt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
  3769. r->w, r->h, spc->stride_in_bytes,
  3770. spc->v_oversample);
  3771. bc->x0 = (stbtt_int16) r->x;
  3772. bc->y0 = (stbtt_int16) r->y;
  3773. bc->x1 = (stbtt_int16) (r->x + r->w);
  3774. bc->y1 = (stbtt_int16) (r->y + r->h);
  3775. bc->xadvance = scale * advance;
  3776. bc->xoff = (float) x0 * recip_h + sub_x;
  3777. bc->yoff = (float) y0 * recip_v + sub_y;
  3778. bc->xoff2 = (x0 + r->w) * recip_h + sub_x;
  3779. bc->yoff2 = (y0 + r->h) * recip_v + sub_y;
  3780. if (glyph == 0)
  3781. missing_glyph = j;
  3782. } else if (spc->skip_missing) {
  3783. return_value = 0;
  3784. } else if (r->was_packed && r->w == 0 && r->h == 0 && missing_glyph >= 0) {
  3785. ranges[i].chardata_for_range[j] = ranges[i].chardata_for_range[missing_glyph];
  3786. } else {
  3787. return_value = 0; // if any fail, report failure
  3788. }
  3789. ++k;
  3790. }
  3791. }
  3792. // restore original values
  3793. spc->h_oversample = old_h_over;
  3794. spc->v_oversample = old_v_over;
  3795. return return_value;
  3796. }
  3797. STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects)
  3798. {
  3799. stbrp_pack_rects((stbrp_context *) spc->pack_info, rects, num_rects);
  3800. }
  3801. STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges)
  3802. {
  3803. stbtt_fontinfo info;
  3804. int i, j, n, return_value; // [DEAR IMGUI] removed = 1;
  3805. //stbrp_context *context = (stbrp_context *) spc->pack_info;
  3806. stbrp_rect *rects;
  3807. // flag all characters as NOT packed
  3808. for (i=0; i < num_ranges; ++i)
  3809. for (j=0; j < ranges[i].num_chars; ++j)
  3810. ranges[i].chardata_for_range[j].x0 =
  3811. ranges[i].chardata_for_range[j].y0 =
  3812. ranges[i].chardata_for_range[j].x1 =
  3813. ranges[i].chardata_for_range[j].y1 = 0;
  3814. n = 0;
  3815. for (i=0; i < num_ranges; ++i)
  3816. n += ranges[i].num_chars;
  3817. rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context);
  3818. if (rects == NULL)
  3819. return 0;
  3820. info.userdata = spc->user_allocator_context;
  3821. stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index));
  3822. n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects);
  3823. stbtt_PackFontRangesPackRects(spc, rects, n);
  3824. return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects);
  3825. STBTT_free(rects, spc->user_allocator_context);
  3826. return return_value;
  3827. }
  3828. STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size,
  3829. int first_unicode_codepoint_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range)
  3830. {
  3831. stbtt_pack_range range;
  3832. range.first_unicode_codepoint_in_range = first_unicode_codepoint_in_range;
  3833. range.array_of_unicode_codepoints = NULL;
  3834. range.num_chars = num_chars_in_range;
  3835. range.chardata_for_range = chardata_for_range;
  3836. range.font_size = font_size;
  3837. return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1);
  3838. }
  3839. STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap)
  3840. {
  3841. int i_ascent, i_descent, i_lineGap;
  3842. float scale;
  3843. stbtt_fontinfo info;
  3844. stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata, index));
  3845. scale = size > 0 ? stbtt_ScaleForPixelHeight(&info, size) : stbtt_ScaleForMappingEmToPixels(&info, -size);
  3846. stbtt_GetFontVMetrics(&info, &i_ascent, &i_descent, &i_lineGap);
  3847. *ascent = (float) i_ascent * scale;
  3848. *descent = (float) i_descent * scale;
  3849. *lineGap = (float) i_lineGap * scale;
  3850. }
  3851. STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer)
  3852. {
  3853. float ipw = 1.0f / pw, iph = 1.0f / ph;
  3854. const stbtt_packedchar *b = chardata + char_index;
  3855. if (align_to_integer) {
  3856. float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5f);
  3857. float y = (float) STBTT_ifloor((*ypos + b->yoff) + 0.5f);
  3858. q->x0 = x;
  3859. q->y0 = y;
  3860. q->x1 = x + b->xoff2 - b->xoff;
  3861. q->y1 = y + b->yoff2 - b->yoff;
  3862. } else {
  3863. q->x0 = *xpos + b->xoff;
  3864. q->y0 = *ypos + b->yoff;
  3865. q->x1 = *xpos + b->xoff2;
  3866. q->y1 = *ypos + b->yoff2;
  3867. }
  3868. q->s0 = b->x0 * ipw;
  3869. q->t0 = b->y0 * iph;
  3870. q->s1 = b->x1 * ipw;
  3871. q->t1 = b->y1 * iph;
  3872. *xpos += b->xadvance;
  3873. }
  3874. //////////////////////////////////////////////////////////////////////////////
  3875. //
  3876. // sdf computation
  3877. //
  3878. #define STBTT_min(a,b) ((a) < (b) ? (a) : (b))
  3879. #define STBTT_max(a,b) ((a) < (b) ? (b) : (a))
  3880. static int stbtt__ray_intersect_bezier(float orig[2], float ray[2], float q0[2], float q1[2], float q2[2], float hits[2][2])
  3881. {
  3882. float q0perp = q0[1]*ray[0] - q0[0]*ray[1];
  3883. float q1perp = q1[1]*ray[0] - q1[0]*ray[1];
  3884. float q2perp = q2[1]*ray[0] - q2[0]*ray[1];
  3885. float roperp = orig[1]*ray[0] - orig[0]*ray[1];
  3886. float a = q0perp - 2*q1perp + q2perp;
  3887. float b = q1perp - q0perp;
  3888. float c = q0perp - roperp;
  3889. float s0 = 0., s1 = 0.;
  3890. int num_s = 0;
  3891. if (a != 0.0) {
  3892. float discr = b*b - a*c;
  3893. if (discr > 0.0) {
  3894. float rcpna = -1 / a;
  3895. float d = (float) STBTT_sqrt(discr);
  3896. s0 = (b+d) * rcpna;
  3897. s1 = (b-d) * rcpna;
  3898. if (s0 >= 0.0 && s0 <= 1.0)
  3899. num_s = 1;
  3900. if (d > 0.0 && s1 >= 0.0 && s1 <= 1.0) {
  3901. if (num_s == 0) s0 = s1;
  3902. ++num_s;
  3903. }
  3904. }
  3905. } else {
  3906. // 2*b*s + c = 0
  3907. // s = -c / (2*b)
  3908. s0 = c / (-2 * b);
  3909. if (s0 >= 0.0 && s0 <= 1.0)
  3910. num_s = 1;
  3911. }
  3912. if (num_s == 0)
  3913. return 0;
  3914. else {
  3915. float rcp_len2 = 1 / (ray[0]*ray[0] + ray[1]*ray[1]);
  3916. float rayn_x = ray[0] * rcp_len2, rayn_y = ray[1] * rcp_len2;
  3917. float q0d = q0[0]*rayn_x + q0[1]*rayn_y;
  3918. float q1d = q1[0]*rayn_x + q1[1]*rayn_y;
  3919. float q2d = q2[0]*rayn_x + q2[1]*rayn_y;
  3920. float rod = orig[0]*rayn_x + orig[1]*rayn_y;
  3921. float q10d = q1d - q0d;
  3922. float q20d = q2d - q0d;
  3923. float q0rd = q0d - rod;
  3924. hits[0][0] = q0rd + s0*(2.0f - 2.0f*s0)*q10d + s0*s0*q20d;
  3925. hits[0][1] = a*s0+b;
  3926. if (num_s > 1) {
  3927. hits[1][0] = q0rd + s1*(2.0f - 2.0f*s1)*q10d + s1*s1*q20d;
  3928. hits[1][1] = a*s1+b;
  3929. return 2;
  3930. } else {
  3931. return 1;
  3932. }
  3933. }
  3934. }
  3935. static int equal(float *a, float *b)
  3936. {
  3937. return (a[0] == b[0] && a[1] == b[1]);
  3938. }
  3939. static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex *verts)
  3940. {
  3941. int i;
  3942. float orig[2], ray[2] = { 1, 0 };
  3943. float y_frac;
  3944. int winding = 0;
  3945. // make sure y never passes through a vertex of the shape
  3946. y_frac = (float) STBTT_fmod(y, 1.0f);
  3947. if (y_frac < 0.01f)
  3948. y += 0.01f;
  3949. else if (y_frac > 0.99f)
  3950. y -= 0.01f;
  3951. orig[0] = x;
  3952. orig[1] = y;
  3953. // test a ray from (-infinity,y) to (x,y)
  3954. for (i=0; i < nverts; ++i) {
  3955. if (verts[i].type == STBTT_vline) {
  3956. int x0 = (int) verts[i-1].x, y0 = (int) verts[i-1].y;
  3957. int x1 = (int) verts[i ].x, y1 = (int) verts[i ].y;
  3958. if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) {
  3959. float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0;
  3960. if (x_inter < x)
  3961. winding += (y0 < y1) ? 1 : -1;
  3962. }
  3963. }
  3964. if (verts[i].type == STBTT_vcurve) {
  3965. int x0 = (int) verts[i-1].x , y0 = (int) verts[i-1].y ;
  3966. int x1 = (int) verts[i ].cx, y1 = (int) verts[i ].cy;
  3967. int x2 = (int) verts[i ].x , y2 = (int) verts[i ].y ;
  3968. int ax = STBTT_min(x0,STBTT_min(x1,x2)), ay = STBTT_min(y0,STBTT_min(y1,y2));
  3969. int by = STBTT_max(y0,STBTT_max(y1,y2));
  3970. if (y > ay && y < by && x > ax) {
  3971. float q0[2],q1[2],q2[2];
  3972. float hits[2][2];
  3973. q0[0] = (float)x0;
  3974. q0[1] = (float)y0;
  3975. q1[0] = (float)x1;
  3976. q1[1] = (float)y1;
  3977. q2[0] = (float)x2;
  3978. q2[1] = (float)y2;
  3979. if (equal(q0,q1) || equal(q1,q2)) {
  3980. x0 = (int)verts[i-1].x;
  3981. y0 = (int)verts[i-1].y;
  3982. x1 = (int)verts[i ].x;
  3983. y1 = (int)verts[i ].y;
  3984. if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) {
  3985. float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0;
  3986. if (x_inter < x)
  3987. winding += (y0 < y1) ? 1 : -1;
  3988. }
  3989. } else {
  3990. int num_hits = stbtt__ray_intersect_bezier(orig, ray, q0, q1, q2, hits);
  3991. if (num_hits >= 1)
  3992. if (hits[0][0] < 0)
  3993. winding += (hits[0][1] < 0 ? -1 : 1);
  3994. if (num_hits >= 2)
  3995. if (hits[1][0] < 0)
  3996. winding += (hits[1][1] < 0 ? -1 : 1);
  3997. }
  3998. }
  3999. }
  4000. }
  4001. return winding;
  4002. }
  4003. static float stbtt__cuberoot( float x )
  4004. {
  4005. if (x<0)
  4006. return -(float) STBTT_pow(-x,1.0f/3.0f);
  4007. else
  4008. return (float) STBTT_pow( x,1.0f/3.0f);
  4009. }
  4010. // x^3 + a*x^2 + b*x + c = 0
  4011. static int stbtt__solve_cubic(float a, float b, float c, float* r)
  4012. {
  4013. float s = -a / 3;
  4014. float p = b - a*a / 3;
  4015. float q = a * (2*a*a - 9*b) / 27 + c;
  4016. float p3 = p*p*p;
  4017. float d = q*q + 4*p3 / 27;
  4018. if (d >= 0) {
  4019. float z = (float) STBTT_sqrt(d);
  4020. float u = (-q + z) / 2;
  4021. float v = (-q - z) / 2;
  4022. u = stbtt__cuberoot(u);
  4023. v = stbtt__cuberoot(v);
  4024. r[0] = s + u + v;
  4025. return 1;
  4026. } else {
  4027. float u = (float) STBTT_sqrt(-p/3);
  4028. float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; // p3 must be negative, since d is negative
  4029. float m = (float) STBTT_cos(v);
  4030. float n = (float) STBTT_cos(v-3.141592/2)*1.732050808f;
  4031. r[0] = s + u * 2 * m;
  4032. r[1] = s - u * (m + n);
  4033. r[2] = s - u * (m - n);
  4034. //STBTT_assert( STBTT_fabs(((r[0]+a)*r[0]+b)*r[0]+c) < 0.05f); // these asserts may not be safe at all scales, though they're in bezier t parameter units so maybe?
  4035. //STBTT_assert( STBTT_fabs(((r[1]+a)*r[1]+b)*r[1]+c) < 0.05f);
  4036. //STBTT_assert( STBTT_fabs(((r[2]+a)*r[2]+b)*r[2]+c) < 0.05f);
  4037. return 3;
  4038. }
  4039. }
  4040. STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff)
  4041. {
  4042. float scale_x = scale, scale_y = scale;
  4043. int ix0,iy0,ix1,iy1;
  4044. int w,h;
  4045. unsigned char *data;
  4046. if (scale == 0) return NULL;
  4047. stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1);
  4048. // if empty, return NULL
  4049. if (ix0 == ix1 || iy0 == iy1)
  4050. return NULL;
  4051. ix0 -= padding;
  4052. iy0 -= padding;
  4053. ix1 += padding;
  4054. iy1 += padding;
  4055. w = (ix1 - ix0);
  4056. h = (iy1 - iy0);
  4057. if (width ) *width = w;
  4058. if (height) *height = h;
  4059. if (xoff ) *xoff = ix0;
  4060. if (yoff ) *yoff = iy0;
  4061. // invert for y-downwards bitmaps
  4062. scale_y = -scale_y;
  4063. {
  4064. int x,y,i,j;
  4065. float *precompute;
  4066. stbtt_vertex *verts;
  4067. int num_verts = stbtt_GetGlyphShape(info, glyph, &verts);
  4068. data = (unsigned char *) STBTT_malloc(w * h, info->userdata);
  4069. precompute = (float *) STBTT_malloc(num_verts * sizeof(float), info->userdata);
  4070. for (i=0,j=num_verts-1; i < num_verts; j=i++) {
  4071. if (verts[i].type == STBTT_vline) {
  4072. float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y;
  4073. float x1 = verts[j].x*scale_x, y1 = verts[j].y*scale_y;
  4074. float dist = (float) STBTT_sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0));
  4075. precompute[i] = (dist == 0) ? 0.0f : 1.0f / dist;
  4076. } else if (verts[i].type == STBTT_vcurve) {
  4077. float x2 = verts[j].x *scale_x, y2 = verts[j].y *scale_y;
  4078. float x1 = verts[i].cx*scale_x, y1 = verts[i].cy*scale_y;
  4079. float x0 = verts[i].x *scale_x, y0 = verts[i].y *scale_y;
  4080. float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2;
  4081. float len2 = bx*bx + by*by;
  4082. if (len2 != 0.0f)
  4083. precompute[i] = 1.0f / (bx*bx + by*by);
  4084. else
  4085. precompute[i] = 0.0f;
  4086. } else
  4087. precompute[i] = 0.0f;
  4088. }
  4089. for (y=iy0; y < iy1; ++y) {
  4090. for (x=ix0; x < ix1; ++x) {
  4091. float val;
  4092. float min_dist = 999999.0f;
  4093. float sx = (float) x + 0.5f;
  4094. float sy = (float) y + 0.5f;
  4095. float x_gspace = (sx / scale_x);
  4096. float y_gspace = (sy / scale_y);
  4097. int winding = stbtt__compute_crossings_x(x_gspace, y_gspace, num_verts, verts); // @OPTIMIZE: this could just be a rasterization, but needs to be line vs. non-tesselated curves so a new path
  4098. for (i=0; i < num_verts; ++i) {
  4099. float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y;
  4100. if (verts[i].type == STBTT_vline && precompute[i] != 0.0f) {
  4101. float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y;
  4102. float dist,dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy);
  4103. if (dist2 < min_dist*min_dist)
  4104. min_dist = (float) STBTT_sqrt(dist2);
  4105. // coarse culling against bbox
  4106. //if (sx > STBTT_min(x0,x1)-min_dist && sx < STBTT_max(x0,x1)+min_dist &&
  4107. // sy > STBTT_min(y0,y1)-min_dist && sy < STBTT_max(y0,y1)+min_dist)
  4108. dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i];
  4109. STBTT_assert(i != 0);
  4110. if (dist < min_dist) {
  4111. // check position along line
  4112. // x' = x0 + t*(x1-x0), y' = y0 + t*(y1-y0)
  4113. // minimize (x'-sx)*(x'-sx)+(y'-sy)*(y'-sy)
  4114. float dx = x1-x0, dy = y1-y0;
  4115. float px = x0-sx, py = y0-sy;
  4116. // minimize (px+t*dx)^2 + (py+t*dy)^2 = px*px + 2*px*dx*t + t^2*dx*dx + py*py + 2*py*dy*t + t^2*dy*dy
  4117. // derivative: 2*px*dx + 2*py*dy + (2*dx*dx+2*dy*dy)*t, set to 0 and solve
  4118. float t = -(px*dx + py*dy) / (dx*dx + dy*dy);
  4119. if (t >= 0.0f && t <= 1.0f)
  4120. min_dist = dist;
  4121. }
  4122. } else if (verts[i].type == STBTT_vcurve) {
  4123. float x2 = verts[i-1].x *scale_x, y2 = verts[i-1].y *scale_y;
  4124. float x1 = verts[i ].cx*scale_x, y1 = verts[i ].cy*scale_y;
  4125. float box_x0 = STBTT_min(STBTT_min(x0,x1),x2);
  4126. float box_y0 = STBTT_min(STBTT_min(y0,y1),y2);
  4127. float box_x1 = STBTT_max(STBTT_max(x0,x1),x2);
  4128. float box_y1 = STBTT_max(STBTT_max(y0,y1),y2);
  4129. // coarse culling against bbox to avoid computing cubic unnecessarily
  4130. if (sx > box_x0-min_dist && sx < box_x1+min_dist && sy > box_y0-min_dist && sy < box_y1+min_dist) {
  4131. int num=0;
  4132. float ax = x1-x0, ay = y1-y0;
  4133. float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2;
  4134. float mx = x0 - sx, my = y0 - sy;
  4135. float res[3] = {0.f,0.f,0.f};
  4136. float px,py,t,it,dist2;
  4137. float a_inv = precompute[i];
  4138. if (a_inv == 0.0) { // if a_inv is 0, it's 2nd degree so use quadratic formula
  4139. float a = 3*(ax*bx + ay*by);
  4140. float b = 2*(ax*ax + ay*ay) + (mx*bx+my*by);
  4141. float c = mx*ax+my*ay;
  4142. if (a == 0.0) { // if a is 0, it's linear
  4143. if (b != 0.0) {
  4144. res[num++] = -c/b;
  4145. }
  4146. } else {
  4147. float discriminant = b*b - 4*a*c;
  4148. if (discriminant < 0)
  4149. num = 0;
  4150. else {
  4151. float root = (float) STBTT_sqrt(discriminant);
  4152. res[0] = (-b - root)/(2*a);
  4153. res[1] = (-b + root)/(2*a);
  4154. num = 2; // don't bother distinguishing 1-solution case, as code below will still work
  4155. }
  4156. }
  4157. } else {
  4158. float b = 3*(ax*bx + ay*by) * a_inv; // could precompute this as it doesn't depend on sample point
  4159. float c = (2*(ax*ax + ay*ay) + (mx*bx+my*by)) * a_inv;
  4160. float d = (mx*ax+my*ay) * a_inv;
  4161. num = stbtt__solve_cubic(b, c, d, res);
  4162. }
  4163. dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy);
  4164. if (dist2 < min_dist*min_dist)
  4165. min_dist = (float) STBTT_sqrt(dist2);
  4166. if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) {
  4167. t = res[0], it = 1.0f - t;
  4168. px = it*it*x0 + 2*t*it*x1 + t*t*x2;
  4169. py = it*it*y0 + 2*t*it*y1 + t*t*y2;
  4170. dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy);
  4171. if (dist2 < min_dist * min_dist)
  4172. min_dist = (float) STBTT_sqrt(dist2);
  4173. }
  4174. if (num >= 2 && res[1] >= 0.0f && res[1] <= 1.0f) {
  4175. t = res[1], it = 1.0f - t;
  4176. px = it*it*x0 + 2*t*it*x1 + t*t*x2;
  4177. py = it*it*y0 + 2*t*it*y1 + t*t*y2;
  4178. dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy);
  4179. if (dist2 < min_dist * min_dist)
  4180. min_dist = (float) STBTT_sqrt(dist2);
  4181. }
  4182. if (num >= 3 && res[2] >= 0.0f && res[2] <= 1.0f) {
  4183. t = res[2], it = 1.0f - t;
  4184. px = it*it*x0 + 2*t*it*x1 + t*t*x2;
  4185. py = it*it*y0 + 2*t*it*y1 + t*t*y2;
  4186. dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy);
  4187. if (dist2 < min_dist * min_dist)
  4188. min_dist = (float) STBTT_sqrt(dist2);
  4189. }
  4190. }
  4191. }
  4192. }
  4193. if (winding == 0)
  4194. min_dist = -min_dist; // if outside the shape, value is negative
  4195. val = onedge_value + pixel_dist_scale * min_dist;
  4196. if (val < 0)
  4197. val = 0;
  4198. else if (val > 255)
  4199. val = 255;
  4200. data[(y-iy0)*w+(x-ix0)] = (unsigned char) val;
  4201. }
  4202. }
  4203. STBTT_free(precompute, info->userdata);
  4204. STBTT_free(verts, info->userdata);
  4205. }
  4206. return data;
  4207. }
  4208. STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff)
  4209. {
  4210. return stbtt_GetGlyphSDF(info, scale, stbtt_FindGlyphIndex(info, codepoint), padding, onedge_value, pixel_dist_scale, width, height, xoff, yoff);
  4211. }
  4212. STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata)
  4213. {
  4214. STBTT_free(bitmap, userdata);
  4215. }
  4216. //////////////////////////////////////////////////////////////////////////////
  4217. //
  4218. // font name matching -- recommended not to use this
  4219. //
  4220. // check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string
  4221. static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2)
  4222. {
  4223. stbtt_int32 i=0;
  4224. // convert utf16 to utf8 and compare the results while converting
  4225. while (len2) {
  4226. stbtt_uint16 ch = s2[0]*256 + s2[1];
  4227. if (ch < 0x80) {
  4228. if (i >= len1) return -1;
  4229. if (s1[i++] != ch) return -1;
  4230. } else if (ch < 0x800) {
  4231. if (i+1 >= len1) return -1;
  4232. if (s1[i++] != 0xc0 + (ch >> 6)) return -1;
  4233. if (s1[i++] != 0x80 + (ch & 0x3f)) return -1;
  4234. } else if (ch >= 0xd800 && ch < 0xdc00) {
  4235. stbtt_uint32 c;
  4236. stbtt_uint16 ch2 = s2[2]*256 + s2[3];
  4237. if (i+3 >= len1) return -1;
  4238. c = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000;
  4239. if (s1[i++] != 0xf0 + (c >> 18)) return -1;
  4240. if (s1[i++] != 0x80 + ((c >> 12) & 0x3f)) return -1;
  4241. if (s1[i++] != 0x80 + ((c >> 6) & 0x3f)) return -1;
  4242. if (s1[i++] != 0x80 + ((c ) & 0x3f)) return -1;
  4243. s2 += 2; // plus another 2 below
  4244. len2 -= 2;
  4245. } else if (ch >= 0xdc00 && ch < 0xe000) {
  4246. return -1;
  4247. } else {
  4248. if (i+2 >= len1) return -1;
  4249. if (s1[i++] != 0xe0 + (ch >> 12)) return -1;
  4250. if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f)) return -1;
  4251. if (s1[i++] != 0x80 + ((ch ) & 0x3f)) return -1;
  4252. }
  4253. s2 += 2;
  4254. len2 -= 2;
  4255. }
  4256. return i;
  4257. }
  4258. static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2)
  4259. {
  4260. return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*) s2, len2);
  4261. }
  4262. // returns results in whatever encoding you request... but note that 2-byte encodings
  4263. // will be BIG-ENDIAN... use stbtt_CompareUTF8toUTF16_bigendian() to compare
  4264. STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID)
  4265. {
  4266. stbtt_int32 i,count,stringOffset;
  4267. stbtt_uint8 *fc = font->data;
  4268. stbtt_uint32 offset = font->fontstart;
  4269. stbtt_uint32 nm = stbtt__find_table(fc, offset, "name");
  4270. if (!nm) return NULL;
  4271. count = ttUSHORT(fc+nm+2);
  4272. stringOffset = nm + ttUSHORT(fc+nm+4);
  4273. for (i=0; i < count; ++i) {
  4274. stbtt_uint32 loc = nm + 6 + 12 * i;
  4275. if (platformID == ttUSHORT(fc+loc+0) && encodingID == ttUSHORT(fc+loc+2)
  4276. && languageID == ttUSHORT(fc+loc+4) && nameID == ttUSHORT(fc+loc+6)) {
  4277. *length = ttUSHORT(fc+loc+8);
  4278. return (const char *) (fc+stringOffset+ttUSHORT(fc+loc+10));
  4279. }
  4280. }
  4281. return NULL;
  4282. }
  4283. static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name, stbtt_int32 nlen, stbtt_int32 target_id, stbtt_int32 next_id)
  4284. {
  4285. stbtt_int32 i;
  4286. stbtt_int32 count = ttUSHORT(fc+nm+2);
  4287. stbtt_int32 stringOffset = nm + ttUSHORT(fc+nm+4);
  4288. for (i=0; i < count; ++i) {
  4289. stbtt_uint32 loc = nm + 6 + 12 * i;
  4290. stbtt_int32 id = ttUSHORT(fc+loc+6);
  4291. if (id == target_id) {
  4292. // find the encoding
  4293. stbtt_int32 platform = ttUSHORT(fc+loc+0), encoding = ttUSHORT(fc+loc+2), language = ttUSHORT(fc+loc+4);
  4294. // is this a Unicode encoding?
  4295. if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) {
  4296. stbtt_int32 slen = ttUSHORT(fc+loc+8);
  4297. stbtt_int32 off = ttUSHORT(fc+loc+10);
  4298. // check if there's a prefix match
  4299. stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc+stringOffset+off,slen);
  4300. if (matchlen >= 0) {
  4301. // check for target_id+1 immediately following, with same encoding & language
  4302. if (i+1 < count && ttUSHORT(fc+loc+12+6) == next_id && ttUSHORT(fc+loc+12) == platform && ttUSHORT(fc+loc+12+2) == encoding && ttUSHORT(fc+loc+12+4) == language) {
  4303. slen = ttUSHORT(fc+loc+12+8);
  4304. off = ttUSHORT(fc+loc+12+10);
  4305. if (slen == 0) {
  4306. if (matchlen == nlen)
  4307. return 1;
  4308. } else if (matchlen < nlen && name[matchlen] == ' ') {
  4309. ++matchlen;
  4310. if (stbtt_CompareUTF8toUTF16_bigendian_internal((char*) (name+matchlen), nlen-matchlen, (char*)(fc+stringOffset+off),slen))
  4311. return 1;
  4312. }
  4313. } else {
  4314. // if nothing immediately following
  4315. if (matchlen == nlen)
  4316. return 1;
  4317. }
  4318. }
  4319. }
  4320. // @TODO handle other encodings
  4321. }
  4322. }
  4323. return 0;
  4324. }
  4325. static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32 flags)
  4326. {
  4327. stbtt_int32 nlen = (stbtt_int32) STBTT_strlen((char *) name);
  4328. stbtt_uint32 nm,hd;
  4329. if (!stbtt__isfont(fc+offset)) return 0;
  4330. // check italics/bold/underline flags in macStyle...
  4331. if (flags) {
  4332. hd = stbtt__find_table(fc, offset, "head");
  4333. if ((ttUSHORT(fc+hd+44) & 7) != (flags & 7)) return 0;
  4334. }
  4335. nm = stbtt__find_table(fc, offset, "name");
  4336. if (!nm) return 0;
  4337. if (flags) {
  4338. // if we checked the macStyle flags, then just check the family and ignore the subfamily
  4339. if (stbtt__matchpair(fc, nm, name, nlen, 16, -1)) return 1;
  4340. if (stbtt__matchpair(fc, nm, name, nlen, 1, -1)) return 1;
  4341. if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1;
  4342. } else {
  4343. if (stbtt__matchpair(fc, nm, name, nlen, 16, 17)) return 1;
  4344. if (stbtt__matchpair(fc, nm, name, nlen, 1, 2)) return 1;
  4345. if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1;
  4346. }
  4347. return 0;
  4348. }
  4349. static int stbtt_FindMatchingFont_internal(unsigned char *font_collection, char *name_utf8, stbtt_int32 flags)
  4350. {
  4351. stbtt_int32 i;
  4352. for (i=0;;++i) {
  4353. stbtt_int32 off = stbtt_GetFontOffsetForIndex(font_collection, i);
  4354. if (off < 0) return off;
  4355. if (stbtt__matches((stbtt_uint8 *) font_collection, off, (stbtt_uint8*) name_utf8, flags))
  4356. return off;
  4357. }
  4358. }
  4359. #if defined(__GNUC__) || defined(__clang__)
  4360. #pragma GCC diagnostic push
  4361. #pragma GCC diagnostic ignored "-Wcast-qual"
  4362. #endif
  4363. STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset,
  4364. float pixel_height, unsigned char *pixels, int pw, int ph,
  4365. int first_char, int num_chars, stbtt_bakedchar *chardata)
  4366. {
  4367. return stbtt_BakeFontBitmap_internal((unsigned char *) data, offset, pixel_height, pixels, pw, ph, first_char, num_chars, chardata);
  4368. }
  4369. STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index)
  4370. {
  4371. return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index);
  4372. }
  4373. STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data)
  4374. {
  4375. return stbtt_GetNumberOfFonts_internal((unsigned char *) data);
  4376. }
  4377. STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset)
  4378. {
  4379. return stbtt_InitFont_internal(info, (unsigned char *) data, offset);
  4380. }
  4381. STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags)
  4382. {
  4383. return stbtt_FindMatchingFont_internal((unsigned char *) fontdata, (char *) name, flags);
  4384. }
  4385. STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2)
  4386. {
  4387. return stbtt_CompareUTF8toUTF16_bigendian_internal((char *) s1, len1, (char *) s2, len2);
  4388. }
  4389. #if defined(__GNUC__) || defined(__clang__)
  4390. #pragma GCC diagnostic pop
  4391. #endif
  4392. #endif // STB_TRUETYPE_IMPLEMENTATION
  4393. // FULL VERSION HISTORY
  4394. //
  4395. // 1.25 (2021-07-11) many fixes
  4396. // 1.24 (2020-02-05) fix warning
  4397. // 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS)
  4398. // 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined
  4399. // 1.21 (2019-02-25) fix warning
  4400. // 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics()
  4401. // 1.19 (2018-02-11) OpenType GPOS kerning (horizontal only), STBTT_fmod
  4402. // 1.18 (2018-01-29) add missing function
  4403. // 1.17 (2017-07-23) make more arguments const; doc fix
  4404. // 1.16 (2017-07-12) SDF support
  4405. // 1.15 (2017-03-03) make more arguments const
  4406. // 1.14 (2017-01-16) num-fonts-in-TTC function
  4407. // 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts
  4408. // 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual
  4409. // 1.11 (2016-04-02) fix unused-variable warning
  4410. // 1.10 (2016-04-02) allow user-defined fabs() replacement
  4411. // fix memory leak if fontsize=0.0
  4412. // fix warning from duplicate typedef
  4413. // 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use alloc userdata for PackFontRanges
  4414. // 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges
  4415. // 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints;
  4416. // allow PackFontRanges to pack and render in separate phases;
  4417. // fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?);
  4418. // fixed an assert() bug in the new rasterizer
  4419. // replace assert() with STBTT_assert() in new rasterizer
  4420. // 1.06 (2015-07-14) performance improvements (~35% faster on x86 and x64 on test machine)
  4421. // also more precise AA rasterizer, except if shapes overlap
  4422. // remove need for STBTT_sort
  4423. // 1.05 (2015-04-15) fix misplaced definitions for STBTT_STATIC
  4424. // 1.04 (2015-04-15) typo in example
  4425. // 1.03 (2015-04-12) STBTT_STATIC, fix memory leak in new packing, various fixes
  4426. // 1.02 (2014-12-10) fix various warnings & compile issues w/ stb_rect_pack, C++
  4427. // 1.01 (2014-12-08) fix subpixel position when oversampling to exactly match
  4428. // non-oversampled; STBTT_POINT_SIZE for packed case only
  4429. // 1.00 (2014-12-06) add new PackBegin etc. API, w/ support for oversampling
  4430. // 0.99 (2014-09-18) fix multiple bugs with subpixel rendering (ryg)
  4431. // 0.9 (2014-08-07) support certain mac/iOS fonts without an MS platformID
  4432. // 0.8b (2014-07-07) fix a warning
  4433. // 0.8 (2014-05-25) fix a few more warnings
  4434. // 0.7 (2013-09-25) bugfix: subpixel glyph bug fixed in 0.5 had come back
  4435. // 0.6c (2012-07-24) improve documentation
  4436. // 0.6b (2012-07-20) fix a few more warnings
  4437. // 0.6 (2012-07-17) fix warnings; added stbtt_ScaleForMappingEmToPixels,
  4438. // stbtt_GetFontBoundingBox, stbtt_IsGlyphEmpty
  4439. // 0.5 (2011-12-09) bugfixes:
  4440. // subpixel glyph renderer computed wrong bounding box
  4441. // first vertex of shape can be off-curve (FreeSans)
  4442. // 0.4b (2011-12-03) fixed an error in the font baking example
  4443. // 0.4 (2011-12-01) kerning, subpixel rendering (tor)
  4444. // bugfixes for:
  4445. // codepoint-to-glyph conversion using table fmt=12
  4446. // codepoint-to-glyph conversion using table fmt=4
  4447. // stbtt_GetBakedQuad with non-square texture (Zer)
  4448. // updated Hello World! sample to use kerning and subpixel
  4449. // fixed some warnings
  4450. // 0.3 (2009-06-24) cmap fmt=12, compound shapes (MM)
  4451. // userdata, malloc-from-userdata, non-zero fill (stb)
  4452. // 0.2 (2009-03-11) Fix unsigned/signed char warnings
  4453. // 0.1 (2009-03-09) First public release
  4454. //
  4455. /*
  4456. ------------------------------------------------------------------------------
  4457. This software is available under 2 licenses -- choose whichever you prefer.
  4458. ------------------------------------------------------------------------------
  4459. ALTERNATIVE A - MIT License
  4460. Copyright (c) 2017 Sean Barrett
  4461. Permission is hereby granted, free of charge, to any person obtaining a copy of
  4462. this software and associated documentation files (the "Software"), to deal in
  4463. the Software without restriction, including without limitation the rights to
  4464. use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
  4465. of the Software, and to permit persons to whom the Software is furnished to do
  4466. so, subject to the following conditions:
  4467. The above copyright notice and this permission notice shall be included in all
  4468. copies or substantial portions of the Software.
  4469. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  4470. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  4471. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  4472. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  4473. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  4474. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  4475. SOFTWARE.
  4476. ------------------------------------------------------------------------------
  4477. ALTERNATIVE B - Public Domain (www.unlicense.org)
  4478. This is free and unencumbered software released into the public domain.
  4479. Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
  4480. software, either in source code form or as a compiled binary, for any purpose,
  4481. commercial or non-commercial, and by any means.
  4482. In jurisdictions that recognize copyright laws, the author or authors of this
  4483. software dedicate any and all copyright interest in the software to the public
  4484. domain. We make this dedication for the benefit of the public at large and to
  4485. the detriment of our heirs and successors. We intend this dedication to be an
  4486. overt act of relinquishment in perpetuity of all present and future rights to
  4487. this software under copyright law.
  4488. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  4489. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  4490. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  4491. AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  4492. ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  4493. WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  4494. ------------------------------------------------------------------------------
  4495. */