DPF

DISTRHO Plugin Framework
Log | Files | Refs | Submodules | README | LICENSE

fontstash.h (49832B)


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