|
@@ -38,6 +38,11 @@ enum FONSalign { |
|
|
FONS_ALIGN_BASELINE = 1<<6, // Default |
|
|
FONS_ALIGN_BASELINE = 1<<6, // Default |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
enum FONSglyphBitmap { |
|
|
|
|
|
FONS_GLYPH_BITMAP_OPTIONAL = 1, |
|
|
|
|
|
FONS_GLYPH_BITMAP_REQUIRED = 2, |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
enum FONSerrorCode { |
|
|
enum FONSerrorCode { |
|
|
// Font atlas is full. |
|
|
// Font atlas is full. |
|
|
FONS_ATLAS_FULL = 1, |
|
|
FONS_ATLAS_FULL = 1, |
|
@@ -78,6 +83,7 @@ struct FONStextIter { |
|
|
const char* next; |
|
|
const char* next; |
|
|
const char* end; |
|
|
const char* end; |
|
|
unsigned int utf8state; |
|
|
unsigned int utf8state; |
|
|
|
|
|
int bitmapOption; |
|
|
}; |
|
|
}; |
|
|
typedef struct FONStextIter FONStextIter; |
|
|
typedef struct FONStextIter FONStextIter; |
|
|
|
|
|
|
|
@@ -122,7 +128,7 @@ void fonsLineBounds(FONScontext* s, float y, float* miny, float* maxy); |
|
|
void fonsVertMetrics(FONScontext* s, float* ascender, float* descender, float* lineh); |
|
|
void fonsVertMetrics(FONScontext* s, float* ascender, float* descender, float* lineh); |
|
|
|
|
|
|
|
|
// Text iterator |
|
|
// Text iterator |
|
|
int fonsTextIterInit(FONScontext* stash, FONStextIter* iter, float x, float y, const char* str, const char* end); |
|
|
|
|
|
|
|
|
int fonsTextIterInit(FONScontext* stash, FONStextIter* iter, float x, float y, const char* str, const char* end, int bitmapOption); |
|
|
int fonsTextIterNext(FONScontext* stash, FONStextIter* iter, struct FONSquad* quad); |
|
|
int fonsTextIterNext(FONScontext* stash, FONStextIter* iter, struct FONSquad* quad); |
|
|
|
|
|
|
|
|
// Pull texture changes |
|
|
// Pull texture changes |
|
@@ -873,7 +879,8 @@ error: |
|
|
int fonsAddFont(FONScontext* stash, const char* name, const char* path) |
|
|
int fonsAddFont(FONScontext* stash, const char* name, const char* path) |
|
|
{ |
|
|
{ |
|
|
FILE* fp = 0; |
|
|
FILE* fp = 0; |
|
|
int dataSize = 0, readed; |
|
|
|
|
|
|
|
|
int dataSize = 0; |
|
|
|
|
|
size_t readed; |
|
|
unsigned char* data = NULL; |
|
|
unsigned char* data = NULL; |
|
|
|
|
|
|
|
|
// Read in the font data. |
|
|
// Read in the font data. |
|
@@ -1029,7 +1036,7 @@ static void fons__blur(FONScontext* stash, unsigned char* dst, int w, int h, int |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static FONSglyph* fons__getGlyph(FONScontext* stash, FONSfont* font, unsigned int codepoint, |
|
|
static FONSglyph* fons__getGlyph(FONScontext* stash, FONSfont* font, unsigned int codepoint, |
|
|
short isize, short iblur) |
|
|
|
|
|
|
|
|
short isize, short iblur, int bitmapOption) |
|
|
{ |
|
|
{ |
|
|
int i, g, advance, lsb, x0, y0, x1, y1, gw, gh, gx, gy, x, y; |
|
|
int i, g, advance, lsb, x0, y0, x1, y1, gw, gh, gx, gy, x, y; |
|
|
float scale; |
|
|
float scale; |
|
@@ -1052,12 +1059,18 @@ static FONSglyph* fons__getGlyph(FONScontext* stash, FONSfont* font, unsigned in |
|
|
h = fons__hashint(codepoint) & (FONS_HASH_LUT_SIZE-1); |
|
|
h = fons__hashint(codepoint) & (FONS_HASH_LUT_SIZE-1); |
|
|
i = font->lut[h]; |
|
|
i = font->lut[h]; |
|
|
while (i != -1) { |
|
|
while (i != -1) { |
|
|
if (font->glyphs[i].codepoint == codepoint && font->glyphs[i].size == isize && font->glyphs[i].blur == iblur) |
|
|
|
|
|
return &font->glyphs[i]; |
|
|
|
|
|
|
|
|
if (font->glyphs[i].codepoint == codepoint && font->glyphs[i].size == isize && font->glyphs[i].blur == iblur) { |
|
|
|
|
|
glyph = &font->glyphs[i]; |
|
|
|
|
|
if (bitmapOption == FONS_GLYPH_BITMAP_OPTIONAL || (glyph->x0 >= 0 && glyph->y0 >= 0)) { |
|
|
|
|
|
return glyph; |
|
|
|
|
|
} |
|
|
|
|
|
// At this point, glyph exists but the bitmap data is not yet created. |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
i = font->glyphs[i].next; |
|
|
i = font->glyphs[i].next; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Could not find glyph, create it. |
|
|
|
|
|
|
|
|
// Create a new glyph or rasterize bitmap data for a cached glyph. |
|
|
g = fons__tt_getGlyphIndex(&font->font, codepoint); |
|
|
g = fons__tt_getGlyphIndex(&font->font, codepoint); |
|
|
// Try to find the glyph in fallback fonts. |
|
|
// Try to find the glyph in fallback fonts. |
|
|
if (g == 0) { |
|
|
if (g == 0) { |
|
@@ -1078,20 +1091,34 @@ static FONSglyph* fons__getGlyph(FONScontext* stash, FONSfont* font, unsigned in |
|
|
gw = x1-x0 + pad*2; |
|
|
gw = x1-x0 + pad*2; |
|
|
gh = y1-y0 + pad*2; |
|
|
gh = y1-y0 + pad*2; |
|
|
|
|
|
|
|
|
// Find free spot for the rect in the atlas |
|
|
|
|
|
added = fons__atlasAddRect(stash->atlas, gw, gh, &gx, &gy); |
|
|
|
|
|
if (added == 0 && stash->handleError != NULL) { |
|
|
|
|
|
// Atlas is full, let the user to resize the atlas (or not), and try again. |
|
|
|
|
|
stash->handleError(stash->errorUptr, FONS_ATLAS_FULL, 0); |
|
|
|
|
|
|
|
|
// Determines the spot to draw glyph in the atlas. |
|
|
|
|
|
if (bitmapOption == FONS_GLYPH_BITMAP_REQUIRED) { |
|
|
|
|
|
// Find free spot for the rect in the atlas |
|
|
added = fons__atlasAddRect(stash->atlas, gw, gh, &gx, &gy); |
|
|
added = fons__atlasAddRect(stash->atlas, gw, gh, &gx, &gy); |
|
|
|
|
|
if (added == 0 && stash->handleError != NULL) { |
|
|
|
|
|
// Atlas is full, let the user to resize the atlas (or not), and try again. |
|
|
|
|
|
stash->handleError(stash->errorUptr, FONS_ATLAS_FULL, 0); |
|
|
|
|
|
added = fons__atlasAddRect(stash->atlas, gw, gh, &gx, &gy); |
|
|
|
|
|
} |
|
|
|
|
|
if (added == 0) return NULL; |
|
|
|
|
|
} else { |
|
|
|
|
|
// Negative coordinate indicates there is no bitmap data created. |
|
|
|
|
|
gx = -1; |
|
|
|
|
|
gy = -1; |
|
|
} |
|
|
} |
|
|
if (added == 0) return NULL; |
|
|
|
|
|
|
|
|
|
|
|
// Init glyph. |
|
|
// Init glyph. |
|
|
glyph = fons__allocGlyph(font); |
|
|
|
|
|
glyph->codepoint = codepoint; |
|
|
|
|
|
glyph->size = isize; |
|
|
|
|
|
glyph->blur = iblur; |
|
|
|
|
|
|
|
|
if (glyph == NULL) { |
|
|
|
|
|
glyph = fons__allocGlyph(font); |
|
|
|
|
|
glyph->codepoint = codepoint; |
|
|
|
|
|
glyph->size = isize; |
|
|
|
|
|
glyph->blur = iblur; |
|
|
|
|
|
glyph->next = 0; |
|
|
|
|
|
|
|
|
|
|
|
// Insert char to hash lookup. |
|
|
|
|
|
glyph->next = font->lut[h]; |
|
|
|
|
|
font->lut[h] = font->nglyphs-1; |
|
|
|
|
|
} |
|
|
glyph->index = g; |
|
|
glyph->index = g; |
|
|
glyph->x0 = (short)gx; |
|
|
glyph->x0 = (short)gx; |
|
|
glyph->y0 = (short)gy; |
|
|
glyph->y0 = (short)gy; |
|
@@ -1100,15 +1127,14 @@ static FONSglyph* fons__getGlyph(FONScontext* stash, FONSfont* font, unsigned in |
|
|
glyph->xadv = (short)(scale * advance * 10.0f); |
|
|
glyph->xadv = (short)(scale * advance * 10.0f); |
|
|
glyph->xoff = (short)(x0 - pad); |
|
|
glyph->xoff = (short)(x0 - pad); |
|
|
glyph->yoff = (short)(y0 - pad); |
|
|
glyph->yoff = (short)(y0 - pad); |
|
|
glyph->next = 0; |
|
|
|
|
|
|
|
|
|
|
|
// Insert char to hash lookup. |
|
|
|
|
|
glyph->next = font->lut[h]; |
|
|
|
|
|
font->lut[h] = font->nglyphs-1; |
|
|
|
|
|
|
|
|
if (bitmapOption == FONS_GLYPH_BITMAP_OPTIONAL) { |
|
|
|
|
|
return glyph; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// Rasterize |
|
|
// Rasterize |
|
|
dst = &stash->texData[(glyph->x0+pad) + (glyph->y0+pad) * stash->params.width]; |
|
|
dst = &stash->texData[(glyph->x0+pad) + (glyph->y0+pad) * stash->params.width]; |
|
|
fons__tt_renderGlyphBitmap(&renderFont->font, dst, gw-pad*2,gh-pad*2, stash->params.width, scale,scale, g); |
|
|
|
|
|
|
|
|
fons__tt_renderGlyphBitmap(&renderFont->font, dst, gw-pad*2,gh-pad*2, stash->params.width, scale, scale, g); |
|
|
|
|
|
|
|
|
// Make sure there is one pixel empty border. |
|
|
// Make sure there is one pixel empty border. |
|
|
dst = &stash->texData[glyph->x0 + glyph->y0 * stash->params.width]; |
|
|
dst = &stash->texData[glyph->x0 + glyph->y0 * stash->params.width]; |
|
@@ -1135,7 +1161,7 @@ static FONSglyph* fons__getGlyph(FONScontext* stash, FONSfont* font, unsigned in |
|
|
if (iblur > 0) { |
|
|
if (iblur > 0) { |
|
|
stash->nscratch = 0; |
|
|
stash->nscratch = 0; |
|
|
bdst = &stash->texData[glyph->x0 + glyph->y0 * stash->params.width]; |
|
|
bdst = &stash->texData[glyph->x0 + glyph->y0 * stash->params.width]; |
|
|
fons__blur(stash, bdst, gw,gh, stash->params.width, iblur); |
|
|
|
|
|
|
|
|
fons__blur(stash, bdst, gw, gh, stash->params.width, iblur); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
stash->dirtyRect[0] = fons__mini(stash->dirtyRect[0], glyph->x0); |
|
|
stash->dirtyRect[0] = fons__mini(stash->dirtyRect[0], glyph->x0); |
|
@@ -1297,7 +1323,7 @@ float fonsDrawText(FONScontext* stash, |
|
|
for (; str != end; ++str) { |
|
|
for (; str != end; ++str) { |
|
|
if (fons__decutf8(&utf8state, &codepoint, *(const unsigned char*)str)) |
|
|
if (fons__decutf8(&utf8state, &codepoint, *(const unsigned char*)str)) |
|
|
continue; |
|
|
continue; |
|
|
glyph = fons__getGlyph(stash, font, codepoint, isize, iblur); |
|
|
|
|
|
|
|
|
glyph = fons__getGlyph(stash, font, codepoint, isize, iblur, FONS_GLYPH_BITMAP_REQUIRED); |
|
|
if (glyph != NULL) { |
|
|
if (glyph != NULL) { |
|
|
fons__getQuad(stash, font, prevGlyphIndex, glyph, scale, state->spacing, &x, &y, &q); |
|
|
fons__getQuad(stash, font, prevGlyphIndex, glyph, scale, state->spacing, &x, &y, &q); |
|
|
|
|
|
|
|
@@ -1320,7 +1346,7 @@ float fonsDrawText(FONScontext* stash, |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
int fonsTextIterInit(FONScontext* stash, FONStextIter* iter, |
|
|
int fonsTextIterInit(FONScontext* stash, FONStextIter* iter, |
|
|
float x, float y, const char* str, const char* end) |
|
|
|
|
|
|
|
|
float x, float y, const char* str, const char* end, int bitmapOption) |
|
|
{ |
|
|
{ |
|
|
FONSstate* state = fons__getState(stash); |
|
|
FONSstate* state = fons__getState(stash); |
|
|
float width; |
|
|
float width; |
|
@@ -1360,6 +1386,7 @@ int fonsTextIterInit(FONScontext* stash, FONStextIter* iter, |
|
|
iter->end = end; |
|
|
iter->end = end; |
|
|
iter->codepoint = 0; |
|
|
iter->codepoint = 0; |
|
|
iter->prevGlyphIndex = -1; |
|
|
iter->prevGlyphIndex = -1; |
|
|
|
|
|
iter->bitmapOption = bitmapOption; |
|
|
|
|
|
|
|
|
return 1; |
|
|
return 1; |
|
|
} |
|
|
} |
|
@@ -1380,7 +1407,8 @@ int fonsTextIterNext(FONScontext* stash, FONStextIter* iter, FONSquad* quad) |
|
|
// Get glyph and quad |
|
|
// Get glyph and quad |
|
|
iter->x = iter->nextx; |
|
|
iter->x = iter->nextx; |
|
|
iter->y = iter->nexty; |
|
|
iter->y = iter->nexty; |
|
|
glyph = fons__getGlyph(stash, iter->font, iter->codepoint, iter->isize, iter->iblur); |
|
|
|
|
|
|
|
|
glyph = fons__getGlyph(stash, iter->font, iter->codepoint, iter->isize, iter->iblur, iter->bitmapOption); |
|
|
|
|
|
// If the iterator was initialized with FONS_GLYPH_BITMAP_OPTIONAL, then the UV coordinates of the quad will be invalid. |
|
|
if (glyph != NULL) |
|
|
if (glyph != NULL) |
|
|
fons__getQuad(stash, iter->font, iter->prevGlyphIndex, glyph, iter->scale, iter->spacing, &iter->nextx, &iter->nexty, quad); |
|
|
fons__getQuad(stash, iter->font, iter->prevGlyphIndex, glyph, iter->scale, iter->spacing, &iter->nextx, &iter->nexty, quad); |
|
|
iter->prevGlyphIndex = glyph != NULL ? glyph->index : -1; |
|
|
iter->prevGlyphIndex = glyph != NULL ? glyph->index : -1; |
|
@@ -1477,7 +1505,7 @@ float fonsTextBounds(FONScontext* stash, |
|
|
for (; str != end; ++str) { |
|
|
for (; str != end; ++str) { |
|
|
if (fons__decutf8(&utf8state, &codepoint, *(const unsigned char*)str)) |
|
|
if (fons__decutf8(&utf8state, &codepoint, *(const unsigned char*)str)) |
|
|
continue; |
|
|
continue; |
|
|
glyph = fons__getGlyph(stash, font, codepoint, isize, iblur); |
|
|
|
|
|
|
|
|
glyph = fons__getGlyph(stash, font, codepoint, isize, iblur, FONS_GLYPH_BITMAP_OPTIONAL); |
|
|
if (glyph != NULL) { |
|
|
if (glyph != NULL) { |
|
|
fons__getQuad(stash, font, prevGlyphIndex, glyph, scale, state->spacing, &x, &y, &q); |
|
|
fons__getQuad(stash, font, prevGlyphIndex, glyph, scale, state->spacing, &x, &y, &q); |
|
|
if (q.x0 < minx) minx = q.x0; |
|
|
if (q.x0 < minx) minx = q.x0; |
|
|