From 9c8a334cc5ba98c60dfce3aad490a80b1727ea50 Mon Sep 17 00:00:00 2001 From: eugeni Date: Sun, 1 Mar 2009 16:01:24 +0000 Subject: With pan-and-scan, keep positioned events in their original positions relative to video. Patch by Grigori Goronzy (greg chown ath cx). git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@28783 b3059339-0415-0410-9bf9-f77b7e298cf2 --- libass/ass_render.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'libass') diff --git a/libass/ass_render.c b/libass/ass_render.c index ead118ddde..a40adec505 100644 --- a/libass/ass_render.c +++ b/libass/ass_render.c @@ -467,6 +467,10 @@ static int x2scr(double x) { return x*frame_context.orig_width_nocrop / frame_context.track->PlayResX + FFMAX(global_settings->left_margin, 0); } +static int x2scr_pos(double x) { + return x*frame_context.orig_width / frame_context.track->PlayResX + + global_settings->left_margin; +} /** * \brief Mapping between script and screen coordinates */ @@ -2014,7 +2018,7 @@ static int ass_render_event(ass_event_t* event, event_images_t* event_images) int base_y = 0; mp_msg(MSGT_ASS, MSGL_DBG2, "positioned event at %f, %f\n", render_context.pos_x, render_context.pos_y); get_base_point(bbox, alignment, &base_x, &base_y); - device_x = x2scr(render_context.pos_x) - base_x; + device_x = x2scr_pos(render_context.pos_x) - base_x; device_y = y2scr(render_context.pos_y) - base_y; } -- cgit v1.2.3 From 20a2db7dfda07b47661dae79a3951af0fb8bc00d Mon Sep 17 00:00:00 2001 From: eugeni Date: Sun, 1 Mar 2009 19:31:29 +0000 Subject: Fix a memory leak. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@28787 b3059339-0415-0410-9bf9-f77b7e298cf2 --- libass/ass_bitmap.c | 1 + 1 file changed, 1 insertion(+) (limited to 'libass') diff --git a/libass/ass_bitmap.c b/libass/ass_bitmap.c index 9ccb1bada9..e6d5e8d60e 100644 --- a/libass/ass_bitmap.c +++ b/libass/ass_bitmap.c @@ -214,6 +214,7 @@ static bitmap_t* glyph_to_bitmap_internal(FT_Glyph glyph, int bord) dst += bm->w; } + FT_Done_Glyph(glyph); return bm; } -- cgit v1.2.3 From 16731f634912b601b7fdd5278b27c8b9888a933e Mon Sep 17 00:00:00 2001 From: greg Date: Thu, 5 Mar 2009 20:05:56 +0000 Subject: Ignore PlayResX/Y aspect ratio for font aspect ratio. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@28814 b3059339-0415-0410-9bf9-f77b7e298cf2 --- libass/ass_render.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'libass') diff --git a/libass/ass_render.c b/libass/ass_render.c index a40adec505..6b8ee70f3e 100644 --- a/libass/ass_render.c +++ b/libass/ass_render.c @@ -2228,10 +2228,7 @@ static int ass_start_frame(ass_renderer_t *priv, ass_track_t* track, long long n frame_context.orig_height / frame_context.track->PlayResY; frame_context.border_scale = ((double)frame_context.orig_height) / frame_context.track->PlayResY; - if (frame_context.orig_width * track->PlayResY == frame_context.orig_height * track->PlayResX) - frame_context.font_scale_x = 1.; - else - frame_context.font_scale_x = ((double)(frame_context.orig_width * track->PlayResY)) / (frame_context.orig_height * track->PlayResX); + frame_context.font_scale_x = 1.; priv->prev_images_root = priv->images_root; priv->images_root = 0; -- cgit v1.2.3 From 153e7ada4c60f2547f3b40828b8a0f86ba12384d Mon Sep 17 00:00:00 2001 From: greg Date: Thu, 5 Mar 2009 20:36:35 +0000 Subject: Hack: half-merge glyph border with outline to avoid ugly anti-aliasing in certain situations. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@28816 b3059339-0415-0410-9bf9-f77b7e298cf2 --- libass/ass_bitmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'libass') diff --git a/libass/ass_bitmap.c b/libass/ass_bitmap.c index e6d5e8d60e..9fb1eab65e 100644 --- a/libass/ass_bitmap.c +++ b/libass/ass_bitmap.c @@ -243,7 +243,7 @@ static bitmap_t* fix_outline_and_shadow(bitmap_t* bm_g, bitmap_t* bm_o) unsigned char c_g, c_o; c_g = g[x]; c_o = o[x]; - o[x] = (c_o > c_g) ? c_o : 0; + o[x] = (c_o > c_g) ? c_o - (c_g/2) : 0; s[x] = (c_o < 0xFF - c_g) ? c_o + c_g : 0xFF; } g += bm_g->w; -- cgit v1.2.3 From a2020815ad088b6bed0329b04a8355388b6411e7 Mon Sep 17 00:00:00 2001 From: greg Date: Thu, 5 Mar 2009 20:36:39 +0000 Subject: Support a vsfilter special case: If PlayResX or Y is 1280/1024 respectively and the other PlayRes attribute isn't provided, use 1280/1024 for it. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@28817 b3059339-0415-0410-9bf9-f77b7e298cf2 --- libass/ass_render.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'libass') diff --git a/libass/ass_render.c b/libass/ass_render.c index 6b8ee70f3e..c01bb74963 100644 --- a/libass/ass_render.c +++ b/libass/ass_render.c @@ -224,9 +224,15 @@ static void ass_lazy_track_init(void) } else { double orig_aspect = (global_settings->aspect * frame_context.height * frame_context.orig_width) / frame_context.orig_height / frame_context.width; - if (!track->PlayResY) { + if (!track->PlayResY && track->PlayResX == 1280) { + track->PlayResY = 1024; + mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_PlayResYUndefinedSettingY, track->PlayResY); + } else if (!track->PlayResY) { track->PlayResY = track->PlayResX / orig_aspect + .5; mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_PlayResYUndefinedSettingY, track->PlayResY); + } else if (!track->PlayResX && track->PlayResY == 1024) { + track->PlayResX = 1280; + mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_PlayResXUndefinedSettingX, track->PlayResX); } else if (!track->PlayResX) { track->PlayResX = track->PlayResY * orig_aspect + .5; mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_PlayResXUndefinedSettingX, track->PlayResX); -- cgit v1.2.3 From c23a1cdfb356bbf39a95ca8ee7bf6fbc8938d061 Mon Sep 17 00:00:00 2001 From: greg Date: Thu, 5 Mar 2009 20:36:41 +0000 Subject: Round shadow displacement to nearest int. Use double for shadow displacement parameter. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@28818 b3059339-0415-0410-9bf9-f77b7e298cf2 --- libass/ass_render.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'libass') diff --git a/libass/ass_render.c b/libass/ass_render.c index c01bb74963..e8d18ed3d3 100644 --- a/libass/ass_render.c +++ b/libass/ass_render.c @@ -45,6 +45,7 @@ #define MAX_LINES 300 #define BE_RADIUS 1.5 #define BLUR_MAX_RADIUS 50.0 +#define ROUND(x) ((int) ((x) + .5)) static int last_render_id = 0; @@ -116,7 +117,7 @@ typedef struct glyph_info_s { // int height; int be; // blur edges double blur; // gaussian blur - int shadow; + double shadow; double frx, fry, frz; // rotation bitmap_hash_key_t hash_key; @@ -165,7 +166,7 @@ typedef struct render_context_s { uint32_t fade; // alpha from \fad char be; // blur edges double blur; // gaussian blur - int shadow; + double shadow; int drawing_mode; // not implemented; when != 0 text is discarded, except for style override tags effect_t effect_type; @@ -421,8 +422,8 @@ static ass_image_t* render_text(text_info_t* text_info, int dst_x, int dst_y) if ((info->symbol == 0) || (info->symbol == '\n') || !info->bm_s || (info->shadow == 0)) continue; - pen_x = dst_x + info->pos.x + info->shadow; - pen_y = dst_y + info->pos.y + info->shadow; + pen_x = dst_x + info->pos.x + ROUND(info->shadow); + pen_y = dst_y + info->pos.y + ROUND(info->shadow); bm = info->bm_s; tail = render_glyph(bm, pen_x, pen_y, info->c[3], 0, 1000000, tail); -- cgit v1.2.3 From a2b82120c0ad97811a8db3212a3a6589b98bd04f Mon Sep 17 00:00:00 2001 From: greg Date: Thu, 5 Mar 2009 20:36:44 +0000 Subject: Scale shadow displacement and blur size like border size. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@28819 b3059339-0415-0410-9bf9-f77b7e298cf2 --- libass/ass_render.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'libass') diff --git a/libass/ass_render.c b/libass/ass_render.c index e8d18ed3d3..399ca533cd 100644 --- a/libass/ass_render.c +++ b/libass/ass_render.c @@ -422,8 +422,8 @@ static ass_image_t* render_text(text_info_t* text_info, int dst_x, int dst_y) if ((info->symbol == 0) || (info->symbol == '\n') || !info->bm_s || (info->shadow == 0)) continue; - pen_x = dst_x + info->pos.x + ROUND(info->shadow); - pen_y = dst_y + info->pos.y + ROUND(info->shadow); + pen_x = dst_x + info->pos.x + ROUND(info->shadow * frame_context.border_scale); + pen_y = dst_y + info->pos.y + ROUND(info->shadow * frame_context.border_scale); bm = info->bm_s; tail = render_glyph(bm, pen_x, pen_y, info->c[3], 0, 1000000, tail); @@ -1397,7 +1397,7 @@ static void get_bitmap_glyph(glyph_info_t* info) ass_renderer->synth_priv_blur, info->glyph, info->outline_glyph, &info->bm, &info->bm_o, - &info->bm_s, info->be, info->blur); + &info->bm_s, info->be, info->blur * frame_context.border_scale); if (error) info->symbol = 0; -- cgit v1.2.3 From 2432bbd43d0dc22af0a5f57d2921448ed76a53c4 Mon Sep 17 00:00:00 2001 From: greg Date: Thu, 5 Mar 2009 20:36:48 +0000 Subject: Support ScaledBorderAndShadow property. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@28820 b3059339-0415-0410-9bf9-f77b7e298cf2 --- libass/ass.c | 2 ++ libass/ass_render.c | 5 ++++- libass/ass_types.h | 1 + libass/ass_utils.c | 11 +++++++++++ libass/ass_utils.h | 1 + 5 files changed, 19 insertions(+), 1 deletion(-) (limited to 'libass') diff --git a/libass/ass.c b/libass/ass.c index 8022dfc9be..e1be966b65 100644 --- a/libass/ass.c +++ b/libass/ass.c @@ -520,6 +520,8 @@ static int process_info_line(ass_track_t* track, char *str) track->Timer = atof(str + 6); } else if (!strncmp(str,"WrapStyle:", 10)) { track->WrapStyle = atoi(str + 10); + } else if (!strncmp(str, "ScaledBorderAndShadow:", 22)) { + track->ScaledBorderAndShadow = parse_bool(str + 22); } return 0; } diff --git a/libass/ass_render.c b/libass/ass_render.c index 399ca533cd..5371afa06d 100644 --- a/libass/ass_render.c +++ b/libass/ass_render.c @@ -2233,7 +2233,10 @@ static int ass_start_frame(ass_renderer_t *priv, ass_track_t* track, long long n frame_context.font_scale = global_settings->font_size_coeff * frame_context.orig_height / frame_context.track->PlayResY; - frame_context.border_scale = ((double)frame_context.orig_height) / frame_context.track->PlayResY; + if (frame_context.track->ScaledBorderAndShadow) + frame_context.border_scale = ((double)frame_context.orig_height) / frame_context.track->PlayResY; + else + frame_context.border_scale = 1.; frame_context.font_scale_x = 1.; diff --git a/libass/ass_types.h b/libass/ass_types.h index 870fab4caa..52aff0fb85 100644 --- a/libass/ass_types.h +++ b/libass/ass_types.h @@ -105,6 +105,7 @@ typedef struct ass_track_s { int PlayResY; double Timer; int WrapStyle; + char ScaledBorderAndShadow; int default_style; // index of default style diff --git a/libass/ass_utils.c b/libass/ass_utils.c index 25e4d4fe7b..7f728f1bb1 100644 --- a/libass/ass_utils.c +++ b/libass/ass_utils.c @@ -96,6 +96,17 @@ int strtocolor(char** q, uint32_t* res) return result; } +// Return a boolean value for a string +char parse_bool(char* str) { + while (*str == ' ' || *str == '\t') + str++; + if (!strncasecmp(str, "yes", 3)) + return 1; + else if (strtol(str, NULL, 10) > 0) + return 1; + return 0; +} + #if 0 static void sprint_tag(uint32_t tag, char* dst) { diff --git a/libass/ass_utils.h b/libass/ass_utils.h index f37bc0edc1..8c5f3e8f49 100644 --- a/libass/ass_utils.h +++ b/libass/ass_utils.h @@ -30,6 +30,7 @@ int mystrtoll(char** p, long long* res); int mystrtou32(char** p, int base, uint32_t* res); int mystrtod(char** p, double* res); int strtocolor(char** q, uint32_t* res); +char parse_bool(char* str); static inline int d6_to_int(int x) { return (x + 32) >> 6; -- cgit v1.2.3 From 40a38da7db1138644e3fb0e477dcbfe9aa8e0277 Mon Sep 17 00:00:00 2001 From: greg Date: Thu, 5 Mar 2009 20:36:52 +0000 Subject: Style override for ScaledBorderAndShadow. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@28821 b3059339-0415-0410-9bf9-f77b7e298cf2 --- libass/ass.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'libass') diff --git a/libass/ass.c b/libass/ass.c index e1be966b65..612c8d6aae 100644 --- a/libass/ass.c +++ b/libass/ass.c @@ -347,6 +347,8 @@ void process_force_style(ass_track_t* track) { track->Timer = atof(token); else if(!strcasecmp(*fs, "WrapStyle")) track->WrapStyle = atoi(token); + else if(!strcasecmp(*fs, "ScaledBorderAndShadow")) + track->ScaledBorderAndShadow = parse_bool(token); dt = strrchr(*fs, '.'); if (dt) { -- cgit v1.2.3 From f9aba2b83aaffe806749031be747bebe853453ca Mon Sep 17 00:00:00 2001 From: greg Date: Thu, 5 Mar 2009 20:36:56 +0000 Subject: Support for subpixel accuracy of 3 bits for \pos and \move. Also, restrict advance subpixel accuracy to 3 bits to reduce cache bloat. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@28822 b3059339-0415-0410-9bf9-f77b7e298cf2 --- libass/ass_render.c | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) (limited to 'libass') diff --git a/libass/ass_render.c b/libass/ass_render.c index 5371afa06d..9db00b0773 100644 --- a/libass/ass_render.c +++ b/libass/ass_render.c @@ -474,14 +474,14 @@ static int x2scr(double x) { return x*frame_context.orig_width_nocrop / frame_context.track->PlayResX + FFMAX(global_settings->left_margin, 0); } -static int x2scr_pos(double x) { +static double x2scr_pos(double x) { return x*frame_context.orig_width / frame_context.track->PlayResX + global_settings->left_margin; } /** * \brief Mapping between script and screen coordinates */ -static int y2scr(double y) { +static double y2scr(double y) { return y * frame_context.orig_height_nocrop / frame_context.track->PlayResY + FFMAX(global_settings->top_margin, 0); } @@ -787,29 +787,29 @@ static char* parse_tag(char* p, double pwr) { val = -1.; // reset to default change_border(val); } else if (mystrcmp(&p, "move")) { - int x1, x2, y1, y2; + double x1, x2, y1, y2; long long t1, t2, delta_t, t; double x, y; double k; skip('('); - mystrtoi(&p, &x1); + mystrtod(&p, &x1); skip(','); - mystrtoi(&p, &y1); + mystrtod(&p, &y1); skip(','); - mystrtoi(&p, &x2); + mystrtod(&p, &x2); skip(','); - mystrtoi(&p, &y2); + mystrtod(&p, &y2); if (*p == ',') { skip(','); mystrtoll(&p, &t1); skip(','); mystrtoll(&p, &t2); - mp_msg(MSGT_ASS, MSGL_DBG2, "movement6: (%d, %d) -> (%d, %d), (%" PRId64 " .. %" PRId64 ")\n", + mp_msg(MSGT_ASS, MSGL_DBG2, "movement6: (%f, %f) -> (%f, %f), (%" PRId64 " .. %" PRId64 ")\n", x1, y1, x2, y2, (int64_t)t1, (int64_t)t2); } else { t1 = 0; t2 = render_context.event->Duration; - mp_msg(MSGT_ASS, MSGL_DBG2, "movement: (%d, %d) -> (%d, %d)\n", x1, y1, x2, y2); + mp_msg(MSGT_ASS, MSGL_DBG2, "movement: (%f, %f) -> (%f, %f)\n", x1, y1, x2, y2); } skip(')'); delta_t = t2 - t1; @@ -895,13 +895,13 @@ static char* parse_tag(char* p, double pwr) { else render_context.alignment = render_context.style->Alignment; } else if (mystrcmp(&p, "pos")) { - int v1, v2; + double v1, v2; skip('('); - mystrtoi(&p, &v1); + mystrtod(&p, &v1); skip(','); - mystrtoi(&p, &v2); + mystrtod(&p, &v2); skip(')'); - mp_msg(MSGT_ASS, MSGL_DBG2, "pos(%d, %d)\n", v1, v2); + mp_msg(MSGT_ASS, MSGL_DBG2, "pos(%f, %f)\n", v1, v2); if (render_context.evt_type != EVENT_POSITIONED) { render_context.evt_type = EVENT_POSITIONED; render_context.detect_collisions = 0; @@ -1859,8 +1859,13 @@ static int ass_render_event(ass_event_t* event, event_images_t* event_images) pen.y += delta.y * render_context.scale_y; } - shift.x = pen.x & 63; - shift.y = pen.y & 63; + shift.x = pen.x & 56; + shift.y = pen.y & 56; + + if (render_context.evt_type == EVENT_POSITIONED) { + shift.x += double_to_d6(x2scr_pos(render_context.pos_x)) & 56; + shift.y -= double_to_d6(y2scr(render_context.pos_y)) & 56; + } ass_font_set_transform(render_context.font, render_context.scale_x * frame_context.font_scale_x, -- cgit v1.2.3 From 8ad008e12aa377fa54c1ed7c218c48d01392bdc7 Mon Sep 17 00:00:00 2001 From: greg Date: Thu, 5 Mar 2009 20:36:59 +0000 Subject: Fix positioned events' y-position when pan-and-scan is used. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@28823 b3059339-0415-0410-9bf9-f77b7e298cf2 --- libass/ass_render.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'libass') diff --git a/libass/ass_render.c b/libass/ass_render.c index 9db00b0773..5027c29110 100644 --- a/libass/ass_render.c +++ b/libass/ass_render.c @@ -485,6 +485,11 @@ static double y2scr(double y) { return y * frame_context.orig_height_nocrop / frame_context.track->PlayResY + FFMAX(global_settings->top_margin, 0); } +static double y2scr_pos(double y) { + return y * frame_context.orig_height / frame_context.track->PlayResY + + global_settings->top_margin; +} + // the same for toptitles static int y2scr_top(double y) { if (global_settings->use_margins) @@ -1864,7 +1869,7 @@ static int ass_render_event(ass_event_t* event, event_images_t* event_images) if (render_context.evt_type == EVENT_POSITIONED) { shift.x += double_to_d6(x2scr_pos(render_context.pos_x)) & 56; - shift.y -= double_to_d6(y2scr(render_context.pos_y)) & 56; + shift.y -= double_to_d6(y2scr_pos(render_context.pos_y)) & 56; } ass_font_set_transform(render_context.font, @@ -2031,7 +2036,7 @@ static int ass_render_event(ass_event_t* event, event_images_t* event_images) mp_msg(MSGT_ASS, MSGL_DBG2, "positioned event at %f, %f\n", render_context.pos_x, render_context.pos_y); get_base_point(bbox, alignment, &base_x, &base_y); device_x = x2scr_pos(render_context.pos_x) - base_x; - device_y = y2scr(render_context.pos_y) - base_y; + device_y = y2scr_pos(render_context.pos_y) - base_y; } // fix clip coordinates (they depend on alignment) -- cgit v1.2.3 From 9bad4bdce4ec7c09fa05022123a33a8edc7506f1 Mon Sep 17 00:00:00 2001 From: greg Date: Thu, 5 Mar 2009 20:47:33 +0000 Subject: Combine adjacent overlapping, translucent glyph borders and shadows to avoid luminance build-up, which looks ugly. The resulting, modified bitmaps are stored in separate bitmap cache. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@28824 b3059339-0415-0410-9bf9-f77b7e298cf2 --- libass/ass_cache.c | 50 ++++++++++++++++++++++++ libass/ass_cache.h | 21 +++++++++++ libass/ass_render.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 177 insertions(+), 1 deletion(-) (limited to 'libass') diff --git a/libass/ass_cache.c b/libass/ass_cache.c index 41645c4a48..0561874606 100644 --- a/libass/ass_cache.c +++ b/libass/ass_cache.c @@ -324,3 +324,53 @@ void ass_glyph_cache_reset(void) ass_glyph_cache_done(); ass_glyph_cache_init(); } + + +//--------------------------------- +// composite cache + +hashmap_t* composite_cache; + +static void composite_hash_dtor(void* key, size_t key_size, void* value, size_t value_size) +{ + composite_hash_val_t* v = value; + free(v->a); + free(v->b); + free(key); + free(value); +} + +void* cache_add_composite(composite_hash_key_t* key, composite_hash_val_t* val) +{ + return hashmap_insert(composite_cache, key, val); +} + +/** + * \brief Get a composite bitmap from composite cache. + * \param key hash key + * \return requested hash val or 0 if not found +*/ +composite_hash_val_t* cache_find_composite(composite_hash_key_t* key) +{ + return hashmap_find(composite_cache, key); +} + +void ass_composite_cache_init(void) +{ + composite_cache = hashmap_init(sizeof(composite_hash_key_t), + sizeof(composite_hash_val_t), + 0xFFFF + 13, + composite_hash_dtor, NULL, NULL); +} + +void ass_composite_cache_done(void) +{ + hashmap_done(composite_cache); +} + +void ass_composite_cache_reset(void) +{ + ass_composite_cache_done(); + ass_composite_cache_init(); +} + diff --git a/libass/ass_cache.h b/libass/ass_cache.h index fdb8a641c9..f7042bed6c 100644 --- a/libass/ass_cache.h +++ b/libass/ass_cache.h @@ -65,6 +65,27 @@ bitmap_hash_val_t* cache_find_bitmap(bitmap_hash_key_t* key); void ass_bitmap_cache_reset(void); void ass_bitmap_cache_done(void); + +// Cache for composited bitmaps +typedef struct composite_hash_key_s { + int aw, ah, bw, bh; + int ax, ay, bx, by; + bitmap_hash_key_t a; + bitmap_hash_key_t b; +} composite_hash_key_t; + +typedef struct composite_hash_val_s { + unsigned char* a; + unsigned char* b; +} composite_hash_val_t; + +void ass_composite_cache_init(void); +void* cache_add_composite(composite_hash_key_t* key, composite_hash_val_t* val); +composite_hash_val_t* cache_find_composite(composite_hash_key_t* key); +void ass_composite_cache_reset(void); +void ass_composite_cache_done(void); + + // describes an outline glyph typedef struct glyph_hash_key_s { ass_font_t* font; diff --git a/libass/ass_render.c b/libass/ass_render.c index 5027c29110..84840fd0ab 100644 --- a/libass/ass_render.c +++ b/libass/ass_render.c @@ -279,6 +279,7 @@ ass_renderer_t* ass_renderer_init(ass_library_t* library) ass_font_cache_init(); ass_bitmap_cache_init(); + ass_composite_cache_init(); ass_glyph_cache_init(); text_info.glyphs = calloc(MAX_GLYPHS, sizeof(glyph_info_t)); @@ -294,6 +295,7 @@ void ass_renderer_done(ass_renderer_t* priv) { ass_font_cache_done(); ass_bitmap_cache_done(); + ass_composite_cache_done(); ass_glyph_cache_done(); if (render_context.stroker) { FT_Stroker_Done(render_context.stroker); @@ -405,6 +407,93 @@ static ass_image_t** render_glyph(bitmap_t* bm, int dst_x, int dst_y, uint32_t c return tail; } +/** + * \brief Calculate overlapping area of two consecutive bitmaps and in case they + * overlap, composite them together + * Mainly useful for translucent glyphs and especially borders, to avoid the + * luminance adding up where they overlap (which looks ugly) + */ +static void render_overlap(ass_image_t** last_tail, ass_image_t** tail, bitmap_hash_key_t *last_hash, bitmap_hash_key_t* hash) { + int left, top, bottom, right; + int old_left, old_top, w, h, cur_left, cur_top; + int x, y, opos, cpos; + char m; + composite_hash_key_t hk; + composite_hash_val_t *hv; + composite_hash_key_t *nhk; + int ax = (*last_tail)->dst_x; + int ay = (*last_tail)->dst_y; + int aw = (*last_tail)->w; + int ah = (*last_tail)->h; + int bx = (*tail)->dst_x; + int by = (*tail)->dst_y; + int bw = (*tail)->w; + int bh = (*tail)->h; + unsigned char* a; + unsigned char* b; + + if ((*last_tail)->bitmap == (*tail)->bitmap) + return; + + // Calculate overlap coordinates + left = (ax > bx) ? ax : bx; + top = (ay > by) ? ay : by; + right = ((ax+aw) < (bx+bw)) ? (ax+aw) : (bx+bw); + bottom = ((ay+ah) < (by+bh)) ? (ay+ah) : (by+bh); + if ((right <= left) || (bottom <= top)) + return; + old_left = left-(ax); + old_top = top-(ay); + w = right-left; + h = bottom-top; + cur_left = left-(bx); + cur_top = top-(by); + + // Query cache + memcpy(&hk.a, last_hash, sizeof(*last_hash)); + memcpy(&hk.b, hash, sizeof(*hash)); + hk.aw = aw; + hk.ah = ah; + hk.bw = bw; + hk.bh = bh; + hk.ax = ax; + hk.ay = ay; + hk.bx = bx; + hk.by = by; + hv = cache_find_composite(&hk); + if (hv) { + (*last_tail)->bitmap = hv->a; + (*tail)->bitmap = hv->b; + return; + } + + // Allocate new bitmaps and copy over data + a = (*last_tail)->bitmap; + b = (*tail)->bitmap; + (*last_tail)->bitmap = malloc(aw*ah); + (*tail)->bitmap = malloc(bw*bh); + memcpy((*last_tail)->bitmap, a, aw*ah); + memcpy((*tail)->bitmap, b, bw*bh); + + // Composite overlapping area + for (y=0; y b[cpos]) ? a[opos] : b[cpos]; + (*last_tail)->bitmap[opos] = 0; + (*tail)->bitmap[cpos] = m; + } + + // Insert bitmaps into the cache + nhk = calloc(1, sizeof(*nhk)); + memcpy(nhk, &hk, sizeof(*nhk)); + hv = calloc(1, sizeof(*hv)); + hv->a = (*last_tail)->bitmap; + hv->b = (*tail)->bitmap; + cache_add_composite(nhk, hv); +} + /** * \brief Convert text_info_t struct to ass_image_t list * Splits glyphs in halves when needed (for \kf karaoke). @@ -416,6 +505,9 @@ static ass_image_t* render_text(text_info_t* text_info, int dst_x, int dst_y) bitmap_t* bm; ass_image_t* head; ass_image_t** tail = &head; + ass_image_t** last_tail = 0; + ass_image_t** here_tail = 0; + bitmap_hash_key_t* last_hash = 0; for (i = 0; i < text_info->length; ++i) { glyph_info_t* info = text_info->glyphs + i; @@ -426,9 +518,15 @@ static ass_image_t* render_text(text_info_t* text_info, int dst_x, int dst_y) pen_y = dst_y + info->pos.y + ROUND(info->shadow * frame_context.border_scale); bm = info->bm_s; + here_tail = tail; tail = render_glyph(bm, pen_x, pen_y, info->c[3], 0, 1000000, tail); + if (last_tail && tail != here_tail && ((info->c[3] & 0xff) > 0)) + render_overlap(last_tail, here_tail, last_hash, &info->hash_key); + last_tail = here_tail; + last_hash = &info->hash_key; } + last_tail = 0; for (i = 0; i < text_info->length; ++i) { glyph_info_t* info = text_info->glyphs + i; if ((info->symbol == 0) || (info->symbol == '\n') || !info->bm_o) @@ -440,8 +538,14 @@ static ass_image_t* render_text(text_info_t* text_info, int dst_x, int dst_y) if ((info->effect_type == EF_KARAOKE_KO) && (info->effect_timing <= info->bbox.xMax)) { // do nothing - } else + } else { + here_tail = tail; tail = render_glyph(bm, pen_x, pen_y, info->c[2], 0, 1000000, tail); + if (last_tail && tail != here_tail && ((info->c[2] & 0xff) > 0)) + render_overlap(last_tail, here_tail, last_hash, &info->hash_key); + last_tail = here_tail; + last_hash = &info->hash_key; + } } for (i = 0; i < text_info->length; ++i) { glyph_info_t* info = text_info->glyphs + i; @@ -2121,6 +2225,7 @@ static void ass_reconfigure(ass_renderer_t* priv) priv->render_id = ++last_render_id; ass_glyph_cache_reset(); ass_bitmap_cache_reset(); + ass_composite_cache_reset(); ass_free_images(priv->prev_images_root); priv->prev_images_root = 0; } -- cgit v1.2.3 From d4423f75164db09d86c6b6109574e43b35d500b9 Mon Sep 17 00:00:00 2001 From: greg Date: Fri, 6 Mar 2009 01:17:05 +0000 Subject: Use blur with kernel [[1,2,1], [2,4,2], [1,2,1]] for \be. This is faster than gaussian blur and similar to vsfilter. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@28834 b3059339-0415-0410-9bf9-f77b7e298cf2 --- libass/ass_bitmap.c | 40 ++++++++++++++++++++++++++++++++-------- libass/ass_bitmap.h | 2 +- libass/ass_render.c | 6 +----- 3 files changed, 34 insertions(+), 14 deletions(-) (limited to 'libass') diff --git a/libass/ass_bitmap.c b/libass/ass_bitmap.c index 9fb1eab65e..dccdc542a6 100644 --- a/libass/ass_bitmap.c +++ b/libass/ass_bitmap.c @@ -255,11 +255,38 @@ 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, ass_synth_priv_t* priv_blur, +/** + * \brief Blur with [[1,2,1]. [2,4,2], [1,2,1]] kernel + * This blur is the same as the one employed by vsfilter. + */ +static void be_blur(unsigned char *buf, int w, int h) { + unsigned int x, y; + unsigned int old_sum, new_sum; + + for (y=0; y> 2; + old_sum = new_sum; + } + } + + for (x=0; x> 2; + old_sum = new_sum; + } + } +} + +int glyph_to_bitmap(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) { - int bord = be ? (be+1) : 0; + int bord = be ? (be/4+1) : 0; blur_radius *= 2; bord = (blur_radius > 0.0) ? blur_radius : bord; @@ -279,19 +306,16 @@ int glyph_to_bitmap(ass_synth_priv_t* priv, ass_synth_priv_t* priv_blur, return 1; } } - if (*bm_o) { - resize_tmp(priv, (*bm_o)->w, (*bm_o)->h); + if (*bm_o) 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) { 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); + be_blur((*bm_o)->buffer, (*bm_o)->w, (*bm_o)->h); 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); + be_blur((*bm_g)->buffer, (*bm_g)->w, (*bm_g)->h); } } else { if (blur_radius > 0.0) { diff --git a/libass/ass_bitmap.h b/libass/ass_bitmap.h index 5f45aae4b2..c0b4ad201f 100644 --- a/libass/ass_bitmap.h +++ b/libass/ass_bitmap.h @@ -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, 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); +int glyph_to_bitmap(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_render.c b/libass/ass_render.c index 84840fd0ab..fa10d245db 100644 --- a/libass/ass_render.c +++ b/libass/ass_render.c @@ -43,7 +43,6 @@ #define MAX_GLYPHS 3000 #define MAX_LINES 300 -#define BE_RADIUS 1.5 #define BLUR_MAX_RADIUS 50.0 #define ROUND(x) ((int) ((x) + .5)) @@ -83,7 +82,6 @@ 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; @@ -270,8 +268,7 @@ ass_renderer_t* ass_renderer_init(ass_library_t* library) goto ass_init_exit; } - priv->synth_priv = ass_synth_init(BE_RADIUS); - priv->synth_priv_blur = ass_synth_init(BLUR_MAX_RADIUS); + priv->synth_priv = ass_synth_init(BLUR_MAX_RADIUS); priv->library = library; priv->ftlibrary = ft; @@ -1503,7 +1500,6 @@ 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->blur * frame_context.border_scale); -- cgit v1.2.3 From d303d39798d85bb38ed394cbee5d4fa178aae2b7 Mon Sep 17 00:00:00 2001 From: greg Date: Fri, 6 Mar 2009 01:26:44 +0000 Subject: Replace magic numbers (for subpixel accuracy masking) with a define. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@28835 b3059339-0415-0410-9bf9-f77b7e298cf2 --- libass/ass_render.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'libass') diff --git a/libass/ass_render.c b/libass/ass_render.c index fa10d245db..0524e027b8 100644 --- a/libass/ass_render.c +++ b/libass/ass_render.c @@ -45,6 +45,7 @@ #define MAX_LINES 300 #define BLUR_MAX_RADIUS 50.0 #define ROUND(x) ((int) ((x) + .5)) +#define SUBPIXEL_MASK 56 // d6 bitmask for subpixel accuracy adjustment static int last_render_id = 0; @@ -1964,12 +1965,12 @@ static int ass_render_event(ass_event_t* event, event_images_t* event_images) pen.y += delta.y * render_context.scale_y; } - shift.x = pen.x & 56; - shift.y = pen.y & 56; + shift.x = pen.x & SUBPIXEL_MASK; + shift.y = pen.y & SUBPIXEL_MASK; if (render_context.evt_type == EVENT_POSITIONED) { - shift.x += double_to_d6(x2scr_pos(render_context.pos_x)) & 56; - shift.y -= double_to_d6(y2scr_pos(render_context.pos_y)) & 56; + shift.x += double_to_d6(x2scr_pos(render_context.pos_x)) & SUBPIXEL_MASK; + shift.y -= double_to_d6(y2scr_pos(render_context.pos_y)) & SUBPIXEL_MASK; } ass_font_set_transform(render_context.font, -- cgit v1.2.3 From 25abe9651df43975b735430ef46145d1eb4ce047 Mon Sep 17 00:00:00 2001 From: greg Date: Fri, 6 Mar 2009 09:20:09 +0000 Subject: Raise max. number of \be applications to 100, introduce #define for it. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@28836 b3059339-0415-0410-9bf9-f77b7e298cf2 --- libass/ass_render.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'libass') diff --git a/libass/ass_render.c b/libass/ass_render.c index 0524e027b8..7263413963 100644 --- a/libass/ass_render.c +++ b/libass/ass_render.c @@ -44,6 +44,7 @@ #define MAX_GLYPHS 3000 #define MAX_LINES 300 #define BLUR_MAX_RADIUS 50.0 +#define MAX_BE 100 #define ROUND(x) ((int) ((x) + .5)) #define SUBPIXEL_MASK 56 // d6 bitmask for subpixel accuracy adjustment @@ -1158,9 +1159,9 @@ static char* parse_tag(char* p, double pwr) { } else if (mystrcmp(&p, "be")) { int val; if (mystrtoi(&p, &val)) { - // Clamp to 10, since high values need excessive CPU + // Clamp to a safe upper limit, since high values need excessive CPU val = (val < 0) ? 0 : val; - val = (val > 10) ? 10 : val; + val = (val > MAX_BE) ? MAX_BE : val; render_context.be = val; } else render_context.be = 0; -- cgit v1.2.3 From 27b512e1f58b273e3f36113f72a121da66cf9a5b Mon Sep 17 00:00:00 2001 From: greg Date: Fri, 6 Mar 2009 09:20:14 +0000 Subject: Fix \be blur start position. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@28837 b3059339-0415-0410-9bf9-f77b7e298cf2 --- libass/ass_bitmap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'libass') diff --git a/libass/ass_bitmap.c b/libass/ass_bitmap.c index dccdc542a6..61457f1fcc 100644 --- a/libass/ass_bitmap.c +++ b/libass/ass_bitmap.c @@ -264,7 +264,7 @@ static void be_blur(unsigned char *buf, int w, int h) { unsigned int old_sum, new_sum; for (y=0; y> 2; @@ -273,7 +273,7 @@ static void be_blur(unsigned char *buf, int w, int h) { } for (x=0; x> 2; -- cgit v1.2.3