libdrawtext
changeset 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 | c750059a1258 |
children | 5beaab3df0cb |
files | Makefile.in configure examples/nofreetype/Makefile examples/nofreetype/serif_s24.glyphmap examples/nofreetype/simple-noft.c src/drawtext.h src/font.c |
diffstat | 7 files changed, 270 insertions(+), 32 deletions(-) [+] |
line diff
1.1 --- a/Makefile.in Tue Apr 15 03:33:39 2014 +0300 1.2 +++ b/Makefile.in Tue Apr 15 05:10:39 2014 +0300 1.3 @@ -5,7 +5,6 @@ 1.4 abi = 0 1.5 rev = 0 1.6 1.7 -name = libdrawtext 1.8 lib_a = $(name).a 1.9 1.10 ifeq ($(shell uname -s), Darwin) 1.11 @@ -40,6 +39,9 @@ 1.12 %.d: %.c 1.13 @$(CPP) $(CFLAGS) -MM $< >$@ 1.14 1.15 +.PHONY: cleanobj 1.16 +cleanobj: 1.17 + rm -f $(obj) 1.18 1.19 .PHONY: clean 1.20 clean: 1.21 @@ -67,3 +69,23 @@ 1.22 rm -f $(PREFIX)/lib/$(linkname) 1.23 rm -f $(PREFIX)/lib/$(soname) 1.24 rm -f $(PREFIX)/include/drawtext.h 1.25 + 1.26 + 1.27 +.PHONY: both 1.28 +both: 1.29 + ./configure --disable-freetype 1.30 + $(MAKE) cleanobj 1.31 + $(MAKE) 1.32 + ./configure --enable-freetype 1.33 + $(MAKE) cleanobj 1.34 + $(MAKE) 1.35 + 1.36 +.PHONY: both-install 1.37 +both-install: 1.38 + ./configure --disable-freetype 1.39 + $(MAKE) cleanobj 1.40 + $(MAKE) install 1.41 + ./configure --enable-freetype 1.42 + $(MAKE) cleanobj 1.43 + $(MAKE) install 1.44 + $(MAKE) cleanobj
2.1 --- a/configure Tue Apr 15 03:33:39 2014 +0300 2.2 +++ b/configure Tue Apr 15 05:10:39 2014 +0300 2.3 @@ -4,6 +4,7 @@ 2.4 opt=false 2.5 dbg=true 2.6 use_ft2=true 2.7 +name=libdrawtext 2.8 2.9 while [ $# != 0 ]; do 2.10 case $1 in 2.11 @@ -24,24 +25,33 @@ 2.12 ;; 2.13 --enable-freetype) 2.14 use_ft2=true 2.15 + name=libdrawtext 2.16 ;; 2.17 --disable-freetype) 2.18 use_ft2=false 2.19 + name=libdrawtext-noft 2.20 ;; 2.21 esac 2.22 shift 2.23 done 2.24 2.25 -echo 'Configuring libdrawtext...' 2.26 +echo "installation prefix: $prefix" 2.27 +$use_ft2 && echo 'use freetype: yes' || echo 'use freetype: no' 2.28 +$opt && echo 'optimizations: yes' || echo 'optimizations: no' 2.29 +$dbg && echo 'debug symbols: yes' || echo 'debug symbols: no' 2.30 + 2.31 +echo "Configuring ${name}..." 2.32 2.33 echo "# do not modify this file manually, it's generated by the configure script" >Makefile 2.34 echo "PREFIX = $prefix" >>Makefile 2.35 $opt && echo '-O3' | xargs echo 'opt =' >>Makefile 2.36 $dbg && echo '-g' | xargs echo 'dbg =' >>Makefile 2.37 if $use_ft2; then 2.38 + echo "name = $name" >>Makefile 2.39 echo 'ft2_cflags = `pkg-config --cflags freetype2`' >>Makefile 2.40 echo 'ft2_libs = `pkg-config --libs freetype2`' >>Makefile 2.41 else 2.42 + echo "name = $name" >>Makefile 2.43 echo 'ft2_cflags = -DNO_FREETYPE' >>Makefile 2.44 fi 2.45 echo '# --- end of generated part, start of Makefile.in ---' >>Makefile
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/examples/nofreetype/Makefile Tue Apr 15 05:10:39 2014 +0300 3.3 @@ -0,0 +1,32 @@ 3.4 +obj = simple-noft.o 3.5 +bin = simple-noft 3.6 + 3.7 +CC = gcc 3.8 +CFLAGS = -pedantic -Wall -g -I../../src -I/usr/local/include 3.9 +LDFLAGS = -Wl,-rpath=. $(lib_so) $(libgl) 3.10 + 3.11 +font = serif.ttf 3.12 + 3.13 +ifeq ($(shell uname -s), Darwin) 3.14 + libgl = -framework OpenGL -framework GLUT 3.15 + lib_so = libdrawtext-noft.dylib 3.16 +else 3.17 + libgl = -lGL -lGLU -lglut 3.18 + lib_so = libdrawtext-noft.so.0.0 3.19 + lib_soname = libdrawtext-noft.so.0 3.20 +endif 3.21 + 3.22 +$(bin): $(obj) $(lib_so) $(lib_soname) 3.23 + $(CC) -o $@ $(obj) $(LDFLAGS) 3.24 + 3.25 +$(lib_so): ../../$(lib_so) 3.26 + rm -f $@ 3.27 + ln -s $< $@ 3.28 + 3.29 +$(lib_soname): ../../$(lib_so) 3.30 + rm -f $@ 3.31 + ln -s $< $@ 3.32 + 3.33 +.PHONY: clean 3.34 +clean: 3.35 + rm -f $(obj) $(bin) $(lib_so)
4.1 Binary file examples/nofreetype/serif_s24.glyphmap has changed
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/examples/nofreetype/simple-noft.c Tue Apr 15 05:10:39 2014 +0300 5.3 @@ -0,0 +1,92 @@ 5.4 +/* Simple libdrawtext example without freetype. 5.5 + */ 5.6 +#include <stdio.h> 5.7 +#include <stdlib.h> 5.8 + 5.9 +#ifndef __APPLE__ 5.10 +#include <GL/glut.h> 5.11 +#else 5.12 +#include <GLUT/glut.h> 5.13 +#endif 5.14 + 5.15 +#include "drawtext.h" 5.16 + 5.17 +void disp(void); 5.18 +void reshape(int x, int y); 5.19 +void keyb(unsigned char key, int x, int y); 5.20 + 5.21 +struct dtx_font *font; 5.22 + 5.23 +int main(int argc, char **argv) 5.24 +{ 5.25 + glutInit(&argc, argv); 5.26 + glutInitWindowSize(512, 384); 5.27 + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); 5.28 + glutCreateWindow("libdrawtext example: simple"); 5.29 + 5.30 + glutDisplayFunc(disp); 5.31 + glutReshapeFunc(reshape); 5.32 + glutKeyboardFunc(keyb); 5.33 + 5.34 + if(!(font = dtx_open_font_glyphmap("serif_s24.glyphmap"))) { 5.35 + fprintf(stderr, "failed to open font\n"); 5.36 + return 1; 5.37 + } 5.38 + dtx_use_font(font, 24); 5.39 + 5.40 + glutMainLoop(); 5.41 + return 0; 5.42 +} 5.43 + 5.44 +const char *text = "Some sample text goes here.\n" 5.45 + "Yada yada yada, more text...\n" 5.46 + "foobar xyzzy\n"; 5.47 + 5.48 +void disp(void) 5.49 +{ 5.50 + glClear(GL_COLOR_BUFFER_BIT); 5.51 + 5.52 + glMatrixMode(GL_MODELVIEW); 5.53 + glLoadIdentity(); 5.54 + 5.55 + glPushMatrix(); 5.56 + glTranslatef(-200, 150, 0); 5.57 + glColor3f(1, 1, 1); 5.58 + /* XXX call dtx_string to draw utf-8 text. 5.59 + * any transformations and the current color apply 5.60 + */ 5.61 + dtx_string(text); 5.62 + glPopMatrix(); 5.63 + 5.64 + glPushMatrix(); 5.65 + glTranslatef(-200, 50, 0); 5.66 + glScalef(2, 0.7, 1); 5.67 + glColor3f(0.6, 0.7, 1.0); 5.68 + dtx_string(text); 5.69 + glPopMatrix(); 5.70 + 5.71 + glPushMatrix(); 5.72 + glTranslatef(-80, -90, 0); 5.73 + glRotatef(20, 0, 0, 1); 5.74 + glColor3f(1.0, 0.7, 0.6); 5.75 + dtx_string(text); 5.76 + glPopMatrix(); 5.77 + 5.78 + glutSwapBuffers(); 5.79 +} 5.80 + 5.81 +void reshape(int x, int y) 5.82 +{ 5.83 + glViewport(0, 0, x, y); 5.84 + 5.85 + glMatrixMode(GL_PROJECTION); 5.86 + glLoadIdentity(); 5.87 + glOrtho(-x/2, x/2, -y/2, y/2, -1, 1); 5.88 +} 5.89 + 5.90 +void keyb(unsigned char key, int x, int y) 5.91 +{ 5.92 + if(key == 27) { 5.93 + exit(0); 5.94 + } 5.95 +}
6.1 --- a/src/drawtext.h Tue Apr 15 03:33:39 2014 +0300 6.2 +++ b/src/drawtext.h Tue Apr 15 05:10:39 2014 +0300 6.3 @@ -50,6 +50,11 @@ 6.4 * nothing will be rendered. 6.5 */ 6.6 struct dtx_font *dtx_open_font(const char *fname, int sz); 6.7 +/* open a font by loading a precompiled glyphmap (see: dtx_save_glyphmap) 6.8 + * this works even when compiled without freetype support 6.9 + */ 6.10 +struct dtx_font *dtx_open_font_glyphmap(const char *fname); 6.11 +/* close a font opened by either of the above */ 6.12 void dtx_close_font(struct dtx_font *fnt); 6.13 6.14 /* prepare an ASCII glyphmap for the specified font size */ 6.15 @@ -89,6 +94,8 @@ 6.16 int dtx_save_glyphmap(const char *fname, const struct dtx_glyphmap *gmap); 6.17 int dtx_save_glyphmap_stream(FILE *fp, const struct dtx_glyphmap *gmap); 6.18 6.19 +/* adds a glyphmap to a font */ 6.20 +void dtx_add_glyphmap(struct dtx_font *fnt, struct dtx_glyphmap *gmap); 6.21 6.22 /* ---- rendering ---- */ 6.23
7.1 --- a/src/font.c Tue Apr 15 03:33:39 2014 +0300 7.2 +++ b/src/font.c Tue Apr 15 05:10:39 2014 +0300 7.3 @@ -68,11 +68,13 @@ 7.4 FT_Done_FreeType(ft); 7.5 } 7.6 } 7.7 +#endif /* USE_FREETYPE */ 7.8 7.9 struct dtx_font *dtx_open_font(const char *fname, int sz) 7.10 { 7.11 - struct dtx_font *fnt; 7.12 + struct dtx_font *fnt = 0; 7.13 7.14 +#ifdef USE_FREETYPE 7.15 init_freetype(); 7.16 7.17 if(!(fnt = calloc(1, sizeof *fnt))) { 7.18 @@ -93,15 +95,41 @@ 7.19 dtx_use_font(fnt, sz); 7.20 } 7.21 } 7.22 +#else 7.23 + fprintf(stderr, "ignoring call to dtx_open_font: not compiled with freetype support!\n"); 7.24 +#endif 7.25 7.26 return fnt; 7.27 } 7.28 7.29 +struct dtx_font *dtx_open_font_glyphmap(const char *fname) 7.30 +{ 7.31 + struct dtx_font *fnt; 7.32 + struct dtx_glyphmap *gmap; 7.33 + 7.34 + if(!(fnt = calloc(1, sizeof *fnt))) { 7.35 + fperror("failed to allocate font structure"); 7.36 + return 0; 7.37 + } 7.38 + 7.39 + if(fname) { 7.40 + if(!(gmap = dtx_load_glyphmap(fname))) { 7.41 + free(fnt); 7.42 + return 0; 7.43 + } 7.44 + 7.45 + dtx_add_glyphmap(fnt, gmap); 7.46 + } 7.47 + return fnt; 7.48 +} 7.49 + 7.50 void dtx_close_font(struct dtx_font *fnt) 7.51 { 7.52 if(!fnt) return; 7.53 7.54 +#ifdef USE_FREETYPE 7.55 FT_Done_Face(fnt->face); 7.56 +#endif 7.57 7.58 /* destroy the glyphmaps */ 7.59 while(fnt->gmaps) { 7.60 @@ -115,12 +143,16 @@ 7.61 7.62 void dtx_prepare(struct dtx_font *fnt, int sz) 7.63 { 7.64 - dtx_get_font_glyphmap_range(fnt, sz, 0, 256); 7.65 + if(!dtx_get_font_glyphmap_range(fnt, sz, 0, 256)) { 7.66 + fprintf(stderr, "%s: failed (sz: %d, range: 0-255 [ascii])\n", __FUNCTION__, sz); 7.67 + } 7.68 } 7.69 7.70 void dtx_prepare_range(struct dtx_font *fnt, int sz, int cstart, int cend) 7.71 { 7.72 - dtx_get_font_glyphmap_range(fnt, sz, cstart, cend); 7.73 + if(!dtx_get_font_glyphmap_range(fnt, sz, cstart, cend)) { 7.74 + fprintf(stderr, "%s: failed (sz: %d, range: %d-%d)\n", __FUNCTION__, sz, cstart, cend); 7.75 + } 7.76 } 7.77 7.78 struct dtx_glyphmap *dtx_get_font_glyphmap(struct dtx_font *fnt, int sz, int code) 7.79 @@ -168,8 +200,10 @@ 7.80 7.81 struct dtx_glyphmap *dtx_create_glyphmap_range(struct dtx_font *fnt, int sz, int cstart, int cend) 7.82 { 7.83 + struct dtx_glyphmap *gmap = 0; 7.84 + 7.85 +#ifdef USE_FREETYPE 7.86 FT_Face face = fnt->face; 7.87 - struct dtx_glyphmap *gmap; 7.88 int i, j; 7.89 int gx, gy; 7.90 int padding = 4; 7.91 @@ -259,12 +293,11 @@ 7.92 } 7.93 7.94 /* add it to the glyphmaps list of the font */ 7.95 - gmap->next = fnt->gmaps; 7.96 - fnt->gmaps = gmap; 7.97 + dtx_add_glyphmap(fnt, gmap); 7.98 +#endif /* USE_FREETYPE */ 7.99 7.100 return gmap; 7.101 } 7.102 -#endif /* USE_FREETYPE */ 7.103 7.104 void dtx_free_glyphmap(struct dtx_glyphmap *gmap) 7.105 { 7.106 @@ -309,6 +342,7 @@ 7.107 int hdr_lines = 0; 7.108 struct dtx_glyphmap *gmap; 7.109 struct glyph *glyphs = 0; 7.110 + struct glyph *g; 7.111 int min_code = INT_MAX; 7.112 int max_code = INT_MIN; 7.113 int i, max_pixval, num_pixels; 7.114 @@ -317,6 +351,8 @@ 7.115 fperror("failed to allocate glyphmap"); 7.116 return 0; 7.117 } 7.118 + gmap->ptsize = -1; 7.119 + gmap->line_advance = FLT_MIN; 7.120 7.121 while(hdr_lines < 3) { 7.122 char *line = buf; 7.123 @@ -330,34 +366,47 @@ 7.124 } 7.125 7.126 if(line[0] == '#') { 7.127 - struct glyph *g; 7.128 int c, res; 7.129 - float x, y, xsz, ysz; 7.130 + float x, y, xsz, ysz, orig_x, orig_y, adv, line_adv; 7.131 + int ptsize; 7.132 7.133 - res = sscanf(line + 1, "%d: %fx%f+%f+%f\n", &c, &xsz, &ysz, &x, &y); 7.134 - if(res != 5) { 7.135 + if((res = sscanf(line + 1, " size: %d\n", &ptsize)) == 1) { 7.136 + gmap->ptsize = ptsize; 7.137 + 7.138 + } else if((res = sscanf(line + 1, " advance: %f\n", &line_adv)) == 1) { 7.139 + gmap->line_advance = line_adv; 7.140 + 7.141 + } else if((res = sscanf(line + 1, " %d: %fx%f+%f+%f o:%f,%f adv:%f\n", 7.142 + &c, &xsz, &ysz, &x, &y, &orig_x, &orig_y, &adv)) == 8) { 7.143 + if(!(g = malloc(sizeof *g))) { 7.144 + fperror("failed to allocate glyph"); 7.145 + goto err; 7.146 + } 7.147 + g->code = c; 7.148 + g->x = x; 7.149 + g->y = y; 7.150 + g->width = xsz; 7.151 + g->height = ysz; 7.152 + g->orig_x = orig_x; 7.153 + g->orig_y = orig_y; 7.154 + g->advance = adv; 7.155 + /* normalized coordinates will be precalculated after everything is loaded */ 7.156 + 7.157 + g->next = glyphs; 7.158 + glyphs = g; 7.159 + 7.160 + if(c < min_code) { 7.161 + min_code = c; 7.162 + } 7.163 + if(c > max_code) { 7.164 + max_code = c; 7.165 + } 7.166 + 7.167 + } else { 7.168 fprintf(stderr, "%s: invalid glyph info line\n", __FUNCTION__); 7.169 goto err; 7.170 } 7.171 7.172 - if(!(g = malloc(sizeof *g))) { 7.173 - fperror("failed to allocate glyph"); 7.174 - goto err; 7.175 - } 7.176 - g->code = c; 7.177 - g->x = x; 7.178 - g->y = y; 7.179 - g->width = xsz; 7.180 - g->height = ysz; 7.181 - g->next = glyphs; 7.182 - glyphs = g; 7.183 - 7.184 - if(c < min_code) { 7.185 - min_code = c; 7.186 - } 7.187 - if(c > max_code) { 7.188 - max_code = c; 7.189 - } 7.190 } else { 7.191 switch(hdr_lines) { 7.192 case 0: 7.193 @@ -392,6 +441,21 @@ 7.194 } 7.195 } 7.196 7.197 + if(gmap->ptsize == -1 || gmap->line_advance == FLT_MIN) { 7.198 + fprintf(stderr, "%s: invalid glyphmap, insufficient information in ppm comments\n", __FUNCTION__); 7.199 + goto err; 7.200 + } 7.201 + 7.202 + /* precalculate normalized glyph coordinates */ 7.203 + g = glyphs; 7.204 + while(g) { 7.205 + g->nx = g->x / gmap->xsz; 7.206 + g->ny = g->y / gmap->ysz; 7.207 + g->nwidth = g->width / gmap->xsz; 7.208 + g->nheight = g->height / gmap->ysz; 7.209 + g = g->next; 7.210 + } 7.211 + 7.212 num_pixels = gmap->xsz * gmap->ysz; 7.213 if(!(gmap->pixels = malloc(num_pixels))) { 7.214 fperror("failed to allocate pixels"); 7.215 @@ -456,8 +520,11 @@ 7.216 struct glyph *g = gmap->glyphs; 7.217 7.218 fprintf(fp, "P6\n%d %d\n", gmap->xsz, gmap->ysz); 7.219 + fprintf(fp, "# size: %d\n", gmap->ptsize); 7.220 + fprintf(fp, "# advance: %g\n", gmap->line_advance); 7.221 for(i=0; i<gmap->crange; i++) { 7.222 - fprintf(fp, "# %d: %fx%f+%f+%f\n", g->code, g->width, g->height, g->x, g->y); 7.223 + fprintf(fp, "# %d: %gx%g+%g+%g o:%g,%g adv:%g\n", g->code, g->width, g->height, g->x, g->y, 7.224 + g->orig_x, g->orig_y, g->advance); 7.225 g++; 7.226 } 7.227 fprintf(fp, "255\n"); 7.228 @@ -472,6 +539,12 @@ 7.229 return 0; 7.230 } 7.231 7.232 +void dtx_add_glyphmap(struct dtx_font *fnt, struct dtx_glyphmap *gmap) 7.233 +{ 7.234 + gmap->next = fnt->gmaps; 7.235 + fnt->gmaps = gmap; 7.236 +} 7.237 + 7.238 7.239 void dtx_use_font(struct dtx_font *fnt, int sz) 7.240 { 7.241 @@ -646,6 +719,7 @@ 7.242 return gmap; 7.243 } 7.244 7.245 +#ifdef USE_FREETYPE 7.246 static void calc_best_size(int total_width, int max_glyph_height, int padding, int pow2, int *imgw, int *imgh) 7.247 { 7.248 int xsz, ysz, num_rows; 7.249 @@ -687,3 +761,4 @@ 7.250 x = (x >> 16) | x; 7.251 return x + 1; 7.252 } 7.253 +#endif