]> granicus.if.org Git - libass/commitdiff
renderer: fix handling of empty outlines
authorDr.Smile <vabnick@gmail.com>
Sat, 8 Apr 2017 17:55:41 +0000 (20:55 +0300)
committerDr.Smile <vabnick@gmail.com>
Mon, 31 Jul 2017 03:27:24 +0000 (06:27 +0300)
libass/ass_bitmap.c
libass/ass_bitmap.h
libass/ass_cache.h
libass/ass_render.c

index f369e25bccc87a940617da521d2a6350a91cf97a..7d991bfc696131b80fd57a3da521676dec08754d 100644 (file)
@@ -202,15 +202,6 @@ Bitmap *outline_to_bitmap(ASS_Renderer *render_priv,
 
     if (bord < 0 || bord > INT_MAX / 2)
         return NULL;
-
-    if (rst->x_min >= rst->x_max || rst->y_min >= rst->y_max) {
-        Bitmap *bm = alloc_bitmap(render_priv->engine, 2 * bord, 2 * bord, true);
-        if (!bm)
-            return NULL;
-        bm->left = bm->top = -bord;
-        return bm;
-    }
-
     if (rst->x_max > INT_MAX - 63 || rst->y_max > INT_MAX - 63)
         return NULL;
 
@@ -443,9 +434,9 @@ int be_padding(int be)
     return FFMAX(128 - be, 0);
 }
 
-int outline_to_bitmap2(ASS_Renderer *render_priv, ASS_Outline *outline,
-                       ASS_Outline *border1, ASS_Outline *border2,
-                       Bitmap **bm_g, Bitmap **bm_o)
+bool outline_to_bitmap2(ASS_Renderer *render_priv, ASS_Outline *outline,
+                        ASS_Outline *border1, ASS_Outline *border2,
+                        Bitmap **bm_g, Bitmap **bm_o)
 {
     assert(bm_g && bm_o);
     *bm_g = *bm_o = NULL;
@@ -457,19 +448,20 @@ int outline_to_bitmap2(ASS_Renderer *render_priv, ASS_Outline *outline,
     if (border2 && !border2->n_points)
         border2 = NULL;
 
-    if (outline)
+    if (outline) {
         *bm_g = outline_to_bitmap(render_priv, outline, NULL, 1);
-    if (!*bm_g)
-        return 1;
+        if (!*bm_g)
+            return false;
+    }
 
     if (border1 || border2) {
         *bm_o = outline_to_bitmap(render_priv, border1, border2, 1);
         if (!*bm_o) {
-            return 1;
+            return false;
         }
     }
 
-    return 0;
+    return true;
 }
 
 /**
index 04cb51b4d1a13a449486eb433e21fff844e01be7..8dc1b19c83dd0645f71393f4fc201197350efb4a 100644 (file)
@@ -117,9 +117,9 @@ void ass_synth_blur(const BitmapEngine *engine, int opaque_box, int be,
  * \param bm_g out: pointer to the bitmap of original glyph is returned here
  * \param bm_o out: pointer to the bitmap of border glyph is returned here
  */
-int outline_to_bitmap2(ASS_Renderer *render_priv, ASS_Outline *outline,
-                       ASS_Outline *border1, ASS_Outline *border2,
-                       Bitmap **bm_g, Bitmap **bm_o);
+bool outline_to_bitmap2(ASS_Renderer *render_priv, ASS_Outline *outline,
+                        ASS_Outline *border1, ASS_Outline *border2,
+                        Bitmap **bm_g, Bitmap **bm_o);
 
 int be_padding(int be);
 void be_blur_pre(uint8_t *buf, intptr_t w,
index 64751df915d8168f8dcbde08ad4395fa6d602280..03e58c76f21253b37092e1b3d8737ab3c43f6361 100644 (file)
@@ -30,6 +30,7 @@ typedef struct cache Cache;
 // cache values
 
 typedef struct {
+    bool valid;
     Bitmap *bm;               // the actual bitmaps
     Bitmap *bm_o;
 } BitmapHashValue;
@@ -41,6 +42,7 @@ typedef struct {
 } CompositeHashValue;
 
 typedef struct {
+    bool valid;
     ASS_Outline outline;
     ASS_Outline border[2];
     FT_BBox bbox_scaled;        // bbox after scaling, but before rotation
index 7e8f6348f0642b6401d01e47d55c50fb8c5b1847..1369a828a28a07a2410e9784675685d9aabf8fd1 100644 (file)
@@ -1030,12 +1030,12 @@ get_outline_glyph(ASS_Renderer *priv, GlyphInfo *info)
         if (info->drawing) {
             ASS_Drawing *drawing = info->drawing;
             ass_drawing_hash(drawing);
-            if(!ass_drawing_parse(drawing, 0)) {
+            if(!ass_drawing_parse(drawing, 0) ||
+                    !outline_copy(&val->outline, &drawing->outline)) {
                 ass_cache_commit(val, 1);
                 ass_cache_dec_ref(val);
                 return;
             }
-            outline_copy(&val->outline, &drawing->outline);
             val->advance.x = drawing->advance.x;
             val->advance.y = drawing->advance.y;
             val->asc = drawing->asc;
@@ -1050,7 +1050,12 @@ get_outline_glyph(ASS_Renderer *priv, GlyphInfo *info)
                         info->symbol, info->face_index, info->glyph_index,
                         priv->settings.hinting, info->flags);
             if (glyph != NULL) {
-                outline_convert(&val->outline, &((FT_OutlineGlyph) glyph)->outline);
+                FT_Outline *src = &((FT_OutlineGlyph) glyph)->outline;
+                if (!outline_convert(&val->outline, src)) {
+                    ass_cache_commit(val, 1);
+                    ass_cache_dec_ref(val);
+                    return;
+                }
                 if (priv->settings.shaper == ASS_SHAPING_SIMPLE) {
                     val->advance.x = d16_to_d6(glyph->advance.x);
                     val->advance.y = d16_to_d6(glyph->advance.y);
@@ -1062,12 +1067,7 @@ get_outline_glyph(ASS_Renderer *priv, GlyphInfo *info)
                 val->desc *= info->scale_y;
             }
         }
-
-        if (!val->outline.n_points) {
-            ass_cache_commit(val, 1);
-            ass_cache_dec_ref(val);
-            return;
-        }
+        val->valid = true;
 
         outline_get_cbox(&val->outline, &val->bbox_scaled);
 
@@ -1082,7 +1082,7 @@ get_outline_glyph(ASS_Renderer *priv, GlyphInfo *info)
                             double_to_d6(info->border_x * priv->border_scale),
                             double_to_d6(info->border_y * priv->border_scale));
 
-        } else if ((info->border_x > 0 || info->border_y > 0)
+        } else if (val->outline.n_points && (info->border_x > 0 || info->border_y > 0)
                 && double_to_d6(info->scale_x) && double_to_d6(info->scale_y)) {
             const int eps = 16;
             int xbord = double_to_d6(info->border_x * priv->border_scale);
@@ -1101,9 +1101,7 @@ get_outline_glyph(ASS_Renderer *priv, GlyphInfo *info)
         }
 
         ass_cache_commit(val, 1);
-    }
-
-    if (!val->outline.n_points) {
+    } else if (!val->valid) {
         ass_cache_dec_ref(val);
         return;
     }
@@ -1209,10 +1207,21 @@ get_bitmap_glyph(ASS_Renderer *render_priv, GlyphInfo *info)
     OutlineBitmapHashKey *key = &info->hash_key.u.outline;
     if (ass_cache_get(render_priv->cache.bitmap_cache, &info->hash_key, &val)) {
         info->image = val;
+        if (!val->valid)
+            info->symbol = 0;
         return;
     }
-    if (!val)
+    if (!val) {
+        info->symbol = 0;
         return;
+    }
+    if (!info->outline) {
+        memset(val, 0, sizeof(*val));
+        ass_cache_commit(val, sizeof(BitmapHashKey) + sizeof(BitmapHashValue));
+        info->image = val;
+        info->symbol = 0;
+        return;
+    }
 
     const int n_outlines = 3;
     ASS_Outline outline[n_outlines];
@@ -1244,10 +1253,10 @@ get_bitmap_glyph(ASS_Renderer *render_priv, GlyphInfo *info)
         outline_translate(&outline[i], key->advance.x, -key->advance.y);
 
     // render glyph
-    int error = outline_to_bitmap2(render_priv,
-                                   &outline[0], &outline[1], &outline[2],
-                                   &val->bm, &val->bm_o);
-    if (error)
+    val->valid = outline_to_bitmap2(render_priv,
+                                    &outline[0], &outline[1], &outline[2],
+                                    &val->bm, &val->bm_o);
+    if (!val->valid)
         info->symbol = 0;
 
     ass_cache_commit(val, bitmap_size(val->bm) + bitmap_size(val->bm_o) +