Merge pull request #1590 from mchiasson/update_nanovg

upgraded nanovg to the latest.
This commit is contained in:
Бранимир Караџић 2018-12-27 20:42:05 -08:00 committed by GitHub
commit 4a49f14b5d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 246 additions and 82 deletions

View File

@ -518,6 +518,32 @@ void drawGraph(struct NVGcontext* vg, float x, float y, float w, float h, float
nvgStrokeWidth(vg, 1.0f); nvgStrokeWidth(vg, 1.0f);
} }
void drawSpinner(struct NVGcontext* vg, float cx, float cy, float r, float t)
{
float a0 = 0.0f + t*6;
float a1 = NVG_PI + t*6;
float r0 = r;
float r1 = r * 0.75f;
float ax,ay, bx,by;
struct NVGpaint paint;
nvgSave(vg);
nvgBeginPath(vg);
nvgArc(vg, cx,cy, r0, a0, a1, NVG_CW);
nvgArc(vg, cx,cy, r1, a1, a0, NVG_CCW);
nvgClosePath(vg);
ax = cx + cosf(a0) * (r0+r1)*0.5f;
ay = cy + sinf(a0) * (r0+r1)*0.5f;
bx = cx + cosf(a1) * (r0+r1)*0.5f;
by = cy + sinf(a1) * (r0+r1)*0.5f;
paint = nvgLinearGradient(vg, ax,ay, bx,by, nvgRGBA(0,0,0,0), nvgRGBA(0,0,0,128) );
nvgFillPaint(vg, paint);
nvgFill(vg);
nvgRestore(vg);
}
void drawThumbnails(struct NVGcontext* vg, float x, float y, float w, float h, const int* images, int nimages, float t) void drawThumbnails(struct NVGcontext* vg, float x, float y, float w, float h, const int* images, int nimages, float t)
{ {
float cornerRadius = 3.0f; float cornerRadius = 3.0f;
@ -529,7 +555,8 @@ void drawThumbnails(struct NVGcontext* vg, float x, float y, float w, float h, c
float stackh = (nimages/2) * (thumb+10) + 10; float stackh = (nimages/2) * (thumb+10) + 10;
int i; int i;
float u = (1+cosf(t*0.5f) )*0.5f; float u = (1+cosf(t*0.5f) )*0.5f;
float scrollh; float u2 = (1-cosf(t*0.2f) )*0.5f;
float scrollh, dv;
nvgSave(vg); nvgSave(vg);
// nvgClearState(vg); // nvgClearState(vg);
@ -556,8 +583,10 @@ void drawThumbnails(struct NVGcontext* vg, float x, float y, float w, float h, c
nvgScissor(vg, x,y,w,h); nvgScissor(vg, x,y,w,h);
nvgTranslate(vg, 0, -(stackh - h)*u); nvgTranslate(vg, 0, -(stackh - h)*u);
dv = 1.0f / (float)(nimages-1);
for (i = 0; i < nimages; i++) { for (i = 0; i < nimages; i++) {
float tx, ty; float tx, ty, v, a;
tx = x+10; tx = x+10;
ty = y+10; ty = y+10;
tx += (i%2) * (thumb+10); tx += (i%2) * (thumb+10);
@ -574,7 +603,14 @@ void drawThumbnails(struct NVGcontext* vg, float x, float y, float w, float h, c
ix = -(iw-thumb)*0.5f; ix = -(iw-thumb)*0.5f;
iy = 0; iy = 0;
} }
imgPaint = nvgImagePattern(vg, tx+ix, ty+iy, iw,ih, 0.0f/180.0f*NVG_PI, images[i], 1.0f);
v = i * dv;
a = bx::clamp((u2-v) / dv, 0.0f, 1.0f);
if (a < 1.0f)
drawSpinner(vg, tx+thumb/2,ty+thumb/2, thumb*0.25f, t);
imgPaint = nvgImagePattern(vg, tx+ix, ty+iy, iw,ih, 0.0f/180.0f*NVG_PI, images[i], a);
nvgBeginPath(vg); nvgBeginPath(vg);
nvgRoundedRect(vg, tx,ty, thumb,thumb, 5); nvgRoundedRect(vg, tx,ty, thumb,thumb, 5);
nvgFillPaint(vg, imgPaint); nvgFillPaint(vg, imgPaint);
@ -786,6 +822,7 @@ void drawLines(struct NVGcontext* vg, float x, float y, float w, float h, float
} }
} }
nvgRestore(vg); nvgRestore(vg);
} }
@ -939,7 +976,7 @@ void drawBlendish(struct NVGcontext* _vg, float _x, float _y, float _w, float _h
struct DemoData struct DemoData
{ {
int fontNormal, fontBold, fontIcons; int fontNormal, fontBold, fontIcons, fontEmoji;
int images[12]; int images[12];
}; };
@ -980,12 +1017,17 @@ int createImage(struct NVGcontext* _ctx, const char* _filePath, int _imageFlags)
int loadDemoData(struct NVGcontext* vg, struct DemoData* data) int loadDemoData(struct NVGcontext* vg, struct DemoData* data)
{ {
for (uint32_t ii = 0; ii < 12; ++ii) int i;
if (vg == NULL)
return -1;
for (i = 0; i < 12; i++)
{ {
char file[128]; char file[128];
bx::snprintf(file, 128, "images/image%d.jpg", ii+1); bx::snprintf(file, 128, "images/image%d.jpg", i+1);
data->images[ii] = createImage(vg, file, 0); data->images[i] = createImage(vg, file, 0);
if (data->images[ii] == 0) if (data->images[i] == 0)
{ {
printf("Could not load %s.\n", file); printf("Could not load %s.\n", file);
return -1; return -1;
@ -1013,6 +1055,15 @@ int loadDemoData(struct NVGcontext* vg, struct DemoData* data)
return -1; return -1;
} }
data->fontEmoji = nvgCreateFont(vg, "emoji", "font/NotoEmoji-Regular.ttf");
if (data->fontEmoji == -1)
{
printf("Could not add font emoji.\n");
return -1;
}
nvgAddFallbackFontId(vg, data->fontNormal, data->fontEmoji);
nvgAddFallbackFontId(vg, data->fontBold, data->fontEmoji);
return 0; return 0;
} }
@ -1031,13 +1082,14 @@ void drawParagraph(struct NVGcontext* vg, float x, float y, float width, float h
{ {
struct NVGtextRow rows[3]; struct NVGtextRow rows[3];
struct NVGglyphPosition glyphs[100]; struct NVGglyphPosition glyphs[100];
const char* text = "This is longer chunk of text.\n \n Would have used lorem ipsum but she was busy jumping over the lazy dog with the fox and all the men who came to the aid of the party."; const char* text = "This is longer chunk of text.\n \n Would have used lorem ipsum but she was busy jumping over the lazy dog with the fox and all the men who came to the aid of the party.🎉";
const char* start; const char* start;
const char* end; const char* end;
int nrows, i, nglyphs, j, lnum = 0; int nrows, i, nglyphs, j, lnum = 0;
float lineh; float lineh;
float caretx, px; float caretx, px;
float bounds[4]; float bounds[4];
float a;
float gx = 0.0f, gy = 0.0f; float gx = 0.0f, gy = 0.0f;
int gutter = 0; int gutter = 0;
NVG_NOTUSED(height); NVG_NOTUSED(height);
@ -1061,7 +1113,7 @@ void drawParagraph(struct NVGcontext* vg, float x, float y, float width, float h
int hit = mx > x && mx < (x+width) && my >= y && my < (y+lineh); int hit = mx > x && mx < (x+width) && my >= y && my < (y+lineh);
nvgBeginPath(vg); nvgBeginPath(vg);
nvgFillColor(vg, nvgRGBA(255,255,255,hit?64:8) ); nvgFillColor(vg, nvgRGBA(255,255,255,hit?64:16) );
nvgRect(vg, x, y, row->width, lineh); nvgRect(vg, x, y, row->width, lineh);
nvgFill(vg); nvgFill(vg);
@ -1127,6 +1179,14 @@ void drawParagraph(struct NVGcontext* vg, float x, float y, float width, float h
nvgTextLineHeight(vg, 1.2f); nvgTextLineHeight(vg, 1.2f);
nvgTextBoxBounds(vg, x,y, 150, "Hover your mouse over the text to see calculated caret position.", NULL, bounds); nvgTextBoxBounds(vg, x,y, 150, "Hover your mouse over the text to see calculated caret position.", NULL, bounds);
// Fade the tooltip out when close to it.
gx = bx::abs((mx - (bounds[0]+bounds[2])*0.5f) / (bounds[0] - bounds[2]) );
gy = bx::abs((my - (bounds[1]+bounds[3])*0.5f) / (bounds[1] - bounds[3]) );
a = bx::max(gx, gy) - 0.5f;
a = bx::clamp(a, 0.0f, 1.0f);
nvgGlobalAlpha(vg, a);
nvgBeginPath(vg); nvgBeginPath(vg);
nvgFillColor(vg, nvgRGBA(220,220,220,255) ); nvgFillColor(vg, nvgRGBA(220,220,220,255) );
nvgRoundedRect(vg nvgRoundedRect(vg
@ -1150,13 +1210,15 @@ void drawParagraph(struct NVGcontext* vg, float x, float y, float width, float h
void drawWidths(struct NVGcontext* vg, float x, float y, float width) void drawWidths(struct NVGcontext* vg, float x, float y, float width)
{ {
int i;
nvgSave(vg); nvgSave(vg);
nvgStrokeColor(vg, nvgRGBA(0,0,0,255) ); nvgStrokeColor(vg, nvgRGBA(0,0,0,255) );
for (uint32_t ii = 0; ii < 20; ++ii) for (i = 0; i < 20; i++)
{ {
float w = (ii+0.5f)*0.1f; float w = (i+0.5f)*0.1f;
nvgStrokeWidth(vg, w); nvgStrokeWidth(vg, w);
nvgBeginPath(vg); nvgBeginPath(vg);
nvgMoveTo(vg, x,y); nvgMoveTo(vg, x,y);
@ -1168,6 +1230,73 @@ void drawWidths(struct NVGcontext* vg, float x, float y, float width)
nvgRestore(vg); nvgRestore(vg);
} }
void drawCaps(struct NVGcontext* vg, float x, float y, float width)
{
int i;
int caps[3] = {NVG_BUTT, NVG_ROUND, NVG_SQUARE};
float lineWidth = 8.0f;
nvgSave(vg);
nvgBeginPath(vg);
nvgRect(vg, x-lineWidth/2, y, width+lineWidth, 40);
nvgFillColor(vg, nvgRGBA(255,255,255,32) );
nvgFill(vg);
nvgBeginPath(vg);
nvgRect(vg, x, y, width, 40);
nvgFillColor(vg, nvgRGBA(255,255,255,32) );
nvgFill(vg);
nvgStrokeWidth(vg, lineWidth);
for (i = 0; i < 3; i++) {
nvgLineCap(vg, caps[i]);
nvgStrokeColor(vg, nvgRGBA(0,0,0,255) );
nvgBeginPath(vg);
nvgMoveTo(vg, x, y + i*10 + 5);
nvgLineTo(vg, x+width, y + i*10 + 5);
nvgStroke(vg);
}
nvgRestore(vg);
}
void drawScissor(struct NVGcontext* vg, float x, float y, float t)
{
nvgSave(vg);
// Draw first rect and set scissor to it's area.
nvgTranslate(vg, x, y);
nvgRotate(vg, nvgDegToRad(5) );
nvgBeginPath(vg);
nvgRect(vg, -20,-20,60,40);
nvgFillColor(vg, nvgRGBA(255,0,0,255) );
nvgFill(vg);
nvgScissor(vg, -20,-20,60,40);
// Draw second rectangle with offset and rotation.
nvgTranslate(vg, 40,0);
nvgRotate(vg, t);
// Draw the intended second rectangle without any scissoring.
nvgSave(vg);
nvgResetScissor(vg);
nvgBeginPath(vg);
nvgRect(vg, -20,-10,60,30);
nvgFillColor(vg, nvgRGBA(255,128,0,64) );
nvgFill(vg);
nvgRestore(vg);
// Draw second rectangle with combined scissoring.
nvgIntersectScissor(vg, -20,-10,60,30);
nvgBeginPath(vg);
nvgRect(vg, -20,-10,60,30);
nvgFillColor(vg, nvgRGBA(255,128,0,255) );
nvgFill(vg);
nvgRestore(vg);
}
void renderDemo(struct NVGcontext* vg, float mx, float my, float width, float height, float t, int blowup, struct DemoData* data) void renderDemo(struct NVGcontext* vg, float mx, float my, float width, float height, float t, int blowup, struct DemoData* data)
{ {
float x,y,popx,popy; float x,y,popx,popy;
@ -1181,6 +1310,14 @@ void renderDemo(struct NVGcontext* vg, float mx, float my, float width, float he
// Line joints // Line joints
drawLines(vg, 50, height-50, 600, 35, t); drawLines(vg, 50, height-50, 600, 35, t);
// Line caps
drawWidths(vg, width-50, 35, 30);
// Line caps
drawCaps(vg, width-50, 260, 30);
drawScissor(vg, 40, height-150, t);
nvgSave(vg); nvgSave(vg);
if (blowup) if (blowup)
{ {
@ -1188,9 +1325,6 @@ void renderDemo(struct NVGcontext* vg, float mx, float my, float width, float he
nvgScale(vg, 2.0f, 2.0f); nvgScale(vg, 2.0f, 2.0f);
} }
// Line width.
drawWidths(vg, width-50, 35, 30);
// Widgets. // Widgets.
x = width-520; y = height-420; x = width-520; y = height-420;
drawWindow(vg, "Widgets `n Stuff", x, y, 300, 400); drawWindow(vg, "Widgets `n Stuff", x, y, 300, 400);
@ -1325,7 +1459,7 @@ public:
// if no other draw calls are submitted to view 0. // if no other draw calls are submitted to view 0.
bgfx::touch(0); bgfx::touch(0);
nvgBeginFrame(m_nvg, m_width, m_height, 1.0f); nvgBeginFrame(m_nvg, float(m_width), float(m_height), 1.0f);
renderDemo(m_nvg, float(m_mouseState.m_mx), float(m_mouseState.m_my), float(m_width), float(m_height), time, 0, &m_data); renderDemo(m_nvg, float(m_mouseState.m_mx), float(m_mouseState.m_my), float(m_width), float(m_height), time, 0, &m_data);

View File

@ -89,7 +89,7 @@ typedef struct FONStextIter FONStextIter;
typedef struct FONScontext FONScontext; typedef struct FONScontext FONScontext;
// Contructor and destructor. // Constructor and destructor.
FONScontext* fonsCreateInternal(FONSparams* params); FONScontext* fonsCreateInternal(FONSparams* params);
void fonsDeleteInternal(FONScontext* s); void fonsDeleteInternal(FONScontext* s);
@ -98,7 +98,7 @@ void fonsSetErrorCallback(FONScontext* s, void (*callback)(void* uptr, int error
void fonsGetAtlasSize(FONScontext* s, int* width, int* height); void fonsGetAtlasSize(FONScontext* s, int* width, int* height);
// Expands the atlas size. // Expands the atlas size.
int fonsExpandAtlas(FONScontext* s, int width, int height); int fonsExpandAtlas(FONScontext* s, int width, int height);
// Reseta the whole stash. // Resets the whole stash.
int fonsResetAtlas(FONScontext* stash, int width, int height); int fonsResetAtlas(FONScontext* stash, int width, int height);
// Add fonts // Add fonts
@ -162,11 +162,19 @@ static FT_Library ftLibrary;
int fons__tt_init(FONScontext *context) int fons__tt_init(FONScontext *context)
{ {
FT_Error ftError; FT_Error ftError;
FONS_NOTUSED(context); FONS_NOTUSED(context);
ftError = FT_Init_FreeType(&ftLibrary); ftError = FT_Init_FreeType(&ftLibrary);
return ftError == 0; return ftError == 0;
} }
int fons__tt_done(FONScontext *context)
{
FT_Error ftError;
FONS_NOTUSED(context);
ftError = FT_Done_FreeType(ftLibrary);
return ftError == 0;
}
int fons__tt_loadFont(FONScontext *context, FONSttFontImpl *font, unsigned char *data, int dataSize) int fons__tt_loadFont(FONScontext *context, FONSttFontImpl *font, unsigned char *data, int dataSize)
{ {
FT_Error ftError; FT_Error ftError;
@ -204,7 +212,7 @@ int fons__tt_buildGlyphBitmap(FONSttFontImpl *font, int glyph, float size, float
ftError = FT_Set_Pixel_Sizes(font->font, 0, (FT_UInt)(size * (float)font->font->units_per_EM / (float)(font->font->ascender - font->font->descender))); 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; if (ftError) return 0;
ftError = FT_Load_Glyph(font->font, glyph, FT_LOAD_RENDER); ftError = FT_Load_Glyph(font->font, glyph, FT_LOAD_RENDER | FT_LOAD_FORCE_AUTOHINT);
if (ftError) return 0; if (ftError) return 0;
ftError = FT_Get_Advance(font->font, glyph, FT_LOAD_NO_SCALE, &advFixed); ftError = FT_Get_Advance(font->font, glyph, FT_LOAD_NO_SCALE, &advFixed);
if (ftError) return 0; if (ftError) return 0;
@ -271,6 +279,12 @@ int fons__tt_init(FONScontext *context)
return 1; return 1;
} }
int fons__tt_done(FONScontext *context)
{
FONS_NOTUSED(context);
return 1;
}
int fons__tt_loadFont(FONScontext *context, FONSttFontImpl *font, unsigned char *data, int dataSize) int fons__tt_loadFont(FONScontext *context, FONSttFontImpl *font, unsigned char *data, int dataSize)
{ {
int stbError; int stbError;
@ -319,7 +333,7 @@ int fons__tt_getGlyphKernAdvance(FONSttFontImpl *font, int glyph1, int glyph2)
#endif #endif
#ifndef FONS_SCRATCH_BUF_SIZE #ifndef FONS_SCRATCH_BUF_SIZE
# define FONS_SCRATCH_BUF_SIZE 64000 # define FONS_SCRATCH_BUF_SIZE 96000
#endif #endif
#ifndef FONS_HASH_LUT_SIZE #ifndef FONS_HASH_LUT_SIZE
# define FONS_HASH_LUT_SIZE 256 # define FONS_HASH_LUT_SIZE 256
@ -406,7 +420,7 @@ struct FONSstate
typedef struct FONSstate FONSstate; typedef struct FONSstate FONSstate;
struct FONSatlasNode { struct FONSatlasNode {
short x, y, width; short x, y, width;
}; };
typedef struct FONSatlasNode FONSatlasNode; typedef struct FONSatlasNode FONSatlasNode;
@ -497,11 +511,11 @@ static unsigned int fons__decutf8(unsigned int* state, unsigned int* codep, unsi
12,12,12,12,12,12,12,24,12,12,12,12, 12,24,12,12,12,12,12,12,12,24,12,12, 12,12,12,12,12,12,12,24,12,12,12,12, 12,24,12,12,12,12,12,12,12,24,12,12,
12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12, 12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12,
12,36,12,12,12,12,12,12,12,12,12,12, 12,36,12,12,12,12,12,12,12,12,12,12,
}; };
unsigned int type = utf8d[byte]; unsigned int type = utf8d[byte];
*codep = (*state != FONS_UTF8_ACCEPT) ? *codep = (*state != FONS_UTF8_ACCEPT) ?
(byte & 0x3fu) | (*codep << 6) : (byte & 0x3fu) | (*codep << 6) :
(0xff >> type) & (byte); (0xff >> type) & (byte);
@ -886,7 +900,7 @@ 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;
size_t dataSize = 0; int dataSize = 0;
size_t readed; size_t readed;
unsigned char* data = NULL; unsigned char* data = NULL;
@ -894,16 +908,16 @@ int fonsAddFont(FONScontext* stash, const char* name, const char* path)
fp = fopen(path, "rb"); fp = fopen(path, "rb");
if (fp == NULL) goto error; if (fp == NULL) goto error;
fseek(fp,0,SEEK_END); fseek(fp,0,SEEK_END);
dataSize = ftell(fp); dataSize = (int)ftell(fp);
fseek(fp,0,SEEK_SET); fseek(fp,0,SEEK_SET);
data = (unsigned char*)malloc(dataSize); data = (unsigned char*)malloc(dataSize);
if (data == NULL) goto error; if (data == NULL) goto error;
readed = fread(data, 1, dataSize, fp); readed = fread(data, 1, dataSize, fp);
fclose(fp); fclose(fp);
fp = 0; fp = 0;
if (readed != dataSize) goto error; if ((int)readed != dataSize) goto error;
return fonsAddFontMem(stash, name, data, int(dataSize), 1); return fonsAddFontMem(stash, name, data, dataSize, 1);
error: error:
if (data) free(data); if (data) free(data);
@ -1637,6 +1651,7 @@ void fonsDeleteInternal(FONScontext* stash)
if (stash->texData) free(stash->texData); if (stash->texData) free(stash->texData);
if (stash->scratch) free(stash->scratch); if (stash->scratch) free(stash->scratch);
free(stash); free(stash);
fons__tt_done(stash);
} }
void fonsSetErrorCallback(FONScontext* stash, void (*callback)(void* uptr, int error, int val), void* uptr) void fonsSetErrorCallback(FONScontext* stash, void (*callback)(void* uptr, int error, int val), void* uptr)

View File

@ -347,7 +347,7 @@ error:
NVGparams* nvgInternalParams(NVGcontext* ctx) NVGparams* nvgInternalParams(NVGcontext* ctx)
{ {
return &ctx->params; return &ctx->params;
} }
void nvgDeleteInternal(NVGcontext* ctx) void nvgDeleteInternal(NVGcontext* ctx)
@ -373,7 +373,7 @@ void nvgDeleteInternal(NVGcontext* ctx)
free(ctx); free(ctx);
} }
void nvgBeginFrame(NVGcontext* ctx, int windowWidth, int windowHeight, float devicePixelRatio) void nvgBeginFrame(NVGcontext* ctx, float windowWidth, float windowHeight, float devicePixelRatio)
{ {
/* printf("Tris: draws:%d fill:%d stroke:%d text:%d TOT:%d\n", /* printf("Tris: draws:%d fill:%d stroke:%d text:%d TOT:%d\n",
ctx->drawCallCount, ctx->fillTriCount, ctx->strokeTriCount, ctx->textTriCount, ctx->drawCallCount, ctx->fillTriCount, ctx->strokeTriCount, ctx->textTriCount,
@ -1421,7 +1421,8 @@ static void nvg__chooseBevel(int bevel, NVGpoint* p0, NVGpoint* p1, float w,
} }
static NVGvertex* nvg__roundJoin(NVGvertex* dst, NVGpoint* p0, NVGpoint* p1, static NVGvertex* nvg__roundJoin(NVGvertex* dst, NVGpoint* p0, NVGpoint* p1,
float lw, float rw, float lu, float ru, int ncap, float fringe) float lw, float rw, float lu, float ru, int ncap,
float fringe)
{ {
int i, n; int i, n;
float dlx0 = p0->dy; float dlx0 = p0->dy;
@ -1554,36 +1555,39 @@ static NVGvertex* nvg__bevelJoin(NVGvertex* dst, NVGpoint* p0, NVGpoint* p1,
} }
static NVGvertex* nvg__buttCapStart(NVGvertex* dst, NVGpoint* p, static NVGvertex* nvg__buttCapStart(NVGvertex* dst, NVGpoint* p,
float dx, float dy, float w, float d, float aa) float dx, float dy, float w, float d,
float aa, float u0, float u1)
{ {
float px = p->x - dx*d; float px = p->x - dx*d;
float py = p->y - dy*d; float py = p->y - dy*d;
float dlx = dy; float dlx = dy;
float dly = -dx; float dly = -dx;
nvg__vset(dst, px + dlx*w - dx*aa, py + dly*w - dy*aa, 0,0); dst++; nvg__vset(dst, px + dlx*w - dx*aa, py + dly*w - dy*aa, u0,0); dst++;
nvg__vset(dst, px - dlx*w - dx*aa, py - dly*w - dy*aa, 1,0); dst++; nvg__vset(dst, px - dlx*w - dx*aa, py - dly*w - dy*aa, u1,0); dst++;
nvg__vset(dst, px + dlx*w, py + dly*w, 0,1); dst++; nvg__vset(dst, px + dlx*w, py + dly*w, u0,1); dst++;
nvg__vset(dst, px - dlx*w, py - dly*w, 1,1); dst++; nvg__vset(dst, px - dlx*w, py - dly*w, u1,1); dst++;
return dst; return dst;
} }
static NVGvertex* nvg__buttCapEnd(NVGvertex* dst, NVGpoint* p, static NVGvertex* nvg__buttCapEnd(NVGvertex* dst, NVGpoint* p,
float dx, float dy, float w, float d, float aa) float dx, float dy, float w, float d,
float aa, float u0, float u1)
{ {
float px = p->x + dx*d; float px = p->x + dx*d;
float py = p->y + dy*d; float py = p->y + dy*d;
float dlx = dy; float dlx = dy;
float dly = -dx; float dly = -dx;
nvg__vset(dst, px + dlx*w, py + dly*w, 0,1); dst++; nvg__vset(dst, px + dlx*w, py + dly*w, u0,1); dst++;
nvg__vset(dst, px - dlx*w, py - dly*w, 1,1); dst++; nvg__vset(dst, px - dlx*w, py - dly*w, u1,1); dst++;
nvg__vset(dst, px + dlx*w + dx*aa, py + dly*w + dy*aa, 0,0); dst++; nvg__vset(dst, px + dlx*w + dx*aa, py + dly*w + dy*aa, u0,0); dst++;
nvg__vset(dst, px - dlx*w + dx*aa, py - dly*w + dy*aa, 1,0); dst++; nvg__vset(dst, px - dlx*w + dx*aa, py - dly*w + dy*aa, u1,0); dst++;
return dst; return dst;
} }
static NVGvertex* nvg__roundCapStart(NVGvertex* dst, NVGpoint* p, static NVGvertex* nvg__roundCapStart(NVGvertex* dst, NVGpoint* p,
float dx, float dy, float w, int ncap, float aa) float dx, float dy, float w, int ncap,
float aa, float u0, float u1)
{ {
int i; int i;
float px = p->x; float px = p->x;
@ -1594,16 +1598,17 @@ static NVGvertex* nvg__roundCapStart(NVGvertex* dst, NVGpoint* p,
for (i = 0; i < ncap; i++) { for (i = 0; i < ncap; i++) {
float a = i/(float)(ncap-1)*NVG_PI; float a = i/(float)(ncap-1)*NVG_PI;
float ax = cosf(a) * w, ay = sinf(a) * w; float ax = cosf(a) * w, ay = sinf(a) * w;
nvg__vset(dst, px - dlx*ax - dx*ay, py - dly*ax - dy*ay, 0,1); dst++; nvg__vset(dst, px - dlx*ax - dx*ay, py - dly*ax - dy*ay, u0,1); dst++;
nvg__vset(dst, px, py, 0.5f,1); dst++; nvg__vset(dst, px, py, 0.5f,1); dst++;
} }
nvg__vset(dst, px + dlx*w, py + dly*w, 0,1); dst++; nvg__vset(dst, px + dlx*w, py + dly*w, u0,1); dst++;
nvg__vset(dst, px - dlx*w, py - dly*w, 1,1); dst++; nvg__vset(dst, px - dlx*w, py - dly*w, u1,1); dst++;
return dst; return dst;
} }
static NVGvertex* nvg__roundCapEnd(NVGvertex* dst, NVGpoint* p, static NVGvertex* nvg__roundCapEnd(NVGvertex* dst, NVGpoint* p,
float dx, float dy, float w, int ncap, float aa) float dx, float dy, float w, int ncap,
float aa, float u0, float u1)
{ {
int i; int i;
float px = p->x; float px = p->x;
@ -1611,13 +1616,13 @@ static NVGvertex* nvg__roundCapEnd(NVGvertex* dst, NVGpoint* p,
float dlx = dy; float dlx = dy;
float dly = -dx; float dly = -dx;
NVG_NOTUSED(aa); NVG_NOTUSED(aa);
nvg__vset(dst, px + dlx*w, py + dly*w, 0,1); dst++; nvg__vset(dst, px + dlx*w, py + dly*w, u0,1); dst++;
nvg__vset(dst, px - dlx*w, py - dly*w, 1,1); dst++; nvg__vset(dst, px - dlx*w, py - dly*w, u1,1); dst++;
for (i = 0; i < ncap; i++) { for (i = 0; i < ncap; i++) {
float a = i/(float)(ncap-1)*NVG_PI; float a = i/(float)(ncap-1)*NVG_PI;
float ax = cosf(a) * w, ay = sinf(a) * w; float ax = cosf(a) * w, ay = sinf(a) * w;
nvg__vset(dst, px, py, 0.5f,1); dst++; nvg__vset(dst, px, py, 0.5f,1); dst++;
nvg__vset(dst, px - dlx*ax + dx*ay, py - dly*ax + dy*ay, 0,1); dst++; nvg__vset(dst, px - dlx*ax + dx*ay, py - dly*ax + dy*ay, u0,1); dst++;
} }
return dst; return dst;
} }
@ -1693,15 +1698,24 @@ static void nvg__calculateJoins(NVGcontext* ctx, float w, int lineJoin, float mi
} }
static int nvg__expandStroke(NVGcontext* ctx, float w, int lineCap, int lineJoin, float miterLimit) static int nvg__expandStroke(NVGcontext* ctx, float w, float fringe, int lineCap, int lineJoin, float miterLimit)
{ {
NVGpathCache* cache = ctx->cache; NVGpathCache* cache = ctx->cache;
NVGvertex* verts; NVGvertex* verts;
NVGvertex* dst; NVGvertex* dst;
int cverts, i, j; int cverts, i, j;
float aa = ctx->fringeWidth; float aa = fringe;//ctx->fringeWidth;
float u0 = 0.0f, u1 = 1.0f;
int ncap = nvg__curveDivs(w, NVG_PI, ctx->tessTol); // Calculate divisions per half circle. int ncap = nvg__curveDivs(w, NVG_PI, ctx->tessTol); // Calculate divisions per half circle.
w += aa * 0.5f;
// Disable the gradient used for antialiasing when antialiasing is not used.
if (aa == 0.0f) {
u0 = 0.5f;
u1 = 0.5f;
}
nvg__calculateJoins(ctx, w, lineJoin, miterLimit); nvg__calculateJoins(ctx, w, lineJoin, miterLimit);
// Calculate max vertex usage. // Calculate max vertex usage.
@ -1762,42 +1776,42 @@ static int nvg__expandStroke(NVGcontext* ctx, float w, int lineCap, int lineJoin
dy = p1->y - p0->y; dy = p1->y - p0->y;
nvg__normalize(&dx, &dy); nvg__normalize(&dx, &dy);
if (lineCap == NVG_BUTT) if (lineCap == NVG_BUTT)
dst = nvg__buttCapStart(dst, p0, dx, dy, w, -aa*0.5f, aa); dst = nvg__buttCapStart(dst, p0, dx, dy, w, -aa*0.5f, aa, u0, u1);
else if (lineCap == NVG_BUTT || lineCap == NVG_SQUARE) else if (lineCap == NVG_BUTT || lineCap == NVG_SQUARE)
dst = nvg__buttCapStart(dst, p0, dx, dy, w, w-aa, aa); dst = nvg__buttCapStart(dst, p0, dx, dy, w, w-aa, aa, u0, u1);
else if (lineCap == NVG_ROUND) else if (lineCap == NVG_ROUND)
dst = nvg__roundCapStart(dst, p0, dx, dy, w, ncap, aa); dst = nvg__roundCapStart(dst, p0, dx, dy, w, ncap, aa, u0, u1);
} }
for (j = s; j < e; ++j) { for (j = s; j < e; ++j) {
if ((p1->flags & (NVG_PT_BEVEL | NVG_PR_INNERBEVEL)) != 0) { if ((p1->flags & (NVG_PT_BEVEL | NVG_PR_INNERBEVEL)) != 0) {
if (lineJoin == NVG_ROUND) { if (lineJoin == NVG_ROUND) {
dst = nvg__roundJoin(dst, p0, p1, w, w, 0, 1, ncap, aa); dst = nvg__roundJoin(dst, p0, p1, w, w, u0, u1, ncap, aa);
} else { } else {
dst = nvg__bevelJoin(dst, p0, p1, w, w, 0, 1, aa); dst = nvg__bevelJoin(dst, p0, p1, w, w, u0, u1, aa);
} }
} else { } else {
nvg__vset(dst, p1->x + (p1->dmx * w), p1->y + (p1->dmy * w), 0,1); dst++; nvg__vset(dst, p1->x + (p1->dmx * w), p1->y + (p1->dmy * w), u0,1); dst++;
nvg__vset(dst, p1->x - (p1->dmx * w), p1->y - (p1->dmy * w), 1,1); dst++; nvg__vset(dst, p1->x - (p1->dmx * w), p1->y - (p1->dmy * w), u1,1); dst++;
} }
p0 = p1++; p0 = p1++;
} }
if (loop) { if (loop) {
// Loop it // Loop it
nvg__vset(dst, verts[0].x, verts[0].y, 0,1); dst++; nvg__vset(dst, verts[0].x, verts[0].y, u0,1); dst++;
nvg__vset(dst, verts[1].x, verts[1].y, 1,1); dst++; nvg__vset(dst, verts[1].x, verts[1].y, u1,1); dst++;
} else { } else {
// Add cap // Add cap
dx = p1->x - p0->x; dx = p1->x - p0->x;
dy = p1->y - p0->y; dy = p1->y - p0->y;
nvg__normalize(&dx, &dy); nvg__normalize(&dx, &dy);
if (lineCap == NVG_BUTT) if (lineCap == NVG_BUTT)
dst = nvg__buttCapEnd(dst, p1, dx, dy, w, -aa*0.5f, aa); dst = nvg__buttCapEnd(dst, p1, dx, dy, w, -aa*0.5f, aa, u0, u1);
else if (lineCap == NVG_BUTT || lineCap == NVG_SQUARE) else if (lineCap == NVG_BUTT || lineCap == NVG_SQUARE)
dst = nvg__buttCapEnd(dst, p1, dx, dy, w, w-aa, aa); dst = nvg__buttCapEnd(dst, p1, dx, dy, w, w-aa, aa, u0, u1);
else if (lineCap == NVG_ROUND) else if (lineCap == NVG_ROUND)
dst = nvg__roundCapEnd(dst, p1, dx, dy, w, ncap, aa); dst = nvg__roundCapEnd(dst, p1, dx, dy, w, ncap, aa, u0, u1);
} }
path->nstroke = (int)(dst - verts); path->nstroke = (int)(dst - verts);
@ -1956,13 +1970,13 @@ void nvgBezierTo(NVGcontext* ctx, float c1x, float c1y, float c2x, float c2y, fl
void nvgQuadTo(NVGcontext* ctx, float cx, float cy, float x, float y) void nvgQuadTo(NVGcontext* ctx, float cx, float cy, float x, float y)
{ {
float x0 = ctx->commandx; float x0 = ctx->commandx;
float y0 = ctx->commandy; float y0 = ctx->commandy;
float vals[] = { NVG_BEZIERTO, float vals[] = { NVG_BEZIERTO,
x0 + 2.0f/3.0f*(cx - x0), y0 + 2.0f/3.0f*(cy - y0), x0 + 2.0f/3.0f*(cx - x0), y0 + 2.0f/3.0f*(cy - y0),
x + 2.0f/3.0f*(cx - x), y + 2.0f/3.0f*(cy - y), x + 2.0f/3.0f*(cx - x), y + 2.0f/3.0f*(cy - y),
x, y }; x, y };
nvg__appendCommands(ctx, vals, NVG_COUNTOF(vals)); nvg__appendCommands(ctx, vals, NVG_COUNTOF(vals));
} }
void nvgArcTo(NVGcontext* ctx, float x1, float y1, float x2, float y2, float radius) void nvgArcTo(NVGcontext* ctx, float x1, float y1, float x2, float y2, float radius)
@ -2221,6 +2235,7 @@ void nvgStroke(NVGcontext* ctx)
const NVGpath* path; const NVGpath* path;
int i; int i;
if (strokeWidth < ctx->fringeWidth) { if (strokeWidth < ctx->fringeWidth) {
// If the stroke width is less than pixel size, use alpha to emulate coverage. // If the stroke width is less than pixel size, use alpha to emulate coverage.
// Since coverage is area, scale by alpha*alpha. // Since coverage is area, scale by alpha*alpha.
@ -2237,9 +2252,9 @@ void nvgStroke(NVGcontext* ctx)
nvg__flattenPaths(ctx); nvg__flattenPaths(ctx);
if (ctx->params.edgeAntiAlias && state->shapeAntiAlias) if (ctx->params.edgeAntiAlias && state->shapeAntiAlias)
nvg__expandStroke(ctx, strokeWidth*0.5f + ctx->fringeWidth*0.5f, state->lineCap, state->lineJoin, state->miterLimit); nvg__expandStroke(ctx, strokeWidth*0.5f, ctx->fringeWidth, state->lineCap, state->lineJoin, state->miterLimit);
else else
nvg__expandStroke(ctx, strokeWidth*0.5f, state->lineCap, state->lineJoin, state->miterLimit); nvg__expandStroke(ctx, strokeWidth*0.5f, 0.0f, state->lineCap, state->lineJoin, state->miterLimit);
ctx->params.renderStroke(ctx->params.userPtr, &strokePaint, state->compositeOperation, &state->scissor, ctx->fringeWidth, ctx->params.renderStroke(ctx->params.userPtr, &strokePaint, state->compositeOperation, &state->scissor, ctx->fringeWidth,
strokeWidth, ctx->cache->paths, ctx->cache->npaths); strokeWidth, ctx->cache->paths, ctx->cache->npaths);
@ -2426,12 +2441,12 @@ float nvgText(NVGcontext* ctx, float x, float y, const char* string, const char*
while (fonsTextIterNext(ctx->fs, &iter, &q)) { while (fonsTextIterNext(ctx->fs, &iter, &q)) {
float c[4*2]; float c[4*2];
if (iter.prevGlyphIndex == -1) { // can not retrieve glyph? if (iter.prevGlyphIndex == -1) { // can not retrieve glyph?
if (!nvg__allocTextAtlas(ctx))
break; // no memory :(
if (nverts != 0) { if (nverts != 0) {
nvg__renderText(ctx, verts, nverts); nvg__renderText(ctx, verts, nverts);
nverts = 0; nverts = 0;
} }
if (!nvg__allocTextAtlas(ctx))
break; // no memory :(
iter = prevIter; iter = prevIter;
fonsTextIterNext(ctx->fs, &iter, &q); // try again fonsTextIterNext(ctx->fs, &iter, &q); // try again
if (iter.prevGlyphIndex == -1) // still can not find glyph? if (iter.prevGlyphIndex == -1) // still can not find glyph?

View File

@ -138,7 +138,7 @@ struct NVGtextRow {
typedef struct NVGtextRow NVGtextRow; typedef struct NVGtextRow NVGtextRow;
enum NVGimageFlags { enum NVGimageFlags {
NVG_IMAGE_GENERATE_MIPMAPS = 1<<0, // Generate mipmaps during creation of the image. NVG_IMAGE_GENERATE_MIPMAPS = 1<<0, // Generate mipmaps during creation of the image.
NVG_IMAGE_REPEATX = 1<<1, // Repeat image in X direction. NVG_IMAGE_REPEATX = 1<<1, // Repeat image in X direction.
NVG_IMAGE_REPEATY = 1<<2, // Repeat image in Y direction. NVG_IMAGE_REPEATY = 1<<2, // Repeat image in Y direction.
NVG_IMAGE_FLIPY = 1<<3, // Flips (inverses) image in Y direction when rendered. NVG_IMAGE_FLIPY = 1<<3, // Flips (inverses) image in Y direction when rendered.
@ -154,7 +154,7 @@ enum NVGimageFlags {
// For example, GLFW returns two dimension for an opened window: window size and // For example, GLFW returns two dimension for an opened window: window size and
// frame buffer size. In that case you would set windowWidth/Height to the window size // frame buffer size. In that case you would set windowWidth/Height to the window size
// devicePixelRatio to: frameBufferWidth / windowWidth. // devicePixelRatio to: frameBufferWidth / windowWidth.
void nvgBeginFrame(NVGcontext* ctx, int windowWidth, int windowHeight, float devicePixelRatio); void nvgBeginFrame(NVGcontext* ctx, float windowWidth, float windowHeight, float devicePixelRatio);
// Cancels drawing the current frame. // Cancels drawing the current frame.
void nvgCancelFrame(NVGcontext* ctx); void nvgCancelFrame(NVGcontext* ctx);
@ -271,7 +271,7 @@ void nvgLineCap(NVGcontext* ctx, int cap);
void nvgLineJoin(NVGcontext* ctx, int join); void nvgLineJoin(NVGcontext* ctx, int join);
// Sets the transparency applied to all rendered shapes. // Sets the transparency applied to all rendered shapes.
// Alreade transparent paths will get proportionally more transparent as well. // Already transparent paths will get proportionally more transparent as well.
void nvgGlobalAlpha(NVGcontext* ctx, float alpha); void nvgGlobalAlpha(NVGcontext* ctx, float alpha);
// //
@ -395,7 +395,7 @@ NVGpaint nvgLinearGradient(NVGcontext* ctx, float sx, float sy, float ex, float
NVGcolor icol, NVGcolor ocol); NVGcolor icol, NVGcolor ocol);
// Creates and returns a box gradient. Box gradient is a feathered rounded rectangle, it is useful for rendering // Creates and returns a box gradient. Box gradient is a feathered rounded rectangle, it is useful for rendering
// drop shadows or hilights for boxes. Parameters (x,y) define the top-left corner of the rectangle, // drop shadows or highlights for boxes. Parameters (x,y) define the top-left corner of the rectangle,
// (w,h) define the size of the rectangle, r defines the corner radius, and f feather. Feather defines how blurry // (w,h) define the size of the rectangle, r defines the corner radius, and f feather. Feather defines how blurry
// the border of the rectangle is. Parameter icol specifies the inner color and ocol the outer color of the gradient. // the border of the rectangle is. Parameter icol specifies the inner color and ocol the outer color of the gradient.
// The gradient is transformed by the current transform when it is passed to nvgFillPaint() or nvgStrokePaint(). // The gradient is transformed by the current transform when it is passed to nvgFillPaint() or nvgStrokePaint().
@ -647,7 +647,7 @@ struct NVGparams {
int (*renderDeleteTexture)(void* uptr, int image); int (*renderDeleteTexture)(void* uptr, int image);
int (*renderUpdateTexture)(void* uptr, int image, int x, int y, int w, int h, const unsigned char* data); int (*renderUpdateTexture)(void* uptr, int image, int x, int y, int w, int h, const unsigned char* data);
int (*renderGetTextureSize)(void* uptr, int image, int* w, int* h); int (*renderGetTextureSize)(void* uptr, int image, int* w, int* h);
void (*renderViewport)(void* uptr, int width, int height, float devicePixelRatio); void (*renderViewport)(void* uptr, float width, float height, float devicePixelRatio);
void (*renderCancel)(void* uptr); void (*renderCancel)(void* uptr);
void (*renderFlush)(void* uptr); void (*renderFlush)(void* uptr);
void (*renderFill)(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, float fringe, const float* bounds, const NVGpath* paths, int npaths); void (*renderFill)(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, float fringe, const float* bounds, const NVGpath* paths, int npaths);

View File

@ -554,11 +554,11 @@ namespace
gl->th = handle; gl->th = handle;
} }
static void nvgRenderViewport(void* _userPtr, int width, int height, float devicePixelRatio) static void nvgRenderViewport(void* _userPtr, float width, float height, float devicePixelRatio)
{ {
struct GLNVGcontext* gl = (struct GLNVGcontext*)_userPtr; struct GLNVGcontext* gl = (struct GLNVGcontext*)_userPtr;
gl->view[0] = (float)width; gl->view[0] = width;
gl->view[1] = (float)height; gl->view[1] = height;
bgfx::setViewRect(gl->viewId, 0, 0, width * devicePixelRatio, height * devicePixelRatio); bgfx::setViewRect(gl->viewId, 0, 0, width * devicePixelRatio, height * devicePixelRatio);
} }

Binary file not shown.