summaryrefslogtreecommitdiffstats
path: root/libass
diff options
context:
space:
mode:
authoreugeni <eugeni@b3059339-0415-0410-9bf9-f77b7e298cf2>2006-09-16 13:32:46 +0000
committereugeni <eugeni@b3059339-0415-0410-9bf9-f77b7e298cf2>2006-09-16 13:32:46 +0000
commit69cbeae8457acc1266d5471c5b7b9fb4dff2d374 (patch)
tree32732bb00905d13ac0ae90a04155af5cb4c73f2e /libass
parentb21382fa5b313ab1faa6a7722e77bf3b56f3be2f (diff)
downloadmpv-69cbeae8457acc1266d5471c5b7b9fb4dff2d374.tar.bz2
mpv-69cbeae8457acc1266d5471c5b7b9fb4dff2d374.tar.xz
Add \be (blur edges) support to libass.
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@19854 b3059339-0415-0410-9bf9-f77b7e298cf2
Diffstat (limited to 'libass')
-rw-r--r--libass/ass_bitmap.c107
-rw-r--r--libass/ass_bitmap.h7
-rw-r--r--libass/ass_cache.c1
-rw-r--r--libass/ass_cache.h1
-rw-r--r--libass/ass_render.c19
5 files changed, 128 insertions, 7 deletions
diff --git a/libass/ass_bitmap.c b/libass/ass_bitmap.c
index 9d98ec000a..c7d5f786aa 100644
--- a/libass/ass_bitmap.c
+++ b/libass/ass_bitmap.c
@@ -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 @@ static bitmap_t* glyph_to_bitmap_internal(FT_Glyph glyph, int bord)
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;
}
diff --git a/libass/ass_bitmap.h b/libass/ass_bitmap.h
index edf4790584..7a6d7d459f 100644
--- a/libass/ass_bitmap.h
+++ b/libass/ass_bitmap.h
@@ -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
diff --git a/libass/ass_cache.c b/libass/ass_cache.c
index 2dce591d93..a4f4be6169 100644
--- a/libass/ass_cache.c
+++ b/libass/ass_cache.c
@@ -131,6 +131,7 @@ static unsigned glyph_hash(glyph_hash_key_t* key) {
val <<= 21;
if (key->bitmap) val &= 0x80000000;
+ if (key->be) val &= 0x40000000;
val += key->index;
val += key->size << 8;
val += key->outline << 3;
diff --git a/libass/ass_cache.h b/libass/ass_cache.h
index f24886e873..b17fcdb2e8 100644
--- a/libass/ass_cache.h
+++ b/libass/ass_cache.h
@@ -26,6 +26,7 @@ typedef struct glyph_hash_key_s {
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
diff --git a/libass/ass_render.c b/libass/ass_render.c
index e0096ca219..d0def4b4c6 100644
--- a/libass/ass_render.c
+++ b/libass/ass_render.c
@@ -38,6 +38,7 @@ struct ass_instance_s {
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 @@ typedef struct glyph_info_s {
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 @@ typedef struct render_context_s {
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 @@ ass_instance_t* ass_init(void)
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 @@ void ass_done(ass_instance_t* priv)
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 @@ static ass_image_t* render_text(text_info_t* text_info, int dst_x, int dst_y)
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 @@ static char* parse_tag(char* p, double pwr) {
// 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 @@ static int init_render_context(ass_event_t* event)
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 @@ static int get_glyph(int index, int symbol, glyph_info_t* info, FT_Vector* advan
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 @@ static int ass_render_event(ass_event_t* event, event_images_t* event_images)
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++;