mirror of
https://github.com/mpv-player/mpv
synced 2025-01-01 04:36:24 +01:00
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
This commit is contained in:
parent
8ad008e12a
commit
9bad4bdce4
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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<h; y++)
|
||||
for (x=0; x<w; x++) {
|
||||
opos = (old_top+y)*(aw) + (old_left+x);
|
||||
cpos = (cur_top+y)*(bw) + (cur_left+x);
|
||||
m = (a[opos] > 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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user