summaryrefslogtreecommitdiff
path: root/dgl/src/nanovg
diff options
context:
space:
mode:
authorfalkTX <falktx@gmail.com>2015-04-27 18:55:37 +0200
committerfalkTX <falktx@gmail.com>2015-04-27 18:55:37 +0200
commit27fb27a320e0fdaef9fc7dc9661a219653292214 (patch)
tree21acff510cf8405e5dfa86d68435338164b29356 /dgl/src/nanovg
parentf0561d522e3bf5e561ae4cfd74957fd26475509c (diff)
Start updating nanovg
Diffstat (limited to 'dgl/src/nanovg')
-rw-r--r--dgl/src/nanovg/fontstash.h363
-rw-r--r--dgl/src/nanovg/nanovg_gl_utils.h132
2 files changed, 321 insertions, 174 deletions
diff --git a/dgl/src/nanovg/fontstash.h b/dgl/src/nanovg/fontstash.h
index a97ce537..71377096 100644
--- a/dgl/src/nanovg/fontstash.h
+++ b/dgl/src/nanovg/fontstash.h
@@ -41,9 +41,9 @@ enum FONSalign {
enum FONSerrorCode {
// Font atlas is full.
FONS_ATLAS_FULL = 1,
- // Scratch memory used to render glyphs is full, requested size reported in 'val', you may need to bump up FONS_SCRATCH_BUF_SIZE.
+ // Scratch memory used to render glyphs is full, requested size reported in 'val', you may need to bump up FONS_SCRATCH_BUF_SIZE.
FONS_SCRATCH_FULL = 2,
- // Calls to fonsPushState has craeted too large stack, if you need deep state stack bump up FONS_MAX_STATES.
+ // Calls to fonsPushState has created too large stack, if you need deep state stack bump up FONS_MAX_STATES.
FONS_STATES_OVERFLOW = 3,
// Trying to pop too many states fonsPopState().
FONS_STATES_UNDERFLOW = 4,
@@ -59,75 +59,80 @@ struct FONSparams {
void (*renderDraw)(void* uptr, const float* verts, const float* tcoords, const unsigned int* colors, int nverts);
void (*renderDelete)(void* uptr);
};
+typedef struct FONSparams FONSparams;
struct FONSquad
{
float x0,y0,s0,t0;
float x1,y1,s1,t1;
};
+typedef struct FONSquad FONSquad;
struct FONStextIter {
float x, y, nextx, nexty, scale, spacing;
unsigned int codepoint;
short isize, iblur;
struct FONSfont* font;
- struct FONSglyph* prevGlyph;
+ int prevGlyphIndex;
const char* str;
const char* next;
const char* end;
unsigned int utf8state;
};
+typedef struct FONStextIter FONStextIter;
-// Contructor and destructor.
-struct FONScontext* fonsCreateInternal(struct FONSparams* params);
-void fonsDeleteInternal(struct FONScontext* s);
+typedef struct FONScontext FONScontext;
-void fonsSetErrorCallback(struct FONScontext* s, void (*callback)(void* uptr, int error, int val), void* uptr);
+// Constructor and destructor.
+FONScontext* fonsCreateInternal(FONSparams* params);
+void fonsDeleteInternal(FONScontext* s);
+
+void fonsSetErrorCallback(FONScontext* s, void (*callback)(void* uptr, int error, int val), void* uptr);
// Returns current atlas size.
-void fonsGetAtlasSize(struct FONScontext* s, int* width, int* height);
-// Expands the atlas size.
-int fonsExpandAtlas(struct FONScontext* s, int width, int height);
-// Reseta the whole stash.
-int fonsResetAtlas(struct FONScontext* stash, int width, int height);
+void fonsGetAtlasSize(FONScontext* s, int* width, int* height);
+// Expands the atlas size.
+int fonsExpandAtlas(FONScontext* s, int width, int height);
+// Resets the whole stash.
+int fonsResetAtlas(FONScontext* stash, int width, int height);
// Add fonts
-int fonsAddFont(struct FONScontext* s, const char* name, const char* path);
-int fonsAddFontMem(struct FONScontext* s, const char* name, unsigned char* data, int ndata, int freeData);
-int fonsGetFontByName(struct FONScontext* s, const char* name);
+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 fonsGetFontByName(FONScontext* s, const char* name);
// State handling
-void fonsPushState(struct FONScontext* s);
-void fonsPopState(struct FONScontext* s);
-void fonsClearState(struct FONScontext* s);
+void fonsPushState(FONScontext* s);
+void fonsPopState(FONScontext* s);
+void fonsClearState(FONScontext* s);
// State setting
-void fonsSetSize(struct FONScontext* s, float size);
-void fonsSetColor(struct FONScontext* s, unsigned int color);
-void fonsSetSpacing(struct FONScontext* s, float spacing);
-void fonsSetBlur(struct FONScontext* s, float blur);
-void fonsSetAlign(struct FONScontext* s, int align);
-void fonsSetFont(struct FONScontext* s, int font);
+void fonsSetSize(FONScontext* s, float size);
+void fonsSetColor(FONScontext* s, unsigned int color);
+void fonsSetSpacing(FONScontext* s, float spacing);
+void fonsSetBlur(FONScontext* s, float blur);
+void fonsSetAlign(FONScontext* s, int align);
+void fonsSetFont(FONScontext* s, int font);
// Draw text
-float fonsDrawText(struct FONScontext* s, float x, float y, const char* string, const char* end);
+float fonsDrawText(FONScontext* s, float x, float y, const char* string, const char* end);
// Measure text
-float fonsTextBounds(struct FONScontext* s, float x, float y, const char* string, const char* end, float* bounds);
-void fonsLineBounds(struct FONScontext* s, float y, float* miny, float* maxy);
-void fonsVertMetrics(struct FONScontext* s, float* ascender, float* descender, float* lineh);
+float fonsTextBounds(FONScontext* s, float x, float y, const char* string, const char* end, float* bounds);
+void fonsLineBounds(FONScontext* s, float y, float* miny, float* maxy);
+void fonsVertMetrics(FONScontext* s, float* ascender, float* descender, float* lineh);
// Text iterator
-int fonsTextIterInit(struct FONScontext* stash, struct FONStextIter* iter, float x, float y, const char* str, const char* end);
-int fonsTextIterNext(struct FONScontext* stash, struct FONStextIter* iter, struct FONSquad* quad);
+int fonsTextIterInit(FONScontext* stash, FONStextIter* iter, float x, float y, const char* str, const char* end);
+int fonsTextIterNext(FONScontext* stash, FONStextIter* iter, struct FONSquad* quad);
// Pull texture changes
-const unsigned char* fonsGetTextureData(struct FONScontext* stash, int* width, int* height);
-int fonsValidateTexture(struct FONScontext* s, int* dirty);
+const unsigned char* fonsGetTextureData(FONScontext* stash, int* width, int* height);
+int fonsValidateTexture(FONScontext* s, int* dirty);
// Draws the stash texture for debugging
-void fonsDrawDebug(struct FONScontext* s, float x, float y);
+void fonsDrawDebug(FONScontext* s, float x, float y);
-#endif // FONS_H
+#endif // FONTSTASH_H
#ifdef FONTSTASH_IMPLEMENTATION
@@ -144,17 +149,19 @@ void fonsDrawDebug(struct FONScontext* s, float x, float y);
struct FONSttFontImpl {
FT_Face font;
};
+typedef struct FONSttFontImpl FONSttFontImpl;
static FT_Library ftLibrary;
-int fons__tt_init()
-{
+int fons__tt_init(FONScontext *context)
+{
FT_Error ftError;
+ FONS_NOTUSED(context);
ftError = FT_Init_FreeType(&ftLibrary);
return ftError == 0;
}
-int fons__tt_loadFont(struct FONScontext *context, struct FONSttFontImpl *font, unsigned char *data, int dataSize)
+int fons__tt_loadFont(FONScontext *context, FONSttFontImpl *font, unsigned char *data, int dataSize)
{
FT_Error ftError;
FONS_NOTUSED(context);
@@ -164,24 +171,25 @@ int fons__tt_loadFont(struct FONScontext *context, struct FONSttFontImpl *font,
return ftError == 0;
}
-void fons__tt_getFontVMetrics(struct FONSttFontImpl *font, int *ascent, int *descent, int *lineGap)
+void fons__tt_getFontVMetrics(FONSttFontImpl *font, int *ascent, int *descent, int *lineGap)
{
*ascent = font->font->ascender;
*descent = font->font->descender;
*lineGap = font->font->height - (*ascent - *descent);
}
-float fons__tt_getPixelHeightScale(struct FONSttFontImpl *font, float size)
+float fons__tt_getPixelHeightScale(FONSttFontImpl *font, float size)
{
return size / (font->font->ascender - font->font->descender);
}
-int fons__tt_getGlyphIndex(struct FONSttFontImpl *font, int codepoint)
+int fons__tt_getGlyphIndex(FONSttFontImpl *font, int codepoint)
{
return FT_Get_Char_Index(font->font, codepoint);
}
-int fons__tt_buildGlyphBitmap(struct FONSttFontImpl *font, int glyph, float size, float scale, int *advance, int *lsb, int *x0, int *y0, int *x1, int *y1)
+int fons__tt_buildGlyphBitmap(FONSttFontImpl *font, int glyph, float size, float scale,
+ int *advance, int *lsb, int *x0, int *y0, int *x1, int *y1)
{
FT_Error ftError;
FT_GlyphSlot ftGlyph;
@@ -202,7 +210,8 @@ int fons__tt_buildGlyphBitmap(struct FONSttFontImpl *font, int glyph, float size
return 1;
}
-void fons__tt_renderGlyphBitmap(struct FONSttFontImpl *font, unsigned char *output, int outWidth, int outHeight, int outStride, float scaleX, float scaleY, int glyph)
+void fons__tt_renderGlyphBitmap(FONSttFontImpl *font, unsigned char *output, int outWidth, int outHeight, int outStride,
+ float scaleX, float scaleY, int glyph)
{
FT_GlyphSlot ftGlyph = font->font->glyph;
int ftGlyphOffset = 0;
@@ -220,7 +229,7 @@ void fons__tt_renderGlyphBitmap(struct FONSttFontImpl *font, unsigned char *outp
}
}
-int fons__tt_getGlyphKernAdvance(struct FONSttFontImpl *font, int glyph1, int glyph2)
+int fons__tt_getGlyphKernAdvance(FONSttFontImpl *font, int glyph1, int glyph2)
{
FT_Vector ftKerning;
FT_Get_Kerning(font->font, glyph1, glyph2, FT_KERNING_DEFAULT, &ftKerning);
@@ -239,14 +248,15 @@ static void fons__tmpfree(void* ptr, void* up);
struct FONSttFontImpl {
stbtt_fontinfo font;
};
+typedef struct FONSttFontImpl FONSttFontImpl;
-int fons__tt_init(struct FONScontext *context)
+int fons__tt_init(FONScontext *context)
{
FONS_NOTUSED(context);
return 1;
}
-int fons__tt_loadFont(struct FONScontext *context, struct FONSttFontImpl *font, unsigned char *data, int dataSize)
+int fons__tt_loadFont(FONScontext *context, FONSttFontImpl *font, unsigned char *data, int dataSize)
{
int stbError;
FONS_NOTUSED(dataSize);
@@ -256,22 +266,23 @@ int fons__tt_loadFont(struct FONScontext *context, struct FONSttFontImpl *font,
return stbError;
}
-void fons__tt_getFontVMetrics(struct FONSttFontImpl *font, int *ascent, int *descent, int *lineGap)
+void fons__tt_getFontVMetrics(FONSttFontImpl *font, int *ascent, int *descent, int *lineGap)
{
stbtt_GetFontVMetrics(&font->font, ascent, descent, lineGap);
}
-float fons__tt_getPixelHeightScale(struct FONSttFontImpl *font, float size)
+float fons__tt_getPixelHeightScale(FONSttFontImpl *font, float size)
{
return stbtt_ScaleForPixelHeight(&font->font, size);
}
-int fons__tt_getGlyphIndex(struct FONSttFontImpl *font, int codepoint)
+int fons__tt_getGlyphIndex(FONSttFontImpl *font, int codepoint)
{
return stbtt_FindGlyphIndex(&font->font, codepoint);
}
-int fons__tt_buildGlyphBitmap(struct FONSttFontImpl *font, int glyph, float size, float scale, int *advance, int *lsb, int *x0, int *y0, int *x1, int *y1)
+int fons__tt_buildGlyphBitmap(FONSttFontImpl *font, int glyph, float size, float scale,
+ int *advance, int *lsb, int *x0, int *y0, int *x1, int *y1)
{
FONS_NOTUSED(size);
stbtt_GetGlyphHMetrics(&font->font, glyph, advance, lsb);
@@ -279,12 +290,13 @@ int fons__tt_buildGlyphBitmap(struct FONSttFontImpl *font, int glyph, float size
return 1;
}
-void fons__tt_renderGlyphBitmap(struct FONSttFontImpl *font, unsigned char *output, int outWidth, int outHeight, int outStride, float scaleX, float scaleY, int glyph)
+void fons__tt_renderGlyphBitmap(FONSttFontImpl *font, unsigned char *output, int outWidth, int outHeight, int outStride,
+ float scaleX, float scaleY, int glyph)
{
stbtt_MakeGlyphBitmap(&font->font, output, outWidth, outHeight, outStride, scaleX, scaleY, glyph);
}
-int fons__tt_getGlyphKernAdvance(struct FONSttFontImpl *font, int glyph1, int glyph2)
+int fons__tt_getGlyphKernAdvance(FONSttFontImpl *font, int glyph1, int glyph2)
{
return stbtt_GetGlyphKernAdvance(&font->font, glyph1, glyph2);
}
@@ -343,10 +355,11 @@ struct FONSglyph
short x0,y0,x1,y1;
short xadv,xoff,yoff;
};
+typedef struct FONSglyph FONSglyph;
struct FONSfont
{
- struct FONSttFontImpl font;
+ FONSttFontImpl font;
char name[64];
unsigned char* data;
int dataSize;
@@ -354,11 +367,12 @@ struct FONSfont
float ascender;
float descender;
float lineh;
- struct FONSglyph* glyphs;
+ FONSglyph* glyphs;
int cglyphs;
int nglyphs;
int lut[FONS_HASH_LUT_SIZE];
};
+typedef struct FONSfont FONSfont;
struct FONSstate
{
@@ -369,36 +383,39 @@ struct FONSstate
float blur;
float spacing;
};
+typedef struct FONSstate FONSstate;
struct FONSatlasNode {
short x, y, width;
};
+typedef struct FONSatlasNode FONSatlasNode;
struct FONSatlas
{
int width, height;
- struct FONSatlasNode* nodes;
+ FONSatlasNode* nodes;
int nnodes;
int cnodes;
};
+typedef struct FONSatlas FONSatlas;
struct FONScontext
{
- struct FONSparams params;
+ FONSparams params;
float itw,ith;
unsigned char* texData;
int dirtyRect[4];
- struct FONSfont** fonts;
- struct FONSatlas* atlas;
+ FONSfont** fonts;
+ FONSatlas* atlas;
int cfonts;
int nfonts;
float verts[FONS_VERTEX_COUNT*2];
float tcoords[FONS_VERTEX_COUNT*2];
unsigned int colors[FONS_VERTEX_COUNT];
int nverts;
- unsigned char *scratch;
+ unsigned char* scratch;
int nscratch;
- struct FONSstate states[FONS_MAX_STATES];
+ FONSstate states[FONS_MAX_STATES];
int nstates;
void (*handleError)(void* uptr, int error, int val);
void* errorUptr;
@@ -407,7 +424,7 @@ struct FONScontext
static void* fons__tmpalloc(size_t size, void* up)
{
unsigned char* ptr;
- struct FONScontext* stash = (struct FONScontext*)up;
+ FONScontext* stash = (FONScontext*)up;
// 16-byte align the returned pointer
size = (size + 0xf) & ~0xf;
@@ -470,29 +487,29 @@ static unsigned int fons__decutf8(unsigned int* state, unsigned int* codep, unsi
// Atlas based on Skyline Bin Packer by Jukka Jylänki
-static void fons__deleteAtlas(struct FONSatlas* atlas)
+static void fons__deleteAtlas(FONSatlas* atlas)
{
if (atlas == NULL) return;
if (atlas->nodes != NULL) free(atlas->nodes);
free(atlas);
}
-static struct FONSatlas* fons__allocAtlas(int w, int h, int nnodes)
+static FONSatlas* fons__allocAtlas(int w, int h, int nnodes)
{
- struct FONSatlas* atlas = NULL;
+ FONSatlas* atlas = NULL;
// Allocate memory for the font stash.
- atlas = (struct FONSatlas*)malloc(sizeof(struct FONSatlas));
+ atlas = (FONSatlas*)malloc(sizeof(FONSatlas));
if (atlas == NULL) goto error;
- memset(atlas, 0, sizeof(struct FONSatlas));
+ memset(atlas, 0, sizeof(FONSatlas));
atlas->width = w;
atlas->height = h;
// Allocate space for skyline nodes
- atlas->nodes = (struct FONSatlasNode*)malloc(sizeof(struct FONSatlasNode) * nnodes);
+ atlas->nodes = (FONSatlasNode*)malloc(sizeof(FONSatlasNode) * nnodes);
if (atlas->nodes == NULL) goto error;
- memset(atlas->nodes, 0, sizeof(struct FONSatlasNode) * nnodes);
+ memset(atlas->nodes, 0, sizeof(FONSatlasNode) * nnodes);
atlas->nnodes = 0;
atlas->cnodes = nnodes;
@@ -509,13 +526,13 @@ error:
return NULL;
}
-static int fons__atlasInsertNode(struct FONSatlas* atlas, int idx, int x, int y, int w)
+static int fons__atlasInsertNode(FONSatlas* atlas, int idx, int x, int y, int w)
{
int i;
// Insert node
if (atlas->nnodes+1 > atlas->cnodes) {
atlas->cnodes = atlas->cnodes == 0 ? 8 : atlas->cnodes * 2;
- atlas->nodes = (struct FONSatlasNode*)realloc(atlas->nodes, sizeof(struct FONSatlasNode) * atlas->cnodes);
+ atlas->nodes = (FONSatlasNode*)realloc(atlas->nodes, sizeof(FONSatlasNode) * atlas->cnodes);
if (atlas->nodes == NULL)
return 0;
}
@@ -529,7 +546,7 @@ static int fons__atlasInsertNode(struct FONSatlas* atlas, int idx, int x, int y,
return 1;
}
-static void fons__atlasRemoveNode(struct FONSatlas* atlas, int idx)
+static void fons__atlasRemoveNode(FONSatlas* atlas, int idx)
{
int i;
if (atlas->nnodes == 0) return;
@@ -538,7 +555,7 @@ static void fons__atlasRemoveNode(struct FONSatlas* atlas, int idx)
atlas->nnodes--;
}
-static void fons__atlasExpand(struct FONSatlas* atlas, int w, int h)
+static void fons__atlasExpand(FONSatlas* atlas, int w, int h)
{
// Insert node for empty space
if (w > atlas->width)
@@ -547,7 +564,7 @@ static void fons__atlasExpand(struct FONSatlas* atlas, int w, int h)
atlas->height = h;
}
-static void fons__atlasReset(struct FONSatlas* atlas, int w, int h)
+static void fons__atlasReset(FONSatlas* atlas, int w, int h)
{
atlas->width = w;
atlas->height = h;
@@ -560,7 +577,7 @@ static void fons__atlasReset(struct FONSatlas* atlas, int w, int h)
atlas->nnodes++;
}
-static int fons__atlasAddSkylineLevel(struct FONSatlas* atlas, int idx, int x, int y, int w, int h)
+static int fons__atlasAddSkylineLevel(FONSatlas* atlas, int idx, int x, int y, int w, int h)
{
int i;
@@ -568,7 +585,7 @@ static int fons__atlasAddSkylineLevel(struct FONSatlas* atlas, int idx, int x, i
if (fons__atlasInsertNode(atlas, idx, x, y+h, w) == 0)
return 0;
- // Delete skyline segments that fall under the shaodw of the new segment.
+ // Delete skyline segments that fall under the shadow of the new segment.
for (i = idx+1; i < atlas->nnodes; i++) {
if (atlas->nodes[i].x < atlas->nodes[i-1].x + atlas->nodes[i-1].width) {
int shrink = atlas->nodes[i-1].x + atlas->nodes[i-1].width - atlas->nodes[i].x;
@@ -597,7 +614,7 @@ static int fons__atlasAddSkylineLevel(struct FONSatlas* atlas, int idx, int x, i
return 1;
}
-static int fons__atlasRectFits(struct FONSatlas* atlas, int i, int w, int h)
+static int fons__atlasRectFits(FONSatlas* atlas, int i, int w, int h)
{
// Checks if there is enough space at the location of skyline span 'i',
// and return the max height of all skyline spans under that at that location,
@@ -618,7 +635,7 @@ static int fons__atlasRectFits(struct FONSatlas* atlas, int i, int w, int h)
return y;
}
-static int fons__atlasAddRect(struct FONSatlas* atlas, int rw, int rh, int* rx, int* ry)
+static int fons__atlasAddRect(FONSatlas* atlas, int rw, int rh, int* rx, int* ry)
{
int besth = atlas->height, bestw = atlas->width, besti = -1;
int bestx = -1, besty = -1, i;
@@ -650,7 +667,7 @@ static int fons__atlasAddRect(struct FONSatlas* atlas, int rw, int rh, int* rx,
return 1;
}
-static void fons__addWhiteRect(struct FONScontext* stash, int w, int h)
+static void fons__addWhiteRect(FONScontext* stash, int w, int h)
{
int x, y, gx, gy;
unsigned char* dst;
@@ -671,14 +688,14 @@ static void fons__addWhiteRect(struct FONScontext* stash, int w, int h)
stash->dirtyRect[3] = fons__maxi(stash->dirtyRect[3], gy+h);
}
-struct FONScontext* fonsCreateInternal(struct FONSparams* params)
+FONScontext* fonsCreateInternal(FONSparams* params)
{
- struct FONScontext* stash = NULL;
+ FONScontext* stash = NULL;
// Allocate memory for the font stash.
- stash = (struct FONScontext*)malloc(sizeof(struct FONScontext));
+ stash = (FONScontext*)malloc(sizeof(FONScontext));
if (stash == NULL) goto error;
- memset(stash, 0, sizeof(struct FONScontext));
+ memset(stash, 0, sizeof(FONScontext));
stash->params = *params;
@@ -698,9 +715,9 @@ struct FONScontext* fonsCreateInternal(struct FONSparams* params)
if (stash->atlas == NULL) goto error;
// Allocate space for fonts.
- stash->fonts = (struct FONSfont**)malloc(sizeof(struct FONSfont*) * FONS_INIT_FONTS);
+ stash->fonts = (FONSfont**)malloc(sizeof(FONSfont*) * FONS_INIT_FONTS);
if (stash->fonts == NULL) goto error;
- memset(stash->fonts, 0, sizeof(struct FONSfont*) * FONS_INIT_FONTS);
+ memset(stash->fonts, 0, sizeof(FONSfont*) * FONS_INIT_FONTS);
stash->cfonts = FONS_INIT_FONTS;
stash->nfonts = 0;
@@ -729,42 +746,42 @@ error:
return NULL;
}
-static struct FONSstate* fons__getState(struct FONScontext* stash)
+static FONSstate* fons__getState(FONScontext* stash)
{
return &stash->states[stash->nstates-1];
}
-void fonsSetSize(struct FONScontext* stash, float size)
+void fonsSetSize(FONScontext* stash, float size)
{
fons__getState(stash)->size = size;
}
-void fonsSetColor(struct FONScontext* stash, unsigned int color)
+void fonsSetColor(FONScontext* stash, unsigned int color)
{
fons__getState(stash)->color = color;
}
-void fonsSetSpacing(struct FONScontext* stash, float spacing)
+void fonsSetSpacing(FONScontext* stash, float spacing)
{
fons__getState(stash)->spacing = spacing;
}
-void fonsSetBlur(struct FONScontext* stash, float blur)
+void fonsSetBlur(FONScontext* stash, float blur)
{
fons__getState(stash)->blur = blur;
}
-void fonsSetAlign(struct FONScontext* stash, int align)
+void fonsSetAlign(FONScontext* stash, int align)
{
fons__getState(stash)->align = align;
}
-void fonsSetFont(struct FONScontext* stash, int font)
+void fonsSetFont(FONScontext* stash, int font)
{
fons__getState(stash)->font = font;
}
-void fonsPushState(struct FONScontext* stash)
+void fonsPushState(FONScontext* stash)
{
if (stash->nstates >= FONS_MAX_STATES) {
if (stash->handleError)
@@ -772,11 +789,11 @@ void fonsPushState(struct FONScontext* stash)
return;
}
if (stash->nstates > 0)
- memcpy(&stash->states[stash->nstates], &stash->states[stash->nstates-1], sizeof(struct FONSstate));
+ memcpy(&stash->states[stash->nstates], &stash->states[stash->nstates-1], sizeof(FONSstate));
stash->nstates++;
}
-void fonsPopState(struct FONScontext* stash)
+void fonsPopState(FONScontext* stash)
{
if (stash->nstates <= 1) {
if (stash->handleError)
@@ -786,9 +803,9 @@ void fonsPopState(struct FONScontext* stash)
stash->nstates--;
}
-void fonsClearState(struct FONScontext* stash)
+void fonsClearState(FONScontext* stash)
{
- struct FONSstate* state = fons__getState(stash);
+ FONSstate* state = fons__getState(stash);
state->size = 12.0f;
state->color = 0xffffffff;
state->font = 0;
@@ -797,7 +814,7 @@ void fonsClearState(struct FONScontext* stash)
state->align = FONS_ALIGN_LEFT | FONS_ALIGN_BASELINE;
}
-static void fons__freeFont(struct FONSfont* font)
+static void fons__freeFont(FONSfont* font)
{
if (font == NULL) return;
if (font->glyphs) free(font->glyphs);
@@ -805,20 +822,20 @@ static void fons__freeFont(struct FONSfont* font)
free(font);
}
-static int fons__allocFont(struct FONScontext* stash)
+static int fons__allocFont(FONScontext* stash)
{
- struct FONSfont* font = NULL;
+ FONSfont* font = NULL;
if (stash->nfonts+1 > stash->cfonts) {
stash->cfonts = stash->cfonts == 0 ? 8 : stash->cfonts * 2;
- stash->fonts = (struct FONSfont**)realloc(stash->fonts, sizeof(struct FONSfont*) * stash->cfonts);
+ stash->fonts = (FONSfont**)realloc(stash->fonts, sizeof(FONSfont*) * stash->cfonts);
if (stash->fonts == NULL)
return -1;
}
- font = (struct FONSfont*)malloc(sizeof(struct FONSfont));
+ font = (FONSfont*)malloc(sizeof(FONSfont));
if (font == NULL) goto error;
- memset(font, 0, sizeof(struct FONSfont));
+ memset(font, 0, sizeof(FONSfont));
- font->glyphs = (struct FONSglyph*)malloc(sizeof(struct FONSglyph) * FONS_INIT_GLYPHS);
+ font->glyphs = (FONSglyph*)malloc(sizeof(FONSglyph) * FONS_INIT_GLYPHS);
if (font->glyphs == NULL) goto error;
font->cglyphs = FONS_INIT_GLYPHS;
font->nglyphs = 0;
@@ -832,39 +849,36 @@ error:
return FONS_INVALID;
}
-int fonsAddFont(struct FONScontext* stash, const char* name, const char* path)
+int fonsAddFont(FONScontext* stash, const char* name, const char* path)
{
FILE* fp = 0;
int dataSize = 0;
unsigned char* data = NULL;
- size_t r;
// Read in the font data.
fp = fopen(path, "rb");
- if (!fp) goto error;
+ if (fp == NULL) goto error;
fseek(fp,0,SEEK_END);
dataSize = (int)ftell(fp);
fseek(fp,0,SEEK_SET);
data = (unsigned char*)malloc(dataSize);
if (data == NULL) goto error;
- r = fread(data, 1, dataSize, fp);
+ fread(data, 1, dataSize, fp);
fclose(fp);
fp = 0;
return fonsAddFontMem(stash, name, data, dataSize, 1);
- NVG_NOTUSED(r);
-
error:
if (data) free(data);
if (fp) fclose(fp);
return FONS_INVALID;
}
-int fonsAddFontMem(struct 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 i, ascent, descent, fh, lineGap;
- struct FONSfont* font;
+ FONSfont* font;
int idx = fons__allocFont(stash);
if (idx == FONS_INVALID)
@@ -904,7 +918,7 @@ error:
return FONS_INVALID;
}
-int fonsGetFontByName(struct FONScontext* s, const char* name)
+int fonsGetFontByName(FONScontext* s, const char* name)
{
int i;
for (i = 0; i < s->nfonts; i++) {
@@ -915,11 +929,11 @@ int fonsGetFontByName(struct FONScontext* s, const char* name)
}
-static struct FONSglyph* fons__allocGlyph(struct FONSfont* font)
+static FONSglyph* fons__allocGlyph(FONSfont* font)
{
if (font->nglyphs+1 > font->cglyphs) {
font->cglyphs = font->cglyphs == 0 ? 8 : font->cglyphs * 2;
- font->glyphs = (struct FONSglyph*)realloc(font->glyphs, sizeof(struct FONSglyph) * font->cglyphs);
+ font->glyphs = (FONSglyph*)realloc(font->glyphs, sizeof(FONSglyph) * font->cglyphs);
if (font->glyphs == NULL) return NULL;
}
font->nglyphs++;
@@ -973,7 +987,7 @@ static void fons__blurRows(unsigned char* dst, int w, int h, int dstStride, int
}
-static void fons__blur(struct FONScontext* stash, unsigned char* dst, int w, int h, int dstStride, int blur)
+static void fons__blur(FONScontext* stash, unsigned char* dst, int w, int h, int dstStride, int blur)
{
int alpha;
float sigma;
@@ -992,12 +1006,12 @@ static void fons__blur(struct FONScontext* stash, unsigned char* dst, int w, int
// fons__blurcols(dst, w, h, dstStride, alpha);
}
-static struct FONSglyph* fons__getGlyph(struct FONScontext* stash, struct FONSfont* font, unsigned int codepoint,
- short isize, short iblur)
+static FONSglyph* fons__getGlyph(FONScontext* stash, FONSfont* font, unsigned int codepoint,
+ short isize, short iblur)
{
int i, g, advance, lsb, x0, y0, x1, y1, gw, gh, gx, gy, x, y;
float scale;
- struct FONSglyph* glyph = NULL;
+ FONSglyph* glyph = NULL;
unsigned int h;
float size = isize/10.0f;
int pad, added;
@@ -1095,20 +1109,20 @@ static struct FONSglyph* fons__getGlyph(struct FONScontext* stash, struct FONSfo
return glyph;
}
-static void fons__getQuad(struct FONScontext* stash, struct FONSfont* font,
- struct FONSglyph* prevGlyph, struct FONSglyph* glyph,
- float scale, float spacing, float* x, float* y, struct FONSquad* q)
+static void fons__getQuad(FONScontext* stash, FONSfont* font,
+ int prevGlyphIndex, FONSglyph* glyph,
+ float scale, float spacing, float* x, float* y, FONSquad* q)
{
float rx,ry,xoff,yoff,x0,y0,x1,y1;
- if (prevGlyph) {
- float adv = fons__tt_getGlyphKernAdvance(&font->font, prevGlyph->index, glyph->index) * scale;
+ if (prevGlyphIndex != -1) {
+ float adv = fons__tt_getGlyphKernAdvance(&font->font, prevGlyphIndex, glyph->index) * scale;
*x += (int)(adv + spacing + 0.5f);
}
// Each glyph has 2px border to allow good interpolation,
// one pixel to prevent leaking, and one to allow good interpolation for rendering.
- // Inset the texture region by one pixel for corret interpolation.
+ // Inset the texture region by one pixel for correct interpolation.
xoff = (short)(glyph->xoff+1);
yoff = (short)(glyph->yoff+1);
x0 = (float)(glyph->x0+1);
@@ -1147,7 +1161,7 @@ static void fons__getQuad(struct FONScontext* stash, struct FONSfont* font,
*x += (int)(glyph->xadv / 10.0f + 0.5f);
}
-static void fons__flush(struct FONScontext* stash)
+static void fons__flush(FONScontext* stash)
{
// Flush texture
if (stash->dirtyRect[0] < stash->dirtyRect[2] && stash->dirtyRect[1] < stash->dirtyRect[3]) {
@@ -1168,7 +1182,7 @@ static void fons__flush(struct FONScontext* stash)
}
}
-static __inline void fons__vertex(struct FONScontext* stash, float x, float y, float s, float t, unsigned int c)
+static __inline void fons__vertex(FONScontext* stash, float x, float y, float s, float t, unsigned int c)
{
stash->verts[stash->nverts*2+0] = x;
stash->verts[stash->nverts*2+1] = y;
@@ -1178,7 +1192,7 @@ static __inline void fons__vertex(struct FONScontext* stash, float x, float y, f
stash->nverts++;
}
-static float fons__getVertAlign(struct FONScontext* stash, struct FONSfont* font, int align, short isize)
+static float fons__getVertAlign(FONScontext* stash, FONSfont* font, int align, short isize)
{
if (stash->params.flags & FONS_ZERO_TOPLEFT) {
if (align & FONS_ALIGN_TOP) {
@@ -1204,26 +1218,26 @@ static float fons__getVertAlign(struct FONScontext* stash, struct FONSfont* font
return 0.0;
}
-float fonsDrawText(struct FONScontext* stash,
+float fonsDrawText(FONScontext* stash,
float x, float y,
const char* str, const char* end)
{
- struct FONSstate* state = fons__getState(stash);
+ FONSstate* state = fons__getState(stash);
unsigned int codepoint;
unsigned int utf8state = 0;
- struct FONSglyph* glyph = NULL;
- struct FONSglyph* prevGlyph = NULL;
- struct FONSquad q;
+ FONSglyph* glyph = NULL;
+ FONSquad q;
+ int prevGlyphIndex = -1;
short isize = (short)(state->size*10.0f);
short iblur = (short)state->blur;
float scale;
- struct FONSfont* font;
+ FONSfont* font;
float width;
if (stash == NULL) return x;
if (state->font < 0 || state->font >= stash->nfonts) return x;
font = stash->fonts[state->font];
- if (!font->data) return x;
+ if (font->data == NULL) return x;
scale = fons__tt_getPixelHeightScale(&font->font, (float)isize/10.0f);
@@ -1247,8 +1261,8 @@ float fonsDrawText(struct FONScontext* stash,
if (fons__decutf8(&utf8state, &codepoint, *(const unsigned char*)str))
continue;
glyph = fons__getGlyph(stash, font, codepoint, isize, iblur);
- if (glyph) {
- fons__getQuad(stash, font, prevGlyph, glyph, scale, state->spacing, &x, &y, &q);
+ if (glyph != NULL) {
+ fons__getQuad(stash, font, prevGlyphIndex, glyph, scale, state->spacing, &x, &y, &q);
if (stash->nverts+6 > FONS_VERTEX_COUNT)
fons__flush(stash);
@@ -1261,17 +1275,17 @@ float fonsDrawText(struct FONScontext* stash,
fons__vertex(stash, q.x0, q.y1, q.s0, q.t1, state->color);
fons__vertex(stash, q.x1, q.y1, q.s1, q.t1, state->color);
}
- prevGlyph = glyph;
+ prevGlyphIndex = glyph != NULL ? glyph->index : -1;
}
fons__flush(stash);
return x;
}
-int fonsTextIterInit(struct FONScontext* stash, struct FONStextIter* iter,
+int fonsTextIterInit(FONScontext* stash, FONStextIter* iter,
float x, float y, const char* str, const char* end)
{
- struct FONSstate* state = fons__getState(stash);
+ FONSstate* state = fons__getState(stash);
float width;
memset(iter, 0, sizeof(*iter));
@@ -1279,7 +1293,7 @@ int fonsTextIterInit(struct FONScontext* stash, struct FONStextIter* iter,
if (stash == NULL) return 0;
if (state->font < 0 || state->font >= stash->nfonts) return 0;
iter->font = stash->fonts[state->font];
- if (!iter->font->data) return 0;
+ if (iter->font->data == NULL) return 0;
iter->isize = (short)(state->size*10.0f);
iter->iblur = (short)state->blur;
@@ -1308,13 +1322,14 @@ int fonsTextIterInit(struct FONScontext* stash, struct FONStextIter* iter,
iter->next = str;
iter->end = end;
iter->codepoint = 0;
+ iter->prevGlyphIndex = -1;
return 1;
}
-int fonsTextIterNext(struct FONScontext* stash, struct FONStextIter* iter, struct FONSquad* quad)
+int fonsTextIterNext(FONScontext* stash, FONStextIter* iter, FONSquad* quad)
{
- struct FONSglyph* glyph = NULL;
+ FONSglyph* glyph = NULL;
const char* str = iter->next;
iter->str = iter->next;
@@ -1330,8 +1345,8 @@ int fonsTextIterNext(struct FONScontext* stash, struct FONStextIter* iter, struc
iter->y = iter->nexty;
glyph = fons__getGlyph(stash, iter->font, iter->codepoint, iter->isize, iter->iblur);
if (glyph != NULL)
- fons__getQuad(stash, iter->font, iter->prevGlyph, glyph, iter->scale, iter->spacing, &iter->nextx, &iter->nexty, quad);
- iter->prevGlyph = glyph;
+ fons__getQuad(stash, iter->font, iter->prevGlyphIndex, glyph, iter->scale, iter->spacing, &iter->nextx, &iter->nexty, quad);
+ iter->prevGlyphIndex = glyph != NULL ? glyph->index : -1;
break;
}
iter->next = str;
@@ -1339,7 +1354,7 @@ int fonsTextIterNext(struct FONScontext* stash, struct FONStextIter* iter, struc
return 1;
}
-void fonsDrawDebug(struct FONScontext* stash, float x, float y)
+void fonsDrawDebug(FONScontext* stash, float x, float y)
{
int i;
int w = stash->params.width;
@@ -1370,7 +1385,7 @@ void fonsDrawDebug(struct FONScontext* stash, float x, float y)
// Drawbug draw atlas
for (i = 0; i < stash->atlas->nnodes; i++) {
- struct FONSatlasNode* n = &stash->atlas->nodes[i];
+ FONSatlasNode* n = &stash->atlas->nodes[i];
if (stash->nverts+6 > FONS_VERTEX_COUNT)
fons__flush(stash);
@@ -1387,28 +1402,28 @@ void fonsDrawDebug(struct FONScontext* stash, float x, float y)
fons__flush(stash);
}
-float fonsTextBounds(struct FONScontext* stash,
- float x, float y,
+float fonsTextBounds(FONScontext* stash,
+ float x, float y,
const char* str, const char* end,
float* bounds)
{
- struct FONSstate* state = fons__getState(stash);
+ FONSstate* state = fons__getState(stash);
unsigned int codepoint;
unsigned int utf8state = 0;
- struct FONSquad q;
- struct FONSglyph* glyph = NULL;
- struct FONSglyph* prevGlyph = NULL;
+ FONSquad q;
+ FONSglyph* glyph = NULL;
+ int prevGlyphIndex = -1;
short isize = (short)(state->size*10.0f);
short iblur = (short)state->blur;
float scale;
- struct FONSfont* font;
+ FONSfont* font;
float startx, advance;
float minx, miny, maxx, maxy;
if (stash == NULL) return 0;
if (state->font < 0 || state->font >= stash->nfonts) return 0;
font = stash->fonts[state->font];
- if (!font->data) return 0;
+ if (font->data == NULL) return 0;
scale = fons__tt_getPixelHeightScale(&font->font, (float)isize/10.0f);
@@ -1426,8 +1441,8 @@ float fonsTextBounds(struct FONScontext* stash,
if (fons__decutf8(&utf8state, &codepoint, *(const unsigned char*)str))
continue;
glyph = fons__getGlyph(stash, font, codepoint, isize, iblur);
- if (glyph) {
- fons__getQuad(stash, font, prevGlyph, glyph, scale, state->spacing, &x, &y, &q);
+ if (glyph != NULL) {
+ fons__getQuad(stash, font, prevGlyphIndex, glyph, scale, state->spacing, &x, &y, &q);
if (q.x0 < minx) minx = q.x0;
if (q.x1 > maxx) maxx = q.x1;
if (stash->params.flags & FONS_ZERO_TOPLEFT) {
@@ -1438,7 +1453,7 @@ float fonsTextBounds(struct FONScontext* stash,
if (q.y0 > maxy) maxy = q.y0;
}
}
- prevGlyph = glyph;
+ prevGlyphIndex = glyph != NULL ? glyph->index : -1;
}
advance = x - startx;
@@ -1464,18 +1479,18 @@ float fonsTextBounds(struct FONScontext* stash,
return advance;
}
-void fonsVertMetrics(struct FONScontext* stash,
+void fonsVertMetrics(FONScontext* stash,
float* ascender, float* descender, float* lineh)
{
- struct FONSfont* font;
- struct FONSstate* state = fons__getState(stash);
+ FONSfont* font;
+ FONSstate* state = fons__getState(stash);
short isize;
if (stash == NULL) return;
if (state->font < 0 || state->font >= stash->nfonts) return;
font = stash->fonts[state->font];
isize = (short)(state->size*10.0f);
- if (!font->data) return;
+ if (font->data == NULL) return;
if (ascender)
*ascender = font->ascender*isize/10.0f;
@@ -1485,17 +1500,17 @@ void fonsVertMetrics(struct FONScontext* stash,
*lineh = font->lineh*isize/10.0f;
}
-void fonsLineBounds(struct FONScontext* stash, float y, float* miny, float* maxy)
+void fonsLineBounds(FONScontext* stash, float y, float* miny, float* maxy)
{
- struct FONSfont* font;
- struct FONSstate* state = fons__getState(stash);
+ FONSfont* font;
+ FONSstate* state = fons__getState(stash);
short isize;
if (stash == NULL) return;
if (state->font < 0 || state->font >= stash->nfonts) return;
font = stash->fonts[state->font];
isize = (short)(state->size*10.0f);
- if (!font->data) return;
+ if (font->data == NULL) return;
y += fons__getVertAlign(stash, font, state->align, isize);
@@ -1508,7 +1523,7 @@ void fonsLineBounds(struct FONScontext* stash, float y, float* miny, float* maxy
}
}
-const unsigned char* fonsGetTextureData(struct FONScontext* stash, int* width, int* height)
+const unsigned char* fonsGetTextureData(FONScontext* stash, int* width, int* height)
{
if (width != NULL)
*width = stash->params.width;
@@ -1517,7 +1532,7 @@ const unsigned char* fonsGetTextureData(struct FONScontext* stash, int* width, i
return stash->texData;
}
-int fonsValidateTexture(struct FONScontext* stash, int* dirty)
+int fonsValidateTexture(FONScontext* stash, int* dirty)
{
if (stash->dirtyRect[0] < stash->dirtyRect[2] && stash->dirtyRect[1] < stash->dirtyRect[3]) {
dirty[0] = stash->dirtyRect[0];
@@ -1534,7 +1549,7 @@ int fonsValidateTexture(struct FONScontext* stash, int* dirty)
return 0;
}
-void fonsDeleteInternal(struct FONScontext* stash)
+void fonsDeleteInternal(FONScontext* stash)
{
int i;
if (stash == NULL) return;
@@ -1552,21 +1567,21 @@ void fonsDeleteInternal(struct FONScontext* stash)
free(stash);
}
-void fonsSetErrorCallback(struct 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)
{
if (stash == NULL) return;
stash->handleError = callback;
stash->errorUptr = uptr;
}
-void fonsGetAtlasSize(struct FONScontext* stash, int* width, int* height)
+void fonsGetAtlasSize(FONScontext* stash, int* width, int* height)
{
if (stash == NULL) return;
*width = stash->params.width;
*height = stash->params.height;
}
-int fonsExpandAtlas(struct FONScontext* stash, int width, int height)
+int fonsExpandAtlas(FONScontext* stash, int width, int height)
{
int i, maxy = 0;
unsigned char* data = NULL;
@@ -1576,7 +1591,7 @@ int fonsExpandAtlas(struct FONScontext* stash, int width, int height)
height = fons__maxi(height, stash->params.height);
if (width == stash->params.width && height == stash->params.height)
- return 1;
+ return 1;
// Flush pending glyphs.
fons__flush(stash);
@@ -1606,7 +1621,7 @@ int fonsExpandAtlas(struct FONScontext* stash, int width, int height)
// Increase atlas size
fons__atlasExpand(stash->atlas, width, height);
- // Add axisting data as dirty.
+ // Add existing data as dirty.
for (i = 0; i < stash->atlas->nnodes; i++)
maxy = fons__maxi(maxy, stash->atlas->nodes[i].y);
stash->dirtyRect[0] = 0;
@@ -1622,7 +1637,7 @@ int fonsExpandAtlas(struct FONScontext* stash, int width, int height)
return 1;
}
-int fonsResetAtlas(struct FONScontext* stash, int width, int height)
+int fonsResetAtlas(FONScontext* stash, int width, int height)
{
int i, j;
if (stash == NULL) return 0;
@@ -1652,7 +1667,7 @@ int fonsResetAtlas(struct FONScontext* stash, int width, int height)
// Reset cached glyphs
for (i = 0; i < stash->nfonts; i++) {
- struct FONSfont* font = stash->fonts[i];
+ FONSfont* font = stash->fonts[i];
font->nglyphs = 0;
for (j = 0; j < FONS_HASH_LUT_SIZE; j++)
font->lut[j] = -1;
diff --git a/dgl/src/nanovg/nanovg_gl_utils.h b/dgl/src/nanovg/nanovg_gl_utils.h
new file mode 100644
index 00000000..89ae4811
--- /dev/null
+++ b/dgl/src/nanovg/nanovg_gl_utils.h
@@ -0,0 +1,132 @@
+//
+// Copyright (c) 2009-2013 Mikko Mononen memon@inside.org
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would be
+// appreciated but is not required.
+// 2. Altered source versions must be plainly marked as such, and must not be
+// misrepresented as being the original software.
+// 3. This notice may not be removed or altered from any source distribution.
+//
+#ifndef NANOVG_GL_UTILS_H
+#define NANOVG_GL_UTILS_H
+
+struct NVGLUframebuffer {
+ NVGcontext* ctx;
+ GLuint fbo;
+ GLuint rbo;
+ GLuint texture;
+ int image;
+};
+typedef struct NVGLUframebuffer NVGLUframebuffer;
+
+// Helper function to create GL frame buffer to render to.
+void nvgluBindFramebuffer(NVGLUframebuffer* fb);
+NVGLUframebuffer* nvgluCreateFramebuffer(NVGcontext* ctx, int w, int h, int imageFlags);
+void nvgluDeleteFramebuffer(NVGcontext* ctx, NVGLUframebuffer* fb);
+
+#endif // NANOVG_GL_UTILS_H
+
+#ifdef NANOVG_GL_IMPLEMENTATION
+
+#if defined(NANOVG_GL3) || defined(NANOVG_GLES2) || defined(NANOVG_GLES3)
+// FBO is core in OpenGL 3>.
+# define NANOVG_FBO_VALID 1
+#elif defined(NANOVG_GL2)
+// On OS X including glext defines FBO on GL2 too.
+# ifdef __APPLE__
+# include <OpenGL/glext.h>
+# define NANOVG_FBO_VALID 1
+# endif
+#endif
+
+static GLint defaultFBO = -1;
+
+NVGLUframebuffer* nvgluCreateFramebuffer(NVGcontext* ctx, int w, int h, int imageFlags)
+{
+#ifdef NANOVG_FBO_VALID
+ GLint defaultFBO;
+ GLint defaultRBO;
+ NVGLUframebuffer* fb = NULL;
+
+ glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO);
+ glGetIntegerv(GL_RENDERBUFFER_BINDING, &defaultRBO);
+
+ fb = (NVGLUframebuffer*)malloc(sizeof(NVGLUframebuffer));
+ if (fb == NULL) goto error;
+ memset(fb, 0, sizeof(NVGLUframebuffer));
+
+ fb->image = nvgCreateImageRGBA(ctx, w, h, imageFlags | NVG_IMAGE_FLIPY | NVG_IMAGE_PREMULTIPLIED, NULL);
+ fb->texture = nvglImageHandle(ctx, fb->image);
+
+ // frame buffer object
+ glGenFramebuffers(1, &fb->fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, fb->fbo);
+
+ // render buffer object
+ glGenRenderbuffers(1, &fb->rbo);
+ glBindRenderbuffer(GL_RENDERBUFFER, fb->rbo);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, w, h);
+
+ // combine all
+ 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) goto error;
+
+ glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO);
+ glBindRenderbuffer(GL_RENDERBUFFER, defaultRBO);
+ return fb;
+error:
+ glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO);
+ glBindRenderbuffer(GL_RENDERBUFFER, defaultRBO);
+ nvgluDeleteFramebuffer(ctx, fb);
+ return NULL;
+#else
+ NVG_NOTUSED(ctx);
+ NVG_NOTUSED(w);
+ NVG_NOTUSED(h);
+ NVG_NOTUSED(imageFlags);
+ return NULL;
+#endif
+}
+
+void nvgluBindFramebuffer(NVGLUframebuffer* fb)
+{
+#ifdef NANOVG_FBO_VALID
+ if (defaultFBO == -1) glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO);
+ glBindFramebuffer(GL_FRAMEBUFFER, fb != NULL ? fb->fbo : defaultFBO);
+#else
+ NVG_NOTUSED(fb);
+#endif
+}
+
+void nvgluDeleteFramebuffer(NVGcontext* ctx, NVGLUframebuffer* fb)
+{
+#ifdef NANOVG_FBO_VALID
+ if (fb == NULL) return;
+ if (fb->fbo != 0)
+ glDeleteFramebuffers(1, &fb->fbo);
+ if (fb->rbo != 0)
+ glDeleteRenderbuffers(1, &fb->rbo);
+ if (fb->image >= 0)
+ nvgDeleteImage(ctx, fb->image);
+ fb->fbo = 0;
+ fb->rbo = 0;
+ fb->texture = 0;
+ fb->image = -1;
+ free(fb);
+#else
+ NVG_NOTUSED(ctx);
+ NVG_NOTUSED(fb);
+#endif
+}
+
+#endif // NANOVG_GL_IMPLEMENTATION