From 22e58d6d832c4954bfb1e9f0e523e8bcf60860e8 Mon Sep 17 00:00:00 2001 From: Mikko Mononen Date: Wed, 26 Feb 2014 12:28:29 +0200 Subject: [PATCH] Merged latest changes from fontstash - merged font stash optional FreeType support --- src/fontstash.h | 187 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 170 insertions(+), 17 deletions(-) diff --git a/src/fontstash.h b/src/fontstash.h index c3da968..5ea77da 100644 --- a/src/fontstash.h +++ b/src/fontstash.h @@ -109,6 +109,103 @@ void fonsDrawDebug(struct FONScontext* s, float x, float y); #ifdef FONTSTASH_IMPLEMENTATION +#define FONS_NOTUSED(v) (void)sizeof(v) + +#ifdef FONS_USE_FREETYPE + +#include +#include FT_FREETYPE_H +#include FT_ADVANCES_H +#include + +struct FONSttFontImpl { + FT_Face font; +}; + +static FT_Library ftLibrary; + +int fons__tt_init() +{ + FT_Error ftError; + ftError = FT_Init_FreeType(&ftLibrary); + return ftError == 0; +} + +int fons__tt_loadFont(struct FONScontext *context, struct FONSttFontImpl *font, unsigned char *data, int dataSize) +{ + FT_Error ftError; + FONS_NOTUSED(context); + + //font->font.userdata = stash; + ftError = FT_New_Memory_Face(ftLibrary, (const FT_Byte*)data, dataSize, 0, &font->font); + return ftError == 0; +} + +void fons__tt_getFontVMetrics(struct FONSttFontImpl *font, int *ascent, int *descent, int *lineGap) +{ + *ascent = font->font->ascender; + *descent = font->font->descender; + *lineGap = font->font->height - (*ascent - *descent); +} + +float fons__tt_getPixelHeightScale(struct FONSttFontImpl *font, float size) +{ + return size / (font->font->ascender - font->font->descender); +} + +int fons__tt_getGlyphIndex(struct FONSttFontImpl *font, int codepoint) +{ + return FT_Get_Char_Index(font->font, codepoint); +} + +int fons__tt_buildGlyphBitmap(struct FONSttFontImpl *font, int glyph, float size, float scale, int *advance, int *lsb, int *x0, int *y0, int *x1, int *y1) +{ + FT_Error ftError; + FT_GlyphSlot ftGlyph; + FONS_NOTUSED(scale); + + ftError = FT_Set_Pixel_Sizes(font->font, 0, (FT_UInt)(size * (float)font->font->units_per_EM / (float)(font->font->ascender - font->font->descender))); + if (ftError) return 0; + ftError = FT_Load_Glyph(font->font, glyph, FT_LOAD_RENDER); + if (ftError) return 0; + ftError = FT_Get_Advance(font->font, glyph, FT_LOAD_NO_SCALE, (FT_Fixed*)advance); + if (ftError) return 0; + ftGlyph = font->font->glyph; + *lsb = ftGlyph->metrics.horiBearingX; + *x0 = ftGlyph->bitmap_left; + *x1 = *x0 + ftGlyph->bitmap.width; + *y0 = -ftGlyph->bitmap_top; + *y1 = *y0 + ftGlyph->bitmap.rows; + return 1; +} + +void fons__tt_renderGlyphBitmap(struct FONSttFontImpl *font, unsigned char *output, int outWidth, int outHeight, int outStride, float scaleX, float scaleY, int glyph) +{ + FT_GlyphSlot ftGlyph = font->font->glyph; + int ftGlyphOffset = 0; + int x, y; + FONS_NOTUSED(outWidth); + FONS_NOTUSED(outHeight); + FONS_NOTUSED(scaleX); + FONS_NOTUSED(scaleY); + FONS_NOTUSED(glyph); // glyph has already been loaded by fons__tt_buildGlyphBitmap + + for ( y = 0; y < ftGlyph->bitmap.rows; y++ ) { + for ( x = 0; x < ftGlyph->bitmap.width; x++ ) { + output[(y * outStride) + x] = ftGlyph->bitmap.buffer[ftGlyphOffset++]; + } + } +} + +int fons__tt_getGlyphKernAdvance(struct FONSttFontImpl *font, int glyph1, int glyph2) +{ + FT_Vector ftKerning; + FT_Get_Kerning(font->font, glyph1, glyph2, FT_KERNING_DEFAULT, &ftKerning); + return ftKerning.x; +} + +#else + #define STB_TRUETYPE_IMPLEMENTATION static void* fons__tmpalloc(size_t size, void* up); static void fons__tmpfree(void* ptr, void* up); @@ -116,6 +213,61 @@ static void fons__tmpfree(void* ptr, void* up); #define STBTT_free(x,u) fons__tmpfree(x,u) #include "stb_truetype.h" +struct FONSttFontImpl { + stbtt_fontinfo font; +}; + +int fons__tt_init(struct FONScontext *context) +{ + FONS_NOTUSED(context); + return 1; +} + +int fons__tt_loadFont(struct FONScontext *context, struct FONSttFontImpl *font, unsigned char *data, int dataSize) +{ + int stbError; + FONS_NOTUSED(dataSize); + + font->font.userdata = context; + stbError = stbtt_InitFont(&font->font, data, 0); + return stbError; +} + +void fons__tt_getFontVMetrics(struct FONSttFontImpl *font, int *ascent, int *descent, int *lineGap) +{ + stbtt_GetFontVMetrics(&font->font, ascent, descent, lineGap); +} + +float fons__tt_getPixelHeightScale(struct FONSttFontImpl *font, float size) +{ + return stbtt_ScaleForPixelHeight(&font->font, size); +} + +int fons__tt_getGlyphIndex(struct FONSttFontImpl *font, int codepoint) +{ + return stbtt_FindGlyphIndex(&font->font, codepoint); +} + +int fons__tt_buildGlyphBitmap(struct FONSttFontImpl *font, int glyph, float size, float scale, int *advance, int *lsb, int *x0, int *y0, int *x1, int *y1) +{ + FONS_NOTUSED(size); + stbtt_GetGlyphHMetrics(&font->font, glyph, advance, lsb); + stbtt_GetGlyphBitmapBox(&font->font, glyph, scale, scale, x0, y0, x1, y1); + return 1; +} + +void fons__tt_renderGlyphBitmap(struct FONSttFontImpl *font, unsigned char *output, int outWidth, int outHeight, int outStride, float scaleX, float scaleY, int glyph) +{ + stbtt_MakeGlyphBitmap(&font->font, output, outWidth, outHeight, outStride, scaleX, scaleY, glyph); +} + +int fons__tt_getGlyphKernAdvance(struct FONSttFontImpl *font, int glyph1, int glyph2) +{ + return stbtt_GetGlyphKernAdvance(&font->font, glyph1, glyph2); +} + +#endif + #ifndef FONS_SCRATCH_BUF_SIZE # define FONS_SCRATCH_BUF_SIZE 16000 #endif @@ -171,7 +323,7 @@ struct FONSglyph struct FONSfont { - stbtt_fontinfo font; + struct FONSttFontImpl font; char name[64]; unsigned char* data; int dataSize; @@ -419,7 +571,7 @@ static int fons__atlasAddRect(struct FONSatlas* atlas, int rw, int rh, int* rx, int bestx = -1, besty = -1, i; // Bottom left fit heuristic. - for (i = 0; i < atlas->nnodes; i++) { + for (i = 0; i < atlas->nnodes; i++) { int y = fons__atlasRectFits(atlas, i, rw, rh); if (y != -1) { if (y + rh < besth || (y + rh == besth && atlas->nodes[i].width < bestw)) { @@ -457,6 +609,9 @@ struct FONScontext* fonsCreateInternal(struct FONSparams* params) stash->params = *params; + // Initialize implementation library + if (!fons__tt_init(stash)) goto error; + if (stash->params.renderCreate != NULL) { if (stash->params.renderCreate(stash->params.userPtr, stash->params.width, stash->params.height) == 0) goto error; @@ -560,7 +715,7 @@ static void fons__freeFont(struct FONSfont* font) { if (font == NULL) return; if (font->glyphs) free(font->glyphs); - if (font->freeData && font->data) free(font->data); + if (font->freeData && font->data) free(font->data); free(font); } @@ -581,7 +736,7 @@ static int fons__allocFont(struct FONScontext* stash) if (font->glyphs == NULL) goto error; font->cglyphs = FONS_INIT_GLYPHS; font->nglyphs = 0; - + stash->fonts[stash->nfonts++] = font; return stash->nfonts-1; @@ -640,14 +795,13 @@ int fonsAddFontMem(struct FONScontext* stash, const char* name, unsigned char* d font->data = data; font->freeData = (unsigned char)freeData; - // Init stb_truetype + // Init font stash->nscratch = 0; - font->font.userdata = stash; - if (!stbtt_InitFont(&font->font, font->data, 0)) goto error; + if (!fons__tt_loadFont(stash, &font->font, data, dataSize)) goto error; // Store normalized line height. The real line height is got // by multiplying the lineh by font size. - stbtt_GetFontVMetrics(&font->font, &ascent, &descent, &lineGap); + fons__tt_getFontVMetrics( &font->font, &ascent, &descent, &lineGap); fh = ascent - descent; font->ascender = (float)ascent / (float)fh; font->descender = (float)descent / (float)fh; @@ -778,10 +932,9 @@ static struct FONSglyph* fons__getGlyph(struct FONScontext* stash, struct FONSfo } // Could not find glyph, create it. - scale = stbtt_ScaleForPixelHeight(&font->font, size); - g = stbtt_FindGlyphIndex(&font->font, codepoint); - stbtt_GetGlyphHMetrics(&font->font, g, &advance, &lsb); - stbtt_GetGlyphBitmapBox(&font->font, g, scale,scale, &x0,&y0,&x1,&y1); + scale = fons__tt_getPixelHeightScale(&font->font, size); + g = fons__tt_getGlyphIndex(&font->font, codepoint); + fons__tt_buildGlyphBitmap(&font->font, g, size, scale, &advance, &lsb, &x0, &y0, &x1, &y1); gw = x1-x0 + pad*2; gh = y1-y0 + pad*2; @@ -810,7 +963,7 @@ static struct FONSglyph* fons__getGlyph(struct FONScontext* stash, struct FONSfo // Rasterize dst = &stash->texData[(glyph->x0+pad) + (glyph->y0+pad) * stash->params.width]; - stbtt_MakeGlyphBitmap(&font->font, dst, gw-pad*2,gh-pad*2, stash->params.width, scale,scale, g); + fons__tt_renderGlyphBitmap(&font->font, dst, gw-pad*2,gh-pad*2, stash->params.width, scale,scale, g); // Make sure there is one pixel empty border. dst = &stash->texData[glyph->x0 + glyph->y0 * stash->params.width]; @@ -855,7 +1008,7 @@ static void fons__getQuad(struct FONScontext* stash, struct FONSfont* font, float rx,ry,xoff,yoff,x0,y0,x1,y1; if (prevGlyph) { - float adv = stbtt_GetGlyphKernAdvance(&font->font, prevGlyph->index, glyph->index) * scale; + float adv = fons__tt_getGlyphKernAdvance(&font->font, prevGlyph->index, glyph->index) * scale; *x += (int)(adv + 0.5f); } @@ -978,7 +1131,7 @@ float fonsDrawText(struct FONScontext* stash, font = stash->fonts[state->font]; if (!font->data) return x; - scale = stbtt_ScaleForPixelHeight(&font->font, (float)isize/10.0f); + scale = fons__tt_getPixelHeightScale(&font->font, (float)isize/10.0f); // Align horizontally if (state->align & FONS_ALIGN_LEFT) { @@ -1036,7 +1189,7 @@ int fonsTextIterInit(struct FONScontext* stash, struct FONStextIter* iter, iter->isize = (short)(state->size*10.0f); iter->iblur = (short)state->blur; - iter->scale = stbtt_ScaleForPixelHeight(&iter->font->font, (float)iter->isize/10.0f); + iter->scale = fons__tt_getPixelHeightScale(&iter->font->font, (float)iter->isize/10.0f); // Align horizontally if (state->align & FONS_ALIGN_LEFT) { @@ -1125,7 +1278,7 @@ float fonsTextBounds(struct FONScontext* stash, font = stash->fonts[state->font]; if (!font->data) return 0; - scale = stbtt_ScaleForPixelHeight(&font->font, (float)isize/10.0f); + scale = fons__tt_getPixelHeightScale(&font->font, (float)isize/10.0f); // Align vertically. y += fons__getVertAlign(stash, font, state->align, isize);