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