fontstash.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818
  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_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) ?
  99. (byte & 0x3fu) | (*codep << 6) :
  100. (0xff >> type) & (byte);
  101. *state = utf8d[256 + *state*16 + type];
  102. return *state;
  103. }
  104. struct sth_stash* sth_create(int cachew, int cacheh, RenderCallbacks* renderCallbacks)
  105. {
  106. struct sth_stash* stash = NULL;
  107. struct sth_texture* texture = NULL;
  108. // Allocate memory for the font stash.
  109. stash = (struct sth_stash*)malloc(sizeof(struct sth_stash));
  110. if (stash == NULL)
  111. {
  112. assert(0);
  113. return NULL;
  114. }
  115. memset(stash,0,sizeof(struct sth_stash));
  116. stash->m_renderCallbacks = renderCallbacks;
  117. // Allocate memory for the first texture
  118. texture = (struct sth_texture*)malloc(sizeof(struct sth_texture));
  119. if (texture == NULL)
  120. {
  121. assert(0);
  122. free(stash);
  123. }
  124. memset(texture,0,sizeof(struct sth_texture));
  125. // Create first texture for the cache.
  126. stash->tw = cachew;
  127. stash->th = cacheh;
  128. stash->itw = 1.0f/cachew;
  129. stash->ith = 1.0f/cacheh;
  130. stash->textures = texture;
  131. stash->m_renderCallbacks->updateTexture(texture, 0, stash->tw, stash->th);
  132. return stash;
  133. }
  134. int sth_add_font_from_memory(struct sth_stash* stash, unsigned char* buffer)
  135. {
  136. int i, ascent, descent, fh, lineGap;
  137. struct sth_font* fnt = NULL;
  138. fnt = (struct sth_font*)malloc(sizeof(struct sth_font));
  139. if (fnt == NULL) goto error;
  140. memset(fnt,0,sizeof(struct sth_font));
  141. // Init hash lookup.
  142. for (i = 0; i < HASH_LUT_SIZE; ++i)
  143. fnt->lut[i] = -1;
  144. fnt->data = buffer;
  145. // Init stb_truetype
  146. if (!stbtt_InitFont(&fnt->font, fnt->data, 0))
  147. goto error;
  148. // Store normalized line height. The real line height is got
  149. // by multiplying the lineh by font size.
  150. stbtt_GetFontVMetrics(&fnt->font, &ascent, &descent, &lineGap);
  151. fh = ascent - descent;
  152. fnt->ascender = (float)ascent / (float)fh;
  153. fnt->descender = (float)descent / (float)fh;
  154. fnt->lineh = (float)(fh + lineGap) / (float)fh;
  155. fnt->idx = idx;
  156. fnt->type = TTFONT_MEM;
  157. fnt->next = stash->fonts;
  158. stash->fonts = fnt;
  159. return idx++;
  160. error:
  161. if (fnt) {
  162. if (fnt->glyphs) free(fnt->glyphs);
  163. free(fnt);
  164. }
  165. return 0;
  166. }
  167. int sth_add_font(struct sth_stash* stash, const char* path)
  168. {
  169. FILE* fp = 0;
  170. int datasize;
  171. unsigned char* data = NULL;
  172. int idx=0;
  173. // Read in the font data.
  174. fp = fopen(path, "rb");
  175. if (!fp) goto error;
  176. fseek(fp,0,SEEK_END);
  177. datasize = (int)ftell(fp);
  178. fseek(fp,0,SEEK_SET);
  179. data = (unsigned char*)malloc(datasize);
  180. if (data == NULL) goto error;
  181. int bytesRead;
  182. bytesRead = fread(data, 1, datasize, fp);
  183. if (bytesRead)
  184. {
  185. idx = sth_add_font_from_memory(stash, data);
  186. }
  187. fclose(fp);
  188. fp = 0;
  189. // Modify type of the loaded font.
  190. if (idx)
  191. stash->fonts->type = TTFONT_FILE;
  192. else
  193. free(data);
  194. return idx;
  195. error:
  196. if (data) free(data);
  197. if (fp) fclose(fp);
  198. return 0;
  199. }
  200. int sth_add_bitmap_font(struct sth_stash* stash, int ascent, int descent, int line_gap)
  201. {
  202. int i, fh;
  203. struct sth_font* fnt = NULL;
  204. fnt = (struct sth_font*)malloc(sizeof(struct sth_font));
  205. if (fnt == NULL) goto error;
  206. memset(fnt,0,sizeof(struct sth_font));
  207. // Init hash lookup.
  208. for (i = 0; i < HASH_LUT_SIZE; ++i) fnt->lut[i] = -1;
  209. // Store normalized line height. The real line height is got
  210. // by multiplying the lineh by font size.
  211. fh = ascent - descent;
  212. fnt->ascender = (float)ascent / (float)fh;
  213. fnt->descender = (float)descent / (float)fh;
  214. fnt->lineh = (float)(fh + line_gap) / (float)fh;
  215. fnt->idx = idx;
  216. fnt->type = BMFONT;
  217. fnt->next = stash->fonts;
  218. stash->fonts = fnt;
  219. return idx++;
  220. error:
  221. if (fnt) free(fnt);
  222. return 0;
  223. }
  224. /*void sth_add_glyph(struct sth_stash* stash,
  225. int idx,
  226. unsigned int id1,
  227. const char* s,
  228. short size, short base,
  229. int x, int y, int w, int h,
  230. float xoffset, float yoffset, float xadvance)
  231. {
  232. struct sth_texture* texture = NULL;
  233. struct sth_font* fnt = NULL;
  234. struct sth_glyph* glyph = NULL;
  235. unsigned int codepoint;
  236. unsigned int state = 0;
  237. if (stash == NULL) return;
  238. texture = stash->textures;
  239. while (texture != NULL && texture->id != id)
  240. texture = texture->next;
  241. if (texture == NULL)
  242. {
  243. // Create new texture
  244. texture = (struct sth_texture*)malloc(sizeof(struct sth_texture));
  245. if (texture == NULL) return;
  246. memset(texture, 0, sizeof(struct sth_texture));
  247. texture->id = id;
  248. texture->next = stash->textures;
  249. stash->textures = texture;
  250. }
  251. fnt = stash->fonts;
  252. while (fnt != NULL && fnt->idx != idx) fnt = fnt->next;
  253. if (fnt == NULL) return;
  254. if (fnt->type != BMFONT) return;
  255. for (; *s; ++s)
  256. {
  257. if (!decutf8(&state, &codepoint, *(unsigned char*)s)) break;
  258. }
  259. if (state != UTF8_ACCEPT) return;
  260. // Alloc space for new glyph.
  261. fnt->nglyphs++;
  262. fnt->glyphs = (sth_glyph*)realloc(fnt->glyphs, fnt->nglyphs*sizeof(struct sth_glyph));
  263. if (!fnt->glyphs) return;
  264. // Init glyph.
  265. glyph = &fnt->glyphs[fnt->nglyphs-1];
  266. memset(glyph, 0, sizeof(struct sth_glyph));
  267. glyph->codepoint = codepoint;
  268. glyph->size = size;
  269. glyph->texture = texture;
  270. glyph->x0_ = x;
  271. glyph->y0 = y;
  272. glyph->x1 = glyph->x0_+w;
  273. glyph->y1 = glyph->y0+h;
  274. glyph->xoff = xoffset;
  275. glyph->yoff = yoffset - base;
  276. glyph->xadv = xadvance;
  277. // Find code point and size.
  278. h = hashint(codepoint) & (HASH_LUT_SIZE-1);
  279. // Insert char to hash lookup.
  280. glyph->next = fnt->lut[h];
  281. fnt->lut[h] = fnt->nglyphs-1;
  282. }
  283. */
  284. static struct sth_glyph* get_glyph(struct sth_stash* stash, struct sth_font* fnt, unsigned int codepoint, short isize)
  285. {
  286. int i,g,advance,lsb,x0,y0,x1,y1,gw,gh;
  287. float scale;
  288. struct sth_texture* texture = NULL;
  289. struct sth_glyph* glyph = NULL;
  290. unsigned int h;
  291. float size = isize/10.0f;
  292. int rh;
  293. struct sth_row* br = NULL;
  294. // Find code point and size.
  295. h = hashint(codepoint) & (HASH_LUT_SIZE-1);
  296. i = fnt->lut[h];
  297. while (i != -1)
  298. {
  299. if (fnt->glyphs[i].codepoint == codepoint && (fnt->type == BMFONT || fnt->glyphs[i].size == isize))
  300. return &fnt->glyphs[i];
  301. i = fnt->glyphs[i].next;
  302. }
  303. // Could not find glyph.
  304. // For bitmap fonts: ignore this glyph.
  305. if (fnt->type == BMFONT) return 0;
  306. // For truetype fonts: create this glyph.
  307. scale = stbtt_ScaleForPixelHeight(&fnt->font, size);
  308. g = stbtt_FindGlyphIndex(&fnt->font, codepoint);
  309. stbtt_GetGlyphHMetrics(&fnt->font, g, &advance, &lsb);
  310. stbtt_GetGlyphBitmapBox(&fnt->font, g, scale,scale, &x0,&y0,&x1,&y1);
  311. gw = x1-x0;
  312. gh = y1-y0;
  313. // Check if glyph is larger than maximum texture size
  314. if (gw >= stash->tw || gh >= stash->th)
  315. return 0;
  316. // Find texture and row where the glyph can be fit.
  317. br = NULL;
  318. rh = (gh+7) & ~7;
  319. texture = stash->textures;
  320. while(br == NULL)
  321. {
  322. for (i = 0; i < texture->nrows; ++i)
  323. {
  324. if (texture->rows[i].h >= rh && texture->rows[i].x+gw+1 <= stash->tw)
  325. br = &texture->rows[i];
  326. }
  327. // If no row is found, there are 3 possibilities:
  328. // - add new row
  329. // - try next texture
  330. // - create new texture
  331. if (br == NULL)
  332. {
  333. short py = BORDER_Y_TOP;
  334. // Check that there is enough space.
  335. if (texture->nrows)
  336. {
  337. py = texture->rows[texture->nrows-1].y + texture->rows[texture->nrows-1].h+1;
  338. if (py+rh > stash->th)
  339. {
  340. if (texture->next != NULL)
  341. {
  342. texture = texture->next;
  343. }
  344. else
  345. {
  346. // Create new texture
  347. texture->next = (struct sth_texture*)malloc(sizeof(struct sth_texture));
  348. texture = texture->next;
  349. if (texture == NULL) goto error;
  350. memset(texture,0,sizeof(struct sth_texture));
  351. stash->m_renderCallbacks->updateTexture(texture,0,stash->tw,stash->th);
  352. }
  353. continue;
  354. }
  355. }
  356. // Init and add row
  357. br = &texture->rows[texture->nrows];
  358. br->x = BORDER_X_LEFT;
  359. br->y = py+BORDER_Y_BOTTOM;
  360. br->h = rh+ADDITIONAL_HEIGHT;
  361. texture->nrows++;
  362. }
  363. }
  364. // Alloc space for new glyph.
  365. fnt->nglyphs++;
  366. fnt->glyphs = (sth_glyph*)realloc(fnt->glyphs, fnt->nglyphs*sizeof(struct sth_glyph));
  367. if (!fnt->glyphs) return 0;
  368. // Init glyph.
  369. glyph = &fnt->glyphs[fnt->nglyphs-1];
  370. memset(glyph, 0, sizeof(struct sth_glyph));
  371. glyph->codepoint = codepoint;
  372. glyph->size = isize;
  373. glyph->texture = texture;
  374. glyph->x0_ = br->x;
  375. glyph->y0 = br->y;
  376. glyph->x1 = glyph->x0_+gw;
  377. glyph->y1 = glyph->y0+gh;
  378. glyph->xadv = scale * advance;
  379. glyph->xoff = (float)x0;
  380. glyph->yoff = (float)y0;
  381. glyph->next = 0;
  382. // Advance row location.
  383. br->x += gw+BORDER_X_RIGHT;
  384. // Insert char to hash lookup.
  385. glyph->next = fnt->lut[h];
  386. fnt->lut[h] = fnt->nglyphs-1;
  387. // Rasterize
  388. {
  389. unsigned char* ptr = texture->m_texels+glyph->x0_+glyph->y0*stash->tw;
  390. stbtt_MakeGlyphBitmap(&fnt->font,ptr , gw,gh,stash->tw, scale,scale, g);
  391. stash->m_renderCallbacks->updateTexture(texture,glyph, stash->tw, stash->th);
  392. }
  393. return glyph;
  394. error:
  395. if (texture)
  396. free(texture);
  397. return 0;
  398. }
  399. 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)
  400. {
  401. float rx,ry;
  402. float scale = 1.f/s_retinaScale;//1.0f;
  403. if (fnt->type == BMFONT)
  404. scale = isize/(glyph->size*10.0f);
  405. rx = (*x + scale * float(glyph->xoff));
  406. ry = (*y + scale * float(glyph->yoff));
  407. q->x0 = rx;
  408. q->y0 = ry + 1.5f*0.5f*float(isize)/10.f;
  409. q->x1 = rx + scale * float(glyph->x1 - glyph->x0_);
  410. q->y1 = ry + scale * float(glyph->y1 - glyph->y0)+ 1.5f*0.5f*float(isize)/10.f;
  411. q->s0 = float(glyph->x0_) * stash->itw;
  412. q->t0 = float(glyph->y0) * stash->ith;
  413. q->s1 = float(glyph->x1) * stash->itw;
  414. q->t1 = float(glyph->y1) * stash->ith;
  415. *x += scale * glyph->xadv;
  416. return 1;
  417. }
  418. static Vertex* setv(Vertex* v, float x, float y, float s, float t, float width, float height)
  419. {
  420. bool scale=true;
  421. if (scale)
  422. {
  423. v->position.p[0] = (x*2-width)/(width);
  424. v->position.p[1] = 1-(y)/(height/2);
  425. } else
  426. {
  427. v->position.p[0] = (x-width)/(width);
  428. v->position.p[1] = (height-y)/(height);
  429. }
  430. v->position.p[2] = 0.f;
  431. v->position.p[3] = 1.f;
  432. v->uv.p[0] = s;
  433. v->uv.p[1] = t;
  434. v->colour.p[0] = 0.1f;//1.f;
  435. v->colour.p[1] = 0.1f;
  436. v->colour.p[2] = 0.1f;
  437. v->colour.p[3] = 1.f;
  438. return v+1;
  439. }
  440. static void flush_draw(struct sth_stash* stash)
  441. {
  442. struct sth_texture* texture = stash->textures;
  443. while (texture)
  444. {
  445. if (texture->nverts > 0)
  446. {
  447. stash->m_renderCallbacks->render(texture);
  448. texture->nverts = 0;
  449. }
  450. texture = texture->next;
  451. }
  452. }
  453. void sth_begin_draw(struct sth_stash* stash)
  454. {
  455. if (stash == NULL) return;
  456. if (stash->drawing)
  457. flush_draw(stash);
  458. stash->drawing = 1;
  459. }
  460. void sth_end_draw(struct sth_stash* stash)
  461. {
  462. if (stash == NULL) return;
  463. if (!stash->drawing) return;
  464. /*
  465. // Debug dump.
  466. if (stash->nverts+6 < VERT_COUNT)
  467. {
  468. float x = 500, y = 100;
  469. float* v = &stash->verts[stash->nverts*4];
  470. v = setv(v, x, y, 0, 0);
  471. v = setv(v, x+stash->tw, y, 1, 0);
  472. v = setv(v, x+stash->tw, y+stash->th, 1, 1);
  473. v = setv(v, x, y, 0, 0);
  474. v = setv(v, x+stash->tw, y+stash->th, 1, 1);
  475. v = setv(v, x, y+stash->th, 0, 1);
  476. stash->nverts += 6;
  477. }
  478. */
  479. flush_draw(stash);
  480. stash->drawing = 0;
  481. }
  482. void sth_draw_texture(struct sth_stash* stash,
  483. int idx, float size,
  484. float x, float y,
  485. int screenwidth, int screenheight,
  486. const char* s, float* dx)
  487. {
  488. int width = stash->tw;
  489. int height=stash->th;
  490. unsigned int codepoint;
  491. struct sth_glyph* glyph = NULL;
  492. struct sth_texture* texture = NULL;
  493. unsigned int state = 0;
  494. struct sth_quad q;
  495. short isize = (short)(size*10.0f);
  496. Vertex* v;
  497. struct sth_font* fnt = NULL;
  498. if (stash == NULL) return;
  499. if (!stash->textures) return;
  500. fnt = stash->fonts;
  501. while(fnt != NULL && fnt->idx != idx) fnt = fnt->next;
  502. if (fnt == NULL) return;
  503. if (fnt->type != BMFONT && !fnt->data) return;
  504. int once = true;
  505. for (; once; ++s)
  506. {
  507. once=false;
  508. if (decutf8(&state, &codepoint, *(unsigned char*)s))
  509. continue;
  510. glyph = get_glyph(stash, fnt, codepoint, isize);
  511. if (!glyph)
  512. continue;
  513. texture = glyph->texture;
  514. if (texture->nverts+6 >= VERT_COUNT)
  515. flush_draw(stash);
  516. if (!get_quad(stash, fnt, glyph, isize, &x, &y, &q))
  517. continue;
  518. v = &texture->newverts[texture->nverts];
  519. q.x0 = 0;
  520. q.y0 = 0;
  521. q.x1 = q.x0+width;
  522. q.y1 = q.y0+height;
  523. v = setv(v, q.x0, q.y0, 0,0,(float)screenwidth,(float)screenheight);
  524. v = setv(v, q.x1, q.y0, 1,0,(float)screenwidth,(float)screenheight);
  525. v = setv(v, q.x1, q.y1, 1,1,(float)screenwidth,(float)screenheight);
  526. v = setv(v, q.x0, q.y0, 0,0,(float)screenwidth,(float)screenheight);
  527. v = setv(v, q.x1, q.y1, 1,1,(float)screenwidth,(float)screenheight);
  528. v = setv(v, q.x0, q.y1, 0,1,(float)screenwidth,(float)screenheight);
  529. texture->nverts += 6;
  530. }
  531. flush_draw(stash);
  532. if (dx) *dx = x;
  533. }
  534. void sth_flush_draw(struct sth_stash* stash)
  535. {
  536. flush_draw(stash);
  537. }
  538. void sth_draw_text(struct sth_stash* stash,
  539. int idx, float size,
  540. float x, float y,
  541. const char* s, float* dx, int screenwidth, int screenheight, int measureOnly, float retinaScale)
  542. {
  543. unsigned int codepoint;
  544. struct sth_glyph* glyph = NULL;
  545. struct sth_texture* texture = NULL;
  546. unsigned int state = 0;
  547. struct sth_quad q;
  548. short isize = (short)(size*10.0f);
  549. Vertex* v;
  550. struct sth_font* fnt = NULL;
  551. s_retinaScale = retinaScale;
  552. if (stash == NULL) return;
  553. if (!stash->textures) return;
  554. fnt = stash->fonts;
  555. while(fnt != NULL && fnt->idx != idx) fnt = fnt->next;
  556. if (fnt == NULL) return;
  557. if (fnt->type != BMFONT && !fnt->data) return;
  558. for (; *s; ++s)
  559. {
  560. if (decutf8(&state, &codepoint, *(unsigned char*)s))
  561. continue;
  562. glyph = get_glyph(stash, fnt, codepoint, isize);
  563. if (!glyph) continue;
  564. texture = glyph->texture;
  565. if (!measureOnly)
  566. {
  567. if (texture->nverts+6 >= VERT_COUNT)
  568. flush_draw(stash);
  569. }
  570. if (!get_quad(stash, fnt, glyph, isize, &x, &y, &q)) continue;
  571. if (!measureOnly)
  572. {
  573. v = &texture->newverts[texture->nverts];
  574. v = setv(v, q.x0, q.y0, q.s0, q.t0,(float)screenwidth,(float)screenheight);
  575. v = setv(v, q.x1, q.y0, q.s1, q.t0,(float)screenwidth,(float)screenheight);
  576. v = setv(v, q.x1, q.y1, q.s1, q.t1,(float)screenwidth,(float)screenheight);
  577. v = setv(v, q.x0, q.y0, q.s0, q.t0,(float)screenwidth,(float)screenheight);
  578. v = setv(v, q.x1, q.y1, q.s1, q.t1,(float)screenwidth,(float)screenheight);
  579. v = setv(v, q.x0, q.y1, q.s0, q.t1,(float)screenwidth,(float)screenheight);
  580. texture->nverts += 6;
  581. }
  582. }
  583. if (dx) *dx = x;
  584. }
  585. void sth_dim_text(struct sth_stash* stash,
  586. int idx, float size,
  587. const char* s,
  588. float* minx, float* miny, float* maxx, float* maxy)
  589. {
  590. unsigned int codepoint;
  591. struct sth_glyph* glyph = NULL;
  592. unsigned int state = 0;
  593. struct sth_quad q;
  594. short isize = (short)(size*10.0f);
  595. struct sth_font* fnt = NULL;
  596. float x = 0, y = 0;
  597. if (stash == NULL)
  598. return;
  599. if (!stash->textures)
  600. return;
  601. fnt = stash->fonts;
  602. while(fnt != NULL && fnt->idx != idx) fnt = fnt->next;
  603. if (fnt == NULL) return;
  604. if (fnt->type != BMFONT && !fnt->data) return;
  605. *minx = *maxx = x;
  606. *miny = *maxy = y;
  607. for (; *s; ++s)
  608. {
  609. if (decutf8(&state, &codepoint, *(unsigned char*)s)) continue;
  610. glyph = get_glyph(stash, fnt, codepoint, isize);
  611. if (!glyph) continue;
  612. if (!get_quad(stash, fnt, glyph, isize, &x, &y, &q)) continue;
  613. if (q.x0 < *minx) *minx = q.x0;
  614. if (q.x1 > *maxx) *maxx = q.x1;
  615. if (q.y1 < *miny) *miny = q.y1;
  616. if (q.y0 > *maxy) *maxy = q.y0;
  617. }
  618. }
  619. void sth_vmetrics(struct sth_stash* stash,
  620. int idx, float size,
  621. float* ascender, float* descender, float* lineh)
  622. {
  623. struct sth_font* fnt = NULL;
  624. if (stash == NULL) return;
  625. if (!stash->textures) return;
  626. fnt = stash->fonts;
  627. while(fnt != NULL && fnt->idx != idx) fnt = fnt->next;
  628. if (fnt == NULL) return;
  629. if (fnt->type != BMFONT && !fnt->data) return;
  630. if (ascender)
  631. *ascender = fnt->ascender*size;
  632. if (descender)
  633. *descender = fnt->descender*size;
  634. if (lineh)
  635. *lineh = fnt->lineh*size;
  636. }
  637. void sth_delete(struct sth_stash* stash)
  638. {
  639. struct sth_texture* tex = NULL;
  640. struct sth_texture* curtex = NULL;
  641. struct sth_font* fnt = NULL;
  642. struct sth_font* curfnt = NULL;
  643. if (!stash) return;
  644. tex = stash->textures;
  645. while(tex != NULL) {
  646. curtex = tex;
  647. delete tex->m_texels;
  648. tex->m_texels=0;
  649. tex = tex->next;
  650. stash->m_renderCallbacks->updateTexture(curtex,0,0,0);
  651. free(curtex);
  652. }
  653. fnt = stash->fonts;
  654. while(fnt != NULL) {
  655. curfnt = fnt;
  656. fnt = fnt->next;
  657. if (curfnt->glyphs)
  658. {
  659. free(curfnt->glyphs);
  660. }
  661. if (curfnt->type == TTFONT_FILE && curfnt->data)
  662. {
  663. free(curfnt->data);
  664. }
  665. free(curfnt);
  666. }
  667. free(stash);
  668. }