diff options
author | Grigori Goronzy <greg@hein> | 2009-06-29 02:10:02 +0200 |
---|---|---|
committer | Grigori Goronzy <greg@hein> | 2009-06-29 02:10:02 +0200 |
commit | e8433c6ff67409c55ff005fa3d7a28e52d8ec21b (patch) | |
tree | ae5f9b0a4ea53bb2c2c87b935eccdee0f1b298ab /libass/ass_bitmap.c | |
parent | a75f6a8d3d3ed6410cc2a4efa866a99152d78af6 (diff) | |
download | libass-e8433c6ff67409c55ff005fa3d7a28e52d8ec21b.tar.bz2 libass-e8433c6ff67409c55ff005fa3d7a28e52d8ec21b.tar.xz |
Subpixel accurate shadow rendering
Shadows are handled different from glyph and outline. A shadow
is the sum of glyph and outline bitmap; therefore shifting to the
correct subpixel amount before rasterization is out of the question.
Instead, the bitmap is shifted by its subpixel amount after being
built from shadow and glyph.
The bitmap cache was extended for this.
Diffstat (limited to 'libass/ass_bitmap.c')
-rw-r--r-- | libass/ass_bitmap.c | 57 |
1 files changed, 56 insertions, 1 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; } |