Mercurial > mplayer.hg
comparison TOOLS/subfont-c/subfont.c @ 1471:00a1f4b77803
dirty fix to get it work with glibc 2.1.x, and changed blur algorithm
author | arpi |
---|---|
date | Thu, 09 Aug 2001 17:29:25 +0000 |
parents | 2c7b0478db0c |
children | 3182755fdee8 |
comparison
equal
deleted
inserted
replaced
1470:2c7b0478db0c | 1471:00a1f4b77803 |
---|---|
15 #include <stdlib.h> | 15 #include <stdlib.h> |
16 #include <iconv.h> | 16 #include <iconv.h> |
17 #include <math.h> | 17 #include <math.h> |
18 #include <string.h> | 18 #include <string.h> |
19 | 19 |
20 #if 1 /* freetype 2.0.1 */ | 20 #if 0 /* freetype 2.0.1 */ |
21 #include <freetype/freetype.h> | 21 #include <freetype/freetype.h> |
22 #else /* freetype 2.0.3 */ | 22 #else /* freetype 2.0.3 */ |
23 #include <ft2build.h> | 23 #include <ft2build.h> |
24 #include FT_FREETYPE_H | 24 #include FT_FREETYPE_H |
25 #endif | 25 #endif |
30 | 30 |
31 #define f266toInt(x) (((x)+32)>>6) /* round fractional fixed point number to integer */ | 31 #define f266toInt(x) (((x)+32)>>6) /* round fractional fixed point number to integer */ |
32 /* coordinates are in 26.6 pixels (i.e. 1/64th of pixels) */ | 32 /* coordinates are in 26.6 pixels (i.e. 1/64th of pixels) */ |
33 | 33 |
34 | 34 |
35 int const test = 0; | 35 int const test = 1; |
36 | 36 |
37 /* default values */ | 37 /* default values */ |
38 char *encoding = "iso-8859-1"; /* target encoding */ | 38 char *encoding = "iso-8859-1"; /* target encoding */ |
39 char *charmap = "ucs-4le"; /* font charmap encoding */ | 39 /* gcc 2.1.3 doesn't support ucs-4le, but supports ucs-4 (==ucs-4be) */ |
40 char *charmap = "ucs-4"; /* ucs-4le font charmap encoding */ | |
40 int ppem = 20; /* font size in pixels */ | 41 int ppem = 20; /* font size in pixels */ |
41 | 42 |
42 int const colors = 256; | 43 int const colors = 256; |
43 int const maxcolor = 255; | 44 int const maxcolor = 255; |
44 int radius = 6; /* blur radius */ | 45 int radius = 2; /* blur radius */ |
45 double minalpha = 1.0; /* good value for minalpha is 0.5 */ | 46 double minalpha = 1.0; /* good value for minalpha is 0.5 */ |
46 double alpha_factor = 1.0; | 47 double alpha_factor = 1.0; |
47 | 48 |
48 int const first_char = 33; | 49 int const first_char = 33; |
49 int const charset_size = 256; | 50 int const charset_size = 256; |
54 | 55 |
55 | 56 |
56 unsigned char *buffer; | 57 unsigned char *buffer; |
57 unsigned char *abuffer; | 58 unsigned char *abuffer; |
58 int width, height; | 59 int width, height; |
59 FT_ULong ustring[256]; | 60 static FT_ULong ustring[256]; |
60 | 61 |
61 #define eprintf(...) fprintf(stderr, __VA_ARGS__) | 62 #define eprintf(...) fprintf(stderr, __VA_ARGS__) |
62 #define ERROR(msg, ...) (eprintf("%s: error: " msg "\n", command, ##__VA_ARGS__), exit(1)) | 63 #define ERROR(msg, ...) (eprintf("%s: error: " msg "\n", command, ##__VA_ARGS__), exit(1)) |
63 #define WARNING(msg, ...) eprintf("%s: warning: " msg "\n", command, ##__VA_ARGS__) | 64 #define WARNING(msg, ...) eprintf("%s: warning: " msg "\n", command, ##__VA_ARGS__) |
64 | 65 |
94 int const max_name = 128; | 95 int const max_name = 128; |
95 char name[max_name]; | 96 char name[max_name]; |
96 | 97 |
97 snprintf(name, max_name, "%s-b.raw", encoding); | 98 snprintf(name, max_name, "%s-b.raw", encoding); |
98 f = fopen(name, "wb"); | 99 f = fopen(name, "wb"); |
99 if (f==NULL) ERROR("fopen failed."); | 100 if (f==NULL) ERROR("fopen failed.",NULL); |
100 write_header(f); | 101 write_header(f); |
101 fwrite(buffer, 1, width*height, f); | 102 fwrite(buffer, 1, width*height, f); |
102 fclose(f); | 103 fclose(f); |
103 | 104 |
104 snprintf(name, max_name, "%s-a.raw", encoding); | 105 snprintf(name, max_name, "%s-a.raw", encoding); |
105 f = fopen(name, "wb"); | 106 f = fopen(name, "wb"); |
106 if (f==NULL) ERROR("fopen failed."); | 107 if (f==NULL) ERROR("fopen failed.",NULL); |
107 write_header(f); | 108 write_header(f); |
108 fwrite(abuffer, 1, width*height, f); | 109 fwrite(abuffer, 1, width*height, f); |
109 fclose(f); | 110 fclose(f); |
110 } | 111 } |
111 | 112 |
123 int baseline, space_advance = 20; | 124 int baseline, space_advance = 20; |
124 | 125 |
125 | 126 |
126 /* initialize freetype */ | 127 /* initialize freetype */ |
127 error = FT_Init_FreeType(&library); | 128 error = FT_Init_FreeType(&library); |
128 if (error) ERROR("Init_FreeType failed."); | 129 if (error) ERROR("Init_FreeType failed.",NULL); |
129 error = FT_New_Face(library, font_path, 0, &face); | 130 error = FT_New_Face(library, font_path, 0, &face); |
130 if (error) ERROR("New_Face failed."); | 131 if (error) ERROR("New_Face failed.",NULL); |
131 | 132 |
132 /* | 133 /* |
133 if (font_metrics) { | 134 if (font_metrics) { |
134 error = FT_Attach_File(face, font_metrics); | 135 error = FT_Attach_File(face, font_metrics); |
135 if (error) WARNING("Attach_File failed."); | 136 if (error) WARNING("Attach_File failed."); |
136 } | 137 } |
137 */ | 138 */ |
138 | 139 |
139 | 140 |
140 if (face->charmap->encoding!=ft_encoding_unicode) | 141 if (face->charmap->encoding!=ft_encoding_unicode) |
141 WARNING("Selected font has no unicode charmap. Very bad!"); | 142 WARNING("Selected font has no unicode charmap. Very bad!",NULL); |
142 | 143 |
143 | 144 |
144 /* set size */ | 145 /* set size */ |
145 if (FT_IS_SCALABLE(face)) { | 146 if (FT_IS_SCALABLE(face)) { |
146 error = FT_Set_Pixel_Sizes(face, ppem, ppem); | 147 error = FT_Set_Pixel_Sizes(face, ppem, ppem); |
155 } | 156 } |
156 } | 157 } |
157 WARNING("Selected font is not scalable. Using ppem=%i", face->available_sizes[j].height); | 158 WARNING("Selected font is not scalable. Using ppem=%i", face->available_sizes[j].height); |
158 error = FT_Set_Pixel_Sizes(face, face->available_sizes[j].width, face->available_sizes[j].height); | 159 error = FT_Set_Pixel_Sizes(face, face->available_sizes[j].width, face->available_sizes[j].height); |
159 } | 160 } |
160 if (error) WARNING("Set_Pixel_Sizes failed."); | 161 if (error) WARNING("Set_Pixel_Sizes failed.",NULL); |
161 | 162 |
162 | 163 |
163 if (FT_IS_FIXED_WIDTH(face)) | 164 if (FT_IS_FIXED_WIDTH(face)) |
164 WARNING("Selected font is fixed-width."); | 165 WARNING("Selected font is fixed-width.",NULL); |
165 | 166 |
166 | 167 |
167 /* compute space advance */ | 168 /* compute space advance */ |
168 error = FT_Load_Char(face, ' ', load_flags); | 169 error = FT_Load_Char(face, ' ', load_flags); |
169 if (error) WARNING("spacewidth set to default."); | 170 if (error) WARNING("spacewidth set to default.",NULL); |
170 else space_advance = f266toInt(face->glyph->advance.x); /* +32 is for rounding */ | 171 else space_advance = f266toInt(face->glyph->advance.x); /* +32 is for rounding */ |
171 | 172 |
172 | 173 |
173 /* create font.desc */ | 174 /* create font.desc */ |
174 f = fopen("font.desc", "w"); | 175 f = fopen("font.desc", "w"); |
175 if (f==NULL) ERROR("fopen failed."); | 176 if (f==NULL) ERROR("fopen failed.",NULL); |
176 | 177 |
177 /* print font.desc header */ | 178 /* print font.desc header */ |
178 fprintf(f, "[info]\n"); | 179 fprintf(f, "[info]\n"); |
179 fprintf(f, "name 'File generated for %s encoding using `%s%s%s' face (%s), ppem=%i'\n", | 180 fprintf(f, "name 'File generated for %s encoding using `%s%s%s' face (%s), ppem=%i'\n", |
180 encoding, | 181 encoding, |
240 | 241 |
241 } | 242 } |
242 | 243 |
243 fclose(f); | 244 fclose(f); |
244 | 245 |
245 if (ymax<=ymin) ERROR("Something went wrong."); | 246 if (ymax<=ymin) ERROR("Something went wrong.",NULL); |
246 | 247 |
247 | 248 |
248 width = pen_x; | 249 width = pen_x; |
249 height = ymax - ymin + 2*radius; | 250 height = ymax - ymin + 2*radius; |
250 baseline = ymax + radius; | 251 baseline = ymax + radius; |
251 eprintf("bitmap size: %ix%i\n", width, height); | 252 eprintf("bitmap size: %ix%i\n", width, height); |
252 | 253 |
253 buffer = (unsigned char*)malloc(width*height); | 254 buffer = (unsigned char*)malloc(width*height); |
254 abuffer = (unsigned char*)malloc(width*height); | 255 abuffer = (unsigned char*)malloc(width*height); |
255 if (buffer==NULL || abuffer==NULL) ERROR("malloc failed."); | 256 if (buffer==NULL || abuffer==NULL) ERROR("malloc failed.",NULL); |
256 | 257 |
257 | 258 |
258 /* render glyphs */ | 259 /* render glyphs */ |
259 pen_x = 0; | 260 pen_x = 0; |
260 pen_y = baseline; | 261 pen_y = baseline; |
284 pen_x = (pen_x+7)&~7; /* 8 byte align */ | 285 pen_x = (pen_x+7)&~7; /* 8 byte align */ |
285 } | 286 } |
286 | 287 |
287 | 288 |
288 error = FT_Done_FreeType(library); | 289 error = FT_Done_FreeType(library); |
289 if (error) ERROR("Done_FreeType failed."); | 290 if (error) ERROR("Done_FreeType failed.",NULL); |
290 } | 291 } |
291 | 292 |
292 void prepare_charset() { | 293 void prepare_charset() { |
293 iconv_t cd; | 294 iconv_t cd; |
294 unsigned char text[charset_size]; | 295 unsigned char text[charset_size]; |
305 cd = iconv_open(charmap, charmap); | 306 cd = iconv_open(charmap, charmap); |
306 if (cd==(iconv_t)-1) ERROR("iconv doesn't know %s encoding. Use the source!", charmap); | 307 if (cd==(iconv_t)-1) ERROR("iconv doesn't know %s encoding. Use the source!", charmap); |
307 iconv_close(cd); | 308 iconv_close(cd); |
308 | 309 |
309 cd = iconv_open(charmap, encoding); | 310 cd = iconv_open(charmap, encoding); |
310 if (cd==(iconv_t)-1) ERROR("Unsupported encoding, use iconv -l to list character sets known on your system."); | 311 if (cd==(iconv_t)-1) ERROR("Unsupported encoding, use iconv -l to list character sets known on your system.",NULL); |
311 while (1) { | 312 while (1) { |
312 count = iconv(cd, &inbuf, &inbuf_left, &outbuf, &outbuf_left); | 313 count = iconv(cd, &inbuf, &inbuf_left, &outbuf, &outbuf_left); |
313 if (inbuf_left==0) break; | 314 if (inbuf_left==0) break; |
314 /* skip undefined characters */ | 315 /* skip undefined characters */ |
315 inbuf+= 1; | 316 inbuf+= 1; |
316 inbuf_left-= 1; | 317 inbuf_left-= 1; |
317 *(FT_ULong*)outbuf = 0; | 318 *(FT_ULong*)outbuf = 0; |
318 outbuf+= 4; | 319 outbuf+=sizeof(FT_ULong); |
319 } | 320 } |
320 iconv_close(cd); | 321 iconv_close(cd); |
322 | |
323 /* converting unicodes BE -> LE */ | |
324 for (i = 0; i<256; ++i){ | |
325 FT_ULong x=ustring[i]; | |
326 x= ((x>>24)&255) | |
327 | (((x>>16)&255)<<8) | |
328 | (((x>> 8)&255)<<16) | |
329 | ((x&255)<<24); | |
330 ustring[i]=x; | |
331 } | |
332 | |
321 } | 333 } |
322 | 334 |
323 void blur() { | 335 void blur() { |
324 int const r = radius; | 336 int const r = radius; |
325 int const w = 2*r+1; /* matrix size */ | 337 int const w = 2*r+1; /* matrix size */ |
326 double const A = log(minalpha/maxcolor)/((r+1)*(r+1)); | 338 double const A = log(1.0/maxcolor)/((r+1)*(r+1)); |
327 double const B = alpha_factor * maxcolor; | 339 double const B = maxcolor; |
340 int sum=0; | |
328 | 341 |
329 int i, x, y, mx, my; | 342 int i, x, y, mx, my; |
330 unsigned char *m = (unsigned char*)malloc(w*w); | 343 unsigned char *m = (unsigned char*)malloc(w*w); |
331 | 344 |
332 if (m==NULL) ERROR("malloc failed"); | 345 if (m==NULL) ERROR("malloc failed",NULL); |
333 | 346 |
334 | 347 |
335 /* Gaussian matrix */ | 348 /* Gaussian matrix */ |
336 for (my = 0; my<w; ++my) { | 349 for (my = 0; my<w; ++my) { |
337 for (mx = 0; mx<w; ++mx) { | 350 for (mx = 0; mx<w; ++mx) { |
338 m[mx+my*w] = (int)(exp(A * ((mx-r)*(mx-r)+(my-r)*(my-r))) * B + .5); | 351 m[mx+my*w] = (int)(exp(A * ((mx-r)*(mx-r)+(my-r)*(my-r))) * B + .5); |
352 sum+=m[mx+my*w]; | |
339 if (test) eprintf("%3i ", m[mx+my*w]); | 353 if (test) eprintf("%3i ", m[mx+my*w]); |
340 } | 354 } |
341 if (test) eprintf("\n"); | 355 if (test) eprintf("\n"); |
342 } | 356 } |
357 printf("gauss sum = %d\n",sum); | |
343 | 358 |
344 /* This is not a gaussian blur! */ | 359 /* This is not a gaussian blur! */ |
345 /* And is very slow */ | 360 /* And is very slow */ |
346 for (y = 0; y<height; ++y) | 361 for (y = 0; y<height; ++y){ |
347 for (x = 0; x<width; ++x) { | 362 for (x = 0; x<width; ++x) { |
348 int max = -1; | 363 float max = 0; |
349 for (my = -r; my<=r; ++my) | 364 for (my = -r; my<=r; ++my) |
350 if (y+my>=0 && y+my<height) | 365 if (y+my>0 && y+my<height-1) |
351 for (mx = -r; mx<=r; ++mx) { | 366 for (mx = -r; mx<=r; ++mx) { |
352 if (x+mx>=0 && x+mx<width) { | 367 if (x+mx>0 && x+mx<width-1) { |
353 int p = buffer[x+mx+(y+my)*width] * m[mx+r+(my+r)*w]; | 368 // int p = buffer[x+mx+(y+my)*width] * m[mx+r+(my+r)*w]; |
354 if (p>max) { | 369 int p = 0; |
355 max = p; | 370 |
356 abuffer[x+y*width] = (p + maxcolor/2) / maxcolor; | 371 p = ( (buffer[x+mx-1+(y+my-1)*width]) + |
357 } | 372 (buffer[x+mx-1+(y+my+1)*width]) + |
373 (buffer[x+mx+1+(y+my-1)*width]) + | |
374 (buffer[x+mx+1+(y+my+1)*width]) )/2 + | |
375 | |
376 ( (buffer[x+mx-1+(y+my)*width]) + | |
377 (buffer[x+mx+1+(y+my)*width]) + | |
378 (buffer[x+mx+(y+my-1)*width]) + | |
379 (buffer[x+mx+(y+my+1)*width]) + | |
380 | |
381 (buffer[x+mx+(y+my)*width]) ) ; | |
382 | |
383 if(p>255) p=255; | |
384 | |
385 // p*=m[mx+r+(my+r)*w]; | |
386 // if (p>max) { | |
387 // max = p; | |
388 // abuffer[x+y*width] = (p + maxcolor/2) / maxcolor; | |
389 // } | |
390 //max+=(p + maxcolor/2) / maxcolor; | |
391 max+=p*m[mx+r+(my+r)*w]/(float)sum; | |
358 } | 392 } |
359 | 393 |
360 } | 394 } |
361 } | 395 max=max*alpha_factor; |
396 // printf("%5.3f ",max); | |
397 if(max>255) max=255; | |
398 abuffer[x+y*width] = max; | |
399 } | |
400 // printf("\n"); | |
401 } | |
362 free(m); | 402 free(m); |
363 } | 403 } |
364 | 404 |
365 void usage() { | 405 void usage() { |
366 printf("Usage: %s encoding ppem font [alphaFactor [minAlpha [radius]]]\n", command); | 406 printf("Usage: %s encoding ppem font [alphaFactor [minAlpha [radius]]]\n", command); |
398 font_path = argv[3]; | 438 font_path = argv[3]; |
399 | 439 |
400 if (argc>4) { | 440 if (argc>4) { |
401 d = atof(argv[4]); | 441 d = atof(argv[4]); |
402 if (d>0.001 && d<1000.) alpha_factor = d; | 442 if (d>0.001 && d<1000.) alpha_factor = d; |
403 else WARNING("alphaFactor set to default."); | 443 else WARNING("alphaFactor set to default.",NULL); |
404 } | 444 } |
405 if (argc>5) { | 445 if (argc>5) { |
406 d = atof(argv[5]); | 446 d = atof(argv[5]); |
407 if (d>0.1 && d<=maxcolor) minalpha = d; | 447 if (d>0.1 && d<=maxcolor) minalpha = d; |
408 else WARNING("minAlpha set to default."); | 448 else WARNING("minAlpha set to default.",NULL); |
409 } | 449 } |
410 if (argc>6) { | 450 if (argc>6) { |
411 i = atoi(argv[6]); | 451 i = atoi(argv[6]); |
412 if (i>=0 && i<20) radius = i; | 452 if (i>=0 && i<20) radius = i; |
413 else WARNING("radius set to default."); | 453 else WARNING("radius set to default.",NULL); |
414 } | 454 } |
415 } | 455 } |
416 | 456 |
417 int main(int argc, char **argv) { | 457 int main(int argc, char **argv) { |
418 parse_args(argc, argv); | 458 parse_args(argc, argv); |