Browse Source

Merged latest changes from fontstash

- merged font stash optional FreeType support
shared-context
Mikko Mononen 11 years ago
parent
commit
22e58d6d83
1 changed files with 170 additions and 17 deletions
  1. +170
    -17
      src/fontstash.h

+ 170
- 17
src/fontstash.h View File

@@ -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 <ft2build.h>
#include FT_FREETYPE_H
#include FT_ADVANCES_H
#include <math.h>

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);


Loading…
Cancel
Save