libdrawtext
changeset 6:7e0c702f1223
implemented the metrics functions
author | John Tsiombikas <nuclear@mutantstargoat.com> |
---|---|
date | Sat, 17 Sep 2011 10:09:58 +0300 |
parents | 095ff7ca4e74 |
children | 10cfb642d0b8 |
files | src/drawgl.c src/drawtext_impl.h src/font.c |
diffstat | 3 files changed, 171 insertions(+), 37 deletions(-) [+] |
line diff
1.1 --- a/src/drawgl.c Fri Sep 16 08:42:07 2011 +0300 1.2 +++ b/src/drawgl.c Sat Sep 17 10:09:58 2011 +0300 1.3 @@ -39,7 +39,6 @@ 1.4 struct vertex v[6]; 1.5 }; 1.6 1.7 -static int init(void); 1.8 static void cleanup(void); 1.9 static void add_glyph(struct glyph *g, float x, float y); 1.10 1.11 @@ -51,11 +50,8 @@ 1.12 static unsigned int font_tex; 1.13 static int buf_mode = DTX_NBF; 1.14 1.15 -static struct dtx_font *font; 1.16 -static int font_sz; 1.17 1.18 - 1.19 -static int init(void) 1.20 +int dtx_gl_init(void) 1.21 { 1.22 if(qbuf) { 1.23 return 0; /* already initialized */ 1.24 @@ -78,14 +74,6 @@ 1.25 } 1.26 1.27 1.28 -void dtx_use_font(struct dtx_font *fnt, int sz) 1.29 -{ 1.30 - init(); 1.31 - 1.32 - font = fnt; 1.33 - font_sz = sz; 1.34 -} 1.35 - 1.36 void dtx_vertex_attribs(int vert_attr, int tex_attr) 1.37 { 1.38 vattr = vert_attr; 1.39 @@ -120,7 +108,7 @@ 1.40 { 1.41 struct dtx_glyphmap *gmap; 1.42 1.43 - if(!font || !(gmap = dtx_get_font_glyphmap(font, font_sz, code))) { 1.44 + if(!dtx_font || !(gmap = dtx_get_font_glyphmap(dtx_font, dtx_font_sz, code))) { 1.45 return; 1.46 } 1.47 set_glyphmap_texture(gmap); 1.48 @@ -136,39 +124,27 @@ 1.49 float pos_x = 0.0f; 1.50 float pos_y = 0.0f; 1.51 1.52 - if(!font) { 1.53 + if(!dtx_font) { 1.54 return; 1.55 } 1.56 1.57 while(*str) { 1.58 + float px, py; 1.59 int code = dtx_utf8_char_code(str); 1.60 str = dtx_utf8_next_char((char*)str); 1.61 1.62 - switch(code) { 1.63 - case '\n': 1.64 - if(buf_mode == DTX_LBF) { 1.65 - should_flush = 1; 1.66 - } 1.67 - pos_x = 0.0; 1.68 - pos_y -= gmap->line_advance; 1.69 - break; 1.70 + if(buf_mode == DTX_LBF && code == '\n') { 1.71 + should_flush = 1; 1.72 + } 1.73 1.74 - case '\t': 1.75 - pos_x = fmod(pos_x, 4.0) + 4.0; 1.76 - break; 1.77 + px = pos_x; 1.78 + py = pos_y; 1.79 1.80 - case '\r': 1.81 - pos_x = 0.0; 1.82 - break; 1.83 + if((gmap = dtx_proc_char(code, &pos_x, &pos_y))) { 1.84 + int idx = code - gmap->cstart; 1.85 1.86 - default: 1.87 - if((gmap = dtx_get_font_glyphmap(font, font_sz, code))) { 1.88 - int idx = code - gmap->cstart; 1.89 - 1.90 - set_glyphmap_texture(gmap); 1.91 - add_glyph(gmap->glyphs + idx, pos_x, pos_y); 1.92 - pos_x += gmap->glyphs[idx].advance; 1.93 - } 1.94 + set_glyphmap_texture(gmap); 1.95 + add_glyph(gmap->glyphs + idx, px, py); 1.96 } 1.97 } 1.98
2.1 --- a/src/drawtext_impl.h Fri Sep 16 08:42:07 2011 +0300 2.2 +++ b/src/drawtext_impl.h Sat Sep 17 10:09:58 2011 +0300 2.3 @@ -56,7 +56,17 @@ 2.4 }; 2.5 2.6 2.7 +struct dtx_font *dtx_font; 2.8 +int dtx_font_sz; 2.9 + 2.10 + 2.11 #define fperror(str) \ 2.12 fprintf(stderr, "%s: %s: %s\n", __func__, (str), strerror(errno)) 2.13 2.14 +int dtx_gl_init(void); 2.15 + 2.16 +/* returns zero if it should NOT be printed and modifies xpos/ypos */ 2.17 +/* implemented in font.c */ 2.18 +struct dtx_glyphmap *dtx_proc_char(int code, float *xpos, float *ypos); 2.19 + 2.20 #endif /* TEXT_IMPL_H_ */
3.1 --- a/src/font.c Fri Sep 16 08:42:07 2011 +0300 3.2 +++ b/src/font.c Sat Sep 17 10:09:58 2011 +0300 3.3 @@ -22,8 +22,10 @@ 3.4 #include <stdio.h> 3.5 #include <stdlib.h> 3.6 #include <string.h> 3.7 +#include <math.h> 3.8 #include <limits.h> 3.9 #include <ctype.h> 3.10 +#include <float.h> 3.11 #include <errno.h> 3.12 #ifdef USE_FREETYPE 3.13 #include <ft2build.h> 3.14 @@ -467,6 +469,152 @@ 3.15 } 3.16 3.17 3.18 +void dtx_use_font(struct dtx_font *fnt, int sz) 3.19 +{ 3.20 + dtx_gl_init(); 3.21 + 3.22 + dtx_font = fnt; 3.23 + dtx_font_sz = sz; 3.24 +} 3.25 + 3.26 +void dtx_glyph_box(int code, struct dtx_box *box) 3.27 +{ 3.28 + int cidx; 3.29 + struct dtx_glyphmap *gmap; 3.30 + gmap = dtx_get_font_glyphmap(dtx_font, dtx_font_sz, code); 3.31 + 3.32 + cidx = code - gmap->cstart; 3.33 + 3.34 + box->x = gmap->glyphs[cidx].orig_x; 3.35 + box->y = gmap->glyphs[cidx].orig_y; 3.36 + box->width = gmap->glyphs[cidx].width; 3.37 + box->height = gmap->glyphs[cidx].height; 3.38 +} 3.39 + 3.40 +float dtx_glyph_width(int code) 3.41 +{ 3.42 + struct dtx_box box; 3.43 + dtx_glyph_box(code, &box); 3.44 + return box.width; 3.45 +} 3.46 + 3.47 +float dtx_glyph_height(int code) 3.48 +{ 3.49 + struct dtx_box box; 3.50 + dtx_glyph_box(code, &box); 3.51 + return box.height; 3.52 +} 3.53 + 3.54 +void dtx_string_box(const char *str, struct dtx_box *box) 3.55 +{ 3.56 + int code; 3.57 + float pos_x = 0.0f, pos_y = 0.0f; 3.58 + struct glyph *g = 0; 3.59 + float x0, y0, x1, y1; 3.60 + 3.61 + x0 = y0 = FLT_MAX; 3.62 + x1 = y1 = -FLT_MAX; 3.63 + 3.64 + while(*str) { 3.65 + float px, py; 3.66 + struct dtx_glyphmap *gmap; 3.67 + 3.68 + code = dtx_utf8_char_code(str); 3.69 + str = dtx_utf8_next_char((char*)str); 3.70 + 3.71 + px = pos_x; 3.72 + py = pos_y; 3.73 + 3.74 + if((gmap = dtx_proc_char(code, &pos_x, &pos_y))) { 3.75 + g = gmap->glyphs + code - gmap->cstart; 3.76 + 3.77 + if(px + g->orig_x < x0) { 3.78 + x0 = px + g->orig_x; 3.79 + } 3.80 + if(py + g->orig_y < y0) { 3.81 + y0 = py + g->orig_y; 3.82 + } 3.83 + if(px + g->orig_x + g->width > x1) { 3.84 + x1 = px + g->orig_x + g->width; 3.85 + } 3.86 + if(py + g->orig_y + g->height > y1) { 3.87 + y1 = py + g->orig_y + g->height; 3.88 + } 3.89 + } 3.90 + } 3.91 + 3.92 + box->x = x0; 3.93 + box->y = y0; 3.94 + box->width = x1 - x0; 3.95 + box->height = y1 - y0; 3.96 +} 3.97 + 3.98 +float dtx_string_width(const char *str) 3.99 +{ 3.100 + struct dtx_box box; 3.101 + 3.102 + dtx_string_box(str, &box); 3.103 + return box.width; 3.104 +} 3.105 + 3.106 +float dtx_string_height(const char *str) 3.107 +{ 3.108 + struct dtx_box box; 3.109 + 3.110 + dtx_string_box(str, &box); 3.111 + return box.height; 3.112 +} 3.113 + 3.114 +float dtx_char_pos(const char *str, int n) 3.115 +{ 3.116 + int i; 3.117 + float pos = 0.0; 3.118 + struct dtx_glyphmap *gmap; 3.119 + 3.120 + for(i=0; i<n; i++) { 3.121 + int code = dtx_utf8_char_code(str); 3.122 + str = dtx_utf8_next_char((char*)str); 3.123 + 3.124 + gmap = dtx_get_font_glyphmap(dtx_font, dtx_font_sz, code); 3.125 + pos += gmap->glyphs[i].advance; 3.126 + } 3.127 + return pos; 3.128 +} 3.129 + 3.130 + 3.131 +struct dtx_glyphmap *dtx_proc_char(int code, float *xpos, float *ypos) 3.132 +{ 3.133 + struct dtx_glyphmap *gmap; 3.134 + gmap = dtx_get_font_glyphmap(dtx_font, dtx_font_sz, code); 3.135 + 3.136 + switch(code) { 3.137 + case '\n': 3.138 + *xpos = 0.0; 3.139 + if(gmap) { 3.140 + *ypos -= gmap->line_advance; 3.141 + } 3.142 + return 0; 3.143 + 3.144 + case '\t': 3.145 + if(gmap) { 3.146 + *xpos = (fmod(*xpos, 4.0) + 4.0) * gmap->glyphs[0].advance; 3.147 + } 3.148 + return 0; 3.149 + 3.150 + case '\r': 3.151 + *xpos = 0.0; 3.152 + return 0; 3.153 + 3.154 + default: 3.155 + break; 3.156 + } 3.157 + 3.158 + if(gmap) { 3.159 + *xpos += gmap->glyphs[code - gmap->cstart].advance; 3.160 + } 3.161 + return gmap; 3.162 +} 3.163 + 3.164 static void calc_best_size(int total_width, int max_glyph_height, int padding, int pow2, int *imgw, int *imgh) 3.165 { 3.166 int xsz, ysz, num_rows;