DPF OpenGL examples
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1671 lines
45KB

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