Browse Source

Merge remote-tracking branch 'origin/master'

shared-context
Mikko Mononen 7 years ago
parent
commit
30a943cb9c
5 changed files with 81 additions and 34 deletions
  1. +2
    -1
      README.md
  2. +54
    -26
      src/fontstash.h
  3. +3
    -4
      src/nanovg.c
  4. +10
    -2
      src/nanovg_gl.h
  5. +12
    -1
      src/nanovg_gl_utils.h

+ 2
- 1
README.md View File

@@ -101,7 +101,8 @@ See the header file [nanovg.h](/src/nanovg.h) for API reference.
## Ports ## Ports


- [DX11 port](https://github.com/cmaughan/nanovg) by [Chris Maughan](https://github.com/cmaughan) - [DX11 port](https://github.com/cmaughan/nanovg) by [Chris Maughan](https://github.com/cmaughan)
- [bgfx port](https://github.com/bkaradzic/bgfx/tree/master/examples/20-nanovg) by [Branimir Karadžić](https://github.com/bkaradzic)
- [Metal port](https://github.com/ollix/MetalNanoVG) by [Olli Wang](https://github.com/olliwang)
- [bgfx port](https://github.com/bkaradzic/bgfx/tree/master/examples/20-nanovg) by [Branimir Karadžić](https://github.com/bkaradzic)


## Projects using NanoVG ## Projects using NanoVG




+ 54
- 26
src/fontstash.h View File

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


+ 3
- 4
src/nanovg.c View File

@@ -390,7 +390,6 @@ void nvgCancelFrame(NVGcontext* ctx)


void nvgEndFrame(NVGcontext* ctx) void nvgEndFrame(NVGcontext* ctx)
{ {
NVGstate* state = nvg__getState(ctx);
ctx->params.renderFlush(ctx->params.userPtr); ctx->params.renderFlush(ctx->params.userPtr);
if (ctx->fontImageIdx != 0) { if (ctx->fontImageIdx != 0) {
int fontImage = ctx->fontImages[ctx->fontImageIdx]; int fontImage = ctx->fontImages[ctx->fontImageIdx];
@@ -2456,7 +2455,7 @@ float nvgText(NVGcontext* ctx, float x, float y, const char* string, const char*
verts = nvg__allocTempVerts(ctx, cverts); verts = nvg__allocTempVerts(ctx, cverts);
if (verts == NULL) return x; if (verts == NULL) return x;


fonsTextIterInit(ctx->fs, &iter, x*scale, y*scale, string, end);
fonsTextIterInit(ctx->fs, &iter, x*scale, y*scale, string, end, FONS_GLYPH_BITMAP_REQUIRED);
prevIter = iter; prevIter = iter;
while (fonsTextIterNext(ctx->fs, &iter, &q)) { while (fonsTextIterNext(ctx->fs, &iter, &q)) {
float c[4*2]; float c[4*2];
@@ -2553,7 +2552,7 @@ int nvgTextGlyphPositions(NVGcontext* ctx, float x, float y, const char* string,
fonsSetAlign(ctx->fs, state->textAlign); fonsSetAlign(ctx->fs, state->textAlign);
fonsSetFont(ctx->fs, state->fontId); fonsSetFont(ctx->fs, state->fontId);


fonsTextIterInit(ctx->fs, &iter, x*scale, y*scale, string, end);
fonsTextIterInit(ctx->fs, &iter, x*scale, y*scale, string, end, FONS_GLYPH_BITMAP_OPTIONAL);
prevIter = iter; prevIter = iter;
while (fonsTextIterNext(ctx->fs, &iter, &q)) { while (fonsTextIterNext(ctx->fs, &iter, &q)) {
if (iter.prevGlyphIndex < 0 && nvg__allocTextAtlas(ctx)) { // can not retrieve glyph? if (iter.prevGlyphIndex < 0 && nvg__allocTextAtlas(ctx)) { // can not retrieve glyph?
@@ -2619,7 +2618,7 @@ int nvgTextBreakLines(NVGcontext* ctx, const char* string, const char* end, floa


breakRowWidth *= scale; breakRowWidth *= scale;


fonsTextIterInit(ctx->fs, &iter, 0, 0, string, end);
fonsTextIterInit(ctx->fs, &iter, 0, 0, string, end, FONS_GLYPH_BITMAP_OPTIONAL);
prevIter = iter; prevIter = iter;
while (fonsTextIterNext(ctx->fs, &iter, &q)) { while (fonsTextIterNext(ctx->fs, &iter, &q)) {
if (iter.prevGlyphIndex < 0 && nvg__allocTextAtlas(ctx)) { // can not retrieve glyph? if (iter.prevGlyphIndex < 0 && nvg__allocTextAtlas(ctx)) { // can not retrieve glyph?


+ 10
- 2
src/nanovg_gl.h View File

@@ -754,7 +754,7 @@ static int glnvg__renderCreateTexture(void* uptr, int type, int w, int h, int im
if (type == NVG_TEXTURE_RGBA) if (type == NVG_TEXTURE_RGBA)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
else else
#if defined(NANOVG_GLES2)
#if defined(NANOVG_GLES2) || defined (NANOVG_GL2)
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data); glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
#elif defined(NANOVG_GLES3) #elif defined(NANOVG_GLES3)
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, data); glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, data);
@@ -846,7 +846,7 @@ static int glnvg__renderUpdateTexture(void* uptr, int image, int x, int y, int w
if (tex->type == NVG_TEXTURE_RGBA) if (tex->type == NVG_TEXTURE_RGBA)
glTexSubImage2D(GL_TEXTURE_2D, 0, x,y, w,h, GL_RGBA, GL_UNSIGNED_BYTE, data); glTexSubImage2D(GL_TEXTURE_2D, 0, x,y, w,h, GL_RGBA, GL_UNSIGNED_BYTE, data);
else else
#ifdef NANOVG_GLES2
#if defined(NANOVG_GLES2) || defined(NANOVG_GL2)
glTexSubImage2D(GL_TEXTURE_2D, 0, x,y, w,h, GL_LUMINANCE, GL_UNSIGNED_BYTE, data); glTexSubImage2D(GL_TEXTURE_2D, 0, x,y, w,h, GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
#else #else
glTexSubImage2D(GL_TEXTURE_2D, 0, x,y, w,h, GL_RED, GL_UNSIGNED_BYTE, data); glTexSubImage2D(GL_TEXTURE_2D, 0, x,y, w,h, GL_RED, GL_UNSIGNED_BYTE, data);
@@ -945,10 +945,17 @@ static int glnvg__convertPaint(GLNVGcontext* gl, GLNVGfragUniforms* frag, NVGpai
} }
frag->type = NSVG_SHADER_FILLIMG; frag->type = NSVG_SHADER_FILLIMG;


#if NANOVG_GL_USE_UNIFORMBUFFER
if (tex->type == NVG_TEXTURE_RGBA) if (tex->type == NVG_TEXTURE_RGBA)
frag->texType = (tex->flags & NVG_IMAGE_PREMULTIPLIED) ? 0 : 1; frag->texType = (tex->flags & NVG_IMAGE_PREMULTIPLIED) ? 0 : 1;
else else
frag->texType = 2; frag->texType = 2;
#else
if (tex->type == NVG_TEXTURE_RGBA)
frag->texType = (tex->flags & NVG_IMAGE_PREMULTIPLIED) ? 0.0f : 1.0f;
else
frag->texType = 2.0f;
#endif
// printf("frag->texType = %d\n", frag->texType); // printf("frag->texType = %d\n", frag->texType);
} else { } else {
frag->type = NSVG_SHADER_FILLGRAD; frag->type = NSVG_SHADER_FILLGRAD;
@@ -984,6 +991,7 @@ static void glnvg__setUniforms(GLNVGcontext* gl, int uniformOffset, int image)


static void glnvg__renderViewport(void* uptr, int width, int height, float devicePixelRatio) static void glnvg__renderViewport(void* uptr, int width, int height, float devicePixelRatio)
{ {
NVG_NOTUSED(devicePixelRatio);
GLNVGcontext* gl = (GLNVGcontext*)uptr; GLNVGcontext* gl = (GLNVGcontext*)uptr;
gl->view[0] = (float)width; gl->view[0] = (float)width;
gl->view[1] = (float)height; gl->view[1] = (float)height;


+ 12
- 1
src/nanovg_gl_utils.h View File

@@ -90,7 +90,18 @@ NVGLUframebuffer* nvgluCreateFramebuffer(NVGcontext* ctx, int w, int h, int imag
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb->texture, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb->texture, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fb->rbo); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fb->rbo);


if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) goto error;
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
#ifdef GL_DEPTH24_STENCIL8
// If GL_STENCIL_INDEX8 is not supported, try GL_DEPTH24_STENCIL8 as a fallback.
// Some graphics cards require a depth buffer along with a stencil.
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, w, h);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb->texture, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fb->rbo);

if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
#endif // GL_DEPTH24_STENCIL8
goto error;
}


glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO); glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO);
glBindRenderbuffer(GL_RENDERBUFFER, defaultRBO); glBindRenderbuffer(GL_RENDERBUFFER, defaultRBO);


Loading…
Cancel
Save