vrshoot
diff 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 diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/libs/drawtext/drawgl.c Sat Feb 01 19:58:19 2014 +0200 1.3 @@ -0,0 +1,307 @@ 1.4 +/* 1.5 +libdrawtext - a simple library for fast text rendering in OpenGL 1.6 +Copyright (C) 2011-2012 John Tsiombikas <nuclear@member.fsf.org> 1.7 + 1.8 +This program is free software: you can redistribute it and/or modify 1.9 +it under the terms of the GNU Lesser General Public License as published by 1.10 +the Free Software Foundation, either version 3 of the License, or 1.11 +(at your option) any later version. 1.12 + 1.13 +This program is distributed in the hope that it will be useful, 1.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of 1.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1.16 +GNU Lesser General Public License for more details. 1.17 + 1.18 +You should have received a copy of the GNU Lesser General Public License 1.19 +along with this program. If not, see <http://www.gnu.org/licenses/>. 1.20 +*/ 1.21 +#ifndef NO_OPENGL 1.22 +#include <stdarg.h> 1.23 +#include <math.h> 1.24 +#include <ctype.h> 1.25 + 1.26 +#include <stdlib.h> 1.27 + 1.28 +#ifdef _MSC_VER 1.29 +#include <malloc.h> 1.30 +#else 1.31 +#include <alloca.h> 1.32 +#endif 1.33 + 1.34 +#ifdef TARGET_IPHONE 1.35 +#include <OpenGLES/ES2/gl.h> 1.36 + 1.37 +#define GL_CLAMP GL_CLAMP_TO_EDGE 1.38 + 1.39 +#else 1.40 +#include <GL/glew.h> 1.41 +#endif 1.42 + 1.43 +#include "drawtext.h" 1.44 +#include "drawtext_impl.h" 1.45 + 1.46 +struct vertex { 1.47 + float x, y; 1.48 + float s, t; 1.49 +}; 1.50 + 1.51 +struct quad { 1.52 + struct vertex v[6]; 1.53 +}; 1.54 + 1.55 +static void cleanup(void); 1.56 +static void add_glyph(struct glyph *g, float x, float y); 1.57 + 1.58 +#define QBUF_SZ 512 1.59 +static struct quad *qbuf; 1.60 +static int num_quads; 1.61 +static int vattr = -1; 1.62 +static int tattr = -1; 1.63 +static unsigned int font_tex; 1.64 +static int buf_mode = DTX_NBF; 1.65 + 1.66 + 1.67 +int dtx_gl_init(void) 1.68 +{ 1.69 + if(qbuf) { 1.70 + return 0; /* already initialized */ 1.71 + } 1.72 + 1.73 + /*glewInit();*/ 1.74 + 1.75 + if(!(qbuf = malloc(QBUF_SZ * sizeof *qbuf))) { 1.76 + return -1; 1.77 + } 1.78 + num_quads = 0; 1.79 + 1.80 + atexit(cleanup); 1.81 + return 0; 1.82 +} 1.83 + 1.84 +static void cleanup(void) 1.85 +{ 1.86 + free(qbuf); 1.87 +} 1.88 + 1.89 + 1.90 +void dtx_vertex_attribs(int vert_attr, int tex_attr) 1.91 +{ 1.92 + vattr = vert_attr; 1.93 + tattr = tex_attr; 1.94 +} 1.95 + 1.96 +static void set_glyphmap_texture(struct dtx_glyphmap *gmap) 1.97 +{ 1.98 + if(!gmap->tex) { 1.99 + glGenTextures(1, &gmap->tex); 1.100 + glBindTexture(GL_TEXTURE_2D, gmap->tex); 1.101 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 1.102 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 1.103 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); 1.104 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); 1.105 + 1.106 +#ifdef GL_ES_VERSION_2_0 1.107 + glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, gmap->xsz, gmap->ysz, 0, GL_ALPHA, GL_UNSIGNED_BYTE, gmap->pixels); 1.108 + glGenerateMipmap(GL_TEXTURE_2D); 1.109 +#else 1.110 + gluBuild2DMipmaps(GL_TEXTURE_2D, GL_ALPHA, gmap->xsz, gmap->ysz, GL_ALPHA, GL_UNSIGNED_BYTE, gmap->pixels); 1.111 +#endif 1.112 + } 1.113 + 1.114 + if(font_tex != gmap->tex) { 1.115 + dtx_flush(); 1.116 + } 1.117 + font_tex = gmap->tex; 1.118 +} 1.119 + 1.120 +void dtx_glyph(int code) 1.121 +{ 1.122 + struct dtx_glyphmap *gmap; 1.123 + 1.124 + if(!dtx_font || !(gmap = dtx_get_font_glyphmap(dtx_font, dtx_font_sz, code))) { 1.125 + return; 1.126 + } 1.127 + set_glyphmap_texture(gmap); 1.128 + 1.129 + add_glyph(gmap->glyphs + code - gmap->cstart, 0, 0); 1.130 + dtx_flush(); 1.131 +} 1.132 + 1.133 +static const char *put_char(const char *str, float *pos_x, float *pos_y, int *should_flush) 1.134 +{ 1.135 + struct dtx_glyphmap *gmap; 1.136 + float px, py; 1.137 + int code = dtx_utf8_char_code(str); 1.138 + str = dtx_utf8_next_char((char*)str); 1.139 + 1.140 + if(buf_mode == DTX_LBF && code == '\n') { 1.141 + *should_flush = 1; 1.142 + } 1.143 + 1.144 + px = *pos_x; 1.145 + py = *pos_y; 1.146 + 1.147 + if((gmap = dtx_proc_char(code, pos_x, pos_y))) { 1.148 + int idx = code - gmap->cstart; 1.149 + 1.150 + set_glyphmap_texture(gmap); 1.151 + add_glyph(gmap->glyphs + idx, px, py); 1.152 + } 1.153 + return str; 1.154 +} 1.155 + 1.156 +void dtx_string(const char *str) 1.157 +{ 1.158 + int should_flush = buf_mode == DTX_NBF; 1.159 + float pos_x = 0.0f; 1.160 + float pos_y = 0.0f; 1.161 + 1.162 + if(!dtx_font) { 1.163 + return; 1.164 + } 1.165 + 1.166 + while(*str) { 1.167 + str = put_char(str, &pos_x, &pos_y, &should_flush); 1.168 + } 1.169 + 1.170 + if(should_flush) { 1.171 + dtx_flush(); 1.172 + } 1.173 +} 1.174 + 1.175 +void dtx_printf(const char *fmt, ...) 1.176 +{ 1.177 + va_list ap; 1.178 + int buf_size; 1.179 + char *buf, tmp; 1.180 + 1.181 + if(!dtx_font) { 1.182 + return; 1.183 + } 1.184 + 1.185 + va_start(ap, fmt); 1.186 + buf_size = vsnprintf(&tmp, 0, fmt, ap); 1.187 + va_end(ap); 1.188 + 1.189 + if(buf_size == -1) { 1.190 + buf_size = 512; 1.191 + } 1.192 + 1.193 + buf = alloca(buf_size + 1); 1.194 + va_start(ap, fmt); 1.195 + vsnprintf(buf, buf_size + 1, fmt, ap); 1.196 + va_end(ap); 1.197 + 1.198 + dtx_string(buf); 1.199 +} 1.200 + 1.201 +static void qvertex(struct vertex *v, float x, float y, float s, float t) 1.202 +{ 1.203 + v->x = x; 1.204 + v->y = y; 1.205 + v->s = s; 1.206 + v->t = t; 1.207 +} 1.208 + 1.209 +static void add_glyph(struct glyph *g, float x, float y) 1.210 +{ 1.211 + struct quad *qptr = qbuf + num_quads; 1.212 + 1.213 + x -= g->orig_x; 1.214 + y -= g->orig_y; 1.215 + 1.216 + qvertex(qptr->v + 0, x, y, g->nx, g->ny + g->nheight); 1.217 + qvertex(qptr->v + 1, x + g->width, y, g->nx + g->nwidth, g->ny + g->nheight); 1.218 + qvertex(qptr->v + 2, x + g->width, y + g->height, g->nx + g->nwidth, g->ny); 1.219 + 1.220 + qvertex(qptr->v + 3, x, y, g->nx, g->ny + g->nheight); 1.221 + qvertex(qptr->v + 4, x + g->width, y + g->height, g->nx + g->nwidth, g->ny); 1.222 + qvertex(qptr->v + 5, x, y + g->height, g->nx, g->ny); 1.223 + 1.224 + if(++num_quads >= QBUF_SZ) { 1.225 + dtx_flush(); 1.226 + } 1.227 +} 1.228 + 1.229 +void dtx_draw_buffering(int mode) 1.230 +{ 1.231 + dtx_flush(); 1.232 + buf_mode = mode; 1.233 +} 1.234 + 1.235 +void dtx_flush(void) 1.236 +{ 1.237 + int vbo; 1.238 + 1.239 + if(!num_quads) { 1.240 + return; 1.241 + } 1.242 + 1.243 + if(glBindBuffer) { 1.244 + glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &vbo); 1.245 + glBindBuffer(GL_ARRAY_BUFFER, 0); 1.246 + } 1.247 + 1.248 +#ifndef GL_ES_VERSION_2_0 1.249 + glPushAttrib(GL_ENABLE_BIT); 1.250 + glEnable(GL_TEXTURE_2D); 1.251 +#endif 1.252 + glBindTexture(GL_TEXTURE_2D, font_tex); 1.253 + 1.254 + if(vattr != -1 && glEnableVertexAttribArray) { 1.255 + glEnableVertexAttribArray(vattr); 1.256 + glVertexAttribPointer(vattr, 2, GL_FLOAT, 0, sizeof(struct vertex), qbuf); 1.257 +#ifndef GL_ES_VERSION_2_0 1.258 + } else { 1.259 + glEnableClientState(GL_VERTEX_ARRAY); 1.260 + glVertexPointer(2, GL_FLOAT, sizeof(struct vertex), qbuf); 1.261 +#endif 1.262 + } 1.263 + if(tattr != -1 && glEnableVertexAttribArray) { 1.264 + glEnableVertexAttribArray(tattr); 1.265 + glVertexAttribPointer(tattr, 2, GL_FLOAT, 0, sizeof(struct vertex), &qbuf->v[0].s); 1.266 +#ifndef GL_ES_VERSION_2_0 1.267 + } else { 1.268 + glEnableClientState(GL_TEXTURE_COORD_ARRAY); 1.269 + glTexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), &qbuf->v[0].s); 1.270 +#endif 1.271 + } 1.272 + 1.273 + glEnable(GL_BLEND); 1.274 + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 1.275 + 1.276 + glDepthMask(0); 1.277 + 1.278 + glDrawArrays(GL_TRIANGLES, 0, num_quads * 6); 1.279 + 1.280 + glDepthMask(1); 1.281 + 1.282 + if(vattr != -1 && glDisableVertexAttribArray) { 1.283 + glDisableVertexAttribArray(vattr); 1.284 +#ifndef GL_ES_VERSION_2_0 1.285 + } else { 1.286 + glDisableClientState(GL_VERTEX_ARRAY); 1.287 +#endif 1.288 + } 1.289 + if(tattr != -1 && glDisableVertexAttribArray) { 1.290 + glDisableVertexAttribArray(tattr); 1.291 +#ifndef GL_ES_VERSION_2_0 1.292 + } else { 1.293 + glDisableClientState(GL_TEXTURE_COORD_ARRAY); 1.294 +#endif 1.295 + } 1.296 + 1.297 +#ifndef GL_ES_VERSION_2_0 1.298 + glPopAttrib(); 1.299 +#else 1.300 + glDisable(GL_BLEND); 1.301 +#endif 1.302 + 1.303 + if(glBindBuffer && vbo) { 1.304 + glBindBuffer(GL_ARRAY_BUFFER, vbo); 1.305 + } 1.306 + 1.307 + num_quads = 0; 1.308 +} 1.309 + 1.310 +#endif /* !def NO_OPENGL */