From abfa6cfdb045d16383b72c78b2ee60929c575a87 Mon Sep 17 00:00:00 2001 From: "Dr.Smile" Date: Sat, 8 Apr 2017 20:55:41 +0300 Subject: renderer: fix handling of empty outlines --- libass/ass_bitmap.c | 26 +++++++++----------------- libass/ass_bitmap.h | 6 +++--- libass/ass_cache.h | 2 ++ libass/ass_render.c | 45 +++++++++++++++++++++++++++------------------ 4 files changed, 41 insertions(+), 38 deletions(-) (limited to 'libass') diff --git a/libass/ass_bitmap.c b/libass/ass_bitmap.c index f369e25..7d991bf 100644 --- a/libass/ass_bitmap.c +++ b/libass/ass_bitmap.c @@ -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; } /** diff --git a/libass/ass_bitmap.h b/libass/ass_bitmap.h index 04cb51b..8dc1b19 100644 --- a/libass/ass_bitmap.h +++ b/libass/ass_bitmap.h @@ -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, diff --git a/libass/ass_cache.h b/libass/ass_cache.h index 64751df..03e58c7 100644 --- a/libass/ass_cache.h +++ b/libass/ass_cache.h @@ -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 diff --git a/libass/ass_render.c b/libass/ass_render.c index 7e8f634..1369a82 100644 --- a/libass/ass_render.c +++ b/libass/ass_render.c @@ -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) + -- cgit v1.2.3