Mercurial > mplayer.hg
changeset 19848:07be98a5dd5f
Add \be (blur edges) support to libass.
author | eugeni |
---|---|
date | Sat, 16 Sep 2006 13:32:46 +0000 |
parents | d7c2e093e406 |
children | f4504b07bdbd |
files | libass/ass_bitmap.c libass/ass_bitmap.h libass/ass_cache.c libass/ass_cache.h libass/ass_render.c |
diffstat | 5 files changed, 128 insertions(+), 7 deletions(-) [+] |
line wrap: on
line diff
--- a/libass/ass_bitmap.c Sat Sep 16 13:32:19 2006 +0000 +++ b/libass/ass_bitmap.c Sat Sep 16 13:32:46 2006 +0000 @@ -6,8 +6,97 @@ #include FT_GLYPH_H #include "mp_msg.h" +#include "libvo/font_load.h" // for blur() #include "ass_bitmap.h" +struct ass_synth_priv_s { + int tmp_w, tmp_h; + unsigned short* tmp; + + int g_r; + int g_w; + + unsigned *g; + unsigned *gt2; +}; + +static const unsigned int maxcolor = 255; +static const unsigned base = 256; +static const double blur_radius = 1.5; + +static int generate_tables(ass_synth_priv_t* priv, double radius) +{ + double A = log(1.0/base)/(radius*radius*2); + int mx, i; + double volume_diff, volume_factor = 0; + unsigned volume; + + priv->g_r = ceil(radius); + priv->g_w = 2*priv->g_r+1; + + if (priv->g_r) { + priv->g = malloc(priv->g_w * sizeof(unsigned)); + priv->gt2 = malloc(256 * priv->g_w * sizeof(unsigned)); + if (priv->g==NULL || priv->gt2==NULL) { + return -1; + } + } + + if (priv->g_r) { + // gaussian curve with volume = 256 + for (volume_diff=10000000; volume_diff>0.0000001; volume_diff*=0.5){ + volume_factor+= volume_diff; + volume=0; + for (i = 0; i<priv->g_w; ++i) { + priv->g[i] = (unsigned)(exp(A * (i-priv->g_r)*(i-priv->g_r)) * volume_factor + .5); + volume+= priv->g[i]; + } + if(volume>256) volume_factor-= volume_diff; + } + volume=0; + for (i = 0; i<priv->g_w; ++i) { + priv->g[i] = (unsigned)(exp(A * (i-priv->g_r)*(i-priv->g_r)) * volume_factor + .5); + volume+= priv->g[i]; + } + + // gauss table: + for(mx=0;mx<priv->g_w;mx++){ + for(i=0;i<256;i++){ + priv->gt2[mx+i*priv->g_w] = i*priv->g[mx]; + } + } + } + + return 0; +} + +static void resize_tmp(ass_synth_priv_t* priv, int w, int h) +{ + if (priv->tmp_w >= w && priv->tmp_h >= h) + return; + if (priv->tmp_w == 0) + priv->tmp_w = 64; + if (priv->tmp_h == 0) + priv->tmp_h = 64; + while (priv->tmp_w < w) priv->tmp_w *= 2; + while (priv->tmp_h < h) priv->tmp_h *= 2; + if (priv->tmp) + free(priv->tmp); + priv->tmp = malloc((priv->tmp_w + 1) * priv->tmp_h * sizeof(short)); +} + +ass_synth_priv_t* ass_synth_init() +{ + ass_synth_priv_t* priv = calloc(1, sizeof(ass_synth_priv_t)); + generate_tables(priv, blur_radius); + return priv; +} + +void ass_synth_done(ass_synth_priv_t* priv) +{ + free(priv); +} + static bitmap_t* alloc_bitmap(int w, int h) { bitmap_t* bm; @@ -70,22 +159,34 @@ return bm; } -int glyph_to_bitmap(FT_Glyph glyph, FT_Glyph outline_glyph, bitmap_t** bm_g, bitmap_t** bm_o) +int glyph_to_bitmap(ass_synth_priv_t* priv, FT_Glyph glyph, FT_Glyph outline_glyph, bitmap_t** bm_g, bitmap_t** bm_o, int be) { + const int bord = ceil(blur_radius); + assert(bm_g); if (glyph) - *bm_g = glyph_to_bitmap_internal(glyph, 0); + *bm_g = glyph_to_bitmap_internal(glyph, bord); if (!*bm_g) return 1; if (outline_glyph && bm_o) { - *bm_o = glyph_to_bitmap_internal(outline_glyph, 0); + *bm_o = glyph_to_bitmap_internal(outline_glyph, bord); if (!*bm_o) { ass_free_bitmap(*bm_g); return 1; } } + if (bm_o) + resize_tmp(priv, (*bm_o)->w, (*bm_o)->h); + resize_tmp(priv, (*bm_g)->w, (*bm_g)->h); + + if (be) { + blur((*bm_g)->buffer, priv->tmp, (*bm_g)->w, (*bm_g)->h, (*bm_g)->w, (int*)priv->gt2, priv->g_r, priv->g_w); + if (bm_o) + blur((*bm_o)->buffer, priv->tmp, (*bm_o)->w, (*bm_o)->h, (*bm_o)->w, (int*)priv->gt2, priv->g_r, priv->g_w); + } + return 0; }
--- a/libass/ass_bitmap.h Sat Sep 16 13:32:19 2006 +0000 +++ b/libass/ass_bitmap.h Sat Sep 16 13:32:46 2006 +0000 @@ -1,13 +1,18 @@ #ifndef __ASS_BITMAP_H__ #define __ASS_BITMAP_H__ +typedef struct ass_synth_priv_s ass_synth_priv_t; + +ass_synth_priv_t* ass_synth_init(); +void ass_synth_done(ass_synth_priv_t* priv); + typedef struct bitmap_s { int left, top; int w, h; // width, height unsigned char* buffer; // w x h buffer } bitmap_t; -int glyph_to_bitmap(FT_Glyph glyph, FT_Glyph outline_glyph, bitmap_t** bm_g, bitmap_t** bm_o); +int glyph_to_bitmap(ass_synth_priv_t* priv, FT_Glyph glyph, FT_Glyph outline_glyph, bitmap_t** bm_g, bitmap_t** bm_o, int be); void ass_free_bitmap(bitmap_t* bm); #endif
--- a/libass/ass_cache.c Sat Sep 16 13:32:19 2006 +0000 +++ b/libass/ass_cache.c Sat Sep 16 13:32:46 2006 +0000 @@ -131,6 +131,7 @@ val <<= 21; if (key->bitmap) val &= 0x80000000; + if (key->be) val &= 0x40000000; val += key->index; val += key->size << 8; val += key->outline << 3;
--- a/libass/ass_cache.h Sat Sep 16 13:32:19 2006 +0000 +++ b/libass/ass_cache.h Sat Sep 16 13:32:46 2006 +0000 @@ -26,6 +26,7 @@ int index; // glyph index in the face unsigned outline; // border width, 16.16 fixed point value int bold, italic; + char be; // blur edges // the following affects bitmap glyphs only unsigned scale_x, scale_y; // 16.16
--- a/libass/ass_render.c Sat Sep 16 13:32:19 2006 +0000 +++ b/libass/ass_render.c Sat Sep 16 13:32:46 2006 +0000 @@ -38,6 +38,7 @@ fc_instance_t* fontconfig_priv; ass_settings_t settings; int render_id; + ass_synth_priv_t* synth_priv; ass_image_t* images_root; // rendering result is stored here }; @@ -66,6 +67,7 @@ int effect_skip_timing; // delay after the end of last karaoke word int asc, desc; // font max ascender and descender // int height; + int be; // blur edges glyph_hash_key_t hash_key; } glyph_info_t; @@ -110,6 +112,7 @@ int clip_x0, clip_y0, clip_x1, clip_y1; char detect_collisions; uint32_t fade; // alpha from \fad + char be; // blur edges effect_t effect_type; int effect_timing; @@ -226,6 +229,8 @@ goto ass_init_exit; } + priv->synth_priv = ass_synth_init(); + priv->library = ft; priv->fontconfig_priv = fc_priv; // images_root and related stuff is zero-filled in calloc @@ -248,6 +253,7 @@ ass_glyph_cache_done(); if (priv && priv->library) FT_Done_FreeType(priv->library); if (priv && priv->fontconfig_priv) fontconfig_done(priv->fontconfig_priv); + if (priv && priv->synth_priv) ass_synth_done(priv->synth_priv); if (priv) free(priv); if (text_info.glyphs) free(text_info.glyphs); } @@ -367,8 +373,9 @@ if (text_info->glyphs[i].glyph) { if ((text_info->glyphs[i].symbol == '\n') || (text_info->glyphs[i].symbol == 0)) continue; - error = glyph_to_bitmap(text_info->glyphs[i].glyph, text_info->glyphs[i].outline_glyph, - &text_info->glyphs[i].bm, &text_info->glyphs[i].bm_o); + error = glyph_to_bitmap(ass_instance->synth_priv, + text_info->glyphs[i].glyph, text_info->glyphs[i].outline_glyph, + &text_info->glyphs[i].bm, &text_info->glyphs[i].bm_o, text_info->glyphs[i].be); if (error) text_info->glyphs[i].symbol = 0; FT_Done_Glyph(text_info->glyphs[i].glyph); @@ -940,7 +947,10 @@ // FIXME: does not reset unsupported attributes. } else if (mystrcmp(&p, "be")) { int val; - mystrtoi(&p, 10, &val); + if (mystrtoi(&p, 10, &val)) + render_context.be = val ? 1 : 0; + else + render_context.be = 0; mp_msg(MSGT_GLOBAL, MSGL_V, "be unimplemented \n"); } else if (mystrcmp(&p, "b")) { int b; @@ -1130,6 +1140,7 @@ render_context.effect_type = EF_NONE; render_context.effect_timing = 0; render_context.effect_skip_timing = 0; + render_context.be = 0; if (render_context.family) free(render_context.family); @@ -1193,6 +1204,7 @@ key->advance = *advance; key->bold = render_context.bold; key->italic = render_context.italic; + key->be = render_context.be; val = cache_find_glyph(key); // val = 0; @@ -1602,6 +1614,7 @@ text_info.glyphs[text_info.length].effect_skip_timing = render_context.effect_skip_timing; text_info.glyphs[text_info.length].asc = get_face_ascender(render_context.face); text_info.glyphs[text_info.length].desc = get_face_descender(render_context.face); + text_info.glyphs[text_info.length].be = render_context.be; text_info.length++;