vrshoot

view libs/drawtext/drawgl.c @ 0:b2f14e535253

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 01 Feb 2014 19:58:19 +0200
parents
children
line source
1 /*
2 libdrawtext - a simple library for fast text rendering in OpenGL
3 Copyright (C) 2011-2012 John Tsiombikas <nuclear@member.fsf.org>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 #ifndef NO_OPENGL
19 #include <stdarg.h>
20 #include <math.h>
21 #include <ctype.h>
23 #include <stdlib.h>
25 #ifdef _MSC_VER
26 #include <malloc.h>
27 #else
28 #include <alloca.h>
29 #endif
31 #ifdef TARGET_IPHONE
32 #include <OpenGLES/ES2/gl.h>
34 #define GL_CLAMP GL_CLAMP_TO_EDGE
36 #else
37 #include <GL/glew.h>
38 #endif
40 #include "drawtext.h"
41 #include "drawtext_impl.h"
43 struct vertex {
44 float x, y;
45 float s, t;
46 };
48 struct quad {
49 struct vertex v[6];
50 };
52 static void cleanup(void);
53 static void add_glyph(struct glyph *g, float x, float y);
55 #define QBUF_SZ 512
56 static struct quad *qbuf;
57 static int num_quads;
58 static int vattr = -1;
59 static int tattr = -1;
60 static unsigned int font_tex;
61 static int buf_mode = DTX_NBF;
64 int dtx_gl_init(void)
65 {
66 if(qbuf) {
67 return 0; /* already initialized */
68 }
70 /*glewInit();*/
72 if(!(qbuf = malloc(QBUF_SZ * sizeof *qbuf))) {
73 return -1;
74 }
75 num_quads = 0;
77 atexit(cleanup);
78 return 0;
79 }
81 static void cleanup(void)
82 {
83 free(qbuf);
84 }
87 void dtx_vertex_attribs(int vert_attr, int tex_attr)
88 {
89 vattr = vert_attr;
90 tattr = tex_attr;
91 }
93 static void set_glyphmap_texture(struct dtx_glyphmap *gmap)
94 {
95 if(!gmap->tex) {
96 glGenTextures(1, &gmap->tex);
97 glBindTexture(GL_TEXTURE_2D, gmap->tex);
98 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
99 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
100 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
101 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
103 #ifdef GL_ES_VERSION_2_0
104 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, gmap->xsz, gmap->ysz, 0, GL_ALPHA, GL_UNSIGNED_BYTE, gmap->pixels);
105 glGenerateMipmap(GL_TEXTURE_2D);
106 #else
107 gluBuild2DMipmaps(GL_TEXTURE_2D, GL_ALPHA, gmap->xsz, gmap->ysz, GL_ALPHA, GL_UNSIGNED_BYTE, gmap->pixels);
108 #endif
109 }
111 if(font_tex != gmap->tex) {
112 dtx_flush();
113 }
114 font_tex = gmap->tex;
115 }
117 void dtx_glyph(int code)
118 {
119 struct dtx_glyphmap *gmap;
121 if(!dtx_font || !(gmap = dtx_get_font_glyphmap(dtx_font, dtx_font_sz, code))) {
122 return;
123 }
124 set_glyphmap_texture(gmap);
126 add_glyph(gmap->glyphs + code - gmap->cstart, 0, 0);
127 dtx_flush();
128 }
130 static const char *put_char(const char *str, float *pos_x, float *pos_y, int *should_flush)
131 {
132 struct dtx_glyphmap *gmap;
133 float px, py;
134 int code = dtx_utf8_char_code(str);
135 str = dtx_utf8_next_char((char*)str);
137 if(buf_mode == DTX_LBF && code == '\n') {
138 *should_flush = 1;
139 }
141 px = *pos_x;
142 py = *pos_y;
144 if((gmap = dtx_proc_char(code, pos_x, pos_y))) {
145 int idx = code - gmap->cstart;
147 set_glyphmap_texture(gmap);
148 add_glyph(gmap->glyphs + idx, px, py);
149 }
150 return str;
151 }
153 void dtx_string(const char *str)
154 {
155 int should_flush = buf_mode == DTX_NBF;
156 float pos_x = 0.0f;
157 float pos_y = 0.0f;
159 if(!dtx_font) {
160 return;
161 }
163 while(*str) {
164 str = put_char(str, &pos_x, &pos_y, &should_flush);
165 }
167 if(should_flush) {
168 dtx_flush();
169 }
170 }
172 void dtx_printf(const char *fmt, ...)
173 {
174 va_list ap;
175 int buf_size;
176 char *buf, tmp;
178 if(!dtx_font) {
179 return;
180 }
182 va_start(ap, fmt);
183 buf_size = vsnprintf(&tmp, 0, fmt, ap);
184 va_end(ap);
186 if(buf_size == -1) {
187 buf_size = 512;
188 }
190 buf = alloca(buf_size + 1);
191 va_start(ap, fmt);
192 vsnprintf(buf, buf_size + 1, fmt, ap);
193 va_end(ap);
195 dtx_string(buf);
196 }
198 static void qvertex(struct vertex *v, float x, float y, float s, float t)
199 {
200 v->x = x;
201 v->y = y;
202 v->s = s;
203 v->t = t;
204 }
206 static void add_glyph(struct glyph *g, float x, float y)
207 {
208 struct quad *qptr = qbuf + num_quads;
210 x -= g->orig_x;
211 y -= g->orig_y;
213 qvertex(qptr->v + 0, x, y, g->nx, g->ny + g->nheight);
214 qvertex(qptr->v + 1, x + g->width, y, g->nx + g->nwidth, g->ny + g->nheight);
215 qvertex(qptr->v + 2, x + g->width, y + g->height, g->nx + g->nwidth, g->ny);
217 qvertex(qptr->v + 3, x, y, g->nx, g->ny + g->nheight);
218 qvertex(qptr->v + 4, x + g->width, y + g->height, g->nx + g->nwidth, g->ny);
219 qvertex(qptr->v + 5, x, y + g->height, g->nx, g->ny);
221 if(++num_quads >= QBUF_SZ) {
222 dtx_flush();
223 }
224 }
226 void dtx_draw_buffering(int mode)
227 {
228 dtx_flush();
229 buf_mode = mode;
230 }
232 void dtx_flush(void)
233 {
234 int vbo;
236 if(!num_quads) {
237 return;
238 }
240 if(glBindBuffer) {
241 glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &vbo);
242 glBindBuffer(GL_ARRAY_BUFFER, 0);
243 }
245 #ifndef GL_ES_VERSION_2_0
246 glPushAttrib(GL_ENABLE_BIT);
247 glEnable(GL_TEXTURE_2D);
248 #endif
249 glBindTexture(GL_TEXTURE_2D, font_tex);
251 if(vattr != -1 && glEnableVertexAttribArray) {
252 glEnableVertexAttribArray(vattr);
253 glVertexAttribPointer(vattr, 2, GL_FLOAT, 0, sizeof(struct vertex), qbuf);
254 #ifndef GL_ES_VERSION_2_0
255 } else {
256 glEnableClientState(GL_VERTEX_ARRAY);
257 glVertexPointer(2, GL_FLOAT, sizeof(struct vertex), qbuf);
258 #endif
259 }
260 if(tattr != -1 && glEnableVertexAttribArray) {
261 glEnableVertexAttribArray(tattr);
262 glVertexAttribPointer(tattr, 2, GL_FLOAT, 0, sizeof(struct vertex), &qbuf->v[0].s);
263 #ifndef GL_ES_VERSION_2_0
264 } else {
265 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
266 glTexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), &qbuf->v[0].s);
267 #endif
268 }
270 glEnable(GL_BLEND);
271 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
273 glDepthMask(0);
275 glDrawArrays(GL_TRIANGLES, 0, num_quads * 6);
277 glDepthMask(1);
279 if(vattr != -1 && glDisableVertexAttribArray) {
280 glDisableVertexAttribArray(vattr);
281 #ifndef GL_ES_VERSION_2_0
282 } else {
283 glDisableClientState(GL_VERTEX_ARRAY);
284 #endif
285 }
286 if(tattr != -1 && glDisableVertexAttribArray) {
287 glDisableVertexAttribArray(tattr);
288 #ifndef GL_ES_VERSION_2_0
289 } else {
290 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
291 #endif
292 }
294 #ifndef GL_ES_VERSION_2_0
295 glPopAttrib();
296 #else
297 glDisable(GL_BLEND);
298 #endif
300 if(glBindBuffer && vbo) {
301 glBindBuffer(GL_ARRAY_BUFFER, vbo);
302 }
304 num_quads = 0;
305 }
307 #endif /* !def NO_OPENGL */