From 26ccc19c66298ee7783f45e6534d4ddee90cca15 Mon Sep 17 00:00:00 2001 From: "Dr.Smile" Date: Thu, 6 Nov 2014 02:57:03 +0300 Subject: Fix subpixel shadow shift --- libass/ass_bitmap.c | 46 ++++++++++++---------------------------------- libass/ass_render.c | 30 +++++++++++++++--------------- 2 files changed, 27 insertions(+), 49 deletions(-) (limited to 'libass') diff --git a/libass/ass_bitmap.c b/libass/ass_bitmap.c index 1f719f8..9a98f5a 100644 --- a/libass/ass_bitmap.c +++ b/libass/ass_bitmap.c @@ -327,45 +327,23 @@ void shift_bitmap(Bitmap *bm, int shift_x, int shift_y) int s = bm->stride; unsigned char *buf = bm->buffer; + assert((shift_x & ~63) == 0 && (shift_y & ~63) == 0); + // Shift in x direction - if (shift_x > 0) { - shift_x &= 0x3F; - for (y = 0; y < h; y++) { - for (x = w - 1; x > 0; x--) { - b = (buf[x + y * s - 1] * shift_x) >> 6; - buf[x + y * s - 1] -= b; - buf[x + y * s] += b; - } - } - } else if (shift_x < 0) { - shift_x = -shift_x & 0x3F; - for (y = 0; y < h; y++) { - for (x = 0; x < w - 1; x++) { - b = (buf[x + y * s + 1] * shift_x) >> 6; - buf[x + y * s + 1] -= b; - buf[x + y * s] += b; - } + for (y = 0; y < h; y++) { + for (x = w - 1; x > 0; x--) { + b = (buf[x + y * s - 1] * shift_x) >> 6; + buf[x + y * s - 1] -= b; + buf[x + y * s] += b; } } // Shift in y direction - if (shift_y > 0) { - shift_y &= 0x3F; - for (x = 0; x < w; x++) { - for (y = h - 1; y > 0; y--) { - b = (buf[x + (y - 1) * s] * shift_y) >> 6; - buf[x + (y - 1) * s] -= b; - buf[x + y * s] += b; - } - } - } else if (shift_y < 0) { - shift_y = -shift_y & 0x3F; - for (x = 0; x < w; x++) { - for (y = 0; y < h - 1; y++) { - b = (buf[x + (y + 1) * s] * shift_y) >> 6; - buf[x + (y + 1) * s] -= b; - buf[x + y * s] += b; - } + for (x = 0; x < w; x++) { + for (y = h - 1; y > 0; y--) { + b = (buf[x + (y - 1) * s] * shift_y) >> 6; + buf[x + (y - 1) * s] -= b; + buf[x + y * s] += b; } } } diff --git a/libass/ass_render.c b/libass/ass_render.c index 8d942f6..d1a47ee 100644 --- a/libass/ass_render.c +++ b/libass/ass_render.c @@ -675,12 +675,8 @@ static ASS_Image *render_text(ASS_Renderer *render_priv, int dst_x, int dst_y) if (render_priv->state.border_style == 4) continue; - pen_x = - dst_x + info->pos.x + - (int) (info->shadow_x * render_priv->border_scale); - pen_y = - dst_y + info->pos.y + - (int) (info->shadow_y * render_priv->border_scale); + pen_x = dst_x + info->pos.x; + pen_y = dst_y + info->pos.y; bm = info->bm_s; tail = @@ -1724,12 +1720,10 @@ fill_bitmap_hash(ASS_Renderer *priv, GlyphInfo *info, hash_key->fay = double_to_d16(info->fay); hash_key->be = info->be; hash_key->blur = info->blur; - hash_key->shadow_offset.x = double_to_d6( - info->shadow_x * priv->border_scale - - (int) (info->shadow_x * priv->border_scale)); - hash_key->shadow_offset.y = double_to_d6( - info->shadow_y * priv->border_scale - - (int) (info->shadow_y * priv->border_scale)); + hash_key->shadow_offset.x = + double_to_d6(info->shadow_x * priv->border_scale) & SUBPIXEL_MASK; + hash_key->shadow_offset.y = + double_to_d6(info->shadow_y * priv->border_scale) & SUBPIXEL_MASK; } /** @@ -1869,7 +1863,7 @@ static void apply_blur(CombinedBitmapInfo *info, ASS_Renderer *render_priv) } } -static void make_shadow_bitmap(CombinedBitmapInfo *info) +static void make_shadow_bitmap(CombinedBitmapInfo *info, ASS_Renderer *render_priv) { // VSFilter compatibility: invisible fill and no border? // In this case no shadow is supposed to be rendered. @@ -1891,7 +1885,13 @@ static void make_shadow_bitmap(CombinedBitmapInfo *info) assert(info->bm_s); - shift_bitmap(info->bm_s, info->shadow_x, info->shadow_y); + // Works right even for negative offsets + // '>>' rounds toward negative infinity, '&' returns correct remainder + int offset_x = double_to_d6(info->shadow_x * render_priv->border_scale); + int offset_y = double_to_d6(info->shadow_y * render_priv->border_scale); + info->bm_s->left += offset_x >> 6; + info->bm_s->top += offset_y >> 6; + shift_bitmap(info->bm_s, offset_x & SUBPIXEL_MASK, offset_y & SUBPIXEL_MASK); } /** @@ -2603,7 +2603,7 @@ ass_render_event(ASS_Renderer *render_priv, ASS_Event *event, CombinedBitmapInfo *info = &combined_info[i]; if(info->bm || info->bm_o){ apply_blur(info, render_priv); - make_shadow_bitmap(info); + make_shadow_bitmap(info, render_priv); } fill_composite_hash(&hk, info); -- cgit v1.2.3