]> granicus.if.org Git - libass/commitdiff
bitmap: remove level of indirection in bitmap functions
authorDr.Smile <vabnick@gmail.com>
Thu, 3 May 2018 00:09:52 +0000 (03:09 +0300)
committerDr.Smile <vabnick@gmail.com>
Sun, 19 May 2019 22:01:40 +0000 (01:01 +0300)
This allows to use Bitmap struct directly as cache value
and to remove bunch of unnecessary allocations.

libass/ass_bitmap.c
libass/ass_bitmap.h
libass/ass_cache.c
libass/ass_cache.h
libass/ass_cache_template.h
libass/ass_render.c
libass/ass_render.h

index a7b80026c54820ef850d1eceaa8919321164f571..b489d8593ffcf5a6a630dc2d8b3dc95697b3db14 100644 (file)
 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;
 }
 
 /**
index 8df445c3cc51354dfe856e5e3cfa4209c3cc7cc0..e3efbf7b377e613ef5feaad94e8f776baaa0c1fc 100644 (file)
@@ -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);
index 1bff578ea5d94ae76d5f2dcae96cdce8b8be39e7..d5106df9de89ba882afea244b90be728f2d03287 100644 (file)
@@ -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);
 }
index 80f9b5c6ea5debd26c1fd478f7c836c41a8ac98c..bb2206d89e723b8d2d7aac0db49bbd9288133c47 100644 (file)
@@ -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 {
index 5de492cfa78956fca0be9c9991f0da3a407382de..4bc6a90d26929cc53b34c19417d1b56c22fb2e6a 100644 (file)
@@ -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)
index 8dc1a1d8007440e6bb99d95da763b82f4f00fb20..468c1842b9bf17485bdb56660a63c12213adb37d 100644 (file)
@@ -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)
index af06e99a3de6d541ba3ce3efa039572007e5ed5b..e654a94d880639d933ce9aa19c34cea1418f6a54 100644 (file)
@@ -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;