summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libass/ass_bitmap.c57
-rw-r--r--libass/ass_bitmap.h2
-rw-r--r--libass/ass_cache_template.c1
-rw-r--r--libass/ass_render.c18
4 files changed, 72 insertions, 6 deletions
diff --git a/libass/ass_bitmap.c b/libass/ass_bitmap.c
index 46ead6ea..d7573ef7 100644
--- a/libass/ass_bitmap.c
+++ b/libass/ass_bitmap.c
@@ -273,6 +273,56 @@ static bitmap_t *fix_outline_and_shadow(bitmap_t *bm_g, bitmap_t *bm_o)
}
/**
+ * \brief Shift a bitmap by the fraction of a pixel in x and y direction
+ * expressed in 26.6 fixed point
+ */
+static void shift_bitmap(unsigned char *buf, int w, int h, int shift_x,
+ int shift_y)
+{
+ int x, y, b;
+
+ // Shift in x direction
+ if (shift_x > 0) {
+ for (y = 0; y < h; y++) {
+ for (x = w - 1; x > 0; x--) {
+ b = (buf[x + y * w - 1] * shift_x) / 64;
+ buf[x + y * w - 1] -= b;
+ buf[x + y * w] += b;
+ }
+ }
+ } else if (shift_x < 0) {
+ shift_x = -shift_x;
+ for (y = 0; y < h; y++) {
+ for (x = 0; x < w - 1; x++) {
+ b = (buf[x + y * w + 1] * shift_x) / 64;
+ buf[x + y * w + 1] -= b;
+ buf[x + y * w] += b;
+ }
+ }
+ }
+
+ // Shift in y direction
+ if (shift_y > 0) {
+ for (x = 0; x < w; x++) {
+ for (y = h - 1; y > 0; y--) {
+ b = (buf[x + (y - 1) * w] * shift_y) / 64;
+ buf[x + (y - 1) * w] -= b;
+ buf[x + y * w] += b;
+ }
+ }
+ } else if (shift_y < 0) {
+ shift_y = -shift_y;
+ for (x = 0; x < w; x++) {
+ for (y = 0; y < h - 1; y++) {
+ b = (buf[x + (y + 1) * w] * shift_y) / 64;
+ buf[x + (y + 1) * w] -= b;
+ buf[x + y * w] += b;
+ }
+ }
+ }
+}
+
+/**
* \brief Blur with [[1,2,1]. [2,4,2], [1,2,1]] kernel
* This blur is the same as the one employed by vsfilter.
*/
@@ -303,11 +353,13 @@ static void be_blur(unsigned char *buf, int w, int h)
int glyph_to_bitmap(ass_synth_priv_t *priv_blur,
FT_Glyph glyph, FT_Glyph outline_glyph,
bitmap_t **bm_g, bitmap_t **bm_o, bitmap_t **bm_s,
- int be, double blur_radius)
+ int be, double blur_radius, FT_Vector shadow_offset)
{
int bord = be ? (be / 4 + 1) : 0;
blur_radius *= 2;
bord = (blur_radius > 0.0) ? blur_radius + 1 : bord;
+ if (bord == 0 && (shadow_offset.x || shadow_offset.y))
+ bord = 1;
assert(bm_g && bm_o && bm_s);
@@ -356,6 +408,9 @@ int glyph_to_bitmap(ass_synth_priv_t *priv_blur,
else
*bm_s = copy_bitmap(*bm_g);
+ shift_bitmap((*bm_s)->buffer, (*bm_s)->w,(*bm_s)->h,
+ shadow_offset.x, shadow_offset.y);
+
assert(bm_s);
return 0;
}
diff --git a/libass/ass_bitmap.h b/libass/ass_bitmap.h
index 73a36698..f6b13805 100644
--- a/libass/ass_bitmap.h
+++ b/libass/ass_bitmap.h
@@ -47,7 +47,7 @@ typedef struct bitmap_s {
int glyph_to_bitmap(ass_synth_priv_t *priv_blur, FT_Glyph glyph,
FT_Glyph outline_glyph, bitmap_t **bm_g,
bitmap_t **bm_o, bitmap_t **bm_s, int be,
- double blur_radius);
+ double blur_radius, FT_Vector shadow_offset);
void ass_free_bitmap(bitmap_t *bm);
diff --git a/libass/ass_cache_template.c b/libass/ass_cache_template.c
index 6c536fbb..dd9adbd4 100644
--- a/libass/ass_cache_template.c
+++ b/libass/ass_cache_template.c
@@ -77,6 +77,7 @@ START(bitmap, bipmap_hash_key_s)
GENERIC(int, shift_x)
GENERIC(int, shift_y)
FTVECTOR(advance) // subpixel shift vector
+ FTVECTOR(shadow_offset) // shadow subpixel shift
END(bitmap_hash_key_t)
// describes an outline glyph
diff --git a/libass/ass_render.c b/libass/ass_render.c
index 2abb9d7f..c779f3b1 100644
--- a/libass/ass_render.c
+++ b/libass/ass_render.c
@@ -41,7 +41,6 @@
#define MAX_LINES_INITIAL 64
#define BLUR_MAX_RADIUS 100.0
#define MAX_BE 100
-#define ROUND(x) ((int) ((x) + .5))
#define SUBPIXEL_MASK 63 // d6 bitmask for subpixel accuracy adjustment
static int last_render_id = 0;
@@ -574,10 +573,10 @@ static ass_image_t *render_text(ass_renderer_t *render_priv, int dst_x,
pen_x =
dst_x + (info->pos.x >> 6) +
- ROUND(info->shadow_x * render_priv->border_scale);
+ (int) (info->shadow_x * render_priv->border_scale);
pen_y =
dst_y + (info->pos.y >> 6) +
- ROUND(info->shadow_y * render_priv->border_scale);
+ (int) (info->shadow_y * render_priv->border_scale);
bm = info->bm_s;
here_tail = tail;
@@ -1874,7 +1873,8 @@ get_bitmap_glyph(ass_renderer_t *render_priv, glyph_info_t *info)
info->glyph, info->outline_glyph,
&info->bm, &info->bm_o,
&info->bm_s, info->be,
- info->blur * render_priv->border_scale);
+ info->blur * render_priv->border_scale,
+ info->hash_key.shadow_offset);
if (error)
info->symbol = 0;
@@ -2439,6 +2439,16 @@ ass_render_event(ass_renderer_t *render_priv, ass_event_t *event,
render_priv->state.be;
text_info->glyphs[text_info->length].hash_key.blur =
render_priv->state.blur;
+ text_info->glyphs[text_info->length].hash_key.shadow_offset.x =
+ double_to_d6(
+ render_priv->state.shadow_x * render_priv->border_scale -
+ (int) (render_priv->state.shadow_x *
+ render_priv->border_scale));
+ text_info->glyphs[text_info->length].hash_key.shadow_offset.y =
+ double_to_d6(
+ render_priv->state.shadow_y * render_priv->border_scale -
+ (int) (render_priv->state.shadow_y *
+ render_priv->border_scale));
text_info->length++;