diff options
author | 2001-08-13 18:37:10 +0000 | |
---|---|---|
committer | 2001-08-13 18:37:10 +0000 | |
commit | 1aef871541c7018a332a5544ee9698398fc994a6 (patch) | |
tree | 8bf4d39f242f52391398ecb8705fc1c958b2ea21 /TOOLS/subfont-c/subfont.c | |
parent | 8632ea05269cd3d71b21bc62832967267accaafa (diff) |
upgraded to 1.0b version by Artur Zaprzala <artur.zaprzala@talex.com.pl>
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@1506 b3059339-0415-0410-9bf9-f77b7e298cf2
Diffstat (limited to 'TOOLS/subfont-c/subfont.c')
-rw-r--r-- | TOOLS/subfont-c/subfont.c | 659 |
1 files changed, 431 insertions, 228 deletions
diff --git a/TOOLS/subfont-c/subfont.c b/TOOLS/subfont-c/subfont.c index b72040776d..ba572273da 100644 --- a/TOOLS/subfont-c/subfont.c +++ b/TOOLS/subfont-c/subfont.c @@ -16,53 +16,72 @@ #include <iconv.h> #include <math.h> #include <string.h> +#include <libgen.h> + + +#ifndef OLD_FREETYPE2 -#if 0 /* freetype 2.0.1 */ -#include <freetype/freetype.h> -#else /* freetype 2.0.3 */ #include <ft2build.h> #include FT_FREETYPE_H -#endif - #include FT_GLYPH_H +#else /* freetype 2.0.1 */ +#include <freetype/freetype.h> +#include <freetype/ftglyph.h> -#define f266toInt(x) (((x)+32)>>6) /* round fractional fixed point number to integer */ - /* coordinates are in 26.6 pixels (i.e. 1/64th of pixels) */ +#endif +#ifndef DEBUG +#define DEBUG 0 +#endif -int const test = 1; -/* default values */ +//// default values char *encoding = "iso-8859-1"; /* target encoding */ -/* gcc 2.1.3 doesn't support ucs-4le, but supports ucs-4 (==ucs-4be) */ -char *charmap = "ucs-4"; /* ucs-4le font charmap encoding */ -int ppem = 20; /* font size in pixels */ +char *charmap = "ucs-4"; /* font charmap encoding, I hope ucs-4 is always big endian */ + /* gcc 2.1.3 doesn't support ucs-4le, but supports ucs-4 (==ucs-4be) */ +int ppem = 22; /* font size in pixels */ + +double radius = 2; /* blur radius */ +double thickness = 1.5; /* outline thickness */ +int padding; + +char* font_desc = "font.desc"; +//char* font_desc = "/dev/stdout"; +//// constants int const colors = 256; int const maxcolor = 255; -int radius = 2; /* blur radius */ -double minalpha = 1.0; /* good value for minalpha is 0.5 */ -double alpha_factor = 1.0; - -int const first_char = 33; -int const charset_size = 256; +unsigned const base = 256; +unsigned const first_char = 33; +#define max_charset_size 60000 +//int const max_charset_size = 256; +unsigned charset_size = 0; +//// char *command; -char *font_path = NULL; -/*char *font_metrics = NULL;*/ - +char *font_path; +//char *font_metrics; +int append_mode = 0; -unsigned char *buffer; -unsigned char *ebuffer; // temporary buffer for alphamap creation (edges) -unsigned char *abuffer; +unsigned char *buffer, *abuffer; int width, height; -static FT_ULong ustring[256]; +static FT_ULong charset[max_charset_size]; /* characters we want to render; Unicode */ +static FT_ULong charcodes[max_charset_size]; /* character codes in 'encoding' */ +iconv_t cd; // iconv conversion descriptor + + #define eprintf(...) fprintf(stderr, __VA_ARGS__) -#define ERROR(msg, ...) (eprintf("%s: error: " msg "\n", command, ##__VA_ARGS__), exit(1)) -#define WARNING(msg, ...) eprintf("%s: warning: " msg "\n", command, ##__VA_ARGS__) +#define ERROR_(msg, ...) (eprintf("%s: error: " msg "\n", command, __VA_ARGS__), exit(1)) +#define WARNING_(msg, ...) eprintf("%s: warning: " msg "\n", command, __VA_ARGS__) +#define ERROR(...) ERROR_(__VA_ARGS__, NULL) +#define WARNING(...) WARNING_(__VA_ARGS__, NULL) + +#define f266toInt(x) (((x)+32)>>6) // round fractional fixed point number to integer + // coordinates are in 26.6 pixels (i.e. 1/64th of pixels) +#define ALIGN(x) (((x)+7)&~7) // 8 byte align @@ -80,6 +99,7 @@ void paste_bitmap(FT_Bitmap *bitmap, int x, int y) { buffer[drow+dp] = bitmap->buffer[srow+sp]; } + void write_header(FILE *f) { static unsigned char header[800] = "mhwanh"; int i; @@ -91,6 +111,7 @@ void write_header(FILE *f) { fwrite(header, 1, 800, f); } + void write_bitmap() { FILE *f; int const max_name = 128; @@ -98,38 +119,40 @@ void write_bitmap() { snprintf(name, max_name, "%s-b.raw", encoding); f = fopen(name, "wb"); - if (f==NULL) ERROR("fopen failed.",NULL); + if (f==NULL) ERROR("fopen failed."); write_header(f); fwrite(buffer, 1, width*height, f); fclose(f); snprintf(name, max_name, "%s-a.raw", encoding); f = fopen(name, "wb"); - if (f==NULL) ERROR("fopen failed.",NULL); + if (f==NULL) ERROR("fopen failed."); write_header(f); fwrite(abuffer, 1, width*height, f); fclose(f); } + void render() { FT_Library library; FT_Face face; FT_Error error; FT_GlyphSlot slot; - FT_ULong glyph_index; - FT_Glyph glyphs[charset_size]; + FT_ULong glyph_index, character, code; + //FT_Glyph glyphs[max_charset_size]; + FT_Glyph glyph; FILE *f; int const load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING; int pen_x, pen_xa, pen_y, ymin, ymax; - int i, c; + int i, uni_charmap = 1; int baseline, space_advance = 20; /* initialize freetype */ error = FT_Init_FreeType(&library); - if (error) ERROR("Init_FreeType failed.",NULL); + if (error) ERROR("Init_FreeType failed."); error = FT_New_Face(library, font_path, 0, &face); - if (error) ERROR("New_Face failed.",NULL); + if (error) ERROR("New_Face failed."); /* if (font_metrics) { @@ -139,8 +162,39 @@ void render() { */ - if (face->charmap->encoding!=ft_encoding_unicode) - WARNING("Selected font has no unicode charmap. Very bad!",NULL); +#if 0 + /************************************************************/ + eprintf("Font encodings:\n"); + for (i = 0; i<face->num_charmaps; ++i) + eprintf("'%.4s'\n", (char*)&face->charmaps[i]->encoding); + + //error = FT_Select_Charmap(face, ft_encoding_unicode); + //error = FT_Select_Charmap(face, ft_encoding_adobe_standard); + //error = FT_Select_Charmap(face, ft_encoding_adobe_custom); + //error = FT_Set_Charmap(face, face->charmaps[1]); + //if (error) WARNING("Select_Charmap failed."); +#endif +#if 0 + /************************************************************/ + if (FT_HAS_GLYPH_NAMES(face)) { + int const max_gname = 128; + char gname[max_gname]; + for (i = 0; i<face->num_glyphs; ++i) { + FT_Get_Glyph_Name(face, i, gname, max_gname); + eprintf("%02x `%s'\n", i, gname); + } + + } +#endif + + + if (face->charmap==NULL || face->charmap->encoding!=ft_encoding_unicode) { + WARNING("Unicode charmap not available for this font. Very bad!"); + uni_charmap = 0; + error = FT_Set_Charmap(face, face->charmaps[0]); + if (error) WARNING("No charmaps! Strange."); + } + /* set size */ @@ -156,38 +210,46 @@ void render() { jppem = face->available_sizes[i].height; } } - WARNING("Selected font is not scalable. Using ppem=%i", face->available_sizes[j].height); + WARNING("Selected font is not scalable. Using ppem=%i.", face->available_sizes[j].height); error = FT_Set_Pixel_Sizes(face, face->available_sizes[j].width, face->available_sizes[j].height); } - if (error) WARNING("Set_Pixel_Sizes failed.",NULL); + if (error) WARNING("Set_Pixel_Sizes failed."); if (FT_IS_FIXED_WIDTH(face)) - WARNING("Selected font is fixed-width.",NULL); + WARNING("Selected font is fixed-width."); /* compute space advance */ error = FT_Load_Char(face, ' ', load_flags); - if (error) WARNING("spacewidth set to default.",NULL); - else space_advance = f266toInt(face->glyph->advance.x); /* +32 is for rounding */ + if (error) WARNING("spacewidth set to default."); + else space_advance = f266toInt(face->glyph->advance.x); /* create font.desc */ - f = fopen("font.desc", "w"); - if (f==NULL) ERROR("fopen failed.",NULL); + f = fopen(font_desc, append_mode ? "a":"w"); + if (f==NULL) ERROR("fopen failed."); /* print font.desc header */ - fprintf(f, "[info]\n"); - fprintf(f, "name 'File generated for %s encoding using `%s%s%s' face (%s), ppem=%i'\n", - encoding, - face->family_name, - face->style_name ? " ":"", face->style_name ? face->style_name:"", - font_path, - ppem); - fprintf(f, "descversion 1\n"); - fprintf(f, "spacewidth %i\n", 2*radius + space_advance); - fprintf(f, "charspace %i\n", -2*radius); - fprintf(f, "height %i\n", f266toInt(face->size->metrics.height)); + if (append_mode) { + fprintf(f, "\n\n# Subtitle font for %s encoding, face \"%s%s%s\", ppem=%i\n", + encoding, + face->family_name, + face->style_name ? " ":"", face->style_name ? face->style_name:"", + ppem); + } else { + fprintf(f, "# This file was generated with subfont for Mplayer.\n# Subfont by Artur Zaprzala <zybi@fanthom.irc.pl>.\n\n"); + fprintf(f, "[info]\n"); + fprintf(f, "name 'Subtitle font for %s encoding, face \"%s%s%s\", ppem=%i'\n", + encoding, + face->family_name, + face->style_name ? " ":"", face->style_name ? face->style_name:"", + ppem); + fprintf(f, "descversion 1\n"); + fprintf(f, "spacewidth %i\n", 2*padding + space_advance); + fprintf(f, "charspace %i\n", -2*padding); + fprintf(f, "height %i\n", f266toInt(face->size->metrics.height)); + } fprintf(f, "\n[files]\n"); fprintf(f, "alpha %s-a.raw\n", encoding); fprintf(f, "bitmap %s-b.raw\n", encoding); @@ -199,288 +261,429 @@ void render() { pen_y = 0; ymin = INT_MAX; ymax = INT_MIN; - for (c= first_char, i= 0; c<charset_size; ++c, ++i) { + for (i= 0; i<charset_size; ++i) { FT_UInt glyph_index; FT_BBox bbox; - - glyph_index = FT_Get_Char_Index(face, ustring[i]); - if (glyph_index<=0) { - WARNING("Glyph for char %3i|%2X|U%04X not found.", c, c, ustring[i]); - continue; + character = charset[i]; + code = charcodes[i]; + + if (character==0) + glyph_index = 0; + else { + glyph_index = FT_Get_Char_Index(face, uni_charmap ? character:code); + if (glyph_index==0) { + WARNING("Glyph for char 0x%02x|U+%04X|%c not found.", code, character, + code<' '||code>255 ? '.':code); + continue; + } } error = FT_Load_Glyph(face, glyph_index, load_flags); if (error) { - WARNING("Load_Glyph %3u|%2X (char %3i|%2X|U%04X) failed.", glyph_index, glyph_index, c, c, ustring[i]); + WARNING("Load_Glyph 0x%02x (char 0x%02x|U+%04X) failed.", glyph_index, code, character); continue; } slot = face->glyph; - error = FT_Get_Glyph(slot, &glyphs[i]); + error = FT_Get_Glyph(slot, &glyph); - FT_Glyph_Get_CBox(glyphs[i], ft_glyph_bbox_pixels, &bbox); + FT_Glyph_Get_CBox(glyph, ft_glyph_bbox_pixels, &bbox); if (pen_y+bbox.yMax>ymax) { ymax = pen_y+bbox.yMax; - /* eprintf("%3i: ymax %i (%c)\n", c, ymax, c); */ + // eprintf("%3i: ymax %i (%c)\n", code, ymax, code); } if (pen_y+bbox.yMin<ymin) { ymin = pen_y+bbox.yMin; - /* eprintf("%3i: ymin %i (%c)\n", c, ymin, c); */ + // eprintf("%3i: ymin %i (%c)\n", code, ymin, code); } /* advance pen */ - pen_xa = pen_x + f266toInt(slot->advance.x) + 2*radius; - /* pen_y += f266toInt(slot->advance.y); // for vertical layout */ + pen_xa = pen_x + f266toInt(slot->advance.x) + 2*padding; + // pen_y += f266toInt(slot->advance.y); // for vertical layout /* font.desc */ - if (c=='\'') - fprintf(f, "\"%c\" %i %i\n", c, pen_x, pen_xa-1); - else - fprintf(f, "'%c' %i %i\n", c, pen_x, pen_xa-1); - pen_x = (pen_xa+7)&~7; /* 8 byte align */ + fprintf(f, "0x%02x %i %i;\tU+%04X|%c\n", code, pen_x, pen_xa-1, character, code<' '||code>255 ? '.':code); + pen_x = ALIGN(pen_xa); } fclose(f); - if (ymax<=ymin) ERROR("Something went wrong.",NULL); + if (ymax<=ymin) ERROR("Something went wrong. Use the source!"); width = pen_x; - height = ymax - ymin + 2*radius; - baseline = ymax + radius; + height = ymax - ymin + 2*padding; + baseline = ymax + padding; eprintf("bitmap size: %ix%i\n", width, height); buffer = (unsigned char*)malloc(width*height); - ebuffer = (unsigned char*)malloc(width*height); abuffer = (unsigned char*)malloc(width*height); - if (buffer==NULL || abuffer==NULL) ERROR("malloc failed.",NULL); + if (buffer==NULL || abuffer==NULL) ERROR("malloc failed."); + + memset(buffer, 0, width*height); /* render glyphs */ pen_x = 0; pen_y = baseline; - for (c= first_char, i= 0; c<charset_size; ++c, ++i) { + for (i= 0; i<charset_size; ++i) { FT_UInt glyph_index; + character = charset[i]; + code = charcodes[i]; + + if (character==0) + glyph_index = 0; + else { + glyph_index = FT_Get_Char_Index(face, uni_charmap ? character:code); + if (glyph_index==0) + continue; + } - glyph_index = FT_Get_Char_Index(face, ustring[i]); - if (glyph_index==0) continue; error = FT_Load_Glyph(face, glyph_index, load_flags); if (error) { - /* WARNING("Load_Glyph failed"); */ + // WARNING("Load_Glyph failed."); continue; } error = FT_Render_Glyph(face->glyph, ft_render_mode_normal); - if (error) WARNING("Render_Glyph %3i|%2X (char %3i|%2X|U%04X) failed.", glyph_index, glyph_index, c, c, ustring[i]); + if (error) WARNING("Render_Glyph 0x%02x (char 0x%02x|U+%04X) failed.", glyph_index, code, character); slot = face->glyph; paste_bitmap(&slot->bitmap, - pen_x + radius + slot->bitmap_left, + pen_x + padding + slot->bitmap_left, pen_y - slot->bitmap_top ); /* advance pen */ - pen_x += f266toInt(slot->advance.x) + 2*radius; - /* pen_y += f266toInt(slot->advance.y); // for vertical layout */ - pen_x = (pen_x+7)&~7; /* 8 byte align */ + pen_x += f266toInt(slot->advance.x) + 2*padding; + // pen_y += f266toInt(slot->advance.y); // for vertical layout + pen_x = ALIGN(pen_x); } error = FT_Done_FreeType(library); - if (error) ERROR("Done_FreeType failed.",NULL); + if (error) ERROR("Done_FreeType failed."); } + +/* decode from 'encoding' to unicode */ +FT_ULong decode_char(char c) { + FT_ULong o; + char *inbuf = &c; + char *outbuf = (char*)&o; + int inbytesleft = 1; + int outbytesleft = sizeof(FT_ULong); + + size_t count = iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft); + if (count==-1) o = 0; + + /* convert unicode BE -> LE */ + o = ((o>>24)&0xff) + | ((o>>8)&0xff00) + | ((o&0xff00)<<8) + | ((o&0xff)<<24); + + /* we don't want control characters */ + if (o>=0x7f && o<0xa0) o = 0; + return o; +} + + void prepare_charset() { - iconv_t cd; - unsigned char text[charset_size]; - char *inbuf = text; - char *outbuf = (char*) ustring; - int inbuf_left = charset_size; - int outbuf_left = 4*charset_size; - int i; - size_t count; - - for (i = first_char; i<charset_size; ++i) text[i-first_char] = i; - - /* check if ucs-4le is available */ - cd = iconv_open(charmap, charmap); - if (cd==(iconv_t)-1) ERROR("iconv doesn't know %s encoding. Use the source!", charmap); - iconv_close(cd); - - cd = iconv_open(charmap, encoding); - if (cd==(iconv_t)-1) ERROR("Unsupported encoding, use iconv -l to list character sets known on your system.",NULL); - while (1) { - count = iconv(cd, &inbuf, &inbuf_left, &outbuf, &outbuf_left); - if (inbuf_left==0) break; - /* skip undefined characters */ - inbuf+= 1; - inbuf_left-= 1; - *(FT_ULong*)outbuf = 0; - outbuf+=sizeof(FT_ULong); + FILE *f; + FT_ULong i; + + f = fopen(encoding, "r"); // try to read custom encoding + if (f==NULL) { + int count = 0; + // check if ucs-4 is available + cd = iconv_open(charmap, charmap); + if (cd==(iconv_t)-1) ERROR("iconv doesn't know %s encoding. Use the source!", charmap); + iconv_close(cd); + + cd = iconv_open(charmap, encoding); + if (cd==(iconv_t)-1) ERROR("Unsupported encoding `%s', use iconv --list to list character sets known on your system.", encoding); + + charset_size = 256 - first_char; + for (i = 0; i<charset_size; ++i) { + charcodes[count] = i+first_char; + charset[count] = decode_char(i+first_char); + //eprintf("%04X U%04X\n", charcodes[count], charset[count]); + if (charset[count]!=0) ++count; + } + charcodes[count] = charset[count] = 0; ++count; + charset_size = count; + + iconv_close(cd); + } else { + unsigned int character, code; + int count; + + eprintf("Reading custom encoding from file '%s'.\n", encoding); + + while ((count = fscanf(f, "%x%*[ \t]%x", &character, &code)) != EOF) { + if (charset_size==max_charset_size) { + WARNING("There is no place for more than %i characters. Use the source!", max_charset_size); + break; + } + if (count==0) ERROR("Unable to parse custom encoding file."); + if (character<32) continue; // skip control characters + charset[charset_size] = character; + charcodes[charset_size] = count==2 ? code : character; + ++charset_size; + } + fclose(f); + encoding = basename(encoding); } - iconv_close(cd); - - /* converting unicodes BE -> LE */ - for (i = 0; i<256; ++i){ - FT_ULong x=ustring[i]; - x= ((x>>24)&255) - | (((x>>16)&255)<<8) - | (((x>> 8)&255)<<16) - | ((x&255)<<24); - ustring[i]=x; + if (charset_size==0) ERROR("No characters to render!"); +} + + +// general outline +void outline( + unsigned char *s, + unsigned char *t, + int width, + int height, + int *m, + int r, + int mwidth) { + + int x, y, mx, my; + for (y = 0; y<height; ++y) { + for (x = 0; x<width; ++x, ++s, ++t) { + unsigned max = 0; + unsigned *mrow = m + r; + unsigned char *srow = s -r*width; + + for (my = -r; my<=r; ++my, srow+= width, mrow+= mwidth) { + if (y+my < 0) continue; + if (y+my >= height) break; + + for (mx = -r; mx<=r; ++mx) { + unsigned v; + if (x+mx < 0) continue; + if (x+mx >= width) break; + + v = srow[mx] * mrow[mx]; + if (v>max) max = v; + } + } + *t = (max + base/2) / base; + } } +} + +// 1 pixel outline +void outline1( + unsigned char *s, + unsigned char *t, + int width, + int height) { + + int x, y, mx, my; + + for (x = 0; x<width; ++x, ++s, ++t) *t = *s; + for (y = 1; y<height-1; ++y) { + *t++ = *s++; + for (x = 1; x<width-1; ++x, ++s, ++t) { + unsigned v = ( + s[-1-width]+ + s[-1+width]+ + s[+1-width]+ + s[+1+width] + )/2 + ( + s[-1]+ + s[+1]+ + s[-width]+ + s[+width]+ + s[0] + ); + *t = v>maxcolor ? maxcolor : v; + } + *t++ = *s++; + } + for (x = 0; x<width; ++x, ++s, ++t) *t = *s; } -void blur() { - int const r = radius; - int const w = 2*r+1; /* matrix size */ - double const A = log(1.0/maxcolor)/((r+1)*(r+1)); - double const B = maxcolor; - int sum=0; - int i, x, y, mx, my; - unsigned char *m = (unsigned char*)malloc(w*w); +// brute-force gaussian blur +void blur( + unsigned char *s, + unsigned char *t, + int width, + int height, + int *m, + int r, + int mwidth, + unsigned volume) { - if (m==NULL) ERROR("malloc failed",NULL); + int x, y, mx, my; + for (y = 0; y<height; ++y) { + for (x = 0; x<width; ++x, ++s, ++t) { + unsigned sum = 0; + unsigned *mrow = m + r; + unsigned char *srow = s -r*width; - /* Gaussian matrix */ - for (my = 0; my<w; ++my) { - for (mx = 0; mx<w; ++mx) { - m[mx+my*w] = (int)(exp(A * ((mx-r)*(mx-r)+(my-r)*(my-r))) * B + .5); - sum+=m[mx+my*w]; - if (test) eprintf("%3i ", m[mx+my*w]); + for (my = -r; my<=r; ++my, srow+= width, mrow+= mwidth) { + if (y+my < 0) continue; + if (y+my >= height) break; + + for (mx = -r; mx<=r; ++mx) { + if (x+mx < 0) continue; + if (x+mx >= width) break; + + sum+= srow[mx] * mrow[mx]; + } + } + *t = (sum + volume/2) / volume; } - if (test) eprintf("\n"); } - printf("gauss sum = %d\n",sum); - - /* This is not a gaussian blur! */ - /* And is very slow */ - - // PASS-1 : build edge mask: - memset(ebuffer,0,width*height); // clear - for (y = 1; y<height-1; ++y){ - int ay=y*width; - int ax; - for (ax = 1; ax<width-1; ++ax) { - int p = - - ( (buffer[ax-1+ay-width]) + - (buffer[ax-1+ay+width]) + - (buffer[ax+1+ay-width]) + - (buffer[ax+1+ay+width]) )/2 + - - ( (buffer[ax-1+ay]) + - (buffer[ax+1+ay]) + - (buffer[ax+ay-width]) + - (buffer[ax+ay+width]) + - - (buffer[ax+ay]) ) ; - - ebuffer[ax+ay]=(p>255)?255:p; +} + + +void alpha() { + int const g_r = ceil(radius); + int const o_r = ceil(thickness); + int const g_w = 2*g_r+1; // matrix size + int const o_w = 2*o_r+1; // matrix size + double const A = log(1.0/base)/(radius*radius*2); + + int mx, my; + unsigned volume = 0; // volume under Gaussian area is exactly -pi*base/A + + unsigned *gm = (unsigned*)malloc(g_w*g_w * sizeof(unsigned)); + unsigned *om = (unsigned*)malloc(o_w*o_w * sizeof(unsigned)); + unsigned char *tbuffer = (unsigned char*)malloc(width*height); + if (gm==NULL || om==NULL || tbuffer==NULL) ERROR("malloc failed."); + + + /* Gaussian matrix */ + for (my = 0; my<g_w; ++my) { + for (mx = 0; mx<g_w; ++mx) { + gm[mx+my*g_w] = (unsigned)(exp(A * ((mx-g_r)*(mx-g_r)+(my-g_r)*(my-g_r))) * base + .5); + volume+= gm[mx+my*g_w]; + if (DEBUG) eprintf("%3i ", gm[mx+my*g_w]); } -// printf("\n"); + if (DEBUG) eprintf("\n"); + } + if (DEBUG) { + eprintf("A= %f\n", A); + eprintf("volume: %i; exact: %.0f; volume/exact: %.6f\n\n", volume, -M_PI*base/A, volume/(-M_PI*base/A)); } - // PASS-2 : blur - for (y = 0; y<height; ++y){ - for (x = 0; x<width; ++x) { - float max = 0; - for (my = -r; my<=r; ++my){ - int ay=y+my; - if(ay>0 && ay<height){ - int by=r+(my+r)*w; - ay*=width; - for (mx = -r; mx<=r; ++mx) - if(x+mx>0 && x+mx<width) - max+=ebuffer[x+mx+ay]*m[mx+by]; - } - } - max*=alpha_factor/(float)sum; -// printf("%5.3f ",max); - if(max>255) max=255; - abuffer[x+y*width] = max; + + /* outline matrix */ + for (my = 0; my<o_w; ++my) { + for (mx = 0; mx<o_w; ++mx) { + // antialiased circle would be perfect here, but this one is good enough + double d = thickness + 1 - sqrt((mx-o_r)*(mx-o_r)+(my-o_r)*(my-o_r)); + om[mx+my*o_w] = d>=1 ? base : d<=0 ? 0 : (d*base + .5); + if (DEBUG) eprintf("%3i ", om[mx+my*o_w]); } -// printf("\n"); + if (DEBUG) eprintf("\n"); } + if (DEBUG) eprintf("\n"); + + + outline(buffer, tbuffer, width, height, om, o_r, o_w); // solid outline + //outline(buffer, tbuffer, width, height, gm, g_r, g_w); // Gaussian outline + //outline1(buffer, tbuffer, width, height); // solid 1 pixel outline + + blur(tbuffer, abuffer, width, height, gm, g_r, g_w, volume); - free(m); + free(gm); + free(om); + free(tbuffer); } + void usage() { - printf("Usage: %s encoding ppem font [alphaFactor [minAlpha [radius]]]\n", command); - printf( + printf("Usage: %s [--append] [--blur b] [--outline o] encoding ppem font\n", command); + printf("\n" " Program creates 3 files: font.desc, <encoding>-a.raw, <encoding>-b.raw.\n" - " You should append font.desc.tail (desc for OSD characters by a'rpi & chass) to font.desc,\n" - " and copy font.desc and all *.raw files to ~/.mplayer/font/ directory.\n" "\n" - " encoding must be 8 bit encoding, like iso-8859-2.\n" - " To list encodings available on your system use iconv -l.\n" - " ppem Font size in pixels (e.g. 24).\n" - " font Font file path. Any format supported by freetype library (*.ttf, *.pf?, *).\n" - " alphaFactor Alpha map scaling factor (default is 1.0), float.\n" - " minAlpha Alpha map minimum value (default is 1.0, max is 255), float.\n" - " radius Alpha map blur radius (default is 6 pixels), integer.\n" + " --append append results to existing font.desc.\n" + " --blur b specify blur radius, float.\n" + " --outline o specify outline thickness, float.\n" + " encoding must be an 8 bit encoding, like iso-8859-2, or path to custom encoding file (see README).\n" + " To list encodings available on your system use iconv --list.\n" + " ppem Font size in pixels (e.g. 24).\n" + " font Font file path. Any format supported by the freetype library (*.ttf, *.pfb, ...).\n" ); exit(1); } + void parse_args(int argc, char **argv) { - int i; + int i, a = 0; double d; - command = strrchr(argv[0], '/'); - if (command==NULL) command = argv[0]; + command = strrchr(argv[a], '/'); + if (command==NULL) command = argv[a]; else ++command; + ++a; --argc; - if (argc<4) usage(); - - encoding = argv[1]; + if (argc==0) usage(); + if (strcmp(argv[a], "--append")==0) { + append_mode = 1; + ++a; --argc; + } - i = atoi(argv[2]); - if (i>1) ppem = i; - font_path = argv[3]; + if (argc==0) usage(); + if (strcmp(argv[a], "--blur")==0) { + ++a; --argc; + if (argc==0) usage(); - if (argc>4) { - d = atof(argv[4]); - if (d>0.001 && d<1000.) alpha_factor = d; - else WARNING("alphaFactor set to default.",NULL); + d = atof(argv[a]); + if (d>=0 && d<20) radius = d; + else WARNING("using default blur radius."); + ++a; --argc; } - if (argc>5) { - d = atof(argv[5]); - if (d>0.1 && d<=maxcolor) minalpha = d; - else WARNING("minAlpha set to default.",NULL); - } - if (argc>6) { - i = atoi(argv[6]); - if (i>=0 && i<20) radius = i; - else WARNING("radius set to default.",NULL); + + if (argc==0) usage(); + if (strcmp(argv[a], "--outline")==0) { + ++a; --argc; + if (argc==0) usage(); + + d = atof(argv[a]); + if (d>=0 && d<20) thickness = d; + else WARNING("using default outline thickness."); + ++a; --argc; } + + if (argc<3) usage(); + + if (argv[a][0]!=0) + encoding = argv[a]; + ++a; --argc; + + i = atoi(argv[a]); + if (i>1) ppem = i; + ++a; --argc; + + font_path = argv[a]; + ++a; --argc; } + int main(int argc, char **argv) { parse_args(argc, argv); + padding = ceil(radius) + ceil(thickness); prepare_charset(); render(); - blur(); + alpha(); write_bitmap(); free(buffer); free(abuffer); - puts( - "\n" - "*****************************************\n" - "* Remember to run: *\n" - "* cat font.desc.tail >> font.desc *\n" - "*****************************************" - ); - +// fflush(stderr); return 0; } |