@@ -0,0 +1,28 @@ | |||||
name: CI | |||||
on: [push] | |||||
env: | |||||
BUILD_TYPE: release | |||||
jobs: | |||||
build: | |||||
runs-on: ${{ matrix.os }} | |||||
strategy: | |||||
matrix: | |||||
os: [ ubuntu-latest] | |||||
steps: | |||||
- uses: actions/checkout@v2 | |||||
- name: Install required packages | |||||
run: sudo apt-get install premake4 build-essential libglfw3-dev libglew-dev pkg-config | |||||
- name: Premake | |||||
run: premake4 gmake | |||||
# due to glew problems with in the current ubuntu-latest, we don't build the examples (yet) | |||||
# https://github.com/openai/mujoco-py/issues/383 has the same problem for reference | |||||
# this doesn't happen in focal | |||||
- name: Make | |||||
run: cd build && make nanovg |
@@ -25,7 +25,7 @@ | |||||
#define ICON_TRASH 0xE729 | #define ICON_TRASH 0xE729 | ||||
//static float minf(float a, float b) { return a < b ? a : b; } | //static float minf(float a, float b) { return a < b ? a : b; } | ||||
static float maxf(float a, float b) { return a > b ? a : b; } | |||||
//static float maxf(float a, float b) { return a > b ? a : b; } | |||||
//static float absf(float a) { return a >= 0.0f ? a : -a; } | //static float absf(float a) { return a >= 0.0f ? a : -a; } | ||||
static float clampf(float a, float mn, float mx) { return a < mn ? mn : (a > mx ? mx : a); } | static float clampf(float a, float mn, float mx) { return a < mn ? mn : (a > mx ? mx : a); } | ||||
@@ -98,7 +98,7 @@ void drawWindow(NVGcontext* vg, const char* title, float x, float y, float w, fl | |||||
nvgStrokeColor(vg, nvgRGBA(0,0,0,32)); | nvgStrokeColor(vg, nvgRGBA(0,0,0,32)); | ||||
nvgStroke(vg); | nvgStroke(vg); | ||||
nvgFontSize(vg, 18.0f); | |||||
nvgFontSize(vg, 15.0f); | |||||
nvgFontFace(vg, "sans-bold"); | nvgFontFace(vg, "sans-bold"); | ||||
nvgTextAlign(vg,NVG_ALIGN_CENTER|NVG_ALIGN_MIDDLE); | nvgTextAlign(vg,NVG_ALIGN_CENTER|NVG_ALIGN_MIDDLE); | ||||
@@ -137,7 +137,7 @@ void drawSearchBox(NVGcontext* vg, const char* text, float x, float y, float w, | |||||
nvgTextAlign(vg,NVG_ALIGN_CENTER|NVG_ALIGN_MIDDLE); | nvgTextAlign(vg,NVG_ALIGN_CENTER|NVG_ALIGN_MIDDLE); | ||||
nvgText(vg, x+h*0.55f, y+h*0.55f, cpToUTF8(ICON_SEARCH,icon), NULL); | nvgText(vg, x+h*0.55f, y+h*0.55f, cpToUTF8(ICON_SEARCH,icon), NULL); | ||||
nvgFontSize(vg, 20.0f); | |||||
nvgFontSize(vg, 17.0f); | |||||
nvgFontFace(vg, "sans"); | nvgFontFace(vg, "sans"); | ||||
nvgFillColor(vg, nvgRGBA(255,255,255,32)); | nvgFillColor(vg, nvgRGBA(255,255,255,32)); | ||||
@@ -168,7 +168,7 @@ void drawDropDown(NVGcontext* vg, const char* text, float x, float y, float w, f | |||||
nvgStrokeColor(vg, nvgRGBA(0,0,0,48)); | nvgStrokeColor(vg, nvgRGBA(0,0,0,48)); | ||||
nvgStroke(vg); | nvgStroke(vg); | ||||
nvgFontSize(vg, 20.0f); | |||||
nvgFontSize(vg, 17.0f); | |||||
nvgFontFace(vg, "sans"); | nvgFontFace(vg, "sans"); | ||||
nvgFillColor(vg, nvgRGBA(255,255,255,160)); | nvgFillColor(vg, nvgRGBA(255,255,255,160)); | ||||
nvgTextAlign(vg,NVG_ALIGN_LEFT|NVG_ALIGN_MIDDLE); | nvgTextAlign(vg,NVG_ALIGN_LEFT|NVG_ALIGN_MIDDLE); | ||||
@@ -185,7 +185,7 @@ void drawLabel(NVGcontext* vg, const char* text, float x, float y, float w, floa | |||||
{ | { | ||||
NVG_NOTUSED(w); | NVG_NOTUSED(w); | ||||
nvgFontSize(vg, 18.0f); | |||||
nvgFontSize(vg, 15.0f); | |||||
nvgFontFace(vg, "sans"); | nvgFontFace(vg, "sans"); | ||||
nvgFillColor(vg, nvgRGBA(255,255,255,128)); | nvgFillColor(vg, nvgRGBA(255,255,255,128)); | ||||
@@ -214,7 +214,7 @@ void drawEditBox(NVGcontext* vg, const char* text, float x, float y, float w, fl | |||||
drawEditBoxBase(vg, x,y, w,h); | drawEditBoxBase(vg, x,y, w,h); | ||||
nvgFontSize(vg, 20.0f); | |||||
nvgFontSize(vg, 17.0f); | |||||
nvgFontFace(vg, "sans"); | nvgFontFace(vg, "sans"); | ||||
nvgFillColor(vg, nvgRGBA(255,255,255,64)); | nvgFillColor(vg, nvgRGBA(255,255,255,64)); | ||||
nvgTextAlign(vg,NVG_ALIGN_LEFT|NVG_ALIGN_MIDDLE); | nvgTextAlign(vg,NVG_ALIGN_LEFT|NVG_ALIGN_MIDDLE); | ||||
@@ -230,13 +230,13 @@ void drawEditBoxNum(NVGcontext* vg, | |||||
uw = nvgTextBounds(vg, 0,0, units, NULL, NULL); | uw = nvgTextBounds(vg, 0,0, units, NULL, NULL); | ||||
nvgFontSize(vg, 18.0f); | |||||
nvgFontSize(vg, 15.0f); | |||||
nvgFontFace(vg, "sans"); | nvgFontFace(vg, "sans"); | ||||
nvgFillColor(vg, nvgRGBA(255,255,255,64)); | nvgFillColor(vg, nvgRGBA(255,255,255,64)); | ||||
nvgTextAlign(vg,NVG_ALIGN_RIGHT|NVG_ALIGN_MIDDLE); | nvgTextAlign(vg,NVG_ALIGN_RIGHT|NVG_ALIGN_MIDDLE); | ||||
nvgText(vg, x+w-h*0.3f,y+h*0.5f,units, NULL); | nvgText(vg, x+w-h*0.3f,y+h*0.5f,units, NULL); | ||||
nvgFontSize(vg, 20.0f); | |||||
nvgFontSize(vg, 17.0f); | |||||
nvgFontFace(vg, "sans"); | nvgFontFace(vg, "sans"); | ||||
nvgFillColor(vg, nvgRGBA(255,255,255,128)); | nvgFillColor(vg, nvgRGBA(255,255,255,128)); | ||||
nvgTextAlign(vg,NVG_ALIGN_RIGHT|NVG_ALIGN_MIDDLE); | nvgTextAlign(vg,NVG_ALIGN_RIGHT|NVG_ALIGN_MIDDLE); | ||||
@@ -249,7 +249,7 @@ void drawCheckBox(NVGcontext* vg, const char* text, float x, float y, float w, f | |||||
char icon[8]; | char icon[8]; | ||||
NVG_NOTUSED(w); | NVG_NOTUSED(w); | ||||
nvgFontSize(vg, 18.0f); | |||||
nvgFontSize(vg, 15.0f); | |||||
nvgFontFace(vg, "sans"); | nvgFontFace(vg, "sans"); | ||||
nvgFillColor(vg, nvgRGBA(255,255,255,160)); | nvgFillColor(vg, nvgRGBA(255,255,255,160)); | ||||
@@ -262,7 +262,7 @@ void drawCheckBox(NVGcontext* vg, const char* text, float x, float y, float w, f | |||||
nvgFillPaint(vg, bg); | nvgFillPaint(vg, bg); | ||||
nvgFill(vg); | nvgFill(vg); | ||||
nvgFontSize(vg, 40); | |||||
nvgFontSize(vg, 33); | |||||
nvgFontFace(vg, "icons"); | nvgFontFace(vg, "icons"); | ||||
nvgFillColor(vg, nvgRGBA(255,255,255,128)); | nvgFillColor(vg, nvgRGBA(255,255,255,128)); | ||||
nvgTextAlign(vg,NVG_ALIGN_CENTER|NVG_ALIGN_MIDDLE); | nvgTextAlign(vg,NVG_ALIGN_CENTER|NVG_ALIGN_MIDDLE); | ||||
@@ -291,7 +291,7 @@ void drawButton(NVGcontext* vg, int preicon, const char* text, float x, float y, | |||||
nvgStrokeColor(vg, nvgRGBA(0,0,0,48)); | nvgStrokeColor(vg, nvgRGBA(0,0,0,48)); | ||||
nvgStroke(vg); | nvgStroke(vg); | ||||
nvgFontSize(vg, 20.0f); | |||||
nvgFontSize(vg, 17.0f); | |||||
nvgFontFace(vg, "sans-bold"); | nvgFontFace(vg, "sans-bold"); | ||||
tw = nvgTextBounds(vg, 0,0, text, NULL, NULL); | tw = nvgTextBounds(vg, 0,0, text, NULL, NULL); | ||||
if (preicon != 0) { | if (preicon != 0) { | ||||
@@ -309,7 +309,7 @@ void drawButton(NVGcontext* vg, int preicon, const char* text, float x, float y, | |||||
nvgText(vg, x+w*0.5f-tw*0.5f-iw*0.75f, y+h*0.5f, cpToUTF8(preicon,icon), NULL); | nvgText(vg, x+w*0.5f-tw*0.5f-iw*0.75f, y+h*0.5f, cpToUTF8(preicon,icon), NULL); | ||||
} | } | ||||
nvgFontSize(vg, 20.0f); | |||||
nvgFontSize(vg, 17.0f); | |||||
nvgFontFace(vg, "sans-bold"); | nvgFontFace(vg, "sans-bold"); | ||||
nvgTextAlign(vg,NVG_ALIGN_LEFT|NVG_ALIGN_MIDDLE); | nvgTextAlign(vg,NVG_ALIGN_LEFT|NVG_ALIGN_MIDDLE); | ||||
nvgFillColor(vg, nvgRGBA(0,0,0,160)); | nvgFillColor(vg, nvgRGBA(0,0,0,160)); | ||||
@@ -868,13 +868,15 @@ void drawParagraph(NVGcontext* vg, float x, float y, float width, float height, | |||||
float caretx, px; | float caretx, px; | ||||
float bounds[4]; | float bounds[4]; | ||||
float a; | float a; | ||||
const char* hoverText = "Hover your mouse over the text to see calculated caret position."; | |||||
float gx,gy; | float gx,gy; | ||||
int gutter = 0; | int gutter = 0; | ||||
const char* boxText = "Testing\nsome multiline\ntext."; | |||||
NVG_NOTUSED(height); | NVG_NOTUSED(height); | ||||
nvgSave(vg); | nvgSave(vg); | ||||
nvgFontSize(vg, 18.0f); | |||||
nvgFontSize(vg, 15.0f); | |||||
nvgFontFace(vg, "sans"); | nvgFontFace(vg, "sans"); | ||||
nvgTextAlign(vg, NVG_ALIGN_LEFT|NVG_ALIGN_TOP); | nvgTextAlign(vg, NVG_ALIGN_LEFT|NVG_ALIGN_TOP); | ||||
nvgTextMetrics(vg, NULL, NULL, &lineh); | nvgTextMetrics(vg, NULL, NULL, &lineh); | ||||
@@ -891,7 +893,7 @@ void drawParagraph(NVGcontext* vg, float x, float y, float width, float height, | |||||
nvgBeginPath(vg); | nvgBeginPath(vg); | ||||
nvgFillColor(vg, nvgRGBA(255,255,255,hit?64:16)); | nvgFillColor(vg, nvgRGBA(255,255,255,hit?64:16)); | ||||
nvgRect(vg, x, y, row->width, lineh); | |||||
nvgRect(vg, x + row->minx, y, row->maxx - row->minx, lineh); | |||||
nvgFill(vg); | nvgFill(vg); | ||||
nvgFillColor(vg, nvgRGBA(255,255,255,255)); | nvgFillColor(vg, nvgRGBA(255,255,255,255)); | ||||
@@ -928,7 +930,7 @@ void drawParagraph(NVGcontext* vg, float x, float y, float width, float height, | |||||
if (gutter) { | if (gutter) { | ||||
char txt[16]; | char txt[16]; | ||||
snprintf(txt, sizeof(txt), "%d", gutter); | snprintf(txt, sizeof(txt), "%d", gutter); | ||||
nvgFontSize(vg, 13.0f); | |||||
nvgFontSize(vg, 12.0f); | |||||
nvgTextAlign(vg, NVG_ALIGN_RIGHT|NVG_ALIGN_MIDDLE); | nvgTextAlign(vg, NVG_ALIGN_RIGHT|NVG_ALIGN_MIDDLE); | ||||
nvgTextBounds(vg, gx,gy, txt, NULL, bounds); | nvgTextBounds(vg, gx,gy, txt, NULL, bounds); | ||||
@@ -944,16 +946,16 @@ void drawParagraph(NVGcontext* vg, float x, float y, float width, float height, | |||||
y += 20.0f; | y += 20.0f; | ||||
nvgFontSize(vg, 13.0f); | |||||
nvgFontSize(vg, 11.0f); | |||||
nvgTextAlign(vg, NVG_ALIGN_LEFT|NVG_ALIGN_TOP); | nvgTextAlign(vg, NVG_ALIGN_LEFT|NVG_ALIGN_TOP); | ||||
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, hoverText, NULL, bounds); | |||||
// Fade the tooltip out when close to it. | // Fade the tooltip out when close to it. | ||||
gx = fabsf((mx - (bounds[0]+bounds[2])*0.5f) / (bounds[0] - bounds[2])); | |||||
gy = fabsf((my - (bounds[1]+bounds[3])*0.5f) / (bounds[1] - bounds[3])); | |||||
a = maxf(gx, gy) - 0.5f; | |||||
gx = clampf(mx, bounds[0], bounds[2]) - mx; | |||||
gy = clampf(my, bounds[1], bounds[3]) - my; | |||||
a = sqrtf(gx*gx + gy*gy) / 30.0f; | |||||
a = clampf(a, 0, 1); | a = clampf(a, 0, 1); | ||||
nvgGlobalAlpha(vg, a); | nvgGlobalAlpha(vg, a); | ||||
@@ -967,7 +969,7 @@ void drawParagraph(NVGcontext* vg, float x, float y, float width, float height, | |||||
nvgFill(vg); | nvgFill(vg); | ||||
nvgFillColor(vg, nvgRGBA(0,0,0,220)); | nvgFillColor(vg, nvgRGBA(0,0,0,220)); | ||||
nvgTextBox(vg, x,y, 150, "Hover your mouse over the text to see calculated caret position.", NULL); | |||||
nvgTextBox(vg, x,y, 150, hoverText, NULL); | |||||
nvgRestore(vg); | nvgRestore(vg); | ||||
} | } | ||||
@@ -151,36 +151,36 @@ void renderGraph(NVGcontext* vg, float x, float y, PerfGraph* fps) | |||||
nvgFontFace(vg, "sans"); | nvgFontFace(vg, "sans"); | ||||
if (fps->name[0] != '\0') { | if (fps->name[0] != '\0') { | ||||
nvgFontSize(vg, 14.0f); | |||||
nvgFontSize(vg, 12.0f); | |||||
nvgTextAlign(vg, NVG_ALIGN_LEFT|NVG_ALIGN_TOP); | nvgTextAlign(vg, NVG_ALIGN_LEFT|NVG_ALIGN_TOP); | ||||
nvgFillColor(vg, nvgRGBA(240,240,240,192)); | nvgFillColor(vg, nvgRGBA(240,240,240,192)); | ||||
nvgText(vg, x+3,y+1, fps->name, NULL); | |||||
nvgText(vg, x+3,y+3, fps->name, NULL); | |||||
} | } | ||||
if (fps->style == GRAPH_RENDER_FPS) { | if (fps->style == GRAPH_RENDER_FPS) { | ||||
nvgFontSize(vg, 18.0f); | |||||
nvgFontSize(vg, 15.0f); | |||||
nvgTextAlign(vg,NVG_ALIGN_RIGHT|NVG_ALIGN_TOP); | nvgTextAlign(vg,NVG_ALIGN_RIGHT|NVG_ALIGN_TOP); | ||||
nvgFillColor(vg, nvgRGBA(240,240,240,255)); | nvgFillColor(vg, nvgRGBA(240,240,240,255)); | ||||
sprintf(str, "%.2f FPS", 1.0f / avg); | sprintf(str, "%.2f FPS", 1.0f / avg); | ||||
nvgText(vg, x+w-3,y+1, str, NULL); | |||||
nvgText(vg, x+w-3,y+3, str, NULL); | |||||
nvgFontSize(vg, 15.0f); | |||||
nvgTextAlign(vg,NVG_ALIGN_RIGHT|NVG_ALIGN_BOTTOM); | |||||
nvgFontSize(vg, 13.0f); | |||||
nvgTextAlign(vg,NVG_ALIGN_RIGHT|NVG_ALIGN_BASELINE); | |||||
nvgFillColor(vg, nvgRGBA(240,240,240,160)); | nvgFillColor(vg, nvgRGBA(240,240,240,160)); | ||||
sprintf(str, "%.2f ms", avg * 1000.0f); | sprintf(str, "%.2f ms", avg * 1000.0f); | ||||
nvgText(vg, x+w-3,y+h-1, str, NULL); | |||||
nvgText(vg, x+w-3,y+h-3, str, NULL); | |||||
} | } | ||||
else if (fps->style == GRAPH_RENDER_PERCENT) { | else if (fps->style == GRAPH_RENDER_PERCENT) { | ||||
nvgFontSize(vg, 18.0f); | |||||
nvgFontSize(vg, 15.0f); | |||||
nvgTextAlign(vg,NVG_ALIGN_RIGHT|NVG_ALIGN_TOP); | nvgTextAlign(vg,NVG_ALIGN_RIGHT|NVG_ALIGN_TOP); | ||||
nvgFillColor(vg, nvgRGBA(240,240,240,255)); | nvgFillColor(vg, nvgRGBA(240,240,240,255)); | ||||
sprintf(str, "%.1f %%", avg * 1.0f); | sprintf(str, "%.1f %%", avg * 1.0f); | ||||
nvgText(vg, x+w-3,y+1, str, NULL); | |||||
nvgText(vg, x+w-3,y+3, str, NULL); | |||||
} else { | } else { | ||||
nvgFontSize(vg, 18.0f); | |||||
nvgFontSize(vg, 15.0f); | |||||
nvgTextAlign(vg,NVG_ALIGN_RIGHT|NVG_ALIGN_TOP); | nvgTextAlign(vg,NVG_ALIGN_RIGHT|NVG_ALIGN_TOP); | ||||
nvgFillColor(vg, nvgRGBA(240,240,240,255)); | nvgFillColor(vg, nvgRGBA(240,240,240,255)); | ||||
sprintf(str, "%.2f ms", avg * 1000.0f); | sprintf(str, "%.2f ms", avg * 1000.0f); | ||||
nvgText(vg, x+w-3,y+1, str, NULL); | |||||
nvgText(vg, x+w-3,y+3, str, NULL); | |||||
} | } | ||||
} | } |
@@ -102,8 +102,8 @@ int fonsExpandAtlas(FONScontext* s, int width, int height); | |||||
int fonsResetAtlas(FONScontext* stash, int width, int height); | int fonsResetAtlas(FONScontext* stash, int width, int height); | ||||
// Add fonts | // Add fonts | ||||
int fonsAddFont(FONScontext* s, const char* name, const char* path); | |||||
int fonsAddFontMem(FONScontext* s, const char* name, unsigned char* data, int ndata, int freeData); | |||||
int fonsAddFont(FONScontext* s, const char* name, const char* path, int fontIndex); | |||||
int fonsAddFontMem(FONScontext* s, const char* name, unsigned char* data, int ndata, int freeData, int fontIndex); | |||||
int fonsGetFontByName(FONScontext* s, const char* name); | int fonsGetFontByName(FONScontext* s, const char* name); | ||||
// State handling | // State handling | ||||
@@ -175,13 +175,13 @@ int fons__tt_done(FONScontext *context) | |||||
return ftError == 0; | 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, int fontIndex) | |||||
{ | { | ||||
FT_Error ftError; | FT_Error ftError; | ||||
FONS_NOTUSED(context); | FONS_NOTUSED(context); | ||||
//font->font.userdata = stash; | //font->font.userdata = stash; | ||||
ftError = FT_New_Memory_Face(ftLibrary, (const FT_Byte*)data, dataSize, 0, &font->font); | |||||
ftError = FT_New_Memory_Face(ftLibrary, (const FT_Byte*)data, dataSize, fontIndex, &font->font); | |||||
return ftError == 0; | return ftError == 0; | ||||
} | } | ||||
@@ -194,7 +194,7 @@ void fons__tt_getFontVMetrics(FONSttFontImpl *font, int *ascent, int *descent, i | |||||
float fons__tt_getPixelHeightScale(FONSttFontImpl *font, float size) | float fons__tt_getPixelHeightScale(FONSttFontImpl *font, float size) | ||||
{ | { | ||||
return size / (font->font->ascender - font->font->descender); | |||||
return size / font->font->units_per_EM; | |||||
} | } | ||||
int fons__tt_getGlyphIndex(FONSttFontImpl *font, int codepoint) | int fons__tt_getGlyphIndex(FONSttFontImpl *font, int codepoint) | ||||
@@ -210,9 +210,9 @@ int fons__tt_buildGlyphBitmap(FONSttFontImpl *font, int glyph, float size, float | |||||
FT_Fixed advFixed; | FT_Fixed advFixed; | ||||
FONS_NOTUSED(scale); | 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))); | |||||
ftError = FT_Set_Pixel_Sizes(font->font, 0, size); | |||||
if (ftError) return 0; | if (ftError) return 0; | ||||
ftError = FT_Load_Glyph(font->font, glyph, FT_LOAD_RENDER | FT_LOAD_FORCE_AUTOHINT); | |||||
ftError = FT_Load_Glyph(font->font, glyph, FT_LOAD_RENDER | FT_LOAD_FORCE_AUTOHINT | FT_LOAD_TARGET_LIGHT); | |||||
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; | ||||
@@ -231,7 +231,7 @@ void fons__tt_renderGlyphBitmap(FONSttFontImpl *font, unsigned char *output, int | |||||
{ | { | ||||
FT_GlyphSlot ftGlyph = font->font->glyph; | FT_GlyphSlot ftGlyph = font->font->glyph; | ||||
int ftGlyphOffset = 0; | int ftGlyphOffset = 0; | ||||
int x, y; | |||||
unsigned int x, y; | |||||
FONS_NOTUSED(outWidth); | FONS_NOTUSED(outWidth); | ||||
FONS_NOTUSED(outHeight); | FONS_NOTUSED(outHeight); | ||||
FONS_NOTUSED(scaleX); | FONS_NOTUSED(scaleX); | ||||
@@ -278,13 +278,18 @@ int fons__tt_done(FONScontext *context) | |||||
return 1; | 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 fontIndex) | |||||
{ | { | ||||
int stbError; | |||||
int offset, stbError; | |||||
FONS_NOTUSED(dataSize); | FONS_NOTUSED(dataSize); | ||||
font->font.userdata = context; | font->font.userdata = context; | ||||
stbError = stbtt_InitFont(&font->font, data, 0); | |||||
offset = stbtt_GetFontOffsetForIndex(data, fontIndex); | |||||
if (offset == -1) { | |||||
stbError = 0; | |||||
} else { | |||||
stbError = stbtt_InitFont(&font->font, data, offset); | |||||
} | |||||
return stbError; | return stbError; | ||||
} | } | ||||
@@ -295,7 +300,7 @@ void fons__tt_getFontVMetrics(FONSttFontImpl *font, int *ascent, int *descent, i | |||||
float fons__tt_getPixelHeightScale(FONSttFontImpl *font, float size) | float fons__tt_getPixelHeightScale(FONSttFontImpl *font, float size) | ||||
{ | { | ||||
return stbtt_ScaleForPixelHeight(&font->font, size); | |||||
return stbtt_ScaleForMappingEmToPixels(&font->font, size); | |||||
} | } | ||||
int fons__tt_getGlyphIndex(FONSttFontImpl *font, int codepoint) | int fons__tt_getGlyphIndex(FONSttFontImpl *font, int codepoint) | ||||
@@ -792,6 +797,17 @@ int fonsAddFallbackFont(FONScontext* stash, int base, int fallback) | |||||
return 0; | return 0; | ||||
} | } | ||||
void fonsResetFallbackFont(FONScontext* stash, int base) | |||||
{ | |||||
int i; | |||||
FONSfont* baseFont = stash->fonts[base]; | |||||
baseFont->nfallbacks = 0; | |||||
baseFont->nglyphs = 0; | |||||
for (i = 0; i < FONS_HASH_LUT_SIZE; i++) | |||||
baseFont->lut[i] = -1; | |||||
} | |||||
void fonsSetSize(FONScontext* stash, float size) | void fonsSetSize(FONScontext* stash, float size) | ||||
{ | { | ||||
fons__getState(stash)->size = size; | fons__getState(stash)->size = size; | ||||
@@ -890,7 +906,7 @@ error: | |||||
return FONS_INVALID; | return FONS_INVALID; | ||||
} | } | ||||
int fonsAddFont(FONScontext* stash, const char* name, const char* path) | |||||
int fonsAddFont(FONScontext* stash, const char* name, const char* path, int fontIndex) | |||||
{ | { | ||||
FILE* fp = 0; | FILE* fp = 0; | ||||
int dataSize = 0; | int dataSize = 0; | ||||
@@ -908,9 +924,9 @@ int fonsAddFont(FONScontext* stash, const char* name, const char* path) | |||||
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 (readed != (size_t)dataSize) goto error; | |||||
return fonsAddFontMem(stash, name, data, dataSize, 1); | |||||
return fonsAddFontMem(stash, name, data, dataSize, 1, fontIndex); | |||||
error: | error: | ||||
if (data) free(data); | if (data) free(data); | ||||
@@ -918,7 +934,7 @@ error: | |||||
return FONS_INVALID; | return FONS_INVALID; | ||||
} | } | ||||
int fonsAddFontMem(FONScontext* stash, const char* name, unsigned char* data, int dataSize, int freeData) | |||||
int fonsAddFontMem(FONScontext* stash, const char* name, unsigned char* data, int dataSize, int freeData, int fontIndex) | |||||
{ | { | ||||
int i, ascent, descent, fh, lineGap; | int i, ascent, descent, fh, lineGap; | ||||
FONSfont* font; | FONSfont* font; | ||||
@@ -943,15 +959,16 @@ int fonsAddFontMem(FONScontext* stash, const char* name, unsigned char* data, in | |||||
// Init font | // Init font | ||||
stash->nscratch = 0; | stash->nscratch = 0; | ||||
if (!fons__tt_loadFont(stash, &font->font, data, dataSize)) goto error; | |||||
if (!fons__tt_loadFont(stash, &font->font, data, dataSize, fontIndex)) goto error; | |||||
// Store normalized line height. The real line height is got | // Store normalized line height. The real line height is got | ||||
// by multiplying the lineh by font size. | // by multiplying the lineh by font size. | ||||
fons__tt_getFontVMetrics( &font->font, &ascent, &descent, &lineGap); | fons__tt_getFontVMetrics( &font->font, &ascent, &descent, &lineGap); | ||||
ascent += lineGap; | |||||
fh = ascent - descent; | fh = ascent - descent; | ||||
font->ascender = (float)ascent / (float)fh; | font->ascender = (float)ascent / (float)fh; | ||||
font->descender = (float)descent / (float)fh; | font->descender = (float)descent / (float)fh; | ||||
font->lineh = (float)(fh + lineGap) / (float)fh; | |||||
font->lineh = font->ascender - font->descender; | |||||
return idx; | return idx; | ||||
@@ -1208,8 +1225,8 @@ static void fons__getQuad(FONScontext* stash, FONSfont* font, | |||||
y1 = (float)(glyph->y1-1); | y1 = (float)(glyph->y1-1); | ||||
if (stash->params.flags & FONS_ZERO_TOPLEFT) { | if (stash->params.flags & FONS_ZERO_TOPLEFT) { | ||||
rx = (float)(int)(*x + xoff); | |||||
ry = (float)(int)(*y + yoff); | |||||
rx = floorf(*x + xoff); | |||||
ry = floorf(*y + yoff); | |||||
q->x0 = rx; | q->x0 = rx; | ||||
q->y0 = ry; | q->y0 = ry; | ||||
@@ -1221,8 +1238,8 @@ static void fons__getQuad(FONScontext* stash, FONSfont* font, | |||||
q->s1 = x1 * stash->itw; | q->s1 = x1 * stash->itw; | ||||
q->t1 = y1 * stash->ith; | q->t1 = y1 * stash->ith; | ||||
} else { | } else { | ||||
rx = (float)(int)(*x + xoff); | |||||
ry = (float)(int)(*y - yoff); | |||||
rx = floorf(*x + xoff); | |||||
ry = floorf(*y - yoff); | |||||
q->x0 = rx; | q->x0 = rx; | ||||
q->y0 = ry; | q->y0 = ry; | ||||
@@ -24,8 +24,11 @@ | |||||
#include "nanovg.h" | #include "nanovg.h" | ||||
#define FONTSTASH_IMPLEMENTATION | #define FONTSTASH_IMPLEMENTATION | ||||
#include "fontstash.h" | #include "fontstash.h" | ||||
#ifndef NVG_NO_STB | |||||
#define STB_IMAGE_IMPLEMENTATION | #define STB_IMAGE_IMPLEMENTATION | ||||
#include "stb_image.h" | #include "stb_image.h" | ||||
#endif | |||||
#ifdef _MSC_VER | #ifdef _MSC_VER | ||||
#pragma warning(disable: 4100) // unreferenced formal parameter | #pragma warning(disable: 4100) // unreferenced formal parameter | ||||
@@ -793,6 +796,7 @@ void nvgFillPaint(NVGcontext* ctx, NVGpaint paint) | |||||
nvgTransformMultiply(state->fill.xform, state->xform); | nvgTransformMultiply(state->fill.xform, state->xform); | ||||
} | } | ||||
#ifndef NVG_NO_STB | |||||
int nvgCreateImage(NVGcontext* ctx, const char* filename, int imageFlags) | int nvgCreateImage(NVGcontext* ctx, const char* filename, int imageFlags) | ||||
{ | { | ||||
int w, h, n, image; | int w, h, n, image; | ||||
@@ -821,6 +825,7 @@ int nvgCreateImageMem(NVGcontext* ctx, int imageFlags, unsigned char* data, int | |||||
stbi_image_free(img); | stbi_image_free(img); | ||||
return image; | return image; | ||||
} | } | ||||
#endif | |||||
int nvgCreateImageRGBA(NVGcontext* ctx, int w, int h, int imageFlags, const unsigned char* data) | int nvgCreateImageRGBA(NVGcontext* ctx, int w, int h, int imageFlags, const unsigned char* data) | ||||
{ | { | ||||
@@ -2296,14 +2301,24 @@ void nvgStroke(NVGcontext* ctx) | |||||
} | } | ||||
// Add fonts | // Add fonts | ||||
int nvgCreateFont(NVGcontext* ctx, const char* name, const char* path) | |||||
int nvgCreateFont(NVGcontext* ctx, const char* name, const char* filename) | |||||
{ | |||||
return fonsAddFont(ctx->fs, name, filename, 0); | |||||
} | |||||
int nvgCreateFontAtIndex(NVGcontext* ctx, const char* name, const char* filename, const int fontIndex) | |||||
{ | { | ||||
return fonsAddFont(ctx->fs, name, path); | |||||
return fonsAddFont(ctx->fs, name, filename, fontIndex); | |||||
} | } | ||||
int nvgCreateFontMem(NVGcontext* ctx, const char* name, unsigned char* data, int ndata, int freeData) | int nvgCreateFontMem(NVGcontext* ctx, const char* name, unsigned char* data, int ndata, int freeData) | ||||
{ | { | ||||
return fonsAddFontMem(ctx->fs, name, data, ndata, freeData); | |||||
return fonsAddFontMem(ctx->fs, name, data, ndata, freeData, 0); | |||||
} | |||||
int nvgCreateFontMemAtIndex(NVGcontext* ctx, const char* name, unsigned char* data, int ndata, int freeData, const int fontIndex) | |||||
{ | |||||
return fonsAddFontMem(ctx->fs, name, data, ndata, freeData, fontIndex); | |||||
} | } | ||||
int nvgFindFont(NVGcontext* ctx, const char* name) | int nvgFindFont(NVGcontext* ctx, const char* name) | ||||
@@ -2324,6 +2339,16 @@ int nvgAddFallbackFont(NVGcontext* ctx, const char* baseFont, const char* fallba | |||||
return nvgAddFallbackFontId(ctx, nvgFindFont(ctx, baseFont), nvgFindFont(ctx, fallbackFont)); | return nvgAddFallbackFontId(ctx, nvgFindFont(ctx, baseFont), nvgFindFont(ctx, fallbackFont)); | ||||
} | } | ||||
void nvgResetFallbackFontsId(NVGcontext* ctx, int baseFont) | |||||
{ | |||||
fonsResetFallbackFont(ctx->fs, baseFont); | |||||
} | |||||
void nvgResetFallbackFonts(NVGcontext* ctx, const char* baseFont) | |||||
{ | |||||
nvgResetFallbackFontsId(ctx, nvgFindFont(ctx, baseFont)); | |||||
} | |||||
// State setting | // State setting | ||||
void nvgFontSize(NVGcontext* ctx, float size) | void nvgFontSize(NVGcontext* ctx, float size) | ||||
{ | { | ||||
@@ -2435,12 +2460,18 @@ static void nvg__renderText(NVGcontext* ctx, NVGvertex* verts, int nverts) | |||||
paint.outerColor.rgba[i] *= state->tint.rgba[i]; | paint.outerColor.rgba[i] *= state->tint.rgba[i]; | ||||
} | } | ||||
ctx->params.renderTriangles(ctx->params.userPtr, &paint, state->compositeOperation, &state->scissor, verts, nverts); | |||||
ctx->params.renderTriangles(ctx->params.userPtr, &paint, state->compositeOperation, &state->scissor, verts, nverts, ctx->fringeWidth); | |||||
ctx->drawCallCount++; | ctx->drawCallCount++; | ||||
ctx->textTriCount += nverts/3; | ctx->textTriCount += nverts/3; | ||||
} | } | ||||
static int nvg__isTransformFlipped(const float *xform) | |||||
{ | |||||
float det = xform[0] * xform[3] - xform[2] * xform[1]; | |||||
return( det < 0); | |||||
} | |||||
float nvgText(NVGcontext* ctx, float x, float y, const char* string, const char* end) | float nvgText(NVGcontext* ctx, float x, float y, const char* string, const char* end) | ||||
{ | { | ||||
NVGstate* state = nvg__getState(ctx); | NVGstate* state = nvg__getState(ctx); | ||||
@@ -2451,6 +2482,7 @@ float nvgText(NVGcontext* ctx, float x, float y, const char* string, const char* | |||||
float invscale = 1.0f / scale; | float invscale = 1.0f / scale; | ||||
int cverts = 0; | int cverts = 0; | ||||
int nverts = 0; | int nverts = 0; | ||||
int isFlipped = nvg__isTransformFlipped(state->xform); | |||||
if (end == NULL) | if (end == NULL) | ||||
end = string + strlen(string); | end = string + strlen(string); | ||||
@@ -2484,6 +2516,12 @@ float nvgText(NVGcontext* ctx, float x, float y, const char* string, const char* | |||||
break; | break; | ||||
} | } | ||||
prevIter = iter; | prevIter = iter; | ||||
if(isFlipped) { | |||||
float tmp; | |||||
tmp = q.y0; q.y0 = q.y1; q.y1 = tmp; | |||||
tmp = q.t0; q.t0 = q.t1; q.t1 = tmp; | |||||
} | |||||
// Transform corners. | // Transform corners. | ||||
nvgTransformPoint(&c[0],&c[1], state->xform, q.x0*invscale, q.y0*invscale); | nvgTransformPoint(&c[0],&c[1], state->xform, q.x0*invscale, q.y0*invscale); | ||||
nvgTransformPoint(&c[2],&c[3], state->xform, q.x1*invscale, q.y0*invscale); | nvgTransformPoint(&c[2],&c[3], state->xform, q.x1*invscale, q.y0*invscale); | ||||
@@ -2696,7 +2734,7 @@ int nvgTextBreakLines(NVGcontext* ctx, const char* string, const char* end, floa | |||||
rowStartX = iter.x; | rowStartX = iter.x; | ||||
rowStart = iter.str; | rowStart = iter.str; | ||||
rowEnd = iter.next; | rowEnd = iter.next; | ||||
rowWidth = iter.nextx - rowStartX; // q.x1 - rowStartX; | |||||
rowWidth = iter.nextx - rowStartX; | |||||
rowMinX = q.x0 - rowStartX; | rowMinX = q.x0 - rowStartX; | ||||
rowMaxX = q.x1 - rowStartX; | rowMaxX = q.x1 - rowStartX; | ||||
wordStart = iter.str; | wordStart = iter.str; | ||||
@@ -2726,7 +2764,7 @@ int nvgTextBreakLines(NVGcontext* ctx, const char* string, const char* end, floa | |||||
if ((ptype == NVG_SPACE && (type == NVG_CHAR || type == NVG_CJK_CHAR)) || type == NVG_CJK_CHAR) { | if ((ptype == NVG_SPACE && (type == NVG_CHAR || type == NVG_CJK_CHAR)) || type == NVG_CJK_CHAR) { | ||||
wordStart = iter.str; | wordStart = iter.str; | ||||
wordStartX = iter.x; | wordStartX = iter.x; | ||||
wordMinX = q.x0 - rowStartX; | |||||
wordMinX = q.x0; | |||||
} | } | ||||
// Break to new line when a character is beyond break width. | // Break to new line when a character is beyond break width. | ||||
@@ -2763,13 +2801,13 @@ int nvgTextBreakLines(NVGcontext* ctx, const char* string, const char* end, floa | |||||
nrows++; | nrows++; | ||||
if (nrows >= maxRows) | if (nrows >= maxRows) | ||||
return nrows; | return nrows; | ||||
// Update row | |||||
rowStartX = wordStartX; | rowStartX = wordStartX; | ||||
rowStart = wordStart; | rowStart = wordStart; | ||||
rowEnd = iter.next; | rowEnd = iter.next; | ||||
rowWidth = iter.nextx - rowStartX; | rowWidth = iter.nextx - rowStartX; | ||||
rowMinX = wordMinX; | |||||
rowMinX = wordMinX - rowStartX; | |||||
rowMaxX = q.x1 - rowStartX; | rowMaxX = q.x1 - rowStartX; | ||||
// No change to the word start | |||||
} | } | ||||
// Set null break point | // Set null break point | ||||
breakEnd = rowStart; | breakEnd = rowStart; | ||||
@@ -415,7 +415,7 @@ NVGpaint nvgBoxGradient(NVGcontext* ctx, float x, float y, float w, float h, | |||||
NVGpaint nvgRadialGradient(NVGcontext* ctx, float cx, float cy, float inr, float outr, | NVGpaint nvgRadialGradient(NVGcontext* ctx, float cx, float cy, float inr, float outr, | ||||
NVGcolor icol, NVGcolor ocol); | NVGcolor icol, NVGcolor ocol); | ||||
// Creates and returns an image patter. Parameters (ox,oy) specify the left-top location of the image pattern, | |||||
// Creates and returns an image pattern. Parameters (ox,oy) specify the left-top location of the image pattern, | |||||
// (ex,ey) the size of one image, angle rotation around the top-left corner, image is handle to the image to render. | // (ex,ey) the size of one image, angle rotation around the top-left corner, image is handle to the image to render. | ||||
// 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(). | ||||
NVGpaint nvgImagePattern(NVGcontext* ctx, float ox, float oy, float ex, float ey, | NVGpaint nvgImagePattern(NVGcontext* ctx, float ox, float oy, float ex, float ey, | ||||
@@ -547,10 +547,16 @@ void nvgStroke(NVGcontext* ctx); | |||||
// Returns handle to the font. | // Returns handle to the font. | ||||
int nvgCreateFont(NVGcontext* ctx, const char* name, const char* filename); | int nvgCreateFont(NVGcontext* ctx, const char* name, const char* filename); | ||||
// fontIndex specifies which font face to load from a .ttf/.ttc file. | |||||
int nvgCreateFontAtIndex(NVGcontext* ctx, const char* name, const char* filename, const int fontIndex); | |||||
// Creates font by loading it from the specified memory chunk. | // Creates font by loading it from the specified memory chunk. | ||||
// Returns handle to the font. | // Returns handle to the font. | ||||
int nvgCreateFontMem(NVGcontext* ctx, const char* name, unsigned char* data, int ndata, int freeData); | int nvgCreateFontMem(NVGcontext* ctx, const char* name, unsigned char* data, int ndata, int freeData); | ||||
// fontIndex specifies which font face to load from a .ttf/.ttc file. | |||||
int nvgCreateFontMemAtIndex(NVGcontext* ctx, const char* name, unsigned char* data, int ndata, int freeData, const int fontIndex); | |||||
// Finds a loaded font of specified name, and returns handle to it, or -1 if the font is not found. | // Finds a loaded font of specified name, and returns handle to it, or -1 if the font is not found. | ||||
int nvgFindFont(NVGcontext* ctx, const char* name); | int nvgFindFont(NVGcontext* ctx, const char* name); | ||||
@@ -560,6 +566,12 @@ int nvgAddFallbackFontId(NVGcontext* ctx, int baseFont, int fallbackFont); | |||||
// Adds a fallback font by name. | // Adds a fallback font by name. | ||||
int nvgAddFallbackFont(NVGcontext* ctx, const char* baseFont, const char* fallbackFont); | int nvgAddFallbackFont(NVGcontext* ctx, const char* baseFont, const char* fallbackFont); | ||||
// Resets fallback fonts by handle. | |||||
void nvgResetFallbackFontsId(NVGcontext* ctx, int baseFont); | |||||
// Resets fallback fonts by name. | |||||
void nvgResetFallbackFonts(NVGcontext* ctx, const char* baseFont); | |||||
// Sets the font size of current text style. | // Sets the font size of current text style. | ||||
void nvgFontSize(NVGcontext* ctx, float size); | void nvgFontSize(NVGcontext* ctx, float size); | ||||
@@ -659,7 +671,7 @@ struct NVGparams { | |||||
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); | ||||
void (*renderStroke)(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, float fringe, float strokeWidth, const NVGpath* paths, int npaths); | void (*renderStroke)(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, float fringe, float strokeWidth, const NVGpath* paths, int npaths); | ||||
void (*renderTriangles)(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, const NVGvertex* verts, int nverts); | |||||
void (*renderTriangles)(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, const NVGvertex* verts, int nverts, float fringe); | |||||
void (*renderDelete)(void* uptr); | void (*renderDelete)(void* uptr); | ||||
}; | }; | ||||
typedef struct NVGparams NVGparams; | typedef struct NVGparams NVGparams; | ||||
@@ -268,6 +268,8 @@ struct GLNVGcontext { | |||||
GLuint stencilFuncMask; | GLuint stencilFuncMask; | ||||
GLNVGblend blendFunc; | GLNVGblend blendFunc; | ||||
#endif | #endif | ||||
int dummyTex; | |||||
}; | }; | ||||
typedef struct GLNVGcontext GLNVGcontext; | typedef struct GLNVGcontext GLNVGcontext; | ||||
@@ -500,6 +502,8 @@ static void glnvg__getUniforms(GLNVGshader* shader) | |||||
#endif | #endif | ||||
} | } | ||||
static int glnvg__renderCreateTexture(void* uptr, int type, int w, int h, int imageFlags, const unsigned char* data); | |||||
static int glnvg__renderCreate(void* uptr) | static int glnvg__renderCreate(void* uptr) | ||||
{ | { | ||||
GLNVGcontext* gl = (GLNVGcontext*)uptr; | GLNVGcontext* gl = (GLNVGcontext*)uptr; | ||||
@@ -700,6 +704,10 @@ static int glnvg__renderCreate(void* uptr) | |||||
#endif | #endif | ||||
gl->fragSize = sizeof(GLNVGfragUniforms) + align - sizeof(GLNVGfragUniforms) % align; | gl->fragSize = sizeof(GLNVGfragUniforms) + align - sizeof(GLNVGfragUniforms) % align; | ||||
// Some platforms does not allow to have samples to unset textures. | |||||
// Create empty one which is bound when there's no texture specified. | |||||
gl->dummyTex = glnvg__renderCreateTexture(gl, NVG_TEXTURE_ALPHA, 1, 1, 0, NULL); | |||||
glnvg__checkError(gl, "create done"); | glnvg__checkError(gl, "create done"); | ||||
glFinish(); | glFinish(); | ||||
@@ -973,6 +981,7 @@ static GLNVGfragUniforms* nvg__fragUniformPtr(GLNVGcontext* gl, int i); | |||||
static void glnvg__setUniforms(GLNVGcontext* gl, int uniformOffset, int image) | static void glnvg__setUniforms(GLNVGcontext* gl, int uniformOffset, int image) | ||||
{ | { | ||||
GLNVGtexture* tex = NULL; | |||||
#if NANOVG_GL_USE_UNIFORMBUFFER | #if NANOVG_GL_USE_UNIFORMBUFFER | ||||
glBindBufferRange(GL_UNIFORM_BUFFER, GLNVG_FRAG_BINDING, gl->fragBuf, uniformOffset, sizeof(GLNVGfragUniforms)); | glBindBufferRange(GL_UNIFORM_BUFFER, GLNVG_FRAG_BINDING, gl->fragBuf, uniformOffset, sizeof(GLNVGfragUniforms)); | ||||
#else | #else | ||||
@@ -981,12 +990,14 @@ static void glnvg__setUniforms(GLNVGcontext* gl, int uniformOffset, int image) | |||||
#endif | #endif | ||||
if (image != 0) { | if (image != 0) { | ||||
GLNVGtexture* tex = glnvg__findTexture(gl, image); | |||||
glnvg__bindTexture(gl, tex != NULL ? tex->tex : 0); | |||||
glnvg__checkError(gl, "tex paint tex"); | |||||
} else { | |||||
glnvg__bindTexture(gl, 0); | |||||
tex = glnvg__findTexture(gl, image); | |||||
} | |||||
// If no image is set, use empty texture | |||||
if (tex == NULL) { | |||||
tex = glnvg__findTexture(gl, gl->dummyTex); | |||||
} | } | ||||
glnvg__bindTexture(gl, tex != NULL ? tex->tex : 0); | |||||
glnvg__checkError(gl, "tex paint tex"); | |||||
} | } | ||||
static void glnvg__renderViewport(void* uptr, float width, float height, float devicePixelRatio) | static void glnvg__renderViewport(void* uptr, float width, float height, float devicePixelRatio) | ||||
@@ -1481,7 +1492,7 @@ error: | |||||
} | } | ||||
static void glnvg__renderTriangles(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, | static void glnvg__renderTriangles(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, | ||||
const NVGvertex* verts, int nverts) | |||||
const NVGvertex* verts, int nverts, float fringe) | |||||
{ | { | ||||
GLNVGcontext* gl = (GLNVGcontext*)uptr; | GLNVGcontext* gl = (GLNVGcontext*)uptr; | ||||
GLNVGcall* call = glnvg__allocCall(gl); | GLNVGcall* call = glnvg__allocCall(gl); | ||||
@@ -1504,7 +1515,7 @@ static void glnvg__renderTriangles(void* uptr, NVGpaint* paint, NVGcompositeOper | |||||
call->uniformOffset = glnvg__allocFragUniforms(gl, 1); | call->uniformOffset = glnvg__allocFragUniforms(gl, 1); | ||||
if (call->uniformOffset == -1) goto error; | if (call->uniformOffset == -1) goto error; | ||||
frag = nvg__fragUniformPtr(gl, call->uniformOffset); | frag = nvg__fragUniformPtr(gl, call->uniformOffset); | ||||
glnvg__convertPaint(gl, frag, paint, scissor, 1.0f, 1.0f, -1.0f); | |||||
glnvg__convertPaint(gl, frag, paint, scissor, 1.0f, fringe, -1.0f); | |||||
frag->type = NSVG_SHADER_IMG; | frag->type = NSVG_SHADER_IMG; | ||||
return; | return; | ||||