istereo2

annotate libs/drawtext/drawgl.c @ 7:a3c4fcc9f8f3

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