summaryrefslogtreecommitdiffstats
path: root/libass
diff options
context:
space:
mode:
authorUoti Urpala <uau@glyph.nonexistent.invalid>2009-02-12 04:17:55 +0200
committerUoti Urpala <uau@glyph.nonexistent.invalid>2009-02-12 04:17:55 +0200
commit1e869638280f962fb80f372d152234f21246c2af (patch)
tree64657f88e7902aa000f44f40be4f8e575f58c8de /libass
parent9790f4e6e72cdc8093be966d3d6e007c8f44a035 (diff)
parent379b176f25905f273a368336c3f5f287eeea51a2 (diff)
downloadmpv-1e869638280f962fb80f372d152234f21246c2af.tar.bz2
mpv-1e869638280f962fb80f372d152234f21246c2af.tar.xz
Merge svn changes up to r28537
Diffstat (limited to 'libass')
-rw-r--r--libass/ass_bitmap.c44
-rw-r--r--libass/ass_bitmap.h4
-rw-r--r--libass/ass_cache_template.c1
-rw-r--r--libass/ass_render.c82
4 files changed, 107 insertions, 24 deletions
diff --git a/libass/ass_bitmap.c b/libass/ass_bitmap.c
index 3d85300d11..0b80d7ab2c 100644
--- a/libass/ass_bitmap.c
+++ b/libass/ass_bitmap.c
@@ -39,11 +39,12 @@ struct ass_synth_priv_s {
unsigned *g;
unsigned *gt2;
+
+ double radius;
};
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)
{
@@ -52,6 +53,11 @@ static int generate_tables(ass_synth_priv_t* priv, double radius)
double volume_diff, volume_factor = 0;
unsigned volume;
+ if (priv->radius == radius)
+ return 0;
+ else
+ priv->radius = radius;
+
priv->g_r = ceil(radius);
priv->g_w = 2*priv->g_r+1;
@@ -106,10 +112,10 @@ static void resize_tmp(ass_synth_priv_t* priv, int w, int h)
priv->tmp = malloc((priv->tmp_w + 1) * priv->tmp_h * sizeof(short));
}
-ass_synth_priv_t* ass_synth_init(void)
+ass_synth_priv_t* ass_synth_init(double radius)
{
ass_synth_priv_t* priv = calloc(1, sizeof(ass_synth_priv_t));
- generate_tables(priv, blur_radius);
+ generate_tables(priv, radius);
return priv;
}
@@ -248,10 +254,12 @@ static bitmap_t* fix_outline_and_shadow(bitmap_t* bm_g, bitmap_t* bm_o)
return bm_s;
}
-int glyph_to_bitmap(ass_synth_priv_t* priv, FT_Glyph glyph, FT_Glyph outline_glyph,
- bitmap_t** bm_g, bitmap_t** bm_o, bitmap_t** bm_s, int be)
+int glyph_to_bitmap(ass_synth_priv_t* priv, ass_synth_priv_t* priv_blur,
+ FT_Glyph glyph, FT_Glyph outline_glyph, bitmap_t** bm_g,
+ bitmap_t** bm_o, bitmap_t** bm_s, int be, double blur_radius)
{
- const int bord = be ? ceil(blur_radius) : 0;
+ int bord = be ? (be+1) : 0;
+ bord = (blur_radius > 0.0) ? blur_radius : bord;
assert(bm_g && bm_o && bm_s);
@@ -269,17 +277,29 @@ int glyph_to_bitmap(ass_synth_priv_t* priv, FT_Glyph glyph, FT_Glyph outline_gly
return 1;
}
}
- if (*bm_o)
+ if (*bm_o) {
resize_tmp(priv, (*bm_o)->w, (*bm_o)->h);
+ resize_tmp(priv_blur, (*bm_o)->w, (*bm_o)->h);
+ }
resize_tmp(priv, (*bm_g)->w, (*bm_g)->h);
+ resize_tmp(priv_blur, (*bm_g)->w, (*bm_g)->h);
if (be) {
- 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);
- else
- blur((*bm_g)->buffer, priv->tmp, (*bm_g)->w, (*bm_g)->h, (*bm_g)->w, (int*)priv->gt2, priv->g_r, priv->g_w);
+ while (be--) {
+ 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);
+ else
+ blur((*bm_g)->buffer, priv->tmp, (*bm_g)->w, (*bm_g)->h, (*bm_g)->w, (int*)priv->gt2, priv->g_r, priv->g_w);
+ }
+ } else {
+ if (blur_radius > 0.0) {
+ generate_tables(priv_blur, blur_radius);
+ if (*bm_o)
+ blur((*bm_o)->buffer, priv_blur->tmp, (*bm_o)->w, (*bm_o)->h, (*bm_o)->w, (int*)priv_blur->gt2, priv_blur->g_r, priv_blur->g_w);
+ else
+ blur((*bm_g)->buffer, priv_blur->tmp, (*bm_g)->w, (*bm_g)->h, (*bm_g)->w, (int*)priv_blur->gt2, priv_blur->g_r, priv_blur->g_w);
+ }
}
-
if (*bm_o)
*bm_s = fix_outline_and_shadow(*bm_g, *bm_o);
else
diff --git a/libass/ass_bitmap.h b/libass/ass_bitmap.h
index 73f9de4dfe..5f45aae4b2 100644
--- a/libass/ass_bitmap.h
+++ b/libass/ass_bitmap.h
@@ -28,7 +28,7 @@
typedef struct ass_synth_priv_s ass_synth_priv_t;
-ass_synth_priv_t* ass_synth_init(void);
+ass_synth_priv_t* ass_synth_init(double);
void ass_synth_done(ass_synth_priv_t* priv);
typedef struct bitmap_s {
@@ -46,7 +46,7 @@ typedef struct bitmap_s {
* \param bm_g out: pointer to the bitmap of glyph shadow is returned here
* \param be 1 = produces blurred bitmaps, 0 = normal bitmaps
*/
-int glyph_to_bitmap(ass_synth_priv_t* priv, FT_Glyph glyph, FT_Glyph outline_glyph, bitmap_t** bm_g, bitmap_t** bm_o, bitmap_t** bm_s, int be);
+int glyph_to_bitmap(ass_synth_priv_t* priv, ass_synth_priv_t* priv_blur, FT_Glyph glyph, FT_Glyph outline_glyph, bitmap_t** bm_g, bitmap_t** bm_o, bitmap_t** bm_s, int be, double blur_radius);
void ass_free_bitmap(bitmap_t* bm);
diff --git a/libass/ass_cache_template.c b/libass/ass_cache_template.c
index 5f77190fa1..7f9ec95f57 100644
--- a/libass/ass_cache_template.c
+++ b/libass/ass_cache_template.c
@@ -55,6 +55,7 @@ START(bitmap, bipmap_hash_key_s)
GENERIC(int, bold)
GENERIC(int, italic)
GENERIC(char, be) // blur edges
+ GENERIC(double, blur) // gaussian blur
GENERIC(unsigned, scale_x) // 16.16
GENERIC(unsigned, scale_y) // 16.16
GENERIC(int, frx) // signed 16.16
diff --git a/libass/ass_render.c b/libass/ass_render.c
index da01caf119..b3ef0ca76f 100644
--- a/libass/ass_render.c
+++ b/libass/ass_render.c
@@ -43,6 +43,8 @@
#define MAX_GLYPHS 3000
#define MAX_LINES 300
+#define BE_RADIUS 1.5
+#define BLUR_MAX_RADIUS 50.0
static int last_render_id = 0;
@@ -80,6 +82,7 @@ struct ass_renderer_s {
ass_settings_t settings;
int render_id;
ass_synth_priv_t* synth_priv;
+ ass_synth_priv_t* synth_priv_blur;
ass_image_t* images_root; // rendering result is stored here
ass_image_t* prev_images_root;
@@ -112,6 +115,7 @@ typedef struct glyph_info_s {
int asc, desc; // font max ascender and descender
// int height;
int be; // blur edges
+ double blur; // gaussian blur
int shadow;
double frx, fry, frz; // rotation
@@ -160,6 +164,7 @@ typedef struct render_context_s {
char detect_collisions;
uint32_t fade; // alpha from \fad
char be; // blur edges
+ double blur; // gaussian blur
int shadow;
int drawing_mode; // not implemented; when != 0 text is discarded, except for style override tags
@@ -258,7 +263,8 @@ ass_renderer_t* ass_renderer_init(ass_library_t* library)
goto ass_init_exit;
}
- priv->synth_priv = ass_synth_init();
+ priv->synth_priv = ass_synth_init(BE_RADIUS);
+ priv->synth_priv_blur = ass_synth_init(BLUR_MAX_RADIUS);
priv->library = library;
priv->ftlibrary = ft;
@@ -688,7 +694,54 @@ static char* parse_tag(char* p, double pwr) {
if ((*p == '}') || (*p == 0))
return p;
- if (mystrcmp(&p, "fsc")) {
+ // New tags introduced in vsfilter 2.39
+ if (mystrcmp(&p, "xbord")) {
+ double val;
+ if (mystrtod(&p, &val))
+ mp_msg(MSGT_ASS, MSGL_V, "stub: \\xbord%.2f\n", val);
+ } else if (mystrcmp(&p, "ybord")) {
+ double val;
+ if (mystrtod(&p, &val))
+ mp_msg(MSGT_ASS, MSGL_V, "stub: \\ybord%.2f\n", val);
+ } else if (mystrcmp(&p, "xshad")) {
+ int val;
+ if (mystrtoi(&p, 10, &val))
+ mp_msg(MSGT_ASS, MSGL_V, "stub: \\xshad%d\n", val);
+ } else if (mystrcmp(&p, "yshad")) {
+ int val;
+ if (mystrtoi(&p, 10, &val))
+ mp_msg(MSGT_ASS, MSGL_V, "stub: \\yshad%d\n", val);
+ } else if (mystrcmp(&p, "fax")) {
+ int val;
+ if (mystrtoi(&p, 10, &val))
+ mp_msg(MSGT_ASS, MSGL_V, "stub: \\fax%d\n", val);
+ } else if (mystrcmp(&p, "fay")) {
+ int val;
+ if (mystrtoi(&p, 10, &val))
+ mp_msg(MSGT_ASS, MSGL_V, "stub: \\fay%d\n", val);
+ } else if (mystrcmp(&p, "iclip")) {
+ int x0, y0, x1, y1;
+ int res = 1;
+ skip('(');
+ res &= mystrtoi(&p, 10, &x0);
+ skip(',');
+ res &= mystrtoi(&p, 10, &y0);
+ skip(',');
+ res &= mystrtoi(&p, 10, &x1);
+ skip(',');
+ res &= mystrtoi(&p, 10, &y1);
+ skip(')');
+ mp_msg(MSGT_ASS, MSGL_V, "stub: \\iclip(%d,%d,%d,%d)\n", x0, y0, x1, y1);
+ } else if (mystrcmp(&p, "blur")) {
+ double val;
+ if (mystrtod(&p, &val)) {
+ val = (val < 0) ? 0 : val;
+ val = (val > BLUR_MAX_RADIUS) ? BLUR_MAX_RADIUS : val;
+ render_context.blur = val;
+ } else
+ render_context.blur = 0.0;
+ // ASS standard tags
+ } else if (mystrcmp(&p, "fsc")) {
char tp = *p++;
double val;
if (tp == 'x') {
@@ -760,10 +813,12 @@ static char* parse_tag(char* p, double pwr) {
else k = ((double)(t - t1)) / delta_t;
x = k * (x2 - x1) + x1;
y = k * (y2 - y1) + y1;
- render_context.pos_x = x;
- render_context.pos_y = y;
- render_context.detect_collisions = 0;
- render_context.evt_type = EVENT_POSITIONED;
+ if (render_context.evt_type != EVENT_POSITIONED) {
+ render_context.pos_x = x;
+ render_context.pos_y = y;
+ render_context.detect_collisions = 0;
+ render_context.evt_type = EVENT_POSITIONED;
+ }
} else if (mystrcmp(&p, "frx")) {
double val;
if (mystrtod(&p, &val)) {
@@ -990,9 +1045,12 @@ static char* parse_tag(char* p, double pwr) {
reset_render_context();
} else if (mystrcmp(&p, "be")) {
int val;
- if (mystrtoi(&p, 10, &val))
- render_context.be = val ? 1 : 0;
- else
+ if (mystrtoi(&p, 10, &val)) {
+ // Clamp to 10, since high values need excessive CPU
+ val = (val < 0) ? 0 : val;
+ val = (val > 10) ? 10 : val;
+ render_context.be = val;
+ } else
render_context.be = 0;
} else if (mystrcmp(&p, "b")) {
int b;
@@ -1186,6 +1244,7 @@ static void reset_render_context(void)
render_context.scale_y = render_context.style->ScaleY;
render_context.hspacing = render_context.style->Spacing;
render_context.be = 0;
+ render_context.blur = 0.0;
render_context.shadow = render_context.style->Shadow;
render_context.frx = render_context.fry = 0.;
render_context.frz = M_PI * render_context.style->Angle / 180.;
@@ -1326,9 +1385,10 @@ static void get_bitmap_glyph(glyph_info_t* info)
// render glyph
error = glyph_to_bitmap(ass_renderer->synth_priv,
+ ass_renderer->synth_priv_blur,
info->glyph, info->outline_glyph,
&info->bm, &info->bm_o,
- &info->bm_s, info->be);
+ &info->bm_s, info->be, info->blur);
if (error)
info->symbol = 0;
@@ -1820,6 +1880,7 @@ static int ass_render_event(ass_event_t* event, event_images_t* event_images)
text_info.glyphs[text_info.length].effect_timing = render_context.effect_timing;
text_info.glyphs[text_info.length].effect_skip_timing = render_context.effect_skip_timing;
text_info.glyphs[text_info.length].be = render_context.be;
+ text_info.glyphs[text_info.length].blur = render_context.blur;
text_info.glyphs[text_info.length].shadow = render_context.shadow;
text_info.glyphs[text_info.length].frx = render_context.frx;
text_info.glyphs[text_info.length].fry = render_context.fry;
@@ -1844,6 +1905,7 @@ static int ass_render_event(ass_event_t* event, event_images_t* event_images)
text_info.glyphs[text_info.length].hash_key.ch = code;
text_info.glyphs[text_info.length].hash_key.advance = shift;
text_info.glyphs[text_info.length].hash_key.be = render_context.be;
+ text_info.glyphs[text_info.length].hash_key.blur = render_context.blur;
text_info.length++;