lnvis

nanovg lightning network visualizer
git clone git://jb55.com/lnvis
Log | Files | Refs | README | LICENSE

fontstash.h (48263B)


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