fontstash.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889
  1. //
  2. // Copyright (c) 2011 Andreas Krinke [email protected]
  3. // Copyright (c) 2009 Mikko Mononen [email protected]
  4. //
  5. // This software is provided 'as-is', without any express or implied
  6. // warranty. In no event will the authors be held liable for any damages
  7. // arising from the use of this software.
  8. // Permission is granted to anyone to use this software for any purpose,
  9. // including commercial applications, and to alter it and redistribute it
  10. // freely, subject to the following restrictions:
  11. // 1. The origin of this software must not be misrepresented; you must not
  12. // claim that you wrote the original software. If you use this software
  13. // in a product, an acknowledgment in the product documentation would be
  14. // appreciated but is not required.
  15. // 2. Altered source versions must be plainly marked as such, and must not be
  16. // misrepresented as being the original software.
  17. // 3. This notice may not be removed or altered from any source distribution.
  18. //
  19. #define STB_TRUETYPE_IMPLEMENTATION
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #ifdef _WIN32
  24. #include <windows.h>
  25. #endif
  26. #include "fontstash.h"
  27. #define BORDER_X_LEFT 2
  28. #define BORDER_X_RIGHT 2
  29. #define BORDER_Y_TOP 2
  30. #define BORDER_Y_BOTTOM 2
  31. #define ADDITIONAL_HEIGHT 2
  32. #define STB_TRUETYPE_IMPLEMENTATION
  33. #define STBTT_malloc(x, u) malloc(x)
  34. #define STBTT_free(x, u) free(x)
  35. #include "stb_image/stb_truetype.h"
  36. #define HASH_LUT_SIZE 256
  37. #define TTFONT_FILE 1
  38. #define TTFONT_MEM 2
  39. #define BMFONT 3
  40. static int idx = 1;
  41. static float s_retinaScale = 1;
  42. static unsigned int hashint(unsigned int a)
  43. {
  44. a += ~(a << 15);
  45. a ^= (a >> 10);
  46. a += (a << 3);
  47. a ^= (a >> 6);
  48. a += ~(a << 11);
  49. a ^= (a >> 16);
  50. return a;
  51. }
  52. struct sth_font
  53. {
  54. int idx;
  55. int type;
  56. stbtt_fontinfo font;
  57. unsigned char* data;
  58. struct sth_glyph* glyphs;
  59. int lut[HASH_LUT_SIZE];
  60. int nglyphs;
  61. float ascender;
  62. float descender;
  63. float lineh;
  64. struct sth_font* next;
  65. };
  66. struct sth_stash
  67. {
  68. int tw, th;
  69. float itw, ith;
  70. struct sth_texture* textures;
  71. struct sth_font* fonts;
  72. int drawing;
  73. RenderCallbacks* m_renderCallbacks;
  74. };
  75. // Copyright (c) 2008-2009 Bjoern Hoehrmann <[email protected]>
  76. // See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details.
  77. #define UTF8_ACCEPT 0
  78. #define UTF8_REJECT 1
  79. static const unsigned char utf8d[] = {
  80. 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, // 00..1f
  81. 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, // 20..3f
  82. 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, // 40..5f
  83. 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, // 60..7f
  84. 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, // 80..9f
  85. 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, // a0..bf
  86. 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, // c0..df
  87. 0xa, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // e0..ef
  88. 0xb, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // f0..ff
  89. 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
  90. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2
  91. 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4
  92. 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6
  93. 1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // s7..s8
  94. };
  95. static unsigned int decutf8(unsigned int* state, unsigned int* codep, unsigned int byte)
  96. {
  97. unsigned int type = utf8d[byte];
  98. *codep = (*state != UTF8_ACCEPT) ? (byte & 0x3fu) | (*codep << 6) : (0xff >> type) & (byte);
  99. *state = utf8d[256 + *state * 16 + type];
  100. return *state;
  101. }
  102. struct sth_stash* sth_create(int cachew, int cacheh, RenderCallbacks* renderCallbacks)
  103. {
  104. struct sth_stash* stash = NULL;
  105. struct sth_texture* texture = NULL;
  106. // Allocate memory for the font stash.
  107. stash = (struct sth_stash*)malloc(sizeof(struct sth_stash));
  108. if (stash == NULL)
  109. {
  110. assert(0);
  111. return NULL;
  112. }
  113. memset(stash, 0, sizeof(struct sth_stash));
  114. stash->m_renderCallbacks = renderCallbacks;
  115. // Allocate memory for the first texture
  116. texture = (struct sth_texture*)malloc(sizeof(struct sth_texture));
  117. if (texture == NULL)
  118. {
  119. assert(0);
  120. free(stash);
  121. }
  122. memset(texture, 0, sizeof(struct sth_texture));
  123. // Create first texture for the cache.
  124. stash->tw = cachew;
  125. stash->th = cacheh;
  126. stash->itw = 1.0f / cachew;
  127. stash->ith = 1.0f / cacheh;
  128. stash->textures = texture;
  129. stash->m_renderCallbacks->updateTexture(texture, 0, stash->tw, stash->th);
  130. return stash;
  131. }
  132. int sth_add_font_from_memory(struct sth_stash* stash, unsigned char* buffer)
  133. {
  134. int i, ascent, descent, fh, lineGap;
  135. struct sth_font* fnt = NULL;
  136. fnt = (struct sth_font*)malloc(sizeof(struct sth_font));
  137. if (fnt == NULL) goto error;
  138. memset(fnt, 0, sizeof(struct sth_font));
  139. // Init hash lookup.
  140. for (i = 0; i < HASH_LUT_SIZE; ++i)
  141. fnt->lut[i] = -1;
  142. fnt->data = buffer;
  143. // Init stb_truetype
  144. if (!stbtt_InitFont(&fnt->font, fnt->data, 0))
  145. goto error;
  146. // Store normalized line height. The real line height is got
  147. // by multiplying the lineh by font size.
  148. stbtt_GetFontVMetrics(&fnt->font, &ascent, &descent, &lineGap);
  149. fh = ascent - descent;
  150. fnt->ascender = (float)ascent / (float)fh;
  151. fnt->descender = (float)descent / (float)fh;
  152. fnt->lineh = (float)(fh + lineGap) / (float)fh;
  153. fnt->idx = idx;
  154. fnt->type = TTFONT_MEM;
  155. fnt->next = stash->fonts;
  156. stash->fonts = fnt;
  157. return idx++;
  158. error:
  159. if (fnt)
  160. {
  161. if (fnt->glyphs) free(fnt->glyphs);
  162. free(fnt);
  163. }
  164. return 0;
  165. }
  166. int sth_add_font(struct sth_stash* stash, const char* path)
  167. {
  168. FILE* fp = 0;
  169. int datasize;
  170. unsigned char* data = NULL;
  171. int idx = 0;
  172. // Read in the font data.
  173. fp = fopen(path, "rb");
  174. if (!fp) goto error;
  175. fseek(fp, 0, SEEK_END);
  176. datasize = (int)ftell(fp);
  177. fseek(fp, 0, SEEK_SET);
  178. data = (unsigned char*)malloc(datasize);
  179. if (data == NULL) goto error;
  180. int bytesRead;
  181. bytesRead = fread(data, 1, datasize, fp);
  182. if (bytesRead)
  183. {
  184. idx = sth_add_font_from_memory(stash, data);
  185. }
  186. fclose(fp);
  187. fp = 0;
  188. // Modify type of the loaded font.
  189. if (idx)
  190. stash->fonts->type = TTFONT_FILE;
  191. else
  192. free(data);
  193. return idx;
  194. error:
  195. if (data) free(data);
  196. if (fp) fclose(fp);
  197. return 0;
  198. }
  199. int sth_add_bitmap_font(struct sth_stash* stash, int ascent, int descent, int line_gap)
  200. {
  201. int i, fh;
  202. struct sth_font* fnt = NULL;
  203. fnt = (struct sth_font*)malloc(sizeof(struct sth_font));
  204. if (fnt == NULL) goto error;
  205. memset(fnt, 0, sizeof(struct sth_font));
  206. // Init hash lookup.
  207. for (i = 0; i < HASH_LUT_SIZE; ++i) fnt->lut[i] = -1;
  208. // Store normalized line height. The real line height is got
  209. // by multiplying the lineh by font size.
  210. fh = ascent - descent;
  211. fnt->ascender = (float)ascent / (float)fh;
  212. fnt->descender = (float)descent / (float)fh;
  213. fnt->lineh = (float)(fh + line_gap) / (float)fh;
  214. fnt->idx = idx;
  215. fnt->type = BMFONT;
  216. fnt->next = stash->fonts;
  217. stash->fonts = fnt;
  218. return idx++;
  219. error:
  220. if (fnt) free(fnt);
  221. return 0;
  222. }
  223. /*void sth_add_glyph(struct sth_stash* stash,
  224. int idx,
  225. unsigned int id1,
  226. const char* s,
  227. short size, short base,
  228. int x, int y, int w, int h,
  229. float xoffset, float yoffset, float xadvance)
  230. {
  231. struct sth_texture* texture = NULL;
  232. struct sth_font* fnt = NULL;
  233. struct sth_glyph* glyph = NULL;
  234. unsigned int codepoint;
  235. unsigned int state = 0;
  236. if (stash == NULL) return;
  237. texture = stash->textures;
  238. while (texture != NULL && texture->id != id)
  239. texture = texture->next;
  240. if (texture == NULL)
  241. {
  242. // Create new texture
  243. texture = (struct sth_texture*)malloc(sizeof(struct sth_texture));
  244. if (texture == NULL) return;
  245. memset(texture, 0, sizeof(struct sth_texture));
  246. texture->id = id;
  247. texture->next = stash->textures;
  248. stash->textures = texture;
  249. }
  250. fnt = stash->fonts;
  251. while (fnt != NULL && fnt->idx != idx) fnt = fnt->next;
  252. if (fnt == NULL) return;
  253. if (fnt->type != BMFONT) return;
  254. for (; *s; ++s)
  255. {
  256. if (!decutf8(&state, &codepoint, *(unsigned char*)s)) break;
  257. }
  258. if (state != UTF8_ACCEPT) return;
  259. // Alloc space for new glyph.
  260. fnt->nglyphs++;
  261. fnt->glyphs = (sth_glyph*)realloc(fnt->glyphs, fnt->nglyphs*sizeof(struct sth_glyph));
  262. if (!fnt->glyphs) return;
  263. // Init glyph.
  264. glyph = &fnt->glyphs[fnt->nglyphs-1];
  265. memset(glyph, 0, sizeof(struct sth_glyph));
  266. glyph->codepoint = codepoint;
  267. glyph->size = size;
  268. glyph->texture = texture;
  269. glyph->x0_ = x;
  270. glyph->y0 = y;
  271. glyph->x1 = glyph->x0_+w;
  272. glyph->y1 = glyph->y0+h;
  273. glyph->xoff = xoffset;
  274. glyph->yoff = yoffset - base;
  275. glyph->xadv = xadvance;
  276. // Find code point and size.
  277. h = hashint(codepoint) & (HASH_LUT_SIZE-1);
  278. // Insert char to hash lookup.
  279. glyph->next = fnt->lut[h];
  280. fnt->lut[h] = fnt->nglyphs-1;
  281. }
  282. */
  283. static struct sth_glyph* get_glyph(struct sth_stash* stash, struct sth_font* fnt, unsigned int codepoint, short isize)
  284. {
  285. int i, g, advance, lsb, x0, y0, x1, y1, gw, gh;
  286. float scale;
  287. struct sth_texture* texture = NULL;
  288. struct sth_glyph* glyph = NULL;
  289. unsigned int h;
  290. float size = isize / 10.0f;
  291. int rh;
  292. struct sth_row* br = NULL;
  293. // Find code point and size.
  294. h = hashint(codepoint) & (HASH_LUT_SIZE - 1);
  295. i = fnt->lut[h];
  296. while (i != -1)
  297. {
  298. if (fnt->glyphs[i].codepoint == codepoint && (fnt->type == BMFONT || fnt->glyphs[i].size == isize))
  299. return &fnt->glyphs[i];
  300. i = fnt->glyphs[i].next;
  301. }
  302. // Could not find glyph.
  303. // For bitmap fonts: ignore this glyph.
  304. if (fnt->type == BMFONT) return 0;
  305. // For truetype fonts: create this glyph.
  306. scale = stbtt_ScaleForPixelHeight(&fnt->font, size);
  307. g = stbtt_FindGlyphIndex(&fnt->font, codepoint);
  308. stbtt_GetGlyphHMetrics(&fnt->font, g, &advance, &lsb);
  309. stbtt_GetGlyphBitmapBox(&fnt->font, g, scale, scale, &x0, &y0, &x1, &y1);
  310. gw = x1 - x0;
  311. gh = y1 - y0;
  312. // Check if glyph is larger than maximum texture size
  313. if (gw >= stash->tw || gh >= stash->th)
  314. return 0;
  315. // Find texture and row where the glyph can be fit.
  316. br = NULL;
  317. rh = (gh + 7) & ~7;
  318. texture = stash->textures;
  319. while (br == NULL)
  320. {
  321. for (i = 0; i < texture->nrows; ++i)
  322. {
  323. if (texture->rows[i].h >= rh && texture->rows[i].x + gw + 1 <= stash->tw)
  324. br = &texture->rows[i];
  325. }
  326. // If no row is found, there are 3 possibilities:
  327. // - add new row
  328. // - try next texture
  329. // - create new texture
  330. if (br == NULL)
  331. {
  332. short py = BORDER_Y_TOP;
  333. // Check that there is enough space.
  334. if (texture->nrows)
  335. {
  336. py = texture->rows[texture->nrows - 1].y + texture->rows[texture->nrows - 1].h + 1;
  337. if (py + rh > stash->th)
  338. {
  339. if (texture->next != NULL)
  340. {
  341. texture = texture->next;
  342. }
  343. else
  344. {
  345. // Create new texture
  346. texture->next = (struct sth_texture*)malloc(sizeof(struct sth_texture));
  347. texture = texture->next;
  348. if (texture == NULL) goto error;
  349. memset(texture, 0, sizeof(struct sth_texture));
  350. stash->m_renderCallbacks->updateTexture(texture, 0, stash->tw, stash->th);
  351. }
  352. continue;
  353. }
  354. }
  355. // Init and add row
  356. br = &texture->rows[texture->nrows];
  357. br->x = BORDER_X_LEFT;
  358. br->y = py + BORDER_Y_BOTTOM;
  359. br->h = rh + ADDITIONAL_HEIGHT;
  360. texture->nrows++;
  361. }
  362. }
  363. // Alloc space for new glyph.
  364. fnt->nglyphs++;
  365. fnt->glyphs = (sth_glyph*)realloc(fnt->glyphs, fnt->nglyphs * sizeof(struct sth_glyph));
  366. if (!fnt->glyphs) return 0;
  367. // Init glyph.
  368. glyph = &fnt->glyphs[fnt->nglyphs - 1];
  369. memset(glyph, 0, sizeof(struct sth_glyph));
  370. glyph->codepoint = codepoint;
  371. glyph->size = isize;
  372. glyph->texture = texture;
  373. glyph->x0_ = br->x;
  374. glyph->y0 = br->y;
  375. glyph->x1 = glyph->x0_ + gw;
  376. glyph->y1 = glyph->y0 + gh;
  377. glyph->xadv = scale * advance;
  378. glyph->xoff = (float)x0;
  379. glyph->yoff = (float)y0;
  380. glyph->next = 0;
  381. // Advance row location.
  382. br->x += gw + BORDER_X_RIGHT;
  383. // Insert char to hash lookup.
  384. glyph->next = fnt->lut[h];
  385. fnt->lut[h] = fnt->nglyphs - 1;
  386. // Rasterize
  387. {
  388. unsigned char* ptr = texture->m_texels + glyph->x0_ + glyph->y0 * stash->tw;
  389. stbtt_MakeGlyphBitmap(&fnt->font, ptr, gw, gh, stash->tw, scale, scale, g);
  390. stash->m_renderCallbacks->updateTexture(texture, glyph, stash->tw, stash->th);
  391. }
  392. return glyph;
  393. error:
  394. if (texture)
  395. free(texture);
  396. return 0;
  397. }
  398. static int get_quad(struct sth_stash* stash, struct sth_font* fnt, struct sth_glyph* glyph, short isize, float* x, float* y, struct sth_quad* q)
  399. {
  400. float rx, ry;
  401. float scale = 1.f / s_retinaScale; //1.0f;
  402. if (fnt->type == BMFONT)
  403. scale = isize / (glyph->size * 10.0f);
  404. rx = (*x + scale * float(glyph->xoff));
  405. ry = (*y + scale * float(glyph->yoff));
  406. q->x0 = rx;
  407. q->y0 = ry + 1.5f * 0.5f * float(isize) / 10.f;
  408. q->x1 = rx + scale * float(glyph->x1 - glyph->x0_);
  409. q->y1 = ry + scale * float(glyph->y1 - glyph->y0) + 1.5f * 0.5f * float(isize) / 10.f;
  410. q->s0 = float(glyph->x0_) * stash->itw;
  411. q->t0 = float(glyph->y0) * stash->ith;
  412. q->s1 = float(glyph->x1) * stash->itw;
  413. q->t1 = float(glyph->y1) * stash->ith;
  414. *x += scale * glyph->xadv;
  415. return 1;
  416. }
  417. static int get_quad3D(struct sth_stash* stash, struct sth_font* fnt, struct sth_glyph* glyph, short isize2, float* x, float* y, struct sth_quad* q, float fontSize, float textScale)
  418. {
  419. short isize = 1;
  420. float rx, ry;
  421. float scale = textScale / fontSize; //0.1;//1.0f;
  422. if (fnt->type == BMFONT)
  423. scale = isize / (glyph->size);
  424. rx = (*x + scale * float(glyph->xoff));
  425. ry = (scale * float(glyph->yoff));
  426. q->x0 = rx;
  427. q->y0 = *y - (ry);
  428. q->x1 = rx + scale * float(glyph->x1 - glyph->x0_);
  429. q->y1 = *y - (ry + scale * float(glyph->y1 - glyph->y0));
  430. q->s0 = float(glyph->x0_) * stash->itw;
  431. q->t0 = float(glyph->y0) * stash->ith;
  432. q->s1 = float(glyph->x1) * stash->itw;
  433. q->t1 = float(glyph->y1) * stash->ith;
  434. *x += scale * glyph->xadv;
  435. return 1;
  436. }
  437. static Vertex* setv(Vertex* v, float x, float y, float s, float t, float width, float height, float colorRGBA[4])
  438. {
  439. bool scale = true;
  440. if (scale)
  441. {
  442. v->position.p[0] = (x * 2 - width) / (width);
  443. v->position.p[1] = 1 - (y) / (height / 2);
  444. }
  445. else
  446. {
  447. v->position.p[0] = (x - width) / (width);
  448. v->position.p[1] = (height - y) / (height);
  449. }
  450. v->position.p[2] = 0.f;
  451. v->position.p[3] = 1.f;
  452. v->uv.p[0] = s;
  453. v->uv.p[1] = t;
  454. v->colour.p[0] = 0.1; //colorRGBA[0];
  455. v->colour.p[1] = 0.1; //colorRGBA[1];
  456. v->colour.p[2] = 0.1; //colorRGBA[2];
  457. v->colour.p[3] = 1.0; //colorRGBA[3];
  458. return v + 1;
  459. }
  460. static Vertex* setv3D(Vertex* v, float x, float y, float z, float s, float t, float colorRGBA[4])
  461. {
  462. v->position.p[0] = x;
  463. v->position.p[1] = y;
  464. v->position.p[2] = z;
  465. v->position.p[3] = 1.f;
  466. v->uv.p[0] = s;
  467. v->uv.p[1] = t;
  468. v->colour.p[0] = colorRGBA[0];
  469. v->colour.p[1] = colorRGBA[1];
  470. v->colour.p[2] = colorRGBA[2];
  471. v->colour.p[3] = colorRGBA[3];
  472. return v + 1;
  473. }
  474. static void flush_draw(struct sth_stash* stash)
  475. {
  476. struct sth_texture* texture = stash->textures;
  477. while (texture)
  478. {
  479. if (texture->nverts > 0)
  480. {
  481. stash->m_renderCallbacks->render(texture);
  482. texture->nverts = 0;
  483. }
  484. texture = texture->next;
  485. }
  486. }
  487. void sth_begin_draw(struct sth_stash* stash)
  488. {
  489. if (stash == NULL) return;
  490. if (stash->drawing)
  491. flush_draw(stash);
  492. stash->drawing = 1;
  493. }
  494. void sth_end_draw(struct sth_stash* stash)
  495. {
  496. if (stash == NULL) return;
  497. if (!stash->drawing) return;
  498. /*
  499. // Debug dump.
  500. if (stash->nverts+6 < VERT_COUNT)
  501. {
  502. float x = 500, y = 100;
  503. float* v = &stash->verts[stash->nverts*4];
  504. v = setv(v, x, y, 0, 0);
  505. v = setv(v, x+stash->tw, y, 1, 0);
  506. v = setv(v, x+stash->tw, y+stash->th, 1, 1);
  507. v = setv(v, x, y, 0, 0);
  508. v = setv(v, x+stash->tw, y+stash->th, 1, 1);
  509. v = setv(v, x, y+stash->th, 0, 1);
  510. stash->nverts += 6;
  511. }
  512. */
  513. flush_draw(stash);
  514. stash->drawing = 0;
  515. }
  516. void sth_draw_texture(struct sth_stash* stash,
  517. int idx, float size,
  518. float x, float y,
  519. int screenwidth, int screenheight,
  520. const char* s, float* dx, float colorRGBA[4])
  521. {
  522. int width = stash->tw;
  523. int height = stash->th;
  524. unsigned int codepoint;
  525. struct sth_glyph* glyph = NULL;
  526. struct sth_texture* texture = NULL;
  527. unsigned int state = 0;
  528. struct sth_quad q;
  529. short isize = (short)(size * 10.0f);
  530. Vertex* v;
  531. struct sth_font* fnt = NULL;
  532. if (stash == NULL) return;
  533. if (!stash->textures) return;
  534. fnt = stash->fonts;
  535. while (fnt != NULL && fnt->idx != idx) fnt = fnt->next;
  536. if (fnt == NULL) return;
  537. if (fnt->type != BMFONT && !fnt->data) return;
  538. int once = true;
  539. for (; once; ++s)
  540. {
  541. once = false;
  542. if (decutf8(&state, &codepoint, *(unsigned char*)s))
  543. continue;
  544. glyph = get_glyph(stash, fnt, codepoint, isize);
  545. if (!glyph)
  546. continue;
  547. texture = glyph->texture;
  548. if (texture->nverts + 6 >= VERT_COUNT)
  549. flush_draw(stash);
  550. if (!get_quad(stash, fnt, glyph, isize, &x, &y, &q))
  551. continue;
  552. v = &texture->newverts[texture->nverts];
  553. q.x0 = 0;
  554. q.y0 = 0;
  555. q.x1 = q.x0 + width;
  556. q.y1 = q.y0 + height;
  557. v = setv(v, q.x0, q.y0, 0, 0, (float)screenwidth, (float)screenheight, colorRGBA);
  558. v = setv(v, q.x1, q.y0, 1, 0, (float)screenwidth, (float)screenheight, colorRGBA);
  559. v = setv(v, q.x1, q.y1, 1, 1, (float)screenwidth, (float)screenheight, colorRGBA);
  560. v = setv(v, q.x0, q.y0, 0, 0, (float)screenwidth, (float)screenheight, colorRGBA);
  561. v = setv(v, q.x1, q.y1, 1, 1, (float)screenwidth, (float)screenheight, colorRGBA);
  562. v = setv(v, q.x0, q.y1, 0, 1, (float)screenwidth, (float)screenheight, colorRGBA);
  563. texture->nverts += 6;
  564. }
  565. flush_draw(stash);
  566. if (dx) *dx = x;
  567. }
  568. void sth_flush_draw(struct sth_stash* stash)
  569. {
  570. flush_draw(stash);
  571. }
  572. void sth_draw_text(struct sth_stash* stash,
  573. int idx, float size,
  574. float x, float y,
  575. const char* s, float* dx, int screenwidth, int screenheight, int measureOnly, float retinaScale, float colorRGBA[4])
  576. {
  577. unsigned int codepoint;
  578. struct sth_glyph* glyph = NULL;
  579. struct sth_texture* texture = NULL;
  580. unsigned int state = 0;
  581. struct sth_quad q;
  582. short isize = (short)(size * 10.0f);
  583. Vertex* v;
  584. struct sth_font* fnt = NULL;
  585. s_retinaScale = retinaScale;
  586. if (stash == NULL) return;
  587. if (!stash->textures) return;
  588. fnt = stash->fonts;
  589. while (fnt != NULL && fnt->idx != idx) fnt = fnt->next;
  590. if (fnt == NULL) return;
  591. if (fnt->type != BMFONT && !fnt->data) return;
  592. for (; *s; ++s)
  593. {
  594. if (decutf8(&state, &codepoint, *(unsigned char*)s))
  595. continue;
  596. glyph = get_glyph(stash, fnt, codepoint, isize);
  597. if (!glyph) continue;
  598. texture = glyph->texture;
  599. if (!measureOnly)
  600. {
  601. if (texture->nverts + 6 >= VERT_COUNT)
  602. flush_draw(stash);
  603. }
  604. if (!get_quad(stash, fnt, glyph, isize, &x, &y, &q)) continue;
  605. if (!measureOnly)
  606. {
  607. v = &texture->newverts[texture->nverts];
  608. v = setv(v, q.x0, q.y0, q.s0, q.t0, (float)screenwidth, (float)screenheight, colorRGBA);
  609. v = setv(v, q.x1, q.y0, q.s1, q.t0, (float)screenwidth, (float)screenheight, colorRGBA);
  610. v = setv(v, q.x1, q.y1, q.s1, q.t1, (float)screenwidth, (float)screenheight, colorRGBA);
  611. v = setv(v, q.x0, q.y0, q.s0, q.t0, (float)screenwidth, (float)screenheight, colorRGBA);
  612. v = setv(v, q.x1, q.y1, q.s1, q.t1, (float)screenwidth, (float)screenheight, colorRGBA);
  613. v = setv(v, q.x0, q.y1, q.s0, q.t1, (float)screenwidth, (float)screenheight, colorRGBA);
  614. texture->nverts += 6;
  615. }
  616. }
  617. if (dx) *dx = x;
  618. }
  619. void sth_draw_text3D(struct sth_stash* stash,
  620. int idx, float fontSize,
  621. float x, float y, float z,
  622. const char* s, float* dx, float textScale, float colorRGBA[4], int unused)
  623. {
  624. unsigned int codepoint;
  625. struct sth_glyph* glyph = NULL;
  626. struct sth_texture* texture = NULL;
  627. unsigned int state = 0;
  628. struct sth_quad q;
  629. short isize = (short)(fontSize * 10.0f);
  630. Vertex* v;
  631. struct sth_font* fnt = NULL;
  632. s_retinaScale = 1;
  633. if (stash == NULL) return;
  634. if (!stash->textures) return;
  635. fnt = stash->fonts;
  636. while (fnt != NULL && fnt->idx != idx) fnt = fnt->next;
  637. if (fnt == NULL) return;
  638. if (fnt->type != BMFONT && !fnt->data) return;
  639. for (; *s; ++s)
  640. {
  641. if (decutf8(&state, &codepoint, *(unsigned char*)s))
  642. continue;
  643. glyph = get_glyph(stash, fnt, codepoint, isize);
  644. if (!glyph) continue;
  645. texture = glyph->texture;
  646. if (texture->nverts + 6 >= VERT_COUNT)
  647. flush_draw(stash);
  648. if (!get_quad3D(stash, fnt, glyph, isize, &x, &y, &q, fontSize, textScale)) continue;
  649. {
  650. v = &texture->newverts[texture->nverts];
  651. v = setv3D(v, q.x0, q.y0, z, q.s0, q.t0, colorRGBA);
  652. v = setv3D(v, q.x1, q.y0, z, q.s1, q.t0, colorRGBA);
  653. v = setv3D(v, q.x1, q.y1, z, q.s1, q.t1, colorRGBA);
  654. v = setv3D(v, q.x0, q.y0, z, q.s0, q.t0, colorRGBA);
  655. v = setv3D(v, q.x1, q.y1, z, q.s1, q.t1, colorRGBA);
  656. v = setv3D(v, q.x0, q.y1, z, q.s0, q.t1, colorRGBA);
  657. texture->nverts += 6;
  658. }
  659. }
  660. if (dx) *dx = x;
  661. }
  662. void sth_dim_text(struct sth_stash* stash,
  663. int idx, float size,
  664. const char* s,
  665. float* minx, float* miny, float* maxx, float* maxy)
  666. {
  667. unsigned int codepoint;
  668. struct sth_glyph* glyph = NULL;
  669. unsigned int state = 0;
  670. struct sth_quad q;
  671. short isize = (short)(size * 10.0f);
  672. struct sth_font* fnt = NULL;
  673. float x = 0, y = 0;
  674. if (stash == NULL)
  675. return;
  676. if (!stash->textures)
  677. return;
  678. fnt = stash->fonts;
  679. while (fnt != NULL && fnt->idx != idx) fnt = fnt->next;
  680. if (fnt == NULL) return;
  681. if (fnt->type != BMFONT && !fnt->data) return;
  682. *minx = *maxx = x;
  683. *miny = *maxy = y;
  684. for (; *s; ++s)
  685. {
  686. if (decutf8(&state, &codepoint, *(unsigned char*)s)) continue;
  687. glyph = get_glyph(stash, fnt, codepoint, isize);
  688. if (!glyph) continue;
  689. if (!get_quad(stash, fnt, glyph, isize, &x, &y, &q)) continue;
  690. if (q.x0 < *minx) *minx = q.x0;
  691. if (q.x1 > *maxx) *maxx = q.x1;
  692. if (q.y1 < *miny) *miny = q.y1;
  693. if (q.y0 > *maxy) *maxy = q.y0;
  694. }
  695. }
  696. void sth_vmetrics(struct sth_stash* stash,
  697. int idx, float size,
  698. float* ascender, float* descender, float* lineh)
  699. {
  700. struct sth_font* fnt = NULL;
  701. if (stash == NULL) return;
  702. if (!stash->textures) return;
  703. fnt = stash->fonts;
  704. while (fnt != NULL && fnt->idx != idx) fnt = fnt->next;
  705. if (fnt == NULL) return;
  706. if (fnt->type != BMFONT && !fnt->data) return;
  707. if (ascender)
  708. *ascender = fnt->ascender * size;
  709. if (descender)
  710. *descender = fnt->descender * size;
  711. if (lineh)
  712. *lineh = fnt->lineh * size;
  713. }
  714. void sth_delete(struct sth_stash* stash)
  715. {
  716. struct sth_texture* tex = NULL;
  717. struct sth_texture* curtex = NULL;
  718. struct sth_font* fnt = NULL;
  719. struct sth_font* curfnt = NULL;
  720. if (!stash) return;
  721. tex = stash->textures;
  722. while (tex != NULL)
  723. {
  724. curtex = tex;
  725. free(tex->m_texels);
  726. tex->m_texels = 0;
  727. tex = tex->next;
  728. stash->m_renderCallbacks->updateTexture(curtex, 0, 0, 0);
  729. free(curtex);
  730. }
  731. fnt = stash->fonts;
  732. while (fnt != NULL)
  733. {
  734. curfnt = fnt;
  735. fnt = fnt->next;
  736. if (curfnt->glyphs)
  737. {
  738. free(curfnt->glyphs);
  739. }
  740. if (curfnt->type == TTFONT_FILE && curfnt->data)
  741. {
  742. free(curfnt->data);
  743. }
  744. free(curfnt);
  745. }
  746. free(stash);
  747. }