mirror of
https://github.com/mpv-player/mpv
synced 2025-03-25 04:38:01 +00:00
Shadow support in libass.
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@19971 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
parent
5e490d613c
commit
1b0251e7ad
@ -122,6 +122,15 @@ void ass_free_bitmap(bitmap_t* bm)
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ static bitmap_t* glyph_to_bitmap_internal(FT_Glyph glyph, int bord)
|
||||
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 @@ static void fix_outline(bitmap_t* bm_g, bitmap_t* bm_o)
|
||||
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 @@ int glyph_to_bitmap(ass_synth_priv_t* priv, FT_Glyph glyph, FT_Glyph outline_gly
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@ typedef struct bitmap_s {
|
||||
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
|
||||
|
@ -202,6 +202,7 @@ void ass_glyph_cache_done(void)
|
||||
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;
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ typedef struct glyph_hash_key_s {
|
||||
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;
|
||||
|
@ -53,8 +53,9 @@ typedef struct glyph_info_s {
|
||||
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 @@ typedef struct glyph_info_s {
|
||||
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 @@ typedef struct render_context_s {
|
||||
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 @@ static ass_image_t* render_text(text_info_t* text_info, int dst_x, int dst_y)
|
||||
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 @@ static ass_image_t* render_text(text_info_t* text_info, int dst_x, int dst_y)
|
||||
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);
|
||||
@ -394,6 +399,18 @@ static ass_image_t* render_text(text_info_t* text_info, int dst_x, int dst_y)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
@ -992,6 +1009,12 @@ static char* parse_tag(char* p, double pwr) {
|
||||
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 @@ static void reset_render_context(void)
|
||||
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 @@ static int get_glyph(int index, int symbol, glyph_info_t* info, FT_Vector* advan
|
||||
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 @@ static int get_glyph(int index, int symbol, glyph_info_t* info, FT_Vector* advan
|
||||
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 @@ static int ass_render_event(ass_event_t* event, event_images_t* event_images)
|
||||
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++;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user