summaryrefslogtreecommitdiffstats
path: root/libass
diff options
context:
space:
mode:
authorDr.Smile <vabnick@gmail.com>2018-05-03 03:09:52 +0300
committerDr.Smile <vabnick@gmail.com>2019-05-20 01:01:40 +0300
commit4293dc36c1fc3a39731e328ab76af920512c888f (patch)
tree044859400d0135018283eac81bf5cee07ab1b685 /libass
parent2beae658967f44c51e272749fd8811b9569d41ac (diff)
downloadlibass-4293dc36c1fc3a39731e328ab76af920512c888f.tar.bz2
libass-4293dc36c1fc3a39731e328ab76af920512c888f.tar.xz
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.
Diffstat (limited to 'libass')
-rw-r--r--libass/ass_bitmap.c108
-rw-r--r--libass/ass_bitmap.h9
-rw-r--r--libass/ass_cache.c19
-rw-r--r--libass/ass_cache.h8
-rw-r--r--libass/ass_cache_template.h4
-rw-r--r--libass/ass_render.c228
-rw-r--r--libass/ass_render.h2
7 files changed, 176 insertions, 202 deletions
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;