123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818 |
- //
- // Copyright (c) 2011 Andreas Krinke [email protected]
- // Copyright (c) 2009 Mikko Mononen [email protected]
- //
- // This software is provided 'as-is', without any express or implied
- // warranty. In no event will the authors be held liable for any damages
- // arising from the use of this software.
- // Permission is granted to anyone to use this software for any purpose,
- // including commercial applications, and to alter it and redistribute it
- // freely, subject to the following restrictions:
- // 1. The origin of this software must not be misrepresented; you must not
- // claim that you wrote the original software. If you use this software
- // in a product, an acknowledgment in the product documentation would be
- // appreciated but is not required.
- // 2. Altered source versions must be plainly marked as such, and must not be
- // misrepresented as being the original software.
- // 3. This notice may not be removed or altered from any source distribution.
- //
- #define STB_TRUETYPE_IMPLEMENTATION
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #ifdef _WIN32
- #include <windows.h>
- #endif
- #include "fontstash.h"
- #define BORDER_X_LEFT 2
- #define BORDER_X_RIGHT 2
- #define BORDER_Y_TOP 2
- #define BORDER_Y_BOTTOM 2
- #define ADDITIONAL_HEIGHT 2
- #define STB_TRUETYPE_IMPLEMENTATION
- #define STBTT_malloc(x,u) malloc(x)
- #define STBTT_free(x,u) free(x)
- #include "stb_truetype.h"
- #define HASH_LUT_SIZE 256
- #define TTFONT_FILE 1
- #define TTFONT_MEM 2
- #define BMFONT 3
- static int idx = 1;
- static float s_retinaScale = 1;
- static unsigned int hashint(unsigned int a)
- {
- a += ~(a<<15);
- a ^= (a>>10);
- a += (a<<3);
- a ^= (a>>6);
- a += ~(a<<11);
- a ^= (a>>16);
- return a;
- }
- struct sth_font
- {
- int idx;
- int type;
- stbtt_fontinfo font;
- unsigned char* data;
- struct sth_glyph* glyphs;
- int lut[HASH_LUT_SIZE];
- int nglyphs;
- float ascender;
- float descender;
- float lineh;
- struct sth_font* next;
- };
- struct sth_stash
- {
- int tw,th;
- float itw,ith;
- struct sth_texture* textures;
- struct sth_font* fonts;
- int drawing;
- RenderCallbacks* m_renderCallbacks;
- };
- // Copyright (c) 2008-2009 Bjoern Hoehrmann <[email protected]>
- // See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details.
- #define UTF8_ACCEPT 0
- #define UTF8_REJECT 1
- static const unsigned char utf8d[] = {
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 0xa,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x4,0x3,0x3, // e0..ef
- 0xb,0x6,0x6,0x6,0x5,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8, // f0..ff
- 0x0,0x1,0x2,0x3,0x5,0x8,0x7,0x1,0x1,0x1,0x4,0x6,0x1,0x1,0x1,0x1, // s0..s0
- 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
- 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
- 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
- 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
- };
- static unsigned int decutf8(unsigned int* state, unsigned int* codep, unsigned int byte)
- {
- unsigned int type = utf8d[byte];
- *codep = (*state != UTF8_ACCEPT) ?
- (byte & 0x3fu) | (*codep << 6) :
- (0xff >> type) & (byte);
- *state = utf8d[256 + *state*16 + type];
- return *state;
- }
- struct sth_stash* sth_create(int cachew, int cacheh, RenderCallbacks* renderCallbacks)
- {
- struct sth_stash* stash = NULL;
- struct sth_texture* texture = NULL;
- // Allocate memory for the font stash.
- stash = (struct sth_stash*)malloc(sizeof(struct sth_stash));
- if (stash == NULL)
- {
- assert(0);
- return NULL;
- }
- memset(stash,0,sizeof(struct sth_stash));
- stash->m_renderCallbacks = renderCallbacks;
- // Allocate memory for the first texture
- texture = (struct sth_texture*)malloc(sizeof(struct sth_texture));
- if (texture == NULL)
- {
- assert(0);
- free(stash);
- }
- memset(texture,0,sizeof(struct sth_texture));
- // Create first texture for the cache.
- stash->tw = cachew;
- stash->th = cacheh;
- stash->itw = 1.0f/cachew;
- stash->ith = 1.0f/cacheh;
- stash->textures = texture;
- stash->m_renderCallbacks->updateTexture(texture, 0, stash->tw, stash->th);
- return stash;
- }
- int sth_add_font_from_memory(struct sth_stash* stash, unsigned char* buffer)
- {
- int i, ascent, descent, fh, lineGap;
- struct sth_font* fnt = NULL;
- fnt = (struct sth_font*)malloc(sizeof(struct sth_font));
- if (fnt == NULL) goto error;
- memset(fnt,0,sizeof(struct sth_font));
- // Init hash lookup.
- for (i = 0; i < HASH_LUT_SIZE; ++i)
- fnt->lut[i] = -1;
- fnt->data = buffer;
- // Init stb_truetype
- if (!stbtt_InitFont(&fnt->font, fnt->data, 0))
- goto error;
- // Store normalized line height. The real line height is got
- // by multiplying the lineh by font size.
- stbtt_GetFontVMetrics(&fnt->font, &ascent, &descent, &lineGap);
- fh = ascent - descent;
- fnt->ascender = (float)ascent / (float)fh;
- fnt->descender = (float)descent / (float)fh;
- fnt->lineh = (float)(fh + lineGap) / (float)fh;
- fnt->idx = idx;
- fnt->type = TTFONT_MEM;
- fnt->next = stash->fonts;
- stash->fonts = fnt;
- return idx++;
- error:
- if (fnt) {
- if (fnt->glyphs) free(fnt->glyphs);
- free(fnt);
- }
- return 0;
- }
- int sth_add_font(struct sth_stash* stash, const char* path)
- {
- FILE* fp = 0;
- int datasize;
- unsigned char* data = NULL;
- int idx=0;
- // Read in the font data.
- fp = fopen(path, "rb");
- if (!fp) goto error;
- fseek(fp,0,SEEK_END);
- datasize = (int)ftell(fp);
- fseek(fp,0,SEEK_SET);
- data = (unsigned char*)malloc(datasize);
- if (data == NULL) goto error;
- int bytesRead;
- bytesRead = fread(data, 1, datasize, fp);
- if (bytesRead)
- {
- idx = sth_add_font_from_memory(stash, data);
- }
- fclose(fp);
- fp = 0;
-
- // Modify type of the loaded font.
- if (idx)
- stash->fonts->type = TTFONT_FILE;
- else
- free(data);
- return idx;
- error:
- if (data) free(data);
- if (fp) fclose(fp);
- return 0;
- }
- int sth_add_bitmap_font(struct sth_stash* stash, int ascent, int descent, int line_gap)
- {
- int i, fh;
- struct sth_font* fnt = NULL;
- fnt = (struct sth_font*)malloc(sizeof(struct sth_font));
- if (fnt == NULL) goto error;
- memset(fnt,0,sizeof(struct sth_font));
- // Init hash lookup.
- for (i = 0; i < HASH_LUT_SIZE; ++i) fnt->lut[i] = -1;
- // Store normalized line height. The real line height is got
- // by multiplying the lineh by font size.
- fh = ascent - descent;
- fnt->ascender = (float)ascent / (float)fh;
- fnt->descender = (float)descent / (float)fh;
- fnt->lineh = (float)(fh + line_gap) / (float)fh;
- fnt->idx = idx;
- fnt->type = BMFONT;
- fnt->next = stash->fonts;
- stash->fonts = fnt;
- return idx++;
- error:
- if (fnt) free(fnt);
- return 0;
- }
- /*void sth_add_glyph(struct sth_stash* stash,
- int idx,
- unsigned int id1,
- const char* s,
- short size, short base,
- int x, int y, int w, int h,
- float xoffset, float yoffset, float xadvance)
- {
- struct sth_texture* texture = NULL;
- struct sth_font* fnt = NULL;
- struct sth_glyph* glyph = NULL;
- unsigned int codepoint;
- unsigned int state = 0;
- if (stash == NULL) return;
- texture = stash->textures;
- while (texture != NULL && texture->id != id)
- texture = texture->next;
- if (texture == NULL)
- {
- // Create new texture
- texture = (struct sth_texture*)malloc(sizeof(struct sth_texture));
- if (texture == NULL) return;
- memset(texture, 0, sizeof(struct sth_texture));
- texture->id = id;
- texture->next = stash->textures;
- stash->textures = texture;
- }
- fnt = stash->fonts;
- while (fnt != NULL && fnt->idx != idx) fnt = fnt->next;
- if (fnt == NULL) return;
- if (fnt->type != BMFONT) return;
- for (; *s; ++s)
- {
- if (!decutf8(&state, &codepoint, *(unsigned char*)s)) break;
- }
- if (state != UTF8_ACCEPT) return;
- // Alloc space for new glyph.
- fnt->nglyphs++;
- fnt->glyphs = (sth_glyph*)realloc(fnt->glyphs, fnt->nglyphs*sizeof(struct sth_glyph));
- if (!fnt->glyphs) return;
- // Init glyph.
- glyph = &fnt->glyphs[fnt->nglyphs-1];
- memset(glyph, 0, sizeof(struct sth_glyph));
- glyph->codepoint = codepoint;
- glyph->size = size;
- glyph->texture = texture;
- glyph->x0_ = x;
- glyph->y0 = y;
- glyph->x1 = glyph->x0_+w;
- glyph->y1 = glyph->y0+h;
- glyph->xoff = xoffset;
- glyph->yoff = yoffset - base;
- glyph->xadv = xadvance;
- // Find code point and size.
- h = hashint(codepoint) & (HASH_LUT_SIZE-1);
- // Insert char to hash lookup.
- glyph->next = fnt->lut[h];
- fnt->lut[h] = fnt->nglyphs-1;
- }
- */
- static struct sth_glyph* get_glyph(struct sth_stash* stash, struct sth_font* fnt, unsigned int codepoint, short isize)
- {
- int i,g,advance,lsb,x0,y0,x1,y1,gw,gh;
- float scale;
- struct sth_texture* texture = NULL;
- struct sth_glyph* glyph = NULL;
- unsigned int h;
- float size = isize/10.0f;
- int rh;
- struct sth_row* br = NULL;
- // Find code point and size.
- h = hashint(codepoint) & (HASH_LUT_SIZE-1);
- i = fnt->lut[h];
- while (i != -1)
- {
- if (fnt->glyphs[i].codepoint == codepoint && (fnt->type == BMFONT || fnt->glyphs[i].size == isize))
- return &fnt->glyphs[i];
- i = fnt->glyphs[i].next;
- }
- // Could not find glyph.
- // For bitmap fonts: ignore this glyph.
- if (fnt->type == BMFONT) return 0;
- // For truetype fonts: create this glyph.
- scale = stbtt_ScaleForPixelHeight(&fnt->font, size);
- g = stbtt_FindGlyphIndex(&fnt->font, codepoint);
- stbtt_GetGlyphHMetrics(&fnt->font, g, &advance, &lsb);
- stbtt_GetGlyphBitmapBox(&fnt->font, g, scale,scale, &x0,&y0,&x1,&y1);
- gw = x1-x0;
- gh = y1-y0;
- // Check if glyph is larger than maximum texture size
- if (gw >= stash->tw || gh >= stash->th)
- return 0;
- // Find texture and row where the glyph can be fit.
- br = NULL;
- rh = (gh+7) & ~7;
- texture = stash->textures;
- while(br == NULL)
- {
- for (i = 0; i < texture->nrows; ++i)
- {
- if (texture->rows[i].h >= rh && texture->rows[i].x+gw+1 <= stash->tw)
- br = &texture->rows[i];
- }
- // If no row is found, there are 3 possibilities:
- // - add new row
- // - try next texture
- // - create new texture
- if (br == NULL)
- {
- short py = BORDER_Y_TOP;
- // Check that there is enough space.
- if (texture->nrows)
- {
- py = texture->rows[texture->nrows-1].y + texture->rows[texture->nrows-1].h+1;
- if (py+rh > stash->th)
- {
- if (texture->next != NULL)
- {
- texture = texture->next;
- }
- else
- {
- // Create new texture
- texture->next = (struct sth_texture*)malloc(sizeof(struct sth_texture));
- texture = texture->next;
- if (texture == NULL) goto error;
- memset(texture,0,sizeof(struct sth_texture));
- stash->m_renderCallbacks->updateTexture(texture,0,stash->tw,stash->th);
- }
- continue;
- }
- }
- // Init and add row
- br = &texture->rows[texture->nrows];
- br->x = BORDER_X_LEFT;
- br->y = py+BORDER_Y_BOTTOM;
- br->h = rh+ADDITIONAL_HEIGHT;
- texture->nrows++;
- }
- }
- // Alloc space for new glyph.
- fnt->nglyphs++;
- fnt->glyphs = (sth_glyph*)realloc(fnt->glyphs, fnt->nglyphs*sizeof(struct sth_glyph));
- if (!fnt->glyphs) return 0;
- // Init glyph.
- glyph = &fnt->glyphs[fnt->nglyphs-1];
- memset(glyph, 0, sizeof(struct sth_glyph));
- glyph->codepoint = codepoint;
- glyph->size = isize;
- glyph->texture = texture;
- glyph->x0_ = br->x;
- glyph->y0 = br->y;
- glyph->x1 = glyph->x0_+gw;
- glyph->y1 = glyph->y0+gh;
- glyph->xadv = scale * advance;
- glyph->xoff = (float)x0;
- glyph->yoff = (float)y0;
- glyph->next = 0;
- // Advance row location.
- br->x += gw+BORDER_X_RIGHT;
- // Insert char to hash lookup.
- glyph->next = fnt->lut[h];
- fnt->lut[h] = fnt->nglyphs-1;
- // Rasterize
- {
- unsigned char* ptr = texture->m_texels+glyph->x0_+glyph->y0*stash->tw;
- stbtt_MakeGlyphBitmap(&fnt->font,ptr , gw,gh,stash->tw, scale,scale, g);
- stash->m_renderCallbacks->updateTexture(texture,glyph, stash->tw, stash->th);
- }
- return glyph;
- error:
- if (texture)
- free(texture);
- return 0;
- }
- 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)
- {
- float rx,ry;
- float scale = 1.f/s_retinaScale;//1.0f;
- if (fnt->type == BMFONT)
- scale = isize/(glyph->size*10.0f);
- rx = (*x + scale * float(glyph->xoff));
- ry = (*y + scale * float(glyph->yoff));
- q->x0 = rx;
- q->y0 = ry + 1.5f*0.5f*float(isize)/10.f;
- q->x1 = rx + scale * float(glyph->x1 - glyph->x0_);
- q->y1 = ry + scale * float(glyph->y1 - glyph->y0)+ 1.5f*0.5f*float(isize)/10.f;
- q->s0 = float(glyph->x0_) * stash->itw;
- q->t0 = float(glyph->y0) * stash->ith;
- q->s1 = float(glyph->x1) * stash->itw;
- q->t1 = float(glyph->y1) * stash->ith;
- *x += scale * glyph->xadv;
- return 1;
- }
- static Vertex* setv(Vertex* v, float x, float y, float s, float t, float width, float height)
- {
- bool scale=true;
- if (scale)
- {
- v->position.p[0] = (x*2-width)/(width);
- v->position.p[1] = 1-(y)/(height/2);
- } else
- {
- v->position.p[0] = (x-width)/(width);
- v->position.p[1] = (height-y)/(height);
- }
- v->position.p[2] = 0.f;
- v->position.p[3] = 1.f;
- v->uv.p[0] = s;
- v->uv.p[1] = t;
- v->colour.p[0] = 0.1f;//1.f;
- v->colour.p[1] = 0.1f;
- v->colour.p[2] = 0.1f;
- v->colour.p[3] = 1.f;
- return v+1;
- }
- static void flush_draw(struct sth_stash* stash)
- {
- struct sth_texture* texture = stash->textures;
- while (texture)
- {
- if (texture->nverts > 0)
- {
- stash->m_renderCallbacks->render(texture);
- texture->nverts = 0;
- }
- texture = texture->next;
- }
- }
- void sth_begin_draw(struct sth_stash* stash)
- {
- if (stash == NULL) return;
- if (stash->drawing)
- flush_draw(stash);
- stash->drawing = 1;
- }
- void sth_end_draw(struct sth_stash* stash)
- {
- if (stash == NULL) return;
- if (!stash->drawing) return;
- /*
- // Debug dump.
- if (stash->nverts+6 < VERT_COUNT)
- {
- float x = 500, y = 100;
- float* v = &stash->verts[stash->nverts*4];
- v = setv(v, x, y, 0, 0);
- v = setv(v, x+stash->tw, y, 1, 0);
- v = setv(v, x+stash->tw, y+stash->th, 1, 1);
- v = setv(v, x, y, 0, 0);
- v = setv(v, x+stash->tw, y+stash->th, 1, 1);
- v = setv(v, x, y+stash->th, 0, 1);
- stash->nverts += 6;
- }
- */
- flush_draw(stash);
- stash->drawing = 0;
- }
- void sth_draw_texture(struct sth_stash* stash,
- int idx, float size,
- float x, float y,
- int screenwidth, int screenheight,
- const char* s, float* dx)
- {
- int width = stash->tw;
- int height=stash->th;
- unsigned int codepoint;
- struct sth_glyph* glyph = NULL;
- struct sth_texture* texture = NULL;
- unsigned int state = 0;
- struct sth_quad q;
- short isize = (short)(size*10.0f);
- Vertex* v;
- struct sth_font* fnt = NULL;
- if (stash == NULL) return;
- if (!stash->textures) return;
- fnt = stash->fonts;
- while(fnt != NULL && fnt->idx != idx) fnt = fnt->next;
- if (fnt == NULL) return;
- if (fnt->type != BMFONT && !fnt->data) return;
- int once = true;
- for (; once; ++s)
- {
- once=false;
- if (decutf8(&state, &codepoint, *(unsigned char*)s))
- continue;
- glyph = get_glyph(stash, fnt, codepoint, isize);
- if (!glyph)
- continue;
- texture = glyph->texture;
- if (texture->nverts+6 >= VERT_COUNT)
- flush_draw(stash);
- if (!get_quad(stash, fnt, glyph, isize, &x, &y, &q))
- continue;
- v = &texture->newverts[texture->nverts];
- q.x0 = 0;
- q.y0 = 0;
- q.x1 = q.x0+width;
- q.y1 = q.y0+height;
- v = setv(v, q.x0, q.y0, 0,0,(float)screenwidth,(float)screenheight);
- v = setv(v, q.x1, q.y0, 1,0,(float)screenwidth,(float)screenheight);
- v = setv(v, q.x1, q.y1, 1,1,(float)screenwidth,(float)screenheight);
- v = setv(v, q.x0, q.y0, 0,0,(float)screenwidth,(float)screenheight);
- v = setv(v, q.x1, q.y1, 1,1,(float)screenwidth,(float)screenheight);
- v = setv(v, q.x0, q.y1, 0,1,(float)screenwidth,(float)screenheight);
- texture->nverts += 6;
- }
- flush_draw(stash);
- if (dx) *dx = x;
- }
- void sth_flush_draw(struct sth_stash* stash)
- {
- flush_draw(stash);
- }
- void sth_draw_text(struct sth_stash* stash,
- int idx, float size,
- float x, float y,
- const char* s, float* dx, int screenwidth, int screenheight, int measureOnly, float retinaScale)
- {
- unsigned int codepoint;
- struct sth_glyph* glyph = NULL;
- struct sth_texture* texture = NULL;
- unsigned int state = 0;
- struct sth_quad q;
- short isize = (short)(size*10.0f);
- Vertex* v;
- struct sth_font* fnt = NULL;
- s_retinaScale = retinaScale;
- if (stash == NULL) return;
- if (!stash->textures) return;
- fnt = stash->fonts;
- while(fnt != NULL && fnt->idx != idx) fnt = fnt->next;
- if (fnt == NULL) return;
- if (fnt->type != BMFONT && !fnt->data) return;
- for (; *s; ++s)
- {
- if (decutf8(&state, &codepoint, *(unsigned char*)s))
- continue;
- glyph = get_glyph(stash, fnt, codepoint, isize);
- if (!glyph) continue;
- texture = glyph->texture;
- if (!measureOnly)
- {
- if (texture->nverts+6 >= VERT_COUNT)
- flush_draw(stash);
- }
- if (!get_quad(stash, fnt, glyph, isize, &x, &y, &q)) continue;
- if (!measureOnly)
- {
- v = &texture->newverts[texture->nverts];
- v = setv(v, q.x0, q.y0, q.s0, q.t0,(float)screenwidth,(float)screenheight);
- v = setv(v, q.x1, q.y0, q.s1, q.t0,(float)screenwidth,(float)screenheight);
- v = setv(v, q.x1, q.y1, q.s1, q.t1,(float)screenwidth,(float)screenheight);
- v = setv(v, q.x0, q.y0, q.s0, q.t0,(float)screenwidth,(float)screenheight);
- v = setv(v, q.x1, q.y1, q.s1, q.t1,(float)screenwidth,(float)screenheight);
- v = setv(v, q.x0, q.y1, q.s0, q.t1,(float)screenwidth,(float)screenheight);
- texture->nverts += 6;
- }
- }
- if (dx) *dx = x;
- }
- void sth_dim_text(struct sth_stash* stash,
- int idx, float size,
- const char* s,
- float* minx, float* miny, float* maxx, float* maxy)
- {
- unsigned int codepoint;
- struct sth_glyph* glyph = NULL;
- unsigned int state = 0;
- struct sth_quad q;
- short isize = (short)(size*10.0f);
- struct sth_font* fnt = NULL;
- float x = 0, y = 0;
- if (stash == NULL)
- return;
- if (!stash->textures)
- return;
- fnt = stash->fonts;
- while(fnt != NULL && fnt->idx != idx) fnt = fnt->next;
- if (fnt == NULL) return;
- if (fnt->type != BMFONT && !fnt->data) return;
- *minx = *maxx = x;
- *miny = *maxy = y;
- for (; *s; ++s)
- {
- if (decutf8(&state, &codepoint, *(unsigned char*)s)) continue;
- glyph = get_glyph(stash, fnt, codepoint, isize);
- if (!glyph) continue;
- if (!get_quad(stash, fnt, glyph, isize, &x, &y, &q)) continue;
- if (q.x0 < *minx) *minx = q.x0;
- if (q.x1 > *maxx) *maxx = q.x1;
- if (q.y1 < *miny) *miny = q.y1;
- if (q.y0 > *maxy) *maxy = q.y0;
- }
- }
- void sth_vmetrics(struct sth_stash* stash,
- int idx, float size,
- float* ascender, float* descender, float* lineh)
- {
- struct sth_font* fnt = NULL;
- if (stash == NULL) return;
- if (!stash->textures) return;
- fnt = stash->fonts;
- while(fnt != NULL && fnt->idx != idx) fnt = fnt->next;
- if (fnt == NULL) return;
- if (fnt->type != BMFONT && !fnt->data) return;
- if (ascender)
- *ascender = fnt->ascender*size;
- if (descender)
- *descender = fnt->descender*size;
- if (lineh)
- *lineh = fnt->lineh*size;
- }
- void sth_delete(struct sth_stash* stash)
- {
- struct sth_texture* tex = NULL;
- struct sth_texture* curtex = NULL;
- struct sth_font* fnt = NULL;
- struct sth_font* curfnt = NULL;
- if (!stash) return;
- tex = stash->textures;
- while(tex != NULL) {
- curtex = tex;
- delete tex->m_texels;
- tex->m_texels=0;
- tex = tex->next;
- stash->m_renderCallbacks->updateTexture(curtex,0,0,0);
- free(curtex);
- }
- fnt = stash->fonts;
- while(fnt != NULL) {
- curfnt = fnt;
- fnt = fnt->next;
- if (curfnt->glyphs)
- {
- free(curfnt->glyphs);
- }
- if (curfnt->type == TTFONT_FILE && curfnt->data)
- {
- free(curfnt->data);
- }
- free(curfnt);
- }
- free(stash);
- }
|