fontstash.h 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714
  1. //
  2. // NOTE sokol: all IO functions have been removed
  3. //
  4. // Copyright (c) 2009-2013 Mikko Mononen [email protected]
  5. //
  6. // This software is provided 'as-is', without any express or implied
  7. // warranty. In no event will the authors be held liable for any damages
  8. // arising from the use of this software.
  9. // Permission is granted to anyone to use this software for any purpose,
  10. // including commercial applications, and to alter it and redistribute it
  11. // freely, subject to the following restrictions:
  12. // 1. The origin of this software must not be misrepresented; you must not
  13. // claim that you wrote the original software. If you use this software
  14. // in a product, an acknowledgment in the product documentation would be
  15. // appreciated but is not required.
  16. // 2. Altered source versions must be plainly marked as such, and must not be
  17. // misrepresented as being the original software.
  18. // 3. This notice may not be removed or altered from any source distribution.
  19. //
  20. #ifndef FONS_H
  21. #define FONS_H
  22. #ifdef __cplusplus
  23. extern "C" {
  24. #endif
  25. // To make the implementation private to the file that generates the implementation
  26. #ifdef FONS_STATIC
  27. #define FONS_DEF static
  28. #else
  29. #define FONS_DEF extern
  30. #endif
  31. #define FONS_INVALID -1
  32. enum FONSflags {
  33. FONS_ZERO_TOPLEFT = 1,
  34. FONS_ZERO_BOTTOMLEFT = 2,
  35. };
  36. enum FONSalign {
  37. // Horizontal align
  38. FONS_ALIGN_LEFT = 1<<0, // Default
  39. FONS_ALIGN_CENTER = 1<<1,
  40. FONS_ALIGN_RIGHT = 1<<2,
  41. // Vertical align
  42. FONS_ALIGN_TOP = 1<<3,
  43. FONS_ALIGN_MIDDLE = 1<<4,
  44. FONS_ALIGN_BOTTOM = 1<<5,
  45. FONS_ALIGN_BASELINE = 1<<6, // Default
  46. };
  47. enum FONSerrorCode {
  48. // Font atlas is full.
  49. FONS_ATLAS_FULL = 1,
  50. // Scratch memory used to render glyphs is full, requested size reported in 'val', you may need to bump up FONS_SCRATCH_BUF_SIZE.
  51. FONS_SCRATCH_FULL = 2,
  52. // Calls to fonsPushState has created too large stack, if you need deep state stack bump up FONS_MAX_STATES.
  53. FONS_STATES_OVERFLOW = 3,
  54. // Trying to pop too many states fonsPopState().
  55. FONS_STATES_UNDERFLOW = 4,
  56. };
  57. struct FONSparams {
  58. int width, height;
  59. unsigned char flags;
  60. void* userPtr;
  61. int (*renderCreate)(void* uptr, int width, int height);
  62. int (*renderResize)(void* uptr, int width, int height);
  63. void (*renderUpdate)(void* uptr, int* rect, const unsigned char* data);
  64. void (*renderDraw)(void* uptr, const float* verts, const float* tcoords, const unsigned int* colors, int nverts);
  65. void (*renderDelete)(void* uptr);
  66. };
  67. typedef struct FONSparams FONSparams;
  68. struct FONSquad
  69. {
  70. float x0,y0,s0,t0;
  71. float x1,y1,s1,t1;
  72. };
  73. typedef struct FONSquad FONSquad;
  74. struct FONStextIter {
  75. float x, y, nextx, nexty, scale, spacing;
  76. unsigned int codepoint;
  77. short isize, iblur;
  78. struct FONSfont* font;
  79. int prevGlyphIndex;
  80. const char* str;
  81. const char* next;
  82. const char* end;
  83. unsigned int utf8state;
  84. };
  85. typedef struct FONStextIter FONStextIter;
  86. typedef struct FONScontext FONScontext;
  87. // Contructor and destructor.
  88. FONS_DEF FONScontext* fonsCreateInternal(FONSparams* params);
  89. FONS_DEF void fonsDeleteInternal(FONScontext* s);
  90. FONS_DEF void fonsSetErrorCallback(FONScontext* s, void (*callback)(void* uptr, int error, int val), void* uptr);
  91. // Returns current atlas size.
  92. FONS_DEF void fonsGetAtlasSize(FONScontext* s, int* width, int* height);
  93. // Expands the atlas size.
  94. FONS_DEF int fonsExpandAtlas(FONScontext* s, int width, int height);
  95. // Resets the whole stash.
  96. FONS_DEF int fonsResetAtlas(FONScontext* stash, int width, int height);
  97. // Add fonts
  98. FONS_DEF int fonsGetFontByName(FONScontext* s, const char* name);
  99. FONS_DEF int fonsAddFallbackFont(FONScontext* stash, int base, int fallback);
  100. // State handling
  101. FONS_DEF void fonsPushState(FONScontext* s);
  102. FONS_DEF void fonsPopState(FONScontext* s);
  103. FONS_DEF void fonsClearState(FONScontext* s);
  104. // State setting
  105. FONS_DEF void fonsSetSize(FONScontext* s, float size);
  106. FONS_DEF void fonsSetColor(FONScontext* s, unsigned int color);
  107. FONS_DEF void fonsSetSpacing(FONScontext* s, float spacing);
  108. FONS_DEF void fonsSetBlur(FONScontext* s, float blur);
  109. FONS_DEF void fonsSetAlign(FONScontext* s, int align);
  110. FONS_DEF void fonsSetFont(FONScontext* s, int font);
  111. // Draw text
  112. FONS_DEF float fonsDrawText(FONScontext* s, float x, float y, const char* string, const char* end);
  113. // Measure text
  114. FONS_DEF float fonsTextBounds(FONScontext* s, float x, float y, const char* string, const char* end, float* bounds);
  115. FONS_DEF void fonsLineBounds(FONScontext* s, float y, float* miny, float* maxy);
  116. FONS_DEF void fonsVertMetrics(FONScontext* s, float* ascender, float* descender, float* lineh);
  117. // Text iterator
  118. FONS_DEF int fonsTextIterInit(FONScontext* stash, FONStextIter* iter, float x, float y, const char* str, const char* end);
  119. FONS_DEF int fonsTextIterNext(FONScontext* stash, FONStextIter* iter, struct FONSquad* quad);
  120. // Pull texture changes
  121. FONS_DEF const unsigned char* fonsGetTextureData(FONScontext* stash, int* width, int* height);
  122. FONS_DEF int fonsValidateTexture(FONScontext* s, int* dirty);
  123. // Draws the stash texture for debugging
  124. FONS_DEF void fonsDrawDebug(FONScontext* s, float x, float y);
  125. #ifdef __cplusplus
  126. }
  127. #endif
  128. #endif // FONS_H
  129. #ifdef FONTSTASH_IMPLEMENTATION
  130. #define FONS_NOTUSED(v) (void)sizeof(v)
  131. #ifdef FONS_USE_FREETYPE
  132. #include <ft2build.h>
  133. #include FT_FREETYPE_H
  134. #include FT_ADVANCES_H
  135. #include <math.h>
  136. struct FONSttFontImpl {
  137. FT_Face font;
  138. };
  139. typedef struct FONSttFontImpl FONSttFontImpl;
  140. static FT_Library ftLibrary;
  141. static int fons__tt_init()
  142. {
  143. FT_Error ftError;
  144. FONS_NOTUSED(context);
  145. ftError = FT_Init_FreeType(&ftLibrary);
  146. return ftError == 0;
  147. }
  148. static int fons__tt_loadFont(FONScontext *context, FONSttFontImpl *font, unsigned char *data, int dataSize)
  149. {
  150. FT_Error ftError;
  151. FONS_NOTUSED(context);
  152. //font->font.userdata = stash;
  153. ftError = FT_New_Memory_Face(ftLibrary, (const FT_Byte*)data, dataSize, 0, &font->font);
  154. return ftError == 0;
  155. }
  156. static void fons__tt_getFontVMetrics(FONSttFontImpl *font, int *ascent, int *descent, int *lineGap)
  157. {
  158. *ascent = font->font->ascender;
  159. *descent = font->font->descender;
  160. *lineGap = font->font->height - (*ascent - *descent);
  161. }
  162. static float fons__tt_getPixelHeightScale(FONSttFontImpl *font, float size)
  163. {
  164. return size / (font->font->ascender - font->font->descender);
  165. }
  166. static int fons__tt_getGlyphIndex(FONSttFontImpl *font, int codepoint)
  167. {
  168. return FT_Get_Char_Index(font->font, codepoint);
  169. }
  170. static int fons__tt_buildGlyphBitmap(FONSttFontImpl *font, int glyph, float size, float scale,
  171. int *advance, int *lsb, int *x0, int *y0, int *x1, int *y1)
  172. {
  173. FT_Error ftError;
  174. FT_GlyphSlot ftGlyph;
  175. FT_Fixed advFixed;
  176. FONS_NOTUSED(scale);
  177. ftError = FT_Set_Pixel_Sizes(font->font, 0, (FT_UInt)(size * (float)font->font->units_per_EM / (float)(font->font->ascender - font->font->descender)));
  178. if (ftError) return 0;
  179. ftError = FT_Load_Glyph(font->font, glyph, FT_LOAD_RENDER);
  180. if (ftError) return 0;
  181. ftError = FT_Get_Advance(font->font, glyph, FT_LOAD_NO_SCALE, &advFixed);
  182. if (ftError) return 0;
  183. ftGlyph = font->font->glyph;
  184. *advance = (int)advFixed;
  185. *lsb = (int)ftGlyph->metrics.horiBearingX;
  186. *x0 = ftGlyph->bitmap_left;
  187. *x1 = *x0 + ftGlyph->bitmap.width;
  188. *y0 = -ftGlyph->bitmap_top;
  189. *y1 = *y0 + ftGlyph->bitmap.rows;
  190. return 1;
  191. }
  192. static void fons__tt_renderGlyphBitmap(FONSttFontImpl *font, unsigned char *output, int outWidth, int outHeight, int outStride,
  193. float scaleX, float scaleY, int glyph)
  194. {
  195. FT_GlyphSlot ftGlyph = font->font->glyph;
  196. int ftGlyphOffset = 0;
  197. int x, y;
  198. FONS_NOTUSED(outWidth);
  199. FONS_NOTUSED(outHeight);
  200. FONS_NOTUSED(scaleX);
  201. FONS_NOTUSED(scaleY);
  202. FONS_NOTUSED(glyph); // glyph has already been loaded by fons__tt_buildGlyphBitmap
  203. for ( y = 0; y < ftGlyph->bitmap.rows; y++ ) {
  204. for ( x = 0; x < ftGlyph->bitmap.width; x++ ) {
  205. output[(y * outStride) + x] = ftGlyph->bitmap.buffer[ftGlyphOffset++];
  206. }
  207. }
  208. }
  209. static int fons__tt_getGlyphKernAdvance(FONSttFontImpl *font, int glyph1, int glyph2)
  210. {
  211. FT_Vector ftKerning;
  212. FT_Get_Kerning(font->font, glyph1, glyph2, FT_KERNING_DEFAULT, &ftKerning);
  213. return (int)((ftKerning.x + 32) >> 6); // Round up and convert to integer
  214. }
  215. #else
  216. #define STB_TRUETYPE_IMPLEMENTATION
  217. #define STBTT_STATIC
  218. static void* fons__tmpalloc(size_t size, void* up);
  219. static void fons__tmpfree(void* ptr, void* up);
  220. #define STBTT_malloc(x,u) fons__tmpalloc(x,u)
  221. #define STBTT_free(x,u) fons__tmpfree(x,u)
  222. #include "stb_truetype.h"
  223. struct FONSttFontImpl {
  224. stbtt_fontinfo font;
  225. };
  226. typedef struct FONSttFontImpl FONSttFontImpl;
  227. static int fons__tt_init(FONScontext *context)
  228. {
  229. FONS_NOTUSED(context);
  230. return 1;
  231. }
  232. static int fons__tt_loadFont(FONScontext *context, FONSttFontImpl *font, unsigned char *data, int dataSize)
  233. {
  234. int stbError;
  235. FONS_NOTUSED(dataSize);
  236. font->font.userdata = context;
  237. stbError = stbtt_InitFont(&font->font, data, 0);
  238. return stbError;
  239. }
  240. static void fons__tt_getFontVMetrics(FONSttFontImpl *font, int *ascent, int *descent, int *lineGap)
  241. {
  242. stbtt_GetFontVMetrics(&font->font, ascent, descent, lineGap);
  243. }
  244. static float fons__tt_getPixelHeightScale(FONSttFontImpl *font, float size)
  245. {
  246. return stbtt_ScaleForPixelHeight(&font->font, size);
  247. }
  248. static int fons__tt_getGlyphIndex(FONSttFontImpl *font, int codepoint)
  249. {
  250. return stbtt_FindGlyphIndex(&font->font, codepoint);
  251. }
  252. static int fons__tt_buildGlyphBitmap(FONSttFontImpl *font, int glyph, float size, float scale,
  253. int *advance, int *lsb, int *x0, int *y0, int *x1, int *y1)
  254. {
  255. FONS_NOTUSED(size);
  256. stbtt_GetGlyphHMetrics(&font->font, glyph, advance, lsb);
  257. stbtt_GetGlyphBitmapBox(&font->font, glyph, scale, scale, x0, y0, x1, y1);
  258. return 1;
  259. }
  260. static void fons__tt_renderGlyphBitmap(FONSttFontImpl *font, unsigned char *output, int outWidth, int outHeight, int outStride,
  261. float scaleX, float scaleY, int glyph)
  262. {
  263. stbtt_MakeGlyphBitmap(&font->font, output, outWidth, outHeight, outStride, scaleX, scaleY, glyph);
  264. }
  265. static int fons__tt_getGlyphKernAdvance(FONSttFontImpl *font, int glyph1, int glyph2)
  266. {
  267. return stbtt_GetGlyphKernAdvance(&font->font, glyph1, glyph2);
  268. }
  269. #endif
  270. #ifndef FONS_SCRATCH_BUF_SIZE
  271. # define FONS_SCRATCH_BUF_SIZE 64000
  272. #endif
  273. #ifndef FONS_HASH_LUT_SIZE
  274. # define FONS_HASH_LUT_SIZE 256
  275. #endif
  276. #ifndef FONS_INIT_FONTS
  277. # define FONS_INIT_FONTS 4
  278. #endif
  279. #ifndef FONS_INIT_GLYPHS
  280. # define FONS_INIT_GLYPHS 256
  281. #endif
  282. #ifndef FONS_INIT_ATLAS_NODES
  283. # define FONS_INIT_ATLAS_NODES 256
  284. #endif
  285. #ifndef FONS_VERTEX_COUNT
  286. # define FONS_VERTEX_COUNT 1024
  287. #endif
  288. #ifndef FONS_MAX_STATES
  289. # define FONS_MAX_STATES 20
  290. #endif
  291. #ifndef FONS_MAX_FALLBACKS
  292. # define FONS_MAX_FALLBACKS 20
  293. #endif
  294. static unsigned int fons__hashint(unsigned int a)
  295. {
  296. a += ~(a<<15);
  297. a ^= (a>>10);
  298. a += (a<<3);
  299. a ^= (a>>6);
  300. a += ~(a<<11);
  301. a ^= (a>>16);
  302. return a;
  303. }
  304. static int fons__mini(int a, int b)
  305. {
  306. return a < b ? a : b;
  307. }
  308. static int fons__maxi(int a, int b)
  309. {
  310. return a > b ? a : b;
  311. }
  312. struct FONSglyph
  313. {
  314. unsigned int codepoint;
  315. int index;
  316. int next;
  317. short size, blur;
  318. short x0,y0,x1,y1;
  319. short xadv,xoff,yoff;
  320. };
  321. typedef struct FONSglyph FONSglyph;
  322. struct FONSfont
  323. {
  324. FONSttFontImpl font;
  325. char name[64];
  326. unsigned char* data;
  327. int dataSize;
  328. unsigned char freeData;
  329. float ascender;
  330. float descender;
  331. float lineh;
  332. FONSglyph* glyphs;
  333. int cglyphs;
  334. int nglyphs;
  335. int lut[FONS_HASH_LUT_SIZE];
  336. int fallbacks[FONS_MAX_FALLBACKS];
  337. int nfallbacks;
  338. };
  339. typedef struct FONSfont FONSfont;
  340. struct FONSstate
  341. {
  342. int font;
  343. int align;
  344. float size;
  345. unsigned int color;
  346. float blur;
  347. float spacing;
  348. };
  349. typedef struct FONSstate FONSstate;
  350. struct FONSatlasNode {
  351. short x, y, width;
  352. };
  353. typedef struct FONSatlasNode FONSatlasNode;
  354. struct FONSatlas
  355. {
  356. int width, height;
  357. FONSatlasNode* nodes;
  358. int nnodes;
  359. int cnodes;
  360. };
  361. typedef struct FONSatlas FONSatlas;
  362. struct FONScontext
  363. {
  364. FONSparams params;
  365. float itw,ith;
  366. unsigned char* texData;
  367. int dirtyRect[4];
  368. FONSfont** fonts;
  369. FONSatlas* atlas;
  370. int cfonts;
  371. int nfonts;
  372. float verts[FONS_VERTEX_COUNT*2];
  373. float tcoords[FONS_VERTEX_COUNT*2];
  374. unsigned int colors[FONS_VERTEX_COUNT];
  375. int nverts;
  376. unsigned char* scratch;
  377. int nscratch;
  378. FONSstate states[FONS_MAX_STATES];
  379. int nstates;
  380. void (*handleError)(void* uptr, int error, int val);
  381. void* errorUptr;
  382. };
  383. #ifdef STB_TRUETYPE_IMPLEMENTATION
  384. static void* fons__tmpalloc(size_t size, void* up)
  385. {
  386. unsigned char* ptr;
  387. FONScontext* stash = (FONScontext*)up;
  388. // 16-byte align the returned pointer
  389. size = (size + 0xf) & ~0xf;
  390. if (stash->nscratch+(int)size > FONS_SCRATCH_BUF_SIZE) {
  391. if (stash->handleError)
  392. stash->handleError(stash->errorUptr, FONS_SCRATCH_FULL, stash->nscratch+(int)size);
  393. return NULL;
  394. }
  395. ptr = stash->scratch + stash->nscratch;
  396. stash->nscratch += (int)size;
  397. return ptr;
  398. }
  399. static void fons__tmpfree(void* ptr, void* up)
  400. {
  401. (void)ptr;
  402. (void)up;
  403. // empty
  404. }
  405. #endif // STB_TRUETYPE_IMPLEMENTATION
  406. // Copyright (c) 2008-2010 Bjoern Hoehrmann <[email protected]>
  407. // See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details.
  408. #define FONS_UTF8_ACCEPT 0
  409. #define FONS_UTF8_REJECT 12
  410. static unsigned int fons__decutf8(unsigned int* state, unsigned int* codep, unsigned int byte)
  411. {
  412. static const unsigned char utf8d[] = {
  413. // The first part of the table maps bytes to character classes that
  414. // to reduce the size of the transition table and create bitmasks.
  415. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  416. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  417. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  418. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  419. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
  420. 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
  421. 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
  422. 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8,
  423. // The second part is a transition table that maps a combination
  424. // of a state of the automaton and a character class to a state.
  425. 0,12,24,36,60,96,84,12,12,12,48,72, 12,12,12,12,12,12,12,12,12,12,12,12,
  426. 12, 0,12,12,12,12,12, 0,12, 0,12,12, 12,24,12,12,12,12,12,24,12,24,12,12,
  427. 12,12,12,12,12,12,12,24,12,12,12,12, 12,24,12,12,12,12,12,12,12,24,12,12,
  428. 12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12,
  429. 12,36,12,12,12,12,12,12,12,12,12,12,
  430. };
  431. unsigned int type = utf8d[byte];
  432. *codep = (*state != FONS_UTF8_ACCEPT) ?
  433. (byte & 0x3fu) | (*codep << 6) :
  434. (0xff >> type) & (byte);
  435. *state = utf8d[256 + *state + type];
  436. return *state;
  437. }
  438. // Atlas based on Skyline Bin Packer by Jukka Jylänki
  439. static void fons__deleteAtlas(FONSatlas* atlas)
  440. {
  441. if (atlas == NULL) return;
  442. if (atlas->nodes != NULL) free(atlas->nodes);
  443. free(atlas);
  444. }
  445. static FONSatlas* fons__allocAtlas(int w, int h, int nnodes)
  446. {
  447. FONSatlas* atlas = NULL;
  448. // Allocate memory for the font stash.
  449. atlas = (FONSatlas*)malloc(sizeof(FONSatlas));
  450. if (atlas == NULL) goto error;
  451. memset(atlas, 0, sizeof(FONSatlas));
  452. atlas->width = w;
  453. atlas->height = h;
  454. // Allocate space for skyline nodes
  455. atlas->nodes = (FONSatlasNode*)malloc(sizeof(FONSatlasNode) * nnodes);
  456. if (atlas->nodes == NULL) goto error;
  457. memset(atlas->nodes, 0, sizeof(FONSatlasNode) * nnodes);
  458. atlas->nnodes = 0;
  459. atlas->cnodes = nnodes;
  460. // Init root node.
  461. atlas->nodes[0].x = 0;
  462. atlas->nodes[0].y = 0;
  463. atlas->nodes[0].width = (short)w;
  464. atlas->nnodes++;
  465. return atlas;
  466. error:
  467. if (atlas) fons__deleteAtlas(atlas);
  468. return NULL;
  469. }
  470. static int fons__atlasInsertNode(FONSatlas* atlas, int idx, int x, int y, int w)
  471. {
  472. int i;
  473. // Insert node
  474. if (atlas->nnodes+1 > atlas->cnodes) {
  475. atlas->cnodes = atlas->cnodes == 0 ? 8 : atlas->cnodes * 2;
  476. atlas->nodes = (FONSatlasNode*)realloc(atlas->nodes, sizeof(FONSatlasNode) * atlas->cnodes);
  477. if (atlas->nodes == NULL)
  478. return 0;
  479. }
  480. for (i = atlas->nnodes; i > idx; i--)
  481. atlas->nodes[i] = atlas->nodes[i-1];
  482. atlas->nodes[idx].x = (short)x;
  483. atlas->nodes[idx].y = (short)y;
  484. atlas->nodes[idx].width = (short)w;
  485. atlas->nnodes++;
  486. return 1;
  487. }
  488. static void fons__atlasRemoveNode(FONSatlas* atlas, int idx)
  489. {
  490. int i;
  491. if (atlas->nnodes == 0) return;
  492. for (i = idx; i < atlas->nnodes-1; i++)
  493. atlas->nodes[i] = atlas->nodes[i+1];
  494. atlas->nnodes--;
  495. }
  496. static void fons__atlasExpand(FONSatlas* atlas, int w, int h)
  497. {
  498. // Insert node for empty space
  499. if (w > atlas->width)
  500. fons__atlasInsertNode(atlas, atlas->nnodes, atlas->width, 0, w - atlas->width);
  501. atlas->width = w;
  502. atlas->height = h;
  503. }
  504. static void fons__atlasReset(FONSatlas* atlas, int w, int h)
  505. {
  506. atlas->width = w;
  507. atlas->height = h;
  508. atlas->nnodes = 0;
  509. // Init root node.
  510. atlas->nodes[0].x = 0;
  511. atlas->nodes[0].y = 0;
  512. atlas->nodes[0].width = (short)w;
  513. atlas->nnodes++;
  514. }
  515. static int fons__atlasAddSkylineLevel(FONSatlas* atlas, int idx, int x, int y, int w, int h)
  516. {
  517. int i;
  518. // Insert new node
  519. if (fons__atlasInsertNode(atlas, idx, x, y+h, w) == 0)
  520. return 0;
  521. // Delete skyline segments that fall under the shadow of the new segment.
  522. for (i = idx+1; i < atlas->nnodes; i++) {
  523. if (atlas->nodes[i].x < atlas->nodes[i-1].x + atlas->nodes[i-1].width) {
  524. int shrink = atlas->nodes[i-1].x + atlas->nodes[i-1].width - atlas->nodes[i].x;
  525. atlas->nodes[i].x += (short)shrink;
  526. atlas->nodes[i].width -= (short)shrink;
  527. if (atlas->nodes[i].width <= 0) {
  528. fons__atlasRemoveNode(atlas, i);
  529. i--;
  530. } else {
  531. break;
  532. }
  533. } else {
  534. break;
  535. }
  536. }
  537. // Merge same height skyline segments that are next to each other.
  538. for (i = 0; i < atlas->nnodes-1; i++) {
  539. if (atlas->nodes[i].y == atlas->nodes[i+1].y) {
  540. atlas->nodes[i].width += atlas->nodes[i+1].width;
  541. fons__atlasRemoveNode(atlas, i+1);
  542. i--;
  543. }
  544. }
  545. return 1;
  546. }
  547. static int fons__atlasRectFits(FONSatlas* atlas, int i, int w, int h)
  548. {
  549. // Checks if there is enough space at the location of skyline span 'i',
  550. // and return the max height of all skyline spans under that at that location,
  551. // (think tetris block being dropped at that position). Or -1 if no space found.
  552. int x = atlas->nodes[i].x;
  553. int y = atlas->nodes[i].y;
  554. int spaceLeft;
  555. if (x + w > atlas->width)
  556. return -1;
  557. spaceLeft = w;
  558. while (spaceLeft > 0) {
  559. if (i == atlas->nnodes) return -1;
  560. y = fons__maxi(y, atlas->nodes[i].y);
  561. if (y + h > atlas->height) return -1;
  562. spaceLeft -= atlas->nodes[i].width;
  563. ++i;
  564. }
  565. return y;
  566. }
  567. static int fons__atlasAddRect(FONSatlas* atlas, int rw, int rh, int* rx, int* ry)
  568. {
  569. int besth = atlas->height, bestw = atlas->width, besti = -1;
  570. int bestx = -1, besty = -1, i;
  571. // Bottom left fit heuristic.
  572. for (i = 0; i < atlas->nnodes; i++) {
  573. int y = fons__atlasRectFits(atlas, i, rw, rh);
  574. if (y != -1) {
  575. if (y + rh < besth || (y + rh == besth && atlas->nodes[i].width < bestw)) {
  576. besti = i;
  577. bestw = atlas->nodes[i].width;
  578. besth = y + rh;
  579. bestx = atlas->nodes[i].x;
  580. besty = y;
  581. }
  582. }
  583. }
  584. if (besti == -1)
  585. return 0;
  586. // Perform the actual packing.
  587. if (fons__atlasAddSkylineLevel(atlas, besti, bestx, besty, rw, rh) == 0)
  588. return 0;
  589. *rx = bestx;
  590. *ry = besty;
  591. return 1;
  592. }
  593. static void fons__addWhiteRect(FONScontext* stash, int w, int h)
  594. {
  595. int x, y, gx, gy;
  596. unsigned char* dst;
  597. if (fons__atlasAddRect(stash->atlas, w, h, &gx, &gy) == 0)
  598. return;
  599. // Rasterize
  600. dst = &stash->texData[gx + gy * stash->params.width];
  601. for (y = 0; y < h; y++) {
  602. for (x = 0; x < w; x++)
  603. dst[x] = 0xff;
  604. dst += stash->params.width;
  605. }
  606. stash->dirtyRect[0] = fons__mini(stash->dirtyRect[0], gx);
  607. stash->dirtyRect[1] = fons__mini(stash->dirtyRect[1], gy);
  608. stash->dirtyRect[2] = fons__maxi(stash->dirtyRect[2], gx+w);
  609. stash->dirtyRect[3] = fons__maxi(stash->dirtyRect[3], gy+h);
  610. }
  611. FONScontext* fonsCreateInternal(FONSparams* params)
  612. {
  613. FONScontext* stash = NULL;
  614. // Allocate memory for the font stash.
  615. stash = (FONScontext*)malloc(sizeof(FONScontext));
  616. if (stash == NULL) goto error;
  617. memset(stash, 0, sizeof(FONScontext));
  618. stash->params = *params;
  619. // Allocate scratch buffer.
  620. stash->scratch = (unsigned char*)malloc(FONS_SCRATCH_BUF_SIZE);
  621. if (stash->scratch == NULL) goto error;
  622. // Initialize implementation library
  623. if (!fons__tt_init(stash)) goto error;
  624. if (stash->params.renderCreate != NULL) {
  625. if (stash->params.renderCreate(stash->params.userPtr, stash->params.width, stash->params.height) == 0)
  626. goto error;
  627. }
  628. stash->atlas = fons__allocAtlas(stash->params.width, stash->params.height, FONS_INIT_ATLAS_NODES);
  629. if (stash->atlas == NULL) goto error;
  630. // Allocate space for fonts.
  631. stash->fonts = (FONSfont**)malloc(sizeof(FONSfont*) * FONS_INIT_FONTS);
  632. if (stash->fonts == NULL) goto error;
  633. memset(stash->fonts, 0, sizeof(FONSfont*) * FONS_INIT_FONTS);
  634. stash->cfonts = FONS_INIT_FONTS;
  635. stash->nfonts = 0;
  636. // Create texture for the cache.
  637. stash->itw = 1.0f/stash->params.width;
  638. stash->ith = 1.0f/stash->params.height;
  639. stash->texData = (unsigned char*)malloc(stash->params.width * stash->params.height);
  640. if (stash->texData == NULL) goto error;
  641. memset(stash->texData, 0, stash->params.width * stash->params.height);
  642. stash->dirtyRect[0] = stash->params.width;
  643. stash->dirtyRect[1] = stash->params.height;
  644. stash->dirtyRect[2] = 0;
  645. stash->dirtyRect[3] = 0;
  646. // Add white rect at 0,0 for debug drawing.
  647. fons__addWhiteRect(stash, 2,2);
  648. fonsPushState(stash);
  649. fonsClearState(stash);
  650. return stash;
  651. error:
  652. fonsDeleteInternal(stash);
  653. return NULL;
  654. }
  655. static FONSstate* fons__getState(FONScontext* stash)
  656. {
  657. return &stash->states[stash->nstates-1];
  658. }
  659. int fonsAddFallbackFont(FONScontext* stash, int base, int fallback)
  660. {
  661. FONSfont* baseFont = stash->fonts[base];
  662. if (baseFont->nfallbacks < FONS_MAX_FALLBACKS) {
  663. baseFont->fallbacks[baseFont->nfallbacks++] = fallback;
  664. return 1;
  665. }
  666. return 0;
  667. }
  668. void fonsSetSize(FONScontext* stash, float size)
  669. {
  670. fons__getState(stash)->size = size;
  671. }
  672. void fonsSetColor(FONScontext* stash, unsigned int color)
  673. {
  674. fons__getState(stash)->color = color;
  675. }
  676. void fonsSetSpacing(FONScontext* stash, float spacing)
  677. {
  678. fons__getState(stash)->spacing = spacing;
  679. }
  680. void fonsSetBlur(FONScontext* stash, float blur)
  681. {
  682. fons__getState(stash)->blur = blur;
  683. }
  684. void fonsSetAlign(FONScontext* stash, int align)
  685. {
  686. fons__getState(stash)->align = align;
  687. }
  688. void fonsSetFont(FONScontext* stash, int font)
  689. {
  690. fons__getState(stash)->font = font;
  691. }
  692. void fonsPushState(FONScontext* stash)
  693. {
  694. if (stash->nstates >= FONS_MAX_STATES) {
  695. if (stash->handleError)
  696. stash->handleError(stash->errorUptr, FONS_STATES_OVERFLOW, 0);
  697. return;
  698. }
  699. if (stash->nstates > 0)
  700. memcpy(&stash->states[stash->nstates], &stash->states[stash->nstates-1], sizeof(FONSstate));
  701. stash->nstates++;
  702. }
  703. void fonsPopState(FONScontext* stash)
  704. {
  705. if (stash->nstates <= 1) {
  706. if (stash->handleError)
  707. stash->handleError(stash->errorUptr, FONS_STATES_UNDERFLOW, 0);
  708. return;
  709. }
  710. stash->nstates--;
  711. }
  712. void fonsClearState(FONScontext* stash)
  713. {
  714. FONSstate* state = fons__getState(stash);
  715. state->size = 12.0f;
  716. state->color = 0xffffffff;
  717. state->font = 0;
  718. state->blur = 0;
  719. state->spacing = 0;
  720. state->align = FONS_ALIGN_LEFT | FONS_ALIGN_BASELINE;
  721. }
  722. static void fons__freeFont(FONSfont* font)
  723. {
  724. if (font == NULL) return;
  725. if (font->glyphs) free(font->glyphs);
  726. if (font->freeData && font->data) free(font->data);
  727. free(font);
  728. }
  729. static int fons__allocFont(FONScontext* stash)
  730. {
  731. FONSfont* font = NULL;
  732. if (stash->nfonts+1 > stash->cfonts) {
  733. stash->cfonts = stash->cfonts == 0 ? 8 : stash->cfonts * 2;
  734. stash->fonts = (FONSfont**)realloc(stash->fonts, sizeof(FONSfont*) * stash->cfonts);
  735. if (stash->fonts == NULL)
  736. return -1;
  737. }
  738. font = (FONSfont*)malloc(sizeof(FONSfont));
  739. if (font == NULL) goto error;
  740. memset(font, 0, sizeof(FONSfont));
  741. font->glyphs = (FONSglyph*)malloc(sizeof(FONSglyph) * FONS_INIT_GLYPHS);
  742. if (font->glyphs == NULL) goto error;
  743. font->cglyphs = FONS_INIT_GLYPHS;
  744. font->nglyphs = 0;
  745. stash->fonts[stash->nfonts++] = font;
  746. return stash->nfonts-1;
  747. error:
  748. fons__freeFont(font);
  749. return FONS_INVALID;
  750. }
  751. int fonsAddFontMem(FONScontext* stash, const char* name, unsigned char* data, int dataSize, int freeData)
  752. {
  753. int i, ascent, descent, fh, lineGap;
  754. FONSfont* font;
  755. int idx = fons__allocFont(stash);
  756. if (idx == FONS_INVALID)
  757. return FONS_INVALID;
  758. font = stash->fonts[idx];
  759. strncpy(font->name, name, sizeof(font->name));
  760. font->name[sizeof(font->name)-1] = '\0';
  761. // Init hash lookup.
  762. for (i = 0; i < FONS_HASH_LUT_SIZE; ++i)
  763. font->lut[i] = -1;
  764. // Read in the font data.
  765. font->dataSize = dataSize;
  766. font->data = data;
  767. font->freeData = (unsigned char)freeData;
  768. // Init font
  769. stash->nscratch = 0;
  770. if (!fons__tt_loadFont(stash, &font->font, data, dataSize)) goto error;
  771. // Store normalized line height. The real line height is got
  772. // by multiplying the lineh by font size.
  773. fons__tt_getFontVMetrics( &font->font, &ascent, &descent, &lineGap);
  774. fh = ascent - descent;
  775. font->ascender = (float)ascent / (float)fh;
  776. font->descender = (float)descent / (float)fh;
  777. font->lineh = (float)(fh + lineGap) / (float)fh;
  778. return idx;
  779. error:
  780. fons__freeFont(font);
  781. stash->nfonts--;
  782. return FONS_INVALID;
  783. }
  784. int fonsGetFontByName(FONScontext* s, const char* name)
  785. {
  786. int i;
  787. for (i = 0; i < s->nfonts; i++) {
  788. if (strcmp(s->fonts[i]->name, name) == 0)
  789. return i;
  790. }
  791. return FONS_INVALID;
  792. }
  793. static FONSglyph* fons__allocGlyph(FONSfont* font)
  794. {
  795. if (font->nglyphs+1 > font->cglyphs) {
  796. font->cglyphs = font->cglyphs == 0 ? 8 : font->cglyphs * 2;
  797. font->glyphs = (FONSglyph*)realloc(font->glyphs, sizeof(FONSglyph) * font->cglyphs);
  798. if (font->glyphs == NULL) return NULL;
  799. }
  800. font->nglyphs++;
  801. return &font->glyphs[font->nglyphs-1];
  802. }
  803. // Based on Exponential blur, Jani Huhtanen, 2006
  804. #define APREC 16
  805. #define ZPREC 7
  806. static void fons__blurCols(unsigned char* dst, int w, int h, int dstStride, int alpha)
  807. {
  808. int x, y;
  809. for (y = 0; y < h; y++) {
  810. int z = 0; // force zero border
  811. for (x = 1; x < w; x++) {
  812. z += (alpha * (((int)(dst[x]) << ZPREC) - z)) >> APREC;
  813. dst[x] = (unsigned char)(z >> ZPREC);
  814. }
  815. dst[w-1] = 0; // force zero border
  816. z = 0;
  817. for (x = w-2; x >= 0; x--) {
  818. z += (alpha * (((int)(dst[x]) << ZPREC) - z)) >> APREC;
  819. dst[x] = (unsigned char)(z >> ZPREC);
  820. }
  821. dst[0] = 0; // force zero border
  822. dst += dstStride;
  823. }
  824. }
  825. static void fons__blurRows(unsigned char* dst, int w, int h, int dstStride, int alpha)
  826. {
  827. int x, y;
  828. for (x = 0; x < w; x++) {
  829. int z = 0; // force zero border
  830. for (y = dstStride; y < h*dstStride; y += dstStride) {
  831. z += (alpha * (((int)(dst[y]) << ZPREC) - z)) >> APREC;
  832. dst[y] = (unsigned char)(z >> ZPREC);
  833. }
  834. dst[(h-1)*dstStride] = 0; // force zero border
  835. z = 0;
  836. for (y = (h-2)*dstStride; y >= 0; y -= dstStride) {
  837. z += (alpha * (((int)(dst[y]) << ZPREC) - z)) >> APREC;
  838. dst[y] = (unsigned char)(z >> ZPREC);
  839. }
  840. dst[0] = 0; // force zero border
  841. dst++;
  842. }
  843. }
  844. static void fons__blur(FONScontext* stash, unsigned char* dst, int w, int h, int dstStride, int blur)
  845. {
  846. int alpha;
  847. float sigma;
  848. (void)stash;
  849. if (blur < 1)
  850. return;
  851. // Calculate the alpha such that 90% of the kernel is within the radius. (Kernel extends to infinity)
  852. sigma = (float)blur * 0.57735f; // 1 / sqrt(3)
  853. alpha = (int)((1<<APREC) * (1.0f - expf(-2.3f / (sigma+1.0f))));
  854. fons__blurRows(dst, w, h, dstStride, alpha);
  855. fons__blurCols(dst, w, h, dstStride, alpha);
  856. fons__blurRows(dst, w, h, dstStride, alpha);
  857. fons__blurCols(dst, w, h, dstStride, alpha);
  858. // fons__blurrows(dst, w, h, dstStride, alpha);
  859. // fons__blurcols(dst, w, h, dstStride, alpha);
  860. }
  861. static FONSglyph* fons__getGlyph(FONScontext* stash, FONSfont* font, unsigned int codepoint,
  862. short isize, short iblur)
  863. {
  864. int i, g, advance, lsb, x0, y0, x1, y1, gw, gh, gx, gy, x, y;
  865. float scale;
  866. FONSglyph* glyph = NULL;
  867. unsigned int h;
  868. float size = isize/10.0f;
  869. int pad, added;
  870. unsigned char* bdst;
  871. unsigned char* dst;
  872. FONSfont* renderFont = font;
  873. if (isize < 2) return NULL;
  874. if (iblur > 20) iblur = 20;
  875. pad = iblur+2;
  876. // Reset allocator.
  877. stash->nscratch = 0;
  878. // Find code point and size.
  879. h = fons__hashint(codepoint) & (FONS_HASH_LUT_SIZE-1);
  880. i = font->lut[h];
  881. while (i != -1) {
  882. if (font->glyphs[i].codepoint == codepoint && font->glyphs[i].size == isize && font->glyphs[i].blur == iblur)
  883. return &font->glyphs[i];
  884. i = font->glyphs[i].next;
  885. }
  886. // Could not find glyph, create it.
  887. g = fons__tt_getGlyphIndex(&font->font, codepoint);
  888. // Try to find the glyph in fallback fonts.
  889. if (g == 0) {
  890. for (i = 0; i < font->nfallbacks; ++i) {
  891. FONSfont* fallbackFont = stash->fonts[font->fallbacks[i]];
  892. int fallbackIndex = fons__tt_getGlyphIndex(&fallbackFont->font, codepoint);
  893. if (fallbackIndex != 0) {
  894. g = fallbackIndex;
  895. renderFont = fallbackFont;
  896. break;
  897. }
  898. }
  899. // It is possible that we did not find a fallback glyph.
  900. // In that case the glyph index 'g' is 0, and we'll proceed below and cache empty glyph.
  901. }
  902. scale = fons__tt_getPixelHeightScale(&renderFont->font, size);
  903. fons__tt_buildGlyphBitmap(&renderFont->font, g, size, scale, &advance, &lsb, &x0, &y0, &x1, &y1);
  904. gw = x1-x0 + pad*2;
  905. gh = y1-y0 + pad*2;
  906. // Find free spot for the rect in the atlas
  907. added = fons__atlasAddRect(stash->atlas, gw, gh, &gx, &gy);
  908. if (added == 0 && stash->handleError != NULL) {
  909. // Atlas is full, let the user to resize the atlas (or not), and try again.
  910. stash->handleError(stash->errorUptr, FONS_ATLAS_FULL, 0);
  911. added = fons__atlasAddRect(stash->atlas, gw, gh, &gx, &gy);
  912. }
  913. if (added == 0) return NULL;
  914. // Init glyph.
  915. glyph = fons__allocGlyph(font);
  916. glyph->codepoint = codepoint;
  917. glyph->size = isize;
  918. glyph->blur = iblur;
  919. glyph->index = g;
  920. glyph->x0 = (short)gx;
  921. glyph->y0 = (short)gy;
  922. glyph->x1 = (short)(glyph->x0+gw);
  923. glyph->y1 = (short)(glyph->y0+gh);
  924. glyph->xadv = (short)(scale * advance * 10.0f);
  925. glyph->xoff = (short)(x0 - pad);
  926. glyph->yoff = (short)(y0 - pad);
  927. glyph->next = 0;
  928. // Insert char to hash lookup.
  929. glyph->next = font->lut[h];
  930. font->lut[h] = font->nglyphs-1;
  931. // Rasterize
  932. dst = &stash->texData[(glyph->x0+pad) + (glyph->y0+pad) * stash->params.width];
  933. fons__tt_renderGlyphBitmap(&renderFont->font, dst, gw-pad*2,gh-pad*2, stash->params.width, scale,scale, g);
  934. // Make sure there is one pixel empty border.
  935. dst = &stash->texData[glyph->x0 + glyph->y0 * stash->params.width];
  936. for (y = 0; y < gh; y++) {
  937. dst[y*stash->params.width] = 0;
  938. dst[gw-1 + y*stash->params.width] = 0;
  939. }
  940. for (x = 0; x < gw; x++) {
  941. dst[x] = 0;
  942. dst[x + (gh-1)*stash->params.width] = 0;
  943. }
  944. // Debug code to color the glyph background
  945. /* unsigned char* fdst = &stash->texData[glyph->x0 + glyph->y0 * stash->params.width];
  946. for (y = 0; y < gh; y++) {
  947. for (x = 0; x < gw; x++) {
  948. int a = (int)fdst[x+y*stash->params.width] + 20;
  949. if (a > 255) a = 255;
  950. fdst[x+y*stash->params.width] = a;
  951. }
  952. }*/
  953. // Blur
  954. if (iblur > 0) {
  955. stash->nscratch = 0;
  956. bdst = &stash->texData[glyph->x0 + glyph->y0 * stash->params.width];
  957. fons__blur(stash, bdst, gw,gh, stash->params.width, iblur);
  958. }
  959. stash->dirtyRect[0] = fons__mini(stash->dirtyRect[0], glyph->x0);
  960. stash->dirtyRect[1] = fons__mini(stash->dirtyRect[1], glyph->y0);
  961. stash->dirtyRect[2] = fons__maxi(stash->dirtyRect[2], glyph->x1);
  962. stash->dirtyRect[3] = fons__maxi(stash->dirtyRect[3], glyph->y1);
  963. return glyph;
  964. }
  965. static void fons__getQuad(FONScontext* stash, FONSfont* font,
  966. int prevGlyphIndex, FONSglyph* glyph,
  967. float scale, float spacing, float* x, float* y, FONSquad* q)
  968. {
  969. float rx,ry,xoff,yoff,x0,y0,x1,y1;
  970. if (prevGlyphIndex != -1) {
  971. float adv = fons__tt_getGlyphKernAdvance(&font->font, prevGlyphIndex, glyph->index) * scale;
  972. *x += (int)(adv + spacing + 0.5f);
  973. }
  974. // Each glyph has 2px border to allow good interpolation,
  975. // one pixel to prevent leaking, and one to allow good interpolation for rendering.
  976. // Inset the texture region by one pixel for correct interpolation.
  977. xoff = (short)(glyph->xoff+1);
  978. yoff = (short)(glyph->yoff+1);
  979. x0 = (float)(glyph->x0+1);
  980. y0 = (float)(glyph->y0+1);
  981. x1 = (float)(glyph->x1-1);
  982. y1 = (float)(glyph->y1-1);
  983. if (stash->params.flags & FONS_ZERO_TOPLEFT) {
  984. rx = (float)(int)(*x + xoff);
  985. ry = (float)(int)(*y + yoff);
  986. q->x0 = rx;
  987. q->y0 = ry;
  988. q->x1 = rx + x1 - x0;
  989. q->y1 = ry + y1 - y0;
  990. q->s0 = x0 * stash->itw;
  991. q->t0 = y0 * stash->ith;
  992. q->s1 = x1 * stash->itw;
  993. q->t1 = y1 * stash->ith;
  994. } else {
  995. rx = (float)(int)(*x + xoff);
  996. ry = (float)(int)(*y - yoff);
  997. q->x0 = rx;
  998. q->y0 = ry;
  999. q->x1 = rx + x1 - x0;
  1000. q->y1 = ry - y1 + y0;
  1001. q->s0 = x0 * stash->itw;
  1002. q->t0 = y0 * stash->ith;
  1003. q->s1 = x1 * stash->itw;
  1004. q->t1 = y1 * stash->ith;
  1005. }
  1006. *x += (int)(glyph->xadv / 10.0f + 0.5f);
  1007. }
  1008. static void fons__flush(FONScontext* stash)
  1009. {
  1010. // Flush texture
  1011. if (stash->dirtyRect[0] < stash->dirtyRect[2] && stash->dirtyRect[1] < stash->dirtyRect[3]) {
  1012. if (stash->params.renderUpdate != NULL)
  1013. stash->params.renderUpdate(stash->params.userPtr, stash->dirtyRect, stash->texData);
  1014. // Reset dirty rect
  1015. stash->dirtyRect[0] = stash->params.width;
  1016. stash->dirtyRect[1] = stash->params.height;
  1017. stash->dirtyRect[2] = 0;
  1018. stash->dirtyRect[3] = 0;
  1019. }
  1020. // Flush triangles
  1021. if (stash->nverts > 0) {
  1022. if (stash->params.renderDraw != NULL)
  1023. stash->params.renderDraw(stash->params.userPtr, stash->verts, stash->tcoords, stash->colors, stash->nverts);
  1024. stash->nverts = 0;
  1025. }
  1026. }
  1027. static __inline void fons__vertex(FONScontext* stash, float x, float y, float s, float t, unsigned int c)
  1028. {
  1029. stash->verts[stash->nverts*2+0] = x;
  1030. stash->verts[stash->nverts*2+1] = y;
  1031. stash->tcoords[stash->nverts*2+0] = s;
  1032. stash->tcoords[stash->nverts*2+1] = t;
  1033. stash->colors[stash->nverts] = c;
  1034. stash->nverts++;
  1035. }
  1036. static float fons__getVertAlign(FONScontext* stash, FONSfont* font, int align, short isize)
  1037. {
  1038. if (stash->params.flags & FONS_ZERO_TOPLEFT) {
  1039. if (align & FONS_ALIGN_TOP) {
  1040. return font->ascender * (float)isize/10.0f;
  1041. } else if (align & FONS_ALIGN_MIDDLE) {
  1042. return (font->ascender + font->descender) / 2.0f * (float)isize/10.0f;
  1043. } else if (align & FONS_ALIGN_BASELINE) {
  1044. return 0.0f;
  1045. } else if (align & FONS_ALIGN_BOTTOM) {
  1046. return font->descender * (float)isize/10.0f;
  1047. }
  1048. } else {
  1049. if (align & FONS_ALIGN_TOP) {
  1050. return -font->ascender * (float)isize/10.0f;
  1051. } else if (align & FONS_ALIGN_MIDDLE) {
  1052. return -(font->ascender + font->descender) / 2.0f * (float)isize/10.0f;
  1053. } else if (align & FONS_ALIGN_BASELINE) {
  1054. return 0.0f;
  1055. } else if (align & FONS_ALIGN_BOTTOM) {
  1056. return -font->descender * (float)isize/10.0f;
  1057. }
  1058. }
  1059. return 0.0;
  1060. }
  1061. FONS_DEF float fonsDrawText(FONScontext* stash,
  1062. float x, float y,
  1063. const char* str, const char* end)
  1064. {
  1065. FONSstate* state = fons__getState(stash);
  1066. unsigned int codepoint;
  1067. unsigned int utf8state = 0;
  1068. FONSglyph* glyph = NULL;
  1069. FONSquad q;
  1070. int prevGlyphIndex = -1;
  1071. short isize = (short)(state->size*10.0f);
  1072. short iblur = (short)state->blur;
  1073. float scale;
  1074. FONSfont* font;
  1075. float width;
  1076. if (stash == NULL) return x;
  1077. if (state->font < 0 || state->font >= stash->nfonts) return x;
  1078. font = stash->fonts[state->font];
  1079. if (font->data == NULL) return x;
  1080. scale = fons__tt_getPixelHeightScale(&font->font, (float)isize/10.0f);
  1081. if (end == NULL)
  1082. end = str + strlen(str);
  1083. // Align horizontally
  1084. if (state->align & FONS_ALIGN_LEFT) {
  1085. // empty
  1086. } else if (state->align & FONS_ALIGN_RIGHT) {
  1087. width = fonsTextBounds(stash, x,y, str, end, NULL);
  1088. x -= width;
  1089. } else if (state->align & FONS_ALIGN_CENTER) {
  1090. width = fonsTextBounds(stash, x,y, str, end, NULL);
  1091. x -= width * 0.5f;
  1092. }
  1093. // Align vertically.
  1094. y += fons__getVertAlign(stash, font, state->align, isize);
  1095. for (; str != end; ++str) {
  1096. if (fons__decutf8(&utf8state, &codepoint, *(const unsigned char*)str))
  1097. continue;
  1098. glyph = fons__getGlyph(stash, font, codepoint, isize, iblur);
  1099. if (glyph != NULL) {
  1100. fons__getQuad(stash, font, prevGlyphIndex, glyph, scale, state->spacing, &x, &y, &q);
  1101. if (stash->nverts+6 > FONS_VERTEX_COUNT)
  1102. fons__flush(stash);
  1103. fons__vertex(stash, q.x0, q.y0, q.s0, q.t0, state->color);
  1104. fons__vertex(stash, q.x1, q.y1, q.s1, q.t1, state->color);
  1105. fons__vertex(stash, q.x1, q.y0, q.s1, q.t0, state->color);
  1106. fons__vertex(stash, q.x0, q.y0, q.s0, q.t0, state->color);
  1107. fons__vertex(stash, q.x0, q.y1, q.s0, q.t1, state->color);
  1108. fons__vertex(stash, q.x1, q.y1, q.s1, q.t1, state->color);
  1109. }
  1110. prevGlyphIndex = glyph != NULL ? glyph->index : -1;
  1111. }
  1112. fons__flush(stash);
  1113. return x;
  1114. }
  1115. FONS_DEF int fonsTextIterInit(FONScontext* stash, FONStextIter* iter,
  1116. float x, float y, const char* str, const char* end)
  1117. {
  1118. FONSstate* state = fons__getState(stash);
  1119. float width;
  1120. memset(iter, 0, sizeof(*iter));
  1121. if (stash == NULL) return 0;
  1122. if (state->font < 0 || state->font >= stash->nfonts) return 0;
  1123. iter->font = stash->fonts[state->font];
  1124. if (iter->font->data == NULL) return 0;
  1125. iter->isize = (short)(state->size*10.0f);
  1126. iter->iblur = (short)state->blur;
  1127. iter->scale = fons__tt_getPixelHeightScale(&iter->font->font, (float)iter->isize/10.0f);
  1128. // Align horizontally
  1129. if (state->align & FONS_ALIGN_LEFT) {
  1130. // empty
  1131. } else if (state->align & FONS_ALIGN_RIGHT) {
  1132. width = fonsTextBounds(stash, x,y, str, end, NULL);
  1133. x -= width;
  1134. } else if (state->align & FONS_ALIGN_CENTER) {
  1135. width = fonsTextBounds(stash, x,y, str, end, NULL);
  1136. x -= width * 0.5f;
  1137. }
  1138. // Align vertically.
  1139. y += fons__getVertAlign(stash, iter->font, state->align, iter->isize);
  1140. if (end == NULL)
  1141. end = str + strlen(str);
  1142. iter->x = iter->nextx = x;
  1143. iter->y = iter->nexty = y;
  1144. iter->spacing = state->spacing;
  1145. iter->str = str;
  1146. iter->next = str;
  1147. iter->end = end;
  1148. iter->codepoint = 0;
  1149. iter->prevGlyphIndex = -1;
  1150. return 1;
  1151. }
  1152. FONS_DEF int fonsTextIterNext(FONScontext* stash, FONStextIter* iter, FONSquad* quad)
  1153. {
  1154. FONSglyph* glyph = NULL;
  1155. const char* str = iter->next;
  1156. iter->str = iter->next;
  1157. if (str == iter->end)
  1158. return 0;
  1159. for (; str != iter->end; str++) {
  1160. if (fons__decutf8(&iter->utf8state, &iter->codepoint, *(const unsigned char*)str))
  1161. continue;
  1162. str++;
  1163. // Get glyph and quad
  1164. iter->x = iter->nextx;
  1165. iter->y = iter->nexty;
  1166. glyph = fons__getGlyph(stash, iter->font, iter->codepoint, iter->isize, iter->iblur);
  1167. if (glyph != NULL)
  1168. fons__getQuad(stash, iter->font, iter->prevGlyphIndex, glyph, iter->scale, iter->spacing, &iter->nextx, &iter->nexty, quad);
  1169. iter->prevGlyphIndex = glyph != NULL ? glyph->index : -1;
  1170. break;
  1171. }
  1172. iter->next = str;
  1173. return 1;
  1174. }
  1175. FONS_DEF void fonsDrawDebug(FONScontext* stash, float x, float y)
  1176. {
  1177. int i;
  1178. int w = stash->params.width;
  1179. int h = stash->params.height;
  1180. float u = w == 0 ? 0 : (1.0f / w);
  1181. float v = h == 0 ? 0 : (1.0f / h);
  1182. if (stash->nverts+6+6 > FONS_VERTEX_COUNT)
  1183. fons__flush(stash);
  1184. // Draw background
  1185. fons__vertex(stash, x+0, y+0, u, v, 0x0fffffff);
  1186. fons__vertex(stash, x+w, y+h, u, v, 0x0fffffff);
  1187. fons__vertex(stash, x+w, y+0, u, v, 0x0fffffff);
  1188. fons__vertex(stash, x+0, y+0, u, v, 0x0fffffff);
  1189. fons__vertex(stash, x+0, y+h, u, v, 0x0fffffff);
  1190. fons__vertex(stash, x+w, y+h, u, v, 0x0fffffff);
  1191. // Draw texture
  1192. fons__vertex(stash, x+0, y+0, 0, 0, 0xffffffff);
  1193. fons__vertex(stash, x+w, y+h, 1, 1, 0xffffffff);
  1194. fons__vertex(stash, x+w, y+0, 1, 0, 0xffffffff);
  1195. fons__vertex(stash, x+0, y+0, 0, 0, 0xffffffff);
  1196. fons__vertex(stash, x+0, y+h, 0, 1, 0xffffffff);
  1197. fons__vertex(stash, x+w, y+h, 1, 1, 0xffffffff);
  1198. // Drawbug draw atlas
  1199. for (i = 0; i < stash->atlas->nnodes; i++) {
  1200. FONSatlasNode* n = &stash->atlas->nodes[i];
  1201. if (stash->nverts+6 > FONS_VERTEX_COUNT)
  1202. fons__flush(stash);
  1203. fons__vertex(stash, x+n->x+0, y+n->y+0, u, v, 0xc00000ff);
  1204. fons__vertex(stash, x+n->x+n->width, y+n->y+1, u, v, 0xc00000ff);
  1205. fons__vertex(stash, x+n->x+n->width, y+n->y+0, u, v, 0xc00000ff);
  1206. fons__vertex(stash, x+n->x+0, y+n->y+0, u, v, 0xc00000ff);
  1207. fons__vertex(stash, x+n->x+0, y+n->y+1, u, v, 0xc00000ff);
  1208. fons__vertex(stash, x+n->x+n->width, y+n->y+1, u, v, 0xc00000ff);
  1209. }
  1210. fons__flush(stash);
  1211. }
  1212. FONS_DEF float fonsTextBounds(FONScontext* stash,
  1213. float x, float y,
  1214. const char* str, const char* end,
  1215. float* bounds)
  1216. {
  1217. FONSstate* state = fons__getState(stash);
  1218. unsigned int codepoint;
  1219. unsigned int utf8state = 0;
  1220. FONSquad q;
  1221. FONSglyph* glyph = NULL;
  1222. int prevGlyphIndex = -1;
  1223. short isize = (short)(state->size*10.0f);
  1224. short iblur = (short)state->blur;
  1225. float scale;
  1226. FONSfont* font;
  1227. float startx, advance;
  1228. float minx, miny, maxx, maxy;
  1229. if (stash == NULL) return 0;
  1230. if (state->font < 0 || state->font >= stash->nfonts) return 0;
  1231. font = stash->fonts[state->font];
  1232. if (font->data == NULL) return 0;
  1233. scale = fons__tt_getPixelHeightScale(&font->font, (float)isize/10.0f);
  1234. // Align vertically.
  1235. y += fons__getVertAlign(stash, font, state->align, isize);
  1236. minx = maxx = x;
  1237. miny = maxy = y;
  1238. startx = x;
  1239. if (end == NULL)
  1240. end = str + strlen(str);
  1241. for (; str != end; ++str) {
  1242. if (fons__decutf8(&utf8state, &codepoint, *(const unsigned char*)str))
  1243. continue;
  1244. glyph = fons__getGlyph(stash, font, codepoint, isize, iblur);
  1245. if (glyph != NULL) {
  1246. fons__getQuad(stash, font, prevGlyphIndex, glyph, scale, state->spacing, &x, &y, &q);
  1247. if (q.x0 < minx) minx = q.x0;
  1248. if (q.x1 > maxx) maxx = q.x1;
  1249. if (stash->params.flags & FONS_ZERO_TOPLEFT) {
  1250. if (q.y0 < miny) miny = q.y0;
  1251. if (q.y1 > maxy) maxy = q.y1;
  1252. } else {
  1253. if (q.y1 < miny) miny = q.y1;
  1254. if (q.y0 > maxy) maxy = q.y0;
  1255. }
  1256. }
  1257. prevGlyphIndex = glyph != NULL ? glyph->index : -1;
  1258. }
  1259. advance = x - startx;
  1260. // Align horizontally
  1261. if (state->align & FONS_ALIGN_LEFT) {
  1262. // empty
  1263. } else if (state->align & FONS_ALIGN_RIGHT) {
  1264. minx -= advance;
  1265. maxx -= advance;
  1266. } else if (state->align & FONS_ALIGN_CENTER) {
  1267. minx -= advance * 0.5f;
  1268. maxx -= advance * 0.5f;
  1269. }
  1270. if (bounds) {
  1271. bounds[0] = minx;
  1272. bounds[1] = miny;
  1273. bounds[2] = maxx;
  1274. bounds[3] = maxy;
  1275. }
  1276. return advance;
  1277. }
  1278. FONS_DEF void fonsVertMetrics(FONScontext* stash,
  1279. float* ascender, float* descender, float* lineh)
  1280. {
  1281. FONSfont* font;
  1282. FONSstate* state = fons__getState(stash);
  1283. short isize;
  1284. if (stash == NULL) return;
  1285. if (state->font < 0 || state->font >= stash->nfonts) return;
  1286. font = stash->fonts[state->font];
  1287. isize = (short)(state->size*10.0f);
  1288. if (font->data == NULL) return;
  1289. if (ascender)
  1290. *ascender = font->ascender*isize/10.0f;
  1291. if (descender)
  1292. *descender = font->descender*isize/10.0f;
  1293. if (lineh)
  1294. *lineh = font->lineh*isize/10.0f;
  1295. }
  1296. FONS_DEF void fonsLineBounds(FONScontext* stash, float y, float* miny, float* maxy)
  1297. {
  1298. FONSfont* font;
  1299. FONSstate* state = fons__getState(stash);
  1300. short isize;
  1301. if (stash == NULL) return;
  1302. if (state->font < 0 || state->font >= stash->nfonts) return;
  1303. font = stash->fonts[state->font];
  1304. isize = (short)(state->size*10.0f);
  1305. if (font->data == NULL) return;
  1306. y += fons__getVertAlign(stash, font, state->align, isize);
  1307. if (stash->params.flags & FONS_ZERO_TOPLEFT) {
  1308. *miny = y - font->ascender * (float)isize/10.0f;
  1309. *maxy = *miny + font->lineh*isize/10.0f;
  1310. } else {
  1311. *maxy = y + font->descender * (float)isize/10.0f;
  1312. *miny = *maxy - font->lineh*isize/10.0f;
  1313. }
  1314. }
  1315. FONS_DEF const unsigned char* fonsGetTextureData(FONScontext* stash, int* width, int* height)
  1316. {
  1317. if (width != NULL)
  1318. *width = stash->params.width;
  1319. if (height != NULL)
  1320. *height = stash->params.height;
  1321. return stash->texData;
  1322. }
  1323. FONS_DEF int fonsValidateTexture(FONScontext* stash, int* dirty)
  1324. {
  1325. if (stash->dirtyRect[0] < stash->dirtyRect[2] && stash->dirtyRect[1] < stash->dirtyRect[3]) {
  1326. dirty[0] = stash->dirtyRect[0];
  1327. dirty[1] = stash->dirtyRect[1];
  1328. dirty[2] = stash->dirtyRect[2];
  1329. dirty[3] = stash->dirtyRect[3];
  1330. // Reset dirty rect
  1331. stash->dirtyRect[0] = stash->params.width;
  1332. stash->dirtyRect[1] = stash->params.height;
  1333. stash->dirtyRect[2] = 0;
  1334. stash->dirtyRect[3] = 0;
  1335. return 1;
  1336. }
  1337. return 0;
  1338. }
  1339. FONS_DEF void fonsDeleteInternal(FONScontext* stash)
  1340. {
  1341. int i;
  1342. if (stash == NULL) return;
  1343. if (stash->params.renderDelete)
  1344. stash->params.renderDelete(stash->params.userPtr);
  1345. for (i = 0; i < stash->nfonts; ++i)
  1346. fons__freeFont(stash->fonts[i]);
  1347. if (stash->atlas) fons__deleteAtlas(stash->atlas);
  1348. if (stash->fonts) free(stash->fonts);
  1349. if (stash->texData) free(stash->texData);
  1350. if (stash->scratch) free(stash->scratch);
  1351. free(stash);
  1352. }
  1353. FONS_DEF void fonsSetErrorCallback(FONScontext* stash, void (*callback)(void* uptr, int error, int val), void* uptr)
  1354. {
  1355. if (stash == NULL) return;
  1356. stash->handleError = callback;
  1357. stash->errorUptr = uptr;
  1358. }
  1359. FONS_DEF void fonsGetAtlasSize(FONScontext* stash, int* width, int* height)
  1360. {
  1361. if (stash == NULL) return;
  1362. *width = stash->params.width;
  1363. *height = stash->params.height;
  1364. }
  1365. FONS_DEF int fonsExpandAtlas(FONScontext* stash, int width, int height)
  1366. {
  1367. int i, maxy = 0;
  1368. unsigned char* data = NULL;
  1369. if (stash == NULL) return 0;
  1370. width = fons__maxi(width, stash->params.width);
  1371. height = fons__maxi(height, stash->params.height);
  1372. if (width == stash->params.width && height == stash->params.height)
  1373. return 1;
  1374. // Flush pending glyphs.
  1375. fons__flush(stash);
  1376. // Create new texture
  1377. if (stash->params.renderResize != NULL) {
  1378. if (stash->params.renderResize(stash->params.userPtr, width, height) == 0)
  1379. return 0;
  1380. }
  1381. // Copy old texture data over.
  1382. data = (unsigned char*)malloc(width * height);
  1383. if (data == NULL)
  1384. return 0;
  1385. for (i = 0; i < stash->params.height; i++) {
  1386. unsigned char* dst = &data[i*width];
  1387. unsigned char* src = &stash->texData[i*stash->params.width];
  1388. memcpy(dst, src, stash->params.width);
  1389. if (width > stash->params.width)
  1390. memset(dst+stash->params.width, 0, width - stash->params.width);
  1391. }
  1392. if (height > stash->params.height)
  1393. memset(&data[stash->params.height * width], 0, (height - stash->params.height) * width);
  1394. free(stash->texData);
  1395. stash->texData = data;
  1396. // Increase atlas size
  1397. fons__atlasExpand(stash->atlas, width, height);
  1398. // Add existing data as dirty.
  1399. for (i = 0; i < stash->atlas->nnodes; i++)
  1400. maxy = fons__maxi(maxy, stash->atlas->nodes[i].y);
  1401. stash->dirtyRect[0] = 0;
  1402. stash->dirtyRect[1] = 0;
  1403. stash->dirtyRect[2] = stash->params.width;
  1404. stash->dirtyRect[3] = maxy;
  1405. stash->params.width = width;
  1406. stash->params.height = height;
  1407. stash->itw = 1.0f/stash->params.width;
  1408. stash->ith = 1.0f/stash->params.height;
  1409. return 1;
  1410. }
  1411. FONS_DEF int fonsResetAtlas(FONScontext* stash, int width, int height)
  1412. {
  1413. int i, j;
  1414. if (stash == NULL) return 0;
  1415. // Flush pending glyphs.
  1416. fons__flush(stash);
  1417. // Create new texture
  1418. if (stash->params.renderResize != NULL) {
  1419. if (stash->params.renderResize(stash->params.userPtr, width, height) == 0)
  1420. return 0;
  1421. }
  1422. // Reset atlas
  1423. fons__atlasReset(stash->atlas, width, height);
  1424. // Clear texture data.
  1425. stash->texData = (unsigned char*)realloc(stash->texData, width * height);
  1426. if (stash->texData == NULL) return 0;
  1427. memset(stash->texData, 0, width * height);
  1428. // Reset dirty rect
  1429. stash->dirtyRect[0] = width;
  1430. stash->dirtyRect[1] = height;
  1431. stash->dirtyRect[2] = 0;
  1432. stash->dirtyRect[3] = 0;
  1433. // Reset cached glyphs
  1434. for (i = 0; i < stash->nfonts; i++) {
  1435. FONSfont* font = stash->fonts[i];
  1436. font->nglyphs = 0;
  1437. for (j = 0; j < FONS_HASH_LUT_SIZE; j++)
  1438. font->lut[j] = -1;
  1439. }
  1440. stash->params.width = width;
  1441. stash->params.height = height;
  1442. stash->itw = 1.0f/stash->params.width;
  1443. stash->ith = 1.0f/stash->params.height;
  1444. // Add white rect at 0,0 for debug drawing.
  1445. fons__addWhiteRect(stash, 2,2);
  1446. return 1;
  1447. }
  1448. #endif // FONTSTASH_IMPLEMENTATION