libdrawtext

changeset 58:11c8b34b0da5

implemented the metrics functions
author John Tsiombikas <nuclear@mutantstargoat.com>
date Sat, 17 Sep 2011 10:09:58 +0300
parents 7b01e04c9c8b
children e0957fc47162
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;