libdrawtext

diff src/font.c @ 22:df6d52b36bd6

- properly supported building of no-freetype version, separately installed as libdrawtext-noft.whatever - saving/loading glyphmaps now work correctly - added nofreetype program in examples, to illustrate how to use libdrawtext-noft with prebuilt glyphmaps (see tools/font2glyphmap)
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 15 Apr 2014 05:10:39 +0300
parents baec6ad7b2dd
children 5beaab3df0cb
line diff
     1.1 --- a/src/font.c	Tue Apr 15 03:33:39 2014 +0300
     1.2 +++ b/src/font.c	Tue Apr 15 05:10:39 2014 +0300
     1.3 @@ -68,11 +68,13 @@
     1.4  		FT_Done_FreeType(ft);
     1.5  	}
     1.6  }
     1.7 +#endif	/* USE_FREETYPE */
     1.8  
     1.9  struct dtx_font *dtx_open_font(const char *fname, int sz)
    1.10  {
    1.11 -	struct dtx_font *fnt;
    1.12 +	struct dtx_font *fnt = 0;
    1.13  
    1.14 +#ifdef USE_FREETYPE
    1.15  	init_freetype();
    1.16  
    1.17  	if(!(fnt = calloc(1, sizeof *fnt))) {
    1.18 @@ -93,15 +95,41 @@
    1.19  			dtx_use_font(fnt, sz);
    1.20  		}
    1.21  	}
    1.22 +#else
    1.23 +	fprintf(stderr, "ignoring call to dtx_open_font: not compiled with freetype support!\n");
    1.24 +#endif
    1.25  
    1.26  	return fnt;
    1.27  }
    1.28  
    1.29 +struct dtx_font *dtx_open_font_glyphmap(const char *fname)
    1.30 +{
    1.31 +	struct dtx_font *fnt;
    1.32 +	struct dtx_glyphmap *gmap;
    1.33 +
    1.34 +	if(!(fnt = calloc(1, sizeof *fnt))) {
    1.35 +		fperror("failed to allocate font structure");
    1.36 +		return 0;
    1.37 +	}
    1.38 +
    1.39 +	if(fname) {
    1.40 +		if(!(gmap = dtx_load_glyphmap(fname))) {
    1.41 +			free(fnt);
    1.42 +			return 0;
    1.43 +		}
    1.44 +
    1.45 +		dtx_add_glyphmap(fnt, gmap);
    1.46 +	}
    1.47 +	return fnt;
    1.48 +}
    1.49 +
    1.50  void dtx_close_font(struct dtx_font *fnt)
    1.51  {
    1.52  	if(!fnt) return;
    1.53  
    1.54 +#ifdef USE_FREETYPE
    1.55  	FT_Done_Face(fnt->face);
    1.56 +#endif
    1.57  
    1.58  	/* destroy the glyphmaps */
    1.59  	while(fnt->gmaps) {
    1.60 @@ -115,12 +143,16 @@
    1.61  
    1.62  void dtx_prepare(struct dtx_font *fnt, int sz)
    1.63  {
    1.64 -	dtx_get_font_glyphmap_range(fnt, sz, 0, 256);
    1.65 +	if(!dtx_get_font_glyphmap_range(fnt, sz, 0, 256)) {
    1.66 +		fprintf(stderr, "%s: failed (sz: %d, range: 0-255 [ascii])\n", __FUNCTION__, sz);
    1.67 +	}
    1.68  }
    1.69  
    1.70  void dtx_prepare_range(struct dtx_font *fnt, int sz, int cstart, int cend)
    1.71  {
    1.72 -	dtx_get_font_glyphmap_range(fnt, sz, cstart, cend);
    1.73 +	if(!dtx_get_font_glyphmap_range(fnt, sz, cstart, cend)) {
    1.74 +		fprintf(stderr, "%s: failed (sz: %d, range: %d-%d)\n", __FUNCTION__, sz, cstart, cend);
    1.75 +	}
    1.76  }
    1.77  
    1.78  struct dtx_glyphmap *dtx_get_font_glyphmap(struct dtx_font *fnt, int sz, int code)
    1.79 @@ -168,8 +200,10 @@
    1.80  
    1.81  struct dtx_glyphmap *dtx_create_glyphmap_range(struct dtx_font *fnt, int sz, int cstart, int cend)
    1.82  {
    1.83 +	struct dtx_glyphmap *gmap = 0;
    1.84 +
    1.85 +#ifdef USE_FREETYPE
    1.86  	FT_Face face = fnt->face;
    1.87 -	struct dtx_glyphmap *gmap;
    1.88  	int i, j;
    1.89  	int gx, gy;
    1.90  	int padding = 4;
    1.91 @@ -259,12 +293,11 @@
    1.92  	}
    1.93  
    1.94  	/* add it to the glyphmaps list of the font */
    1.95 -	gmap->next = fnt->gmaps;
    1.96 -	fnt->gmaps = gmap;
    1.97 +	dtx_add_glyphmap(fnt, gmap);
    1.98 +#endif	/* USE_FREETYPE */
    1.99  
   1.100  	return gmap;
   1.101  }
   1.102 -#endif	/* USE_FREETYPE */
   1.103  
   1.104  void dtx_free_glyphmap(struct dtx_glyphmap *gmap)
   1.105  {
   1.106 @@ -309,6 +342,7 @@
   1.107  	int hdr_lines = 0;
   1.108  	struct dtx_glyphmap *gmap;
   1.109  	struct glyph *glyphs = 0;
   1.110 +	struct glyph *g;
   1.111  	int min_code = INT_MAX;
   1.112  	int max_code = INT_MIN;
   1.113  	int i, max_pixval, num_pixels;
   1.114 @@ -317,6 +351,8 @@
   1.115  		fperror("failed to allocate glyphmap");
   1.116  		return 0;
   1.117  	}
   1.118 +	gmap->ptsize = -1;
   1.119 +	gmap->line_advance = FLT_MIN;
   1.120  
   1.121  	while(hdr_lines < 3) {
   1.122  		char *line = buf;
   1.123 @@ -330,34 +366,47 @@
   1.124  		}
   1.125  
   1.126  		if(line[0] == '#') {
   1.127 -			struct glyph *g;
   1.128  			int c, res;
   1.129 -			float x, y, xsz, ysz;
   1.130 +			float x, y, xsz, ysz, orig_x, orig_y, adv, line_adv;
   1.131 +			int ptsize;
   1.132  
   1.133 -			res = sscanf(line + 1, "%d: %fx%f+%f+%f\n", &c, &xsz, &ysz, &x, &y);
   1.134 -			if(res != 5) {
   1.135 +			if((res = sscanf(line + 1, " size: %d\n", &ptsize)) == 1) {
   1.136 +				gmap->ptsize = ptsize;
   1.137 +
   1.138 +			} else if((res = sscanf(line + 1, " advance: %f\n", &line_adv)) == 1) {
   1.139 +				gmap->line_advance = line_adv;
   1.140 +
   1.141 +			} else if((res = sscanf(line + 1, " %d: %fx%f+%f+%f o:%f,%f adv:%f\n",
   1.142 +							&c, &xsz, &ysz, &x, &y, &orig_x, &orig_y, &adv)) == 8) {
   1.143 +				if(!(g = malloc(sizeof *g))) {
   1.144 +					fperror("failed to allocate glyph");
   1.145 +					goto err;
   1.146 +				}
   1.147 +				g->code = c;
   1.148 +				g->x = x;
   1.149 +				g->y = y;
   1.150 +				g->width = xsz;
   1.151 +				g->height = ysz;
   1.152 +				g->orig_x = orig_x;
   1.153 +				g->orig_y = orig_y;
   1.154 +				g->advance = adv;
   1.155 +				/* normalized coordinates will be precalculated after everything is loaded */
   1.156 +
   1.157 +				g->next = glyphs;
   1.158 +				glyphs = g;
   1.159 +
   1.160 +				if(c < min_code) {
   1.161 +					min_code = c;
   1.162 +				}
   1.163 +				if(c > max_code) {
   1.164 +					max_code = c;
   1.165 +				}
   1.166 +
   1.167 +			} else {
   1.168  				fprintf(stderr, "%s: invalid glyph info line\n", __FUNCTION__);
   1.169  				goto err;
   1.170  			}
   1.171  
   1.172 -			if(!(g = malloc(sizeof *g))) {
   1.173 -				fperror("failed to allocate glyph");
   1.174 -				goto err;
   1.175 -			}
   1.176 -			g->code = c;
   1.177 -			g->x = x;
   1.178 -			g->y = y;
   1.179 -			g->width = xsz;
   1.180 -			g->height = ysz;
   1.181 -			g->next = glyphs;
   1.182 -			glyphs = g;
   1.183 -
   1.184 -			if(c < min_code) {
   1.185 -				min_code = c;
   1.186 -			}
   1.187 -			if(c > max_code) {
   1.188 -				max_code = c;
   1.189 -			}
   1.190  		} else {
   1.191  			switch(hdr_lines) {
   1.192  			case 0:
   1.193 @@ -392,6 +441,21 @@
   1.194  		}
   1.195  	}
   1.196  
   1.197 +	if(gmap->ptsize == -1 || gmap->line_advance == FLT_MIN) {
   1.198 +		fprintf(stderr, "%s: invalid glyphmap, insufficient information in ppm comments\n", __FUNCTION__);
   1.199 +		goto err;
   1.200 +	}
   1.201 +
   1.202 +	/* precalculate normalized glyph coordinates */
   1.203 +	g = glyphs;
   1.204 +	while(g) {
   1.205 +		g->nx = g->x / gmap->xsz;
   1.206 +		g->ny = g->y / gmap->ysz;
   1.207 +		g->nwidth = g->width / gmap->xsz;
   1.208 +		g->nheight = g->height / gmap->ysz;
   1.209 +		g = g->next;
   1.210 +	}
   1.211 +
   1.212  	num_pixels = gmap->xsz * gmap->ysz;
   1.213  	if(!(gmap->pixels = malloc(num_pixels))) {
   1.214  		fperror("failed to allocate pixels");
   1.215 @@ -456,8 +520,11 @@
   1.216  	struct glyph *g = gmap->glyphs;
   1.217  
   1.218  	fprintf(fp, "P6\n%d %d\n", gmap->xsz, gmap->ysz);
   1.219 +	fprintf(fp, "# size: %d\n", gmap->ptsize);
   1.220 +	fprintf(fp, "# advance: %g\n", gmap->line_advance);
   1.221  	for(i=0; i<gmap->crange; i++) {
   1.222 -		fprintf(fp, "# %d: %fx%f+%f+%f\n", g->code, g->width, g->height, g->x, g->y);
   1.223 +		fprintf(fp, "# %d: %gx%g+%g+%g o:%g,%g adv:%g\n", g->code, g->width, g->height, g->x, g->y,
   1.224 +				g->orig_x, g->orig_y, g->advance);
   1.225  		g++;
   1.226  	}
   1.227  	fprintf(fp, "255\n");
   1.228 @@ -472,6 +539,12 @@
   1.229  	return 0;
   1.230  }
   1.231  
   1.232 +void dtx_add_glyphmap(struct dtx_font *fnt, struct dtx_glyphmap *gmap)
   1.233 +{
   1.234 +	gmap->next = fnt->gmaps;
   1.235 +	fnt->gmaps = gmap;
   1.236 +}
   1.237 +
   1.238  
   1.239  void dtx_use_font(struct dtx_font *fnt, int sz)
   1.240  {
   1.241 @@ -646,6 +719,7 @@
   1.242  	return gmap;
   1.243  }
   1.244  
   1.245 +#ifdef USE_FREETYPE
   1.246  static void calc_best_size(int total_width, int max_glyph_height, int padding, int pow2, int *imgw, int *imgh)
   1.247  {
   1.248  	int xsz, ysz, num_rows;
   1.249 @@ -687,3 +761,4 @@
   1.250  	x = (x >> 16) | x;
   1.251  	return x + 1;
   1.252  }
   1.253 +#endif