From 4293dc36c1fc3a39731e328ab76af920512c888f Mon Sep 17 00:00:00 2001 From: "Dr.Smile" Date: Thu, 3 May 2018 03:09:52 +0300 Subject: bitmap: remove level of indirection in bitmap functions This allows to use Bitmap struct directly as cache value and to remove bunch of unnecessary allocations. --- libass/ass_bitmap.c | 108 +++++++++------------ libass/ass_bitmap.h | 9 +- libass/ass_cache.c | 19 ++-- libass/ass_cache.h | 8 +- libass/ass_cache_template.h | 4 +- libass/ass_render.c | 228 ++++++++++++++++++++++---------------------- libass/ass_render.h | 2 +- 7 files changed, 176 insertions(+), 202 deletions(-) (limited to 'libass') diff --git a/libass/ass_bitmap.c b/libass/ass_bitmap.c index a7b8002..b489d85 100644 --- a/libass/ass_bitmap.c +++ b/libass/ass_bitmap.c @@ -62,14 +62,14 @@ void ass_synth_blur(const BitmapEngine *engine, int opaque_box, int be, double blur_radius, Bitmap *bm_g, Bitmap *bm_o) { - bool blur_g = !bm_o || opaque_box; - if (blur_g && !bm_g) + bool blur_g = !bm_o->buffer || opaque_box; + if (blur_g && !bm_g->buffer) return; // Apply gaussian blur double r2 = blur_radius * blur_radius / log(256); if (r2 > 0.001) { - if (bm_o) + if (bm_o->buffer) ass_gaussian_blur(engine, bm_o, r2); if (blur_g) ass_gaussian_blur(engine, bm_g, r2); @@ -78,7 +78,7 @@ void ass_synth_blur(const BitmapEngine *engine, int opaque_box, int be, // Apply box blur (multiple passes, if requested) if (be) { size_t size_o = 0, size_g = 0; - if (bm_o) + if (bm_o->buffer) size_o = sizeof(uint16_t) * bm_o->stride * 2; if (blur_g) size_g = sizeof(uint16_t) * bm_g->stride * 2; @@ -86,7 +86,7 @@ void ass_synth_blur(const BitmapEngine *engine, int opaque_box, int be, uint16_t *tmp = size ? ass_aligned_alloc(32, size, false) : NULL; if (!tmp) return; - if (bm_o) { + if (bm_o->buffer) { int passes = be; int32_t w = bm_o->w; int32_t h = bm_o->h; @@ -128,8 +128,8 @@ void ass_synth_blur(const BitmapEngine *engine, int opaque_box, int be, } } -static bool alloc_bitmap_buffer(const BitmapEngine *engine, Bitmap *bm, - int32_t w, int32_t h, bool zero) +bool alloc_bitmap(const BitmapEngine *engine, Bitmap *bm, + int32_t w, int32_t h, bool zero) { unsigned align = 1 << engine->align_order; size_t s = ass_align(align, w); @@ -146,23 +146,10 @@ static bool alloc_bitmap_buffer(const BitmapEngine *engine, Bitmap *bm, return true; } -Bitmap *alloc_bitmap(const BitmapEngine *engine, int32_t w, int32_t h, bool zero) -{ - Bitmap *bm = malloc(sizeof(Bitmap)); - if (!bm) - return NULL; - if (!alloc_bitmap_buffer(engine, bm, w, h, zero)) { - free(bm); - return NULL; - } - bm->left = bm->top = 0; - return bm; -} - bool realloc_bitmap(const BitmapEngine *engine, Bitmap *bm, int32_t w, int32_t h) { uint8_t *old = bm->buffer; - if (!alloc_bitmap_buffer(engine, bm, w, h, false)) + if (!alloc_bitmap(engine, bm, w, h, false)) return false; ass_aligned_free(old); return true; @@ -170,77 +157,70 @@ bool realloc_bitmap(const BitmapEngine *engine, Bitmap *bm, int32_t w, int32_t h void ass_free_bitmap(Bitmap *bm) { - if (bm) - ass_aligned_free(bm->buffer); - free(bm); + ass_aligned_free(bm->buffer); } -Bitmap *copy_bitmap(const BitmapEngine *engine, const Bitmap *src) +bool copy_bitmap(const BitmapEngine *engine, Bitmap *dst, const Bitmap *src) { - Bitmap *dst = alloc_bitmap(engine, src->w, src->h, false); - if (!dst) - return NULL; + if (!src->buffer) { + memset(dst, 0, sizeof(*dst)); + return true; + } + if (!alloc_bitmap(engine, dst, src->w, src->h, false)) + return false; dst->left = src->left; - dst->top = src->top; + dst->top = src->top; memcpy(dst->buffer, src->buffer, src->stride * src->h); - return dst; + return true; } -Bitmap *outline_to_bitmap(ASS_Renderer *render_priv, - ASS_Outline *outline1, ASS_Outline *outline2, - int bord) +bool outline_to_bitmap(ASS_Renderer *render_priv, Bitmap *bm, + ASS_Outline *outline1, ASS_Outline *outline2) { RasterizerData *rst = &render_priv->rasterizer; if (outline1 && !rasterizer_set_outline(rst, outline1, false)) { ass_msg(render_priv->library, MSGL_WARN, "Failed to process glyph outline!\n"); - return NULL; + return false; } if (outline2 && !rasterizer_set_outline(rst, outline2, !!outline1)) { ass_msg(render_priv->library, MSGL_WARN, "Failed to process glyph outline!\n"); - return NULL; + return false; } - if (rst->bbox.x_min > rst->bbox.x_max || rst->bbox.y_min > rst->bbox.y_max) - return NULL; - - if (bord < 0 || bord > INT_MAX / 2) - return NULL; - if (rst->bbox.x_max > INT_MAX - 63 || rst->bbox.y_max > INT_MAX - 63) - return NULL; + return false; - int x_min = rst->bbox.x_min >> 6; - int y_min = rst->bbox.y_min >> 6; - int x_max = (rst->bbox.x_max + 63) >> 6; - int y_max = (rst->bbox.y_max + 63) >> 6; - int w = x_max - x_min; - int h = y_max - y_min; + // enlarge by 1/64th of pixel to bypass slow rasterizer path, add 1 pixel for shift_bitmap + int32_t x_min = (rst->bbox.x_min - 1) >> 6; + int32_t y_min = (rst->bbox.y_min - 1) >> 6; + int32_t x_max = (rst->bbox.x_max + 127) >> 6; + int32_t y_max = (rst->bbox.y_max + 127) >> 6; + int32_t w = x_max - x_min; + int32_t h = y_max - y_min; int mask = (1 << render_priv->engine->tile_order) - 1; - if (w < 0 || h < 0 || - w > INT_MAX - (2 * bord + mask) || h > INT_MAX - (2 * bord + mask)) { - ass_msg(render_priv->library, MSGL_WARN, "Glyph bounding box too large: %dx%dpx", - w, h); - return NULL; + // XXX: is that possible to trigger at all? + if (w < 0 || h < 0 || w > INT_MAX - mask || h > INT_MAX - mask) { + ass_msg(render_priv->library, MSGL_WARN, + "Glyph bounding box too large: %dx%dpx", w, h); + return false; } - int tile_w = (w + 2 * bord + mask) & ~mask; - int tile_h = (h + 2 * bord + mask) & ~mask; - Bitmap *bm = alloc_bitmap(render_priv->engine, tile_w, tile_h, false); - if (!bm) - return NULL; - bm->left = x_min - bord; - bm->top = y_min - bord; + int32_t tile_w = (w + mask) & ~mask; + int32_t tile_h = (h + mask) & ~mask; + if (!alloc_bitmap(render_priv->engine, bm, tile_w, tile_h, false)) + return false; + bm->left = x_min; + bm->top = y_min; if (!rasterizer_fill(render_priv->engine, rst, bm->buffer, - x_min - bord, y_min - bord, - bm->stride, tile_h, bm->stride)) { + x_min, y_min, bm->stride, tile_h, bm->stride)) { ass_msg(render_priv->library, MSGL_WARN, "Failed to rasterize glyph!\n"); ass_free_bitmap(bm); - return NULL; + return false; } - return bm; + return true; } /** diff --git a/libass/ass_bitmap.h b/libass/ass_bitmap.h index 8df445c..e3efbf7 100644 --- a/libass/ass_bitmap.h +++ b/libass/ass_bitmap.h @@ -96,14 +96,13 @@ typedef struct { uint8_t *buffer; // h * stride buffer } Bitmap; -Bitmap *alloc_bitmap(const BitmapEngine *engine, int32_t w, int32_t h, bool zero); +bool alloc_bitmap(const BitmapEngine *engine, Bitmap *bm, int32_t w, int32_t h, bool zero); bool realloc_bitmap(const BitmapEngine *engine, Bitmap *bm, int32_t w, int32_t h); -Bitmap *copy_bitmap(const BitmapEngine *engine, const Bitmap *src); +bool copy_bitmap(const BitmapEngine *engine, Bitmap *dst, const Bitmap *src); void ass_free_bitmap(Bitmap *bm); -Bitmap *outline_to_bitmap(ASS_Renderer *render_priv, - ASS_Outline *outline1, ASS_Outline *outline2, - int bord); +bool outline_to_bitmap(ASS_Renderer *render_priv, Bitmap *bm, + ASS_Outline *outline1, ASS_Outline *outline2); void ass_synth_blur(const BitmapEngine *engine, int opaque_box, int be, double blur_radius, Bitmap *bm_g, Bitmap *bm_o); diff --git a/libass/ass_cache.c b/libass/ass_cache.c index 1bff578..d5106df 100644 --- a/libass/ass_cache.c +++ b/libass/ass_cache.c @@ -104,9 +104,8 @@ static bool bitmap_key_move(void *dst, void *src) static void bitmap_destruct(void *key, void *value) { - BitmapHashValue *v = value; BitmapHashKey *k = key; - ass_free_bitmap(v->bm); + ass_free_bitmap(value); ass_cache_dec_ref(k->outline); } @@ -119,7 +118,7 @@ const CacheDesc bitmap_cache_desc = { .construct_func = ass_bitmap_construct, .destruct_func = bitmap_destruct, .key_size = sizeof(BitmapHashKey), - .value_size = sizeof(BitmapHashValue) + .value_size = sizeof(Bitmap) }; @@ -155,8 +154,8 @@ static bool composite_key_move(void *dst, void *src) } CompositeHashKey *k = src; for (size_t i = 0; i < k->bitmap_count; i++) { - ass_cache_dec_ref(k->bitmaps[i].image); - ass_cache_dec_ref(k->bitmaps[i].image_o); + ass_cache_dec_ref(k->bitmaps[i].bm); + ass_cache_dec_ref(k->bitmaps[i].bm_o); } free(k->bitmaps); return true; @@ -166,12 +165,12 @@ static void composite_destruct(void *key, void *value) { CompositeHashValue *v = value; CompositeHashKey *k = key; - ass_free_bitmap(v->bm); - ass_free_bitmap(v->bm_o); - ass_free_bitmap(v->bm_s); + ass_free_bitmap(&v->bm); + ass_free_bitmap(&v->bm_o); + ass_free_bitmap(&v->bm_s); for (size_t i = 0; i < k->bitmap_count; i++) { - ass_cache_dec_ref(k->bitmaps[i].image); - ass_cache_dec_ref(k->bitmaps[i].image_o); + ass_cache_dec_ref(k->bitmaps[i].bm); + ass_cache_dec_ref(k->bitmaps[i].bm_o); } free(k->bitmaps); } diff --git a/libass/ass_cache.h b/libass/ass_cache.h index 80f9b5c..bb2206d 100644 --- a/libass/ass_cache.h +++ b/libass/ass_cache.h @@ -30,13 +30,7 @@ typedef struct cache Cache; // cache values typedef struct { - Bitmap *bm; // the actual bitmap -} BitmapHashValue; - -typedef struct { - Bitmap *bm; - Bitmap *bm_o; - Bitmap *bm_s; + Bitmap bm, bm_o, bm_s; } CompositeHashValue; typedef struct { diff --git a/libass/ass_cache_template.h b/libass/ass_cache_template.h index 5de492c..4bc6a90 100644 --- a/libass/ass_cache_template.h +++ b/libass/ass_cache_template.h @@ -103,8 +103,8 @@ END(FilterDesc) // describes glyph bitmap reference START(bitmap_ref, bitmap_ref_key) - GENERIC(BitmapHashValue *, image) - GENERIC(BitmapHashValue *, image_o) + GENERIC(Bitmap *, bm) + GENERIC(Bitmap *, bm_o) VECTOR(pos) VECTOR(pos_o) END(BitmapRef) diff --git a/libass/ass_render.c b/libass/ass_render.c index 8dc1a1d..468c184 100644 --- a/libass/ass_render.c +++ b/libass/ass_render.c @@ -622,9 +622,9 @@ static void restore_transform(double m[3][3], const BitmapHashKey *key) } // Calculate bitmap memory footprint -static inline size_t bitmap_size(Bitmap *bm) +static inline size_t bitmap_size(const Bitmap *bm) { - return bm ? sizeof(Bitmap) + bm->stride * bm->h : 0; + return bm->stride * bm->h; } /** @@ -657,12 +657,11 @@ static void blend_vector_clip(ASS_Renderer *render_priv, ASS_Image *head) ass_cache_dec_ref(key.outline); return; } - BitmapHashValue *val = ass_cache_get(render_priv->cache.bitmap_cache, &key, render_priv); - if (!val || !val->bm) { - ass_cache_dec_ref(val); + Bitmap *clip_bm = ass_cache_get(render_priv->cache.bitmap_cache, &key, render_priv); + if (!clip_bm || !clip_bm->buffer) { + ass_cache_dec_ref(clip_bm); return; } - Bitmap *clip_bm = val->bm; // Iterate through bitmaps and blend/clip them for (ASS_Image *cur = head; cur; cur = cur->next) { @@ -747,7 +746,7 @@ static void blend_vector_clip(ASS_Renderer *render_priv, ASS_Image *head) priv->source = NULL; } - ass_cache_dec_ref(val); + ass_cache_dec_ref(clip_bm); } /** @@ -1293,7 +1292,7 @@ static void calc_transform_matrix(ASS_Renderer *render_priv, * Tries to get glyph bitmaps from bitmap cache. * If they can't be found, they are generated by rotating and rendering the glyph. * After that, bitmaps are added to the cache. - * They are returned in info->image (glyph), info->image_o (outline). + * They are returned in info->bm (glyph), info->bm_o (outline). */ static void get_bitmap_glyph(ASS_Renderer *render_priv, GlyphInfo *info, @@ -1320,7 +1319,11 @@ get_bitmap_glyph(ASS_Renderer *render_priv, GlyphInfo *info, ass_cache_dec_ref(info->outline); return; } - info->image = ass_cache_get(render_priv->cache.bitmap_cache, &key, render_priv); + info->bm = ass_cache_get(render_priv->cache.bitmap_cache, &key, render_priv); + if (!info->bm || !info->bm->buffer) { + ass_cache_dec_ref(info->bm); + info->bm = NULL; + } *pos_o = *pos; OutlineHashKey ol_key; @@ -1424,15 +1427,20 @@ get_bitmap_glyph(ASS_Renderer *render_priv, GlyphInfo *info, ass_cache_dec_ref(key.outline); return; } - info->image_o = ass_cache_get(render_priv->cache.bitmap_cache, &key, render_priv); + info->bm_o = ass_cache_get(render_priv->cache.bitmap_cache, &key, render_priv); + if (!info->bm_o || !info->bm_o->buffer) { + ass_cache_dec_ref(info->bm_o); + info->bm_o = NULL; + *pos_o = *pos; + } else if (!info->bm) + *pos = *pos_o; } size_t ass_bitmap_construct(void *key, void *value, void *priv) { ASS_Renderer *render_priv = priv; BitmapHashKey *k = key; - BitmapHashValue *v = value; - v->bm = NULL; + Bitmap *bm = value; double m[3][3]; restore_transform(m, k); @@ -1454,11 +1462,12 @@ size_t ass_bitmap_construct(void *key, void *value, void *priv) } } - v->bm = outline_to_bitmap(render_priv, &outline[0], &outline[1], 1); + if (!outline_to_bitmap(render_priv, bm, &outline[0], &outline[1])) + memset(bm, 0, sizeof(*bm)); outline_free(&outline[0]); outline_free(&outline[1]); - return bitmap_size(v->bm) + sizeof(BitmapHashKey) + sizeof(BitmapHashValue); + return sizeof(BitmapHashKey) + sizeof(Bitmap) + bitmap_size(bm); } /** @@ -1831,36 +1840,38 @@ static bool is_new_bm_run(GlyphInfo *info, GlyphInfo *last) static void make_shadow_bitmap(ASS_Renderer *render_priv, CompositeHashValue *val, const FilterDesc *filter) { + Bitmap *bm = &val->bm, *bm_o = &val->bm_o, *bm_s = &val->bm_s; + if (!(filter->flags & FILTER_NONZERO_SHADOW)) { - if (val->bm && val->bm_o && !(filter->flags & FILTER_BORDER_STYLE_3)) { - fix_outline(val->bm, val->bm_o); - } else if (val->bm_o && !(filter->flags & FILTER_NONZERO_BORDER)) { - ass_free_bitmap(val->bm_o); - val->bm_o = NULL; + if (bm->buffer && bm_o->buffer && !(filter->flags & FILTER_BORDER_STYLE_3)) { + fix_outline(bm, bm_o); + } else if (bm_o->buffer && !(filter->flags & FILTER_NONZERO_BORDER)) { + ass_free_bitmap(bm_o); + memset(bm_o, 0, sizeof(*bm_o)); } return; } // Create shadow and fix outline as needed - if (val->bm && val->bm_o && !(filter->flags & FILTER_BORDER_STYLE_3)) { - val->bm_s = copy_bitmap(render_priv->engine, val->bm_o); - fix_outline(val->bm, val->bm_o); - } else if (val->bm_o && (filter->flags & FILTER_NONZERO_BORDER)) { - val->bm_s = copy_bitmap(render_priv->engine, val->bm_o); - } else if (val->bm_o) { - val->bm_s = val->bm_o; - val->bm_o = NULL; - } else if (val->bm) - val->bm_s = copy_bitmap(render_priv->engine, val->bm); - - if (!val->bm_s) + if (bm->buffer && bm_o->buffer && !(filter->flags & FILTER_BORDER_STYLE_3)) { + copy_bitmap(render_priv->engine, bm_s, bm_o); + fix_outline(bm, bm_o); + } else if (bm_o->buffer && (filter->flags & FILTER_NONZERO_BORDER)) { + copy_bitmap(render_priv->engine, bm_s, bm_o); + } else if (bm_o->buffer) { + *bm_s = *bm_o; + memset(bm_o, 0, sizeof(*bm_o)); + } else if (bm->buffer) + copy_bitmap(render_priv->engine, bm_s, bm); + + if (!bm_s->buffer) return; // Works right even for negative offsets // '>>' rounds toward negative infinity, '&' returns correct remainder - val->bm_s->left += filter->shadow.x >> 6; - val->bm_s->top += filter->shadow.y >> 6; - shift_bitmap(val->bm_s, filter->shadow.x & SUBPIXEL_MASK, filter->shadow.y & SUBPIXEL_MASK); + bm_s->left += filter->shadow.x >> 6; + bm_s->top += filter->shadow.y >> 6; + shift_bitmap(bm_s, filter->shadow.x & SUBPIXEL_MASK, filter->shadow.y & SUBPIXEL_MASK); } // Parse event text. @@ -2214,8 +2225,8 @@ static void render_and_combine_glyphs(ASS_Renderer *render_priv, if (nb_bitmaps >= text_info->max_bitmaps) { size_t new_size = 2 * text_info->max_bitmaps; if (!ASS_REALLOC_ARRAY(text_info->combined_bitmaps, new_size)) { - ass_cache_dec_ref(info->image); - ass_cache_dec_ref(info->image_o); + ass_cache_dec_ref(info->bm); + ass_cache_dec_ref(info->bm_o); continue; } text_info->max_bitmaps = new_size; @@ -2252,8 +2263,8 @@ static void render_and_combine_glyphs(ASS_Renderer *render_priv, current_info->bitmap_count = current_info->max_bitmap_count = 0; current_info->bitmaps = malloc(MAX_SUB_BITMAPS_INITIAL * sizeof(BitmapRef)); if (!current_info->bitmaps) { - ass_cache_dec_ref(info->image); - ass_cache_dec_ref(info->image_o); + ass_cache_dec_ref(info->bm); + ass_cache_dec_ref(info->bm_o); continue; } current_info->max_bitmap_count = MAX_SUB_BITMAPS_INITIAL; @@ -2262,23 +2273,23 @@ static void render_and_combine_glyphs(ASS_Renderer *render_priv, } last_info = info; - if (!info->image || !current_info) { - ass_cache_dec_ref(info->image); - ass_cache_dec_ref(info->image_o); + if (!current_info || (!info->bm && !info->bm_o)) { + ass_cache_dec_ref(info->bm); + ass_cache_dec_ref(info->bm_o); continue; } if (current_info->bitmap_count >= current_info->max_bitmap_count) { size_t new_size = 2 * current_info->max_bitmap_count; if (!ASS_REALLOC_ARRAY(current_info->bitmaps, new_size)) { - ass_cache_dec_ref(info->image); - ass_cache_dec_ref(info->image_o); + ass_cache_dec_ref(info->bm); + ass_cache_dec_ref(info->bm_o); continue; } current_info->max_bitmap_count = new_size; } - current_info->bitmaps[current_info->bitmap_count].image = info->image; - current_info->bitmaps[current_info->bitmap_count].image_o = info->image_o; + current_info->bitmaps[current_info->bitmap_count].bm = info->bm; + current_info->bitmaps[current_info->bitmap_count].bm_o = info->bm_o; current_info->bitmaps[current_info->bitmap_count].pos = pos; current_info->bitmaps[current_info->bitmap_count].pos_o = pos_o; current_info->bitmap_count++; @@ -2305,9 +2316,12 @@ static void render_and_combine_glyphs(ASS_Renderer *render_priv, if (!val) continue; - info->bm = val->bm; - info->bm_o = val->bm_o; - info->bm_s = val->bm_s; + if (val->bm.buffer) + info->bm = &val->bm; + if (val->bm_o.buffer) + info->bm_o = &val->bm_o; + if (val->bm_s.buffer) + info->bm_s = &val->bm_s; info->image = val; continue; } @@ -2327,7 +2341,7 @@ size_t ass_composite_construct(void *key, void *value, void *priv) ASS_Renderer *render_priv = priv; CompositeHashKey *k = key; CompositeHashValue *v = value; - v->bm = v->bm_o = v->bm_s = NULL; + memset(v, 0, sizeof(*v)); ASS_Rect rect, rect_o; rectangle_reset(&rect); @@ -2337,13 +2351,13 @@ size_t ass_composite_construct(void *key, void *value, void *priv) BitmapRef *last = NULL, *last_o = NULL; for (int i = 0; i < k->bitmap_count; i++) { BitmapRef *ref = &k->bitmaps[i]; - if (ref->image && ref->image->bm) { - rectangle_combine(&rect, ref->image->bm, ref->pos); + if (ref->bm) { + rectangle_combine(&rect, ref->bm, ref->pos); last = ref; n_bm++; } - if (ref->image_o && ref->image_o->bm) { - rectangle_combine(&rect_o, ref->image_o->bm, ref->pos_o); + if (ref->bm_o) { + rectangle_combine(&rect_o, ref->bm_o, ref->pos_o); last_o = ref; n_bm_o++; } @@ -2351,77 +2365,65 @@ size_t ass_composite_construct(void *key, void *value, void *priv) int bord = be_padding(k->filter.be); if (!bord && n_bm == 1) { - v->bm = copy_bitmap(render_priv->engine, last->image->bm); - if (v->bm) { - v->bm->left += last->pos.x; - v->bm->top += last->pos.y; - } - } else if (n_bm) { - v->bm = alloc_bitmap(render_priv->engine, - rect.x_max - rect.x_min + 2 * bord, - rect.y_max - rect.y_min + 2 * bord, true); - Bitmap *dst = v->bm; - if (dst) { - dst->left = rect.x_min - bord; - dst->top = rect.y_min - bord; - for (int i = 0; i < k->bitmap_count; i++) { - if (!k->bitmaps[i].image) - continue; - Bitmap *src = k->bitmaps[i].image->bm; - if (!src) - continue; - int x = k->bitmaps[i].pos.x + src->left - dst->left; - int y = k->bitmaps[i].pos.y + src->top - dst->top; - assert(x >= 0 && x + src->w <= dst->w); - assert(y >= 0 && y + src->h <= dst->h); - unsigned char *buf = dst->buffer + y * dst->stride + x; - render_priv->engine->add_bitmaps(buf, dst->stride, - src->buffer, src->stride, - src->h, src->w); - } + copy_bitmap(render_priv->engine, &v->bm, last->bm); + v->bm.left += last->pos.x; + v->bm.top += last->pos.y; + } else if (n_bm && alloc_bitmap(render_priv->engine, &v->bm, + rect.x_max - rect.x_min + 2 * bord, + rect.y_max - rect.y_min + 2 * bord, + true)) { + Bitmap *dst = &v->bm; + dst->left = rect.x_min - bord; + dst->top = rect.y_min - bord; + for (int i = 0; i < k->bitmap_count; i++) { + Bitmap *src = k->bitmaps[i].bm; + if (!src) + continue; + int x = k->bitmaps[i].pos.x + src->left - dst->left; + int y = k->bitmaps[i].pos.y + src->top - dst->top; + assert(x >= 0 && x + src->w <= dst->w); + assert(y >= 0 && y + src->h <= dst->h); + unsigned char *buf = dst->buffer + y * dst->stride + x; + render_priv->engine->add_bitmaps(buf, dst->stride, + src->buffer, src->stride, + src->h, src->w); } } if (!bord && n_bm_o == 1) { - v->bm_o = copy_bitmap(render_priv->engine, last_o->image_o->bm); - if (v->bm_o) { - v->bm_o->left += last_o->pos_o.x; - v->bm_o->top += last_o->pos_o.y; - } - } else if (n_bm_o) { - v->bm_o = alloc_bitmap(render_priv->engine, - rect_o.x_max - rect_o.x_min + 2 * bord, - rect_o.y_max - rect_o.y_min + 2 * bord, true); - Bitmap *dst = v->bm_o; - if (dst) { - dst->left = rect_o.x_min - bord; - dst->top = rect_o.y_min - bord; - for (int i = 0; i < k->bitmap_count; i++) { - if (!k->bitmaps[i].image_o) - continue; - Bitmap *src = k->bitmaps[i].image_o->bm; - if (!src) - continue; - int x = k->bitmaps[i].pos_o.x + src->left - dst->left; - int y = k->bitmaps[i].pos_o.y + src->top - dst->top; - assert(x >= 0 && x + src->w <= dst->w); - assert(y >= 0 && y + src->h <= dst->h); - unsigned char *buf = dst->buffer + y * dst->stride + x; - render_priv->engine->add_bitmaps(buf, dst->stride, - src->buffer, src->stride, - src->h, src->w); - } + copy_bitmap(render_priv->engine, &v->bm_o, last_o->bm_o); + v->bm_o.left += last_o->pos_o.x; + v->bm_o.top += last_o->pos_o.y; + } else if (n_bm_o && alloc_bitmap(render_priv->engine, &v->bm_o, + rect_o.x_max - rect_o.x_min + 2 * bord, + rect_o.y_max - rect_o.y_min + 2 * bord, + true)) { + Bitmap *dst = &v->bm_o; + dst->left = rect_o.x_min - bord; + dst->top = rect_o.y_min - bord; + for (int i = 0; i < k->bitmap_count; i++) { + Bitmap *src = k->bitmaps[i].bm_o; + if (!src) + continue; + int x = k->bitmaps[i].pos_o.x + src->left - dst->left; + int y = k->bitmaps[i].pos_o.y + src->top - dst->top; + assert(x >= 0 && x + src->w <= dst->w); + assert(y >= 0 && y + src->h <= dst->h); + unsigned char *buf = dst->buffer + y * dst->stride + x; + render_priv->engine->add_bitmaps(buf, dst->stride, + src->buffer, src->stride, + src->h, src->w); } } - if (v->bm || v->bm_o) { + if (v->bm.buffer || v->bm_o.buffer) { ass_synth_blur(render_priv->engine, k->filter.flags & FILTER_BORDER_STYLE_3, - k->filter.be, k->filter.blur, v->bm, v->bm_o); + k->filter.be, k->filter.blur, &v->bm, &v->bm_o); if (k->filter.flags & FILTER_DRAW_SHADOW) make_shadow_bitmap(render_priv, v, &k->filter); } - return bitmap_size(v->bm) + bitmap_size(v->bm_o) + bitmap_size(v->bm_s) + - sizeof(CompositeHashKey) + sizeof(CompositeHashValue); + return sizeof(CompositeHashKey) + sizeof(CompositeHashValue) + + bitmap_size(&v->bm) + bitmap_size(&v->bm_o) + bitmap_size(&v->bm_s); } static void add_background(ASS_Renderer *render_priv, EventImages *event_images) diff --git a/libass/ass_render.h b/libass/ass_render.h index af06e99..e654a94 100644 --- a/libass/ass_render.h +++ b/libass/ass_render.h @@ -171,7 +171,7 @@ typedef struct glyph_info { int shape_run_id; ASS_Vector shift; - BitmapHashValue *image, *image_o; + Bitmap *bm, *bm_o; // next glyph in this cluster struct glyph_info *next; -- cgit v1.2.3