summaryrefslogtreecommitdiffstats
path: root/libass
diff options
context:
space:
mode:
authorDr.Smile <vabnick@gmail.com>2014-11-06 02:57:03 +0300
committerDr.Smile <vabnick@gmail.com>2014-11-06 02:57:03 +0300
commit26ccc19c66298ee7783f45e6534d4ddee90cca15 (patch)
tree8fc206a7432910ae2c317f6ce2dc1240c41596a2 /libass
parentde756cf85b851c423a397ff7f8e4d98dbb0f5abb (diff)
downloadlibass-26ccc19c66298ee7783f45e6534d4ddee90cca15.tar.bz2
libass-26ccc19c66298ee7783f45e6534d4ddee90cca15.tar.xz
Fix subpixel shadow shift
Diffstat (limited to 'libass')
-rw-r--r--libass/ass_bitmap.c46
-rw-r--r--libass/ass_render.c30
2 files changed, 27 insertions, 49 deletions
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);