#ifndef GLFONTSTASH_H
#define GLFONTSTASH_H
FONScontext* glfonsCreate(int width, int height, int flags);
void glfonsDelete(FONScontext* ctx);
unsigned int glfonsRGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a);
#endif
#ifdef GLFONTSTASH_IMPLEMENTATION
struct GLFONScontext {
GLuint tex;
int width, height;
};
typedef struct GLFONScontext GLFONScontext;
static int glfons__renderCreate(void* userPtr, int width, int height)
{
GLFONScontext* gl = (GLFONScontext*)userPtr;
if (gl->tex != 0) {
glDeleteTextures(1, &gl->tex);
gl->tex = 0;
}
glGenTextures(1, &gl->tex);
if (!gl->tex) return 0;
gl->width = width;
gl->height = height;
glBindTexture(GL_TEXTURE_2D, gl->tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, gl->width, gl->height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
return 1;
}
static int glfons__renderResize(void* userPtr, int width, int height)
{
return glfons__renderCreate(userPtr, width, height);
}
static void glfons__renderUpdate(void* userPtr, int* rect, const unsigned char* data)
{
GLFONScontext* gl = (GLFONScontext*)userPtr;
int w = rect[2] - rect[0];
int h = rect[3] - rect[1];
if (gl->tex == 0) return;
glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
glBindTexture(GL_TEXTURE_2D, gl->tex);
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
glPixelStorei(GL_UNPACK_ROW_LENGTH, gl->width);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, rect[0]);
glPixelStorei(GL_UNPACK_SKIP_ROWS, rect[1]);
glTexSubImage2D(GL_TEXTURE_2D, 0, rect[0], rect[1], w, h, GL_ALPHA,GL_UNSIGNED_BYTE, data);
glPopClientAttrib();
}
static void glfons__renderDraw(void* userPtr, const float* verts, const float* tcoords, const unsigned int* colors, int nverts)
{
GLFONScontext* gl = (GLFONScontext*)userPtr;
if (gl->tex == 0) return;
glBindTexture(GL_TEXTURE_2D, gl->tex);
glEnable(GL_TEXTURE_2D);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(2, GL_FLOAT, sizeof(float)*2, verts);
glTexCoordPointer(2, GL_FLOAT, sizeof(float)*2, tcoords);
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(unsigned int), colors);
glDrawArrays(GL_TRIANGLES, 0, nverts);
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
}
static void glfons__renderDelete(void* userPtr)
{
GLFONScontext* gl = (GLFONScontext*)userPtr;
if (gl->tex != 0)
glDeleteTextures(1, &gl->tex);
gl->tex = 0;
free(gl);
}
FONScontext* glfonsCreate(int width, int height, int flags)
{
FONSparams params;
GLFONScontext* gl;
gl = (GLFONScontext*)malloc(sizeof(GLFONScontext));
if (gl == NULL) goto error;
memset(gl, 0, sizeof(GLFONScontext));
memset(¶ms, 0, sizeof(params));
params.width = width;
params.height = height;
params.flags = (unsigned char)flags;
params.renderCreate = glfons__renderCreate;
params.renderResize = glfons__renderResize;
params.renderUpdate = glfons__renderUpdate;
params.renderDraw = glfons__renderDraw;
params.renderDelete = glfons__renderDelete;
params.userPtr = gl;
return fonsCreateInternal(¶ms);
error:
if (gl != NULL) free(gl);
return NULL;
}
void glfonsDelete(FONScontext* ctx)
{
fonsDeleteInternal(ctx);
}
unsigned int glfonsRGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
{
return (r) | (g << 8) | (b << 16) | (a << 24);
}
#endif