1 //
2 // Copyright (c) 2009-2013 Mikko Mononen memon@inside.org
3 //
4 // This software is provided 'as-is', without any express or implied
5 // warranty.  In no event will the authors be held liable for any damages
6 // arising from the use of this software.
7 // Permission is granted to anyone to use this software for any purpose,
8 // including commercial applications, and to alter it and redistribute it
9 // freely, subject to the following restrictions:
10 // 1. The origin of this software must not be misrepresented; you must not
11 //    claim that you wrote the original software. If you use this software
12 //    in a product, an acknowledgment in the product documentation would be
13 //    appreciated but is not required.
14 // 2. Altered source versions must be plainly marked as such, and must not be
15 //    misrepresented as being the original software.
16 // 3. This notice may not be removed or altered from any source distribution.
17 //
18 #ifndef GLFONTSTASH_H
19 #define GLFONTSTASH_H
20 
21 FONScontext* glfonsCreate(int width, int height, int flags);
22 void glfonsDelete(FONScontext* ctx);
23 
24 unsigned int glfonsRGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a);
25 
26 #endif
27 
28 #ifdef GLFONTSTASH_IMPLEMENTATION
29 
30 struct GLFONScontext {
31 	GLuint tex;
32 	int width, height;
33 };
34 typedef struct GLFONScontext GLFONScontext;
35 
glfons__renderCreate(void * userPtr,int width,int height)36 static int glfons__renderCreate(void* userPtr, int width, int height)
37 {
38 	GLFONScontext* gl = (GLFONScontext*)userPtr;
39 	// Create may be called multiple times, delete existing texture.
40 	if (gl->tex != 0) {
41 		glDeleteTextures(1, &gl->tex);
42 		gl->tex = 0;
43 	}
44 	glGenTextures(1, &gl->tex);
45 	if (!gl->tex) return 0;
46 	gl->width = width;
47 	gl->height = height;
48 	glBindTexture(GL_TEXTURE_2D, gl->tex);
49 	glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, gl->width, gl->height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, 0);
50 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
51 	return 1;
52 }
53 
glfons__renderResize(void * userPtr,int width,int height)54 static int glfons__renderResize(void* userPtr, int width, int height)
55 {
56 	// Reuse create to resize too.
57 	return glfons__renderCreate(userPtr, width, height);
58 }
59 
glfons__renderUpdate(void * userPtr,int * rect,const unsigned char * data)60 static void glfons__renderUpdate(void* userPtr, int* rect, const unsigned char* data)
61 {
62 	GLFONScontext* gl = (GLFONScontext*)userPtr;
63 	int w = rect[2] - rect[0];
64 	int h = rect[3] - rect[1];
65 
66 	if (gl->tex == 0) return;
67 	glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
68 	glBindTexture(GL_TEXTURE_2D, gl->tex);
69 	glPixelStorei(GL_UNPACK_ALIGNMENT,1);
70 	glPixelStorei(GL_UNPACK_ROW_LENGTH, gl->width);
71 	glPixelStorei(GL_UNPACK_SKIP_PIXELS, rect[0]);
72 	glPixelStorei(GL_UNPACK_SKIP_ROWS, rect[1]);
73 	glTexSubImage2D(GL_TEXTURE_2D, 0, rect[0], rect[1], w, h, GL_ALPHA,GL_UNSIGNED_BYTE, data);
74 	glPopClientAttrib();
75 }
76 
glfons__renderDraw(void * userPtr,const float * verts,const float * tcoords,const unsigned int * colors,int nverts)77 static void glfons__renderDraw(void* userPtr, const float* verts, const float* tcoords, const unsigned int* colors, int nverts)
78 {
79 	GLFONScontext* gl = (GLFONScontext*)userPtr;
80 	if (gl->tex == 0) return;
81 	glBindTexture(GL_TEXTURE_2D, gl->tex);
82 	glEnable(GL_TEXTURE_2D);
83 	glEnableClientState(GL_VERTEX_ARRAY);
84 	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
85 	glEnableClientState(GL_COLOR_ARRAY);
86 
87 	glVertexPointer(2, GL_FLOAT, sizeof(float)*2, verts);
88 	glTexCoordPointer(2, GL_FLOAT, sizeof(float)*2, tcoords);
89 	glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(unsigned int), colors);
90 
91 	glDrawArrays(GL_TRIANGLES, 0, nverts);
92 
93 	glDisable(GL_TEXTURE_2D);
94 	glDisableClientState(GL_VERTEX_ARRAY);
95 	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
96 	glDisableClientState(GL_COLOR_ARRAY);
97 }
98 
glfons__renderDelete(void * userPtr)99 static void glfons__renderDelete(void* userPtr)
100 {
101 	GLFONScontext* gl = (GLFONScontext*)userPtr;
102 	if (gl->tex != 0)
103 		glDeleteTextures(1, &gl->tex);
104 	gl->tex = 0;
105 	free(gl);
106 }
107 
108 
glfonsCreate(int width,int height,int flags)109 FONScontext* glfonsCreate(int width, int height, int flags)
110 {
111 	FONSparams params;
112 	GLFONScontext* gl;
113 
114 	gl = (GLFONScontext*)malloc(sizeof(GLFONScontext));
115 	if (gl == NULL) goto error;
116 	memset(gl, 0, sizeof(GLFONScontext));
117 
118 	memset(&params, 0, sizeof(params));
119 	params.width = width;
120 	params.height = height;
121 	params.flags = (unsigned char)flags;
122 	params.renderCreate = glfons__renderCreate;
123 	params.renderResize = glfons__renderResize;
124 	params.renderUpdate = glfons__renderUpdate;
125 	params.renderDraw = glfons__renderDraw;
126 	params.renderDelete = glfons__renderDelete;
127 	params.userPtr = gl;
128 
129 	return fonsCreateInternal(&params);
130 
131 error:
132 	if (gl != NULL) free(gl);
133 	return NULL;
134 }
135 
glfonsDelete(FONScontext * ctx)136 void glfonsDelete(FONScontext* ctx)
137 {
138 	fonsDeleteInternal(ctx);
139 }
140 
glfonsRGBA(unsigned char r,unsigned char g,unsigned char b,unsigned char a)141 unsigned int glfonsRGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
142 {
143 	return (r) | (g << 8) | (b << 16) | (a << 24);
144 }
145 
146 #endif
147