libdrawtext
diff src/drawgl.c @ 0:bfe431dd1d80
initial commit
author | John Tsiombikas <nuclear@mutantstargoat.com> |
---|---|
date | Thu, 15 Sep 2011 10:47:38 +0300 |
parents | |
children | fe0c54e574ae |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/drawgl.c Thu Sep 15 10:47:38 2011 +0300 1.3 @@ -0,0 +1,255 @@ 1.4 +#ifndef NO_OPENGL 1.5 +#include <math.h> 1.6 +#include <ctype.h> 1.7 + 1.8 +#include <stdlib.h> 1.9 + 1.10 +#if defined(__IPHONE_3_0) || defined(__IPHONE_3_2) || defined(__IPHONE_4_0) 1.11 +#include <OpenGLES/ES2/gl.h> 1.12 +#else 1.13 +#include <GL/glew.h> 1.14 +#endif 1.15 + 1.16 +#include "drawtext.h" 1.17 +#include "drawtext_impl.h" 1.18 + 1.19 +struct vertex { 1.20 + float x, y; 1.21 + float s, t; 1.22 +}; 1.23 + 1.24 +struct quad { 1.25 + struct vertex v[6]; 1.26 +}; 1.27 + 1.28 +static int init(void); 1.29 +static void cleanup(void); 1.30 +static void add_glyph(struct glyph *g, float x, float y); 1.31 + 1.32 +#define QBUF_SZ 512 1.33 +static struct quad *qbuf; 1.34 +static int num_quads; 1.35 +static int vattr = -1; 1.36 +static int tattr = -1; 1.37 +static unsigned int font_tex; 1.38 +static int buf_mode = DTX_LBF; 1.39 + 1.40 +static struct dtx_font *font; 1.41 +static int font_sz; 1.42 + 1.43 + 1.44 +static int init(void) 1.45 +{ 1.46 + if(qbuf) { 1.47 + return 0; /* already initialized */ 1.48 + } 1.49 + 1.50 + glewInit(); 1.51 + 1.52 + if(!(qbuf = malloc(QBUF_SZ * sizeof *qbuf))) { 1.53 + return -1; 1.54 + } 1.55 + num_quads = 0; 1.56 + 1.57 + atexit(cleanup); 1.58 + return 0; 1.59 +} 1.60 + 1.61 +static void cleanup(void) 1.62 +{ 1.63 + free(qbuf); 1.64 +} 1.65 + 1.66 + 1.67 +void dtx_use_font(struct dtx_font *fnt, int sz) 1.68 +{ 1.69 + init(); 1.70 + 1.71 + font = fnt; 1.72 + font_sz = sz; 1.73 +} 1.74 + 1.75 +void dtx_vertex_attribs(int vert_attr, int tex_attr) 1.76 +{ 1.77 + vattr = vert_attr; 1.78 + tattr = tex_attr; 1.79 +} 1.80 + 1.81 +static void set_glyphmap_texture(struct dtx_glyphmap *gmap) 1.82 +{ 1.83 + if(!gmap->tex) { 1.84 + glGenTextures(1, &gmap->tex); 1.85 + glBindTexture(GL_TEXTURE_2D, gmap->tex); 1.86 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 1.87 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 1.88 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); 1.89 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); 1.90 + 1.91 +#ifdef GL_ES 1.92 + glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, gmap->xsz, gmap->ysz, 0, GL_ALPHA, GL_UNSIGNED_BYTE, gmap->pixels); 1.93 + glGenerateMipmap(GL_TEXTURE_2D); 1.94 +#else 1.95 + gluBuild2DMipmaps(GL_TEXTURE_2D, GL_ALPHA, gmap->xsz, gmap->ysz, GL_ALPHA, GL_UNSIGNED_BYTE, gmap->pixels); 1.96 +#endif 1.97 + } 1.98 + 1.99 + if(font_tex != gmap->tex) { 1.100 + dtx_flush(); 1.101 + } 1.102 + font_tex = gmap->tex; 1.103 +} 1.104 + 1.105 +void dtx_glyph(int code) 1.106 +{ 1.107 + struct dtx_glyphmap *gmap; 1.108 + 1.109 + if(!font || !(gmap = dtx_get_font_glyphmap(font, font_sz, code))) { 1.110 + return; 1.111 + } 1.112 + set_glyphmap_texture(gmap); 1.113 + 1.114 + add_glyph(gmap->glyphs + code - gmap->cstart, 0, 0); 1.115 + dtx_flush(); 1.116 +} 1.117 + 1.118 +void dtx_string(const char *str) 1.119 +{ 1.120 + struct dtx_glyphmap *gmap; 1.121 + int should_flush = buf_mode == DTX_NBF; 1.122 + float pos_x = 0.0f; 1.123 + float pos_y = 0.0f; 1.124 + 1.125 + if(!font) { 1.126 + return; 1.127 + } 1.128 + 1.129 + while(*str) { 1.130 + int code = dtx_utf8_char_code(str); 1.131 + str = dtx_utf8_next_char((char*)str); 1.132 + 1.133 + switch(code) { 1.134 + case '\n': 1.135 + if(buf_mode == DTX_LBF) { 1.136 + should_flush = 1; 1.137 + } 1.138 + pos_x = 0.0; 1.139 + pos_y -= gmap->line_advance; 1.140 + break; 1.141 + 1.142 + case '\t': 1.143 + pos_x = fmod(pos_x, 4.0) + 4.0; 1.144 + break; 1.145 + 1.146 + case '\r': 1.147 + pos_x = 0.0; 1.148 + break; 1.149 + 1.150 + default: 1.151 + if((gmap = dtx_get_font_glyphmap(font, font_sz, code))) { 1.152 + int idx = code - gmap->cstart; 1.153 + 1.154 + set_glyphmap_texture(gmap); 1.155 + add_glyph(gmap->glyphs + idx, pos_x, pos_y); 1.156 + pos_x += gmap->glyphs[idx].advance; 1.157 + } 1.158 + } 1.159 + } 1.160 + 1.161 + if(should_flush) { 1.162 + dtx_flush(); 1.163 + } 1.164 +} 1.165 + 1.166 +static void qvertex(struct vertex *v, float x, float y, float s, float t) 1.167 +{ 1.168 + v->x = x; 1.169 + v->y = y; 1.170 + v->s = s; 1.171 + v->t = t; 1.172 +} 1.173 + 1.174 +static void add_glyph(struct glyph *g, float x, float y) 1.175 +{ 1.176 + struct quad *qptr = qbuf + num_quads; 1.177 + 1.178 + x -= g->orig_x; 1.179 + y -= g->orig_y; 1.180 + 1.181 + qvertex(qptr->v + 0, x, y, g->nx, g->ny + g->nheight); 1.182 + qvertex(qptr->v + 1, x + g->width, y, g->nx + g->nwidth, g->ny + g->nheight); 1.183 + qvertex(qptr->v + 2, x + g->width, y + g->height, g->nx + g->nwidth, g->ny); 1.184 + 1.185 + qvertex(qptr->v + 3, x, y, g->nx, g->ny + g->nheight); 1.186 + qvertex(qptr->v + 4, x + g->width, y + g->height, g->nx + g->nwidth, g->ny); 1.187 + qvertex(qptr->v + 5, x, y + g->height, g->nx, g->ny); 1.188 + 1.189 + if(++num_quads >= QBUF_SZ) { 1.190 + dtx_flush(); 1.191 + } 1.192 +} 1.193 + 1.194 +void dtx_flush(void) 1.195 +{ 1.196 + if(!num_quads) { 1.197 + return; 1.198 + } 1.199 + 1.200 +#ifndef GL_ES 1.201 + glPushAttrib(GL_ENABLE_BIT); 1.202 + glEnable(GL_TEXTURE_2D); 1.203 +#endif 1.204 + glBindTexture(GL_TEXTURE_2D, font_tex); 1.205 + 1.206 + if(vattr != -1 && glEnableVertexAttribArray) { 1.207 + glEnableVertexAttribArray(vattr); 1.208 + glVertexAttribPointer(vattr, 2, GL_FLOAT, 0, sizeof(struct vertex), qbuf); 1.209 +#ifndef GL_ES 1.210 + } else { 1.211 + glEnableClientState(GL_VERTEX_ARRAY); 1.212 + glVertexPointer(2, GL_FLOAT, sizeof(struct vertex), qbuf); 1.213 +#endif 1.214 + } 1.215 + if(tattr != -1 && glEnableVertexAttribArray) { 1.216 + glEnableVertexAttribArray(tattr); 1.217 + glVertexAttribPointer(tattr, 2, GL_FLOAT, 0, sizeof(struct vertex), &qbuf->v[0].s); 1.218 +#ifndef GL_ES 1.219 + } else { 1.220 + glEnableClientState(GL_TEXTURE_COORD_ARRAY); 1.221 + glTexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), &qbuf->v[0].s); 1.222 +#endif 1.223 + } 1.224 + 1.225 + glEnable(GL_BLEND); 1.226 + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 1.227 + 1.228 + glDepthMask(0); 1.229 + 1.230 + glDrawArrays(GL_TRIANGLES, 0, num_quads * 6); 1.231 + 1.232 + glDepthMask(1); 1.233 + 1.234 + if(vattr != -1 && glDisableVertexAttribArray) { 1.235 + glDisableVertexAttribArray(vattr); 1.236 +#ifndef GL_ES 1.237 + } else { 1.238 + glDisableClientState(GL_VERTEX_ARRAY); 1.239 +#endif 1.240 + } 1.241 + if(tattr != -1 && glDisableVertexAttribArray) { 1.242 + glDisableVertexAttribArray(tattr); 1.243 +#ifndef GL_ES 1.244 + } else { 1.245 + glDisableClientState(GL_TEXTURE_COORD_ARRAY); 1.246 +#endif 1.247 + } 1.248 + 1.249 +#ifndef GL_ES 1.250 + glPopAttrib(); 1.251 +#else 1.252 + glDisable(GL_BLEND); 1.253 +#endif 1.254 + 1.255 + num_quads = 0; 1.256 +} 1.257 + 1.258 +#endif /* !def NO_OPENGL */