Mercurial > mplayer.hg
changeset 19965:70352570e9ae
Shadow support in libass.
author | eugeni |
---|---|
date | Sun, 24 Sep 2006 16:04:37 +0000 |
parents | edee81101156 |
children | 27187c1ac20b |
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, 63 insertions(+), 14 deletions(-) [+] |
line wrap: on
line diff
--- a/libass/ass_bitmap.c Sun Sep 24 15:55:10 2006 +0000 +++ b/libass/ass_bitmap.c Sun Sep 24 16:04:37 2006 +0000 @@ -122,6 +122,15 @@ } } +static bitmap_t* copy_bitmap(const bitmap_t* src) +{ + bitmap_t* dst = alloc_bitmap(src->w, src->h); + dst->left = src->left; + dst->top = src->top; + memcpy(dst->buffer, src->buffer, src->w * src->h); + return dst; +} + static bitmap_t* glyph_to_bitmap_internal(FT_Glyph glyph, int bord) { FT_BitmapGlyph bg; @@ -165,15 +174,19 @@ return bm; } -static void fix_outline(bitmap_t* bm_g, bitmap_t* bm_o) +static bitmap_t* fix_outline_and_shadow(bitmap_t* bm_g, bitmap_t* bm_o) { int x, y; const int l = bm_o->left > bm_g->left ? bm_o->left : bm_g->left; const int t = bm_o->top > bm_g->top ? bm_o->top : bm_g->top; const int r = bm_o->left + bm_o->w < bm_g->left + bm_g->w ? bm_o->left + bm_o->w : bm_g->left + bm_g->w; const int b = bm_o->top + bm_o->h < bm_g->top + bm_g->h ? bm_o->top + bm_o->h : bm_g->top + bm_g->h; + + bitmap_t* bm_s = copy_bitmap(bm_o); + unsigned char* g = bm_g->buffer + (t - bm_g->top) * bm_g->w + (l - bm_g->left); unsigned char* o = bm_o->buffer + (t - bm_o->top) * bm_o->w + (l - bm_o->left); + unsigned char* s = bm_s->buffer + (t - bm_s->top) * bm_s->w + (l - bm_s->left); for (y = 0; y < b - t; ++y) { for (x = 0; x < r - l; ++x) { @@ -181,33 +194,38 @@ c_g = g[x]; c_o = o[x]; o[x] = (c_o > c_g) ? c_o - c_g : 0; + s[x] = (c_o < 0xFF - c_g) ? c_o + c_g : 0xFF; } g += bm_g->w; o += bm_o->w; + s += bm_s->w; } + + assert(bm_s); + 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, int be) +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) { const int bord = be ? ceil(blur_radius) : 0; - assert(bm_g && bm_o); + assert(bm_g && bm_o && bm_s); + + *bm_g = *bm_o = *bm_s = 0; if (glyph) *bm_g = glyph_to_bitmap_internal(glyph, bord); - else - *bm_g = 0; if (!*bm_g) return 1; + if (outline_glyph) { *bm_o = glyph_to_bitmap_internal(outline_glyph, bord); if (!*bm_o) { ass_free_bitmap(*bm_g); return 1; } - } else - *bm_o = 0; - + } if (*bm_o) resize_tmp(priv, (*bm_o)->w, (*bm_o)->h); resize_tmp(priv, (*bm_g)->w, (*bm_g)->h); @@ -219,8 +237,11 @@ } if (*bm_o) - fix_outline(*bm_g, *bm_o); + *bm_s = fix_outline_and_shadow(*bm_g, *bm_o); + else + *bm_s = copy_bitmap(*bm_g); + assert(bm_s); return 0; }
--- a/libass/ass_bitmap.h Sun Sep 24 15:55:10 2006 +0000 +++ b/libass/ass_bitmap.h Sun Sep 24 16:04:37 2006 +0000 @@ -12,7 +12,7 @@ unsigned char* buffer; // w x h buffer } bitmap_t; -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); +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); void ass_free_bitmap(bitmap_t* bm); #endif
--- a/libass/ass_cache.c Sun Sep 24 15:55:10 2006 +0000 +++ b/libass/ass_cache.c Sun Sep 24 16:04:37 2006 +0000 @@ -202,6 +202,7 @@ glyph_hash_item_t* next = item->next; if (item->val.bm) ass_free_bitmap(item->val.bm); if (item->val.bm_o) ass_free_bitmap(item->val.bm_o); + if (item->val.bm_s) ass_free_bitmap(item->val.bm_s); free(item); item = next; }
--- a/libass/ass_cache.h Sun Sep 24 15:55:10 2006 +0000 +++ b/libass/ass_cache.h Sun Sep 24 16:04:37 2006 +0000 @@ -38,6 +38,7 @@ typedef struct glyph_hash_val_s { bitmap_t* bm; // the actual glyph bitmaps bitmap_t* bm_o; + bitmap_t* bm_s; FT_BBox bbox_scaled; // bbox after scaling, but before rotation FT_Vector advance; // 26.6, advance distance to the next glyph in line } glyph_hash_val_t;
--- a/libass/ass_render.c Sun Sep 24 15:55:10 2006 +0000 +++ b/libass/ass_render.c Sun Sep 24 16:04:37 2006 +0000 @@ -53,8 +53,9 @@ unsigned symbol; FT_Glyph glyph; FT_Glyph outline_glyph; - bitmap_t* bm; - bitmap_t* bm_o; + bitmap_t* bm; // glyph bitmap + bitmap_t* bm_o; // outline bitmap + bitmap_t* bm_s; // shadow bitmap FT_BBox bbox; FT_Vector pos; char linebreak; // the first (leading) glyph of some line ? @@ -68,6 +69,7 @@ int asc, desc; // font max ascender and descender // int height; int be; // blur edges + int shadow; glyph_hash_key_t hash_key; } glyph_info_t; @@ -113,6 +115,7 @@ char detect_collisions; uint32_t fade; // alpha from \fad char be; // blur edges + int shadow; effect_t effect_type; int effect_timing; @@ -376,7 +379,8 @@ continue; 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); + &text_info->glyphs[i].bm, &text_info->glyphs[i].bm_o, + &text_info->glyphs[i].bm_s, text_info->glyphs[i].be); if (error) text_info->glyphs[i].symbol = 0; FT_Done_Glyph(text_info->glyphs[i].glyph); @@ -387,6 +391,7 @@ hash_val.bbox_scaled = text_info->glyphs[i].bbox; hash_val.bm_o = text_info->glyphs[i].bm_o; hash_val.bm = text_info->glyphs[i].bm; + hash_val.bm_s = text_info->glyphs[i].bm_s; hash_val.advance.x = text_info->glyphs[i].advance.x; hash_val.advance.y = text_info->glyphs[i].advance.y; cache_add_glyph(&(text_info->glyphs[i].hash_key), &hash_val); @@ -396,6 +401,18 @@ 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_s || (info->shadow == 0)) + continue; + + pen_x = dst_x + info->pos.x + info->shadow; + pen_y = dst_y + info->pos.y + info->shadow; + bm = info->bm_s; + + tail = render_glyph(bm, pen_x, pen_y, info->c[3], 0, 1000000, tail); + } + + 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) continue; @@ -992,6 +1009,12 @@ if (render_context.effect_timing) render_context.effect_skip_timing += render_context.effect_timing; render_context.effect_timing = val * 10; + } else if (mystrcmp(&p, "shad")) { + int val; + if (mystrtoi(&p, 10, &val)) + render_context.shadow = val; + else + render_context.shadow = render_context.style->Shadow; } return p; @@ -1137,6 +1160,7 @@ render_context.scale_y = render_context.style->ScaleY; render_context.hspacing = 0; // FIXME render_context.be = 0; + render_context.shadow = render_context.style->Shadow; // FIXME: does not reset unsupported attributes. } @@ -1208,6 +1232,7 @@ info->glyph = info->outline_glyph = 0; info->bm = val->bm; info->bm_o = val->bm_o; + info->bm_s = val->bm_s; info->bbox = val->bbox_scaled; info->advance.x = val->advance.x; info->advance.y = val->advance.y; @@ -1252,7 +1277,7 @@ info->outline_glyph = 0; } - info->bm = info->bm_o = 0; + info->bm = info->bm_o = info->bm_s = 0; return 0; } @@ -1625,6 +1650,7 @@ 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.glyphs[text_info.length].shadow = render_context.shadow; text_info.length++;