diff options
Diffstat (limited to 'libass/ass_render.c')
-rw-r--r-- | libass/ass_render.c | 228 |
1 files changed, 115 insertions, 113 deletions
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) |