diff options
author | Dr.Smile <vabnick@gmail.com> | 2018-12-02 23:26:08 +0300 |
---|---|---|
committer | Dr.Smile <vabnick@gmail.com> | 2019-05-20 01:09:11 +0300 |
commit | 4c45b6f79fcdd82b30ecc55df6572776a051d363 (patch) | |
tree | 280b64289a6c8fd8b6e79976318de6d3dd7b97b3 /libass | |
parent | 891ada89c9cb91c468ea6e829ed9760d11cabf85 (diff) | |
download | libass-4c45b6f79fcdd82b30ecc55df6572776a051d363.tar.bz2 libass-4c45b6f79fcdd82b30ecc55df6572776a051d363.tar.xz |
renderer: synchronize glyph motion to help composite cache
Slow movement of one glyph looks like periodic jumps by quantization step.
In case of multiple glyphs at different subpixel shifts
jumps of individual glyphs occur at different frames.
That leads to performance penalty due to composite image
regeneration at every such jump.
This commit aligns glyphs in such a way that all jumps coincide
at the same frames, greatly improving performance of \move commands.
That optimization also helps in case of fast motion.
Diffstat (limited to 'libass')
-rw-r--r-- | libass/ass_render.c | 43 |
1 files changed, 29 insertions, 14 deletions
diff --git a/libass/ass_render.c b/libass/ass_render.c index fc66569..af93ba4 100644 --- a/libass/ass_render.c +++ b/libass/ass_render.c @@ -449,6 +449,7 @@ render_glyph(ASS_Renderer *render_priv, Bitmap *bm, int dst_x, int dst_y, } static bool quantize_transform(double m[3][3], ASS_Vector *pos, + ASS_DVector *offset, bool first, BitmapHashKey *key) { // Full transform: @@ -482,9 +483,16 @@ static bool quantize_transform(double m[3][3], ASS_Vector *pos, for (int j = 0; j < 2; j++) m[i][j] -= m[2][j] * center[i]; - int32_t qr[2]; + double delta[2] = {0}; + if (!first) { + delta[0] = offset->x; + delta[1] = offset->y; + } + + int32_t qr[2]; // quantized center position for (int i = 0; i < 2; i++) { center[i] /= 64 >> SUBPIXEL_ORDER; + center[i] -= delta[i]; if (!(fabs(center[i]) < max_val)) return false; qr[i] = lrint(center[i]); @@ -574,6 +582,10 @@ static bool quantize_transform(double m[3][3], ASS_Vector *pos, qm[2][j] = lrint(val); } + if (first && offset) { + offset->x = center[0] - qr[0]; + offset->y = center[1] - qr[1]; + } pos->x = qr[0] >> SUBPIXEL_ORDER; pos->y = qr[1] >> SUBPIXEL_ORDER; key->offset.x = qr[0] & ((1 << SUBPIXEL_ORDER) - 1); @@ -654,7 +666,8 @@ static void blend_vector_clip(ASS_Renderer *render_priv, ASS_Image *head) ASS_Vector pos; BitmapHashKey key; key.outline = ass_cache_get(render_priv->cache.outline_cache, &ol_key, render_priv); - if (!key.outline || !key.outline->valid || !quantize_transform(m, &pos, &key)) { + if (!key.outline || !key.outline->valid || + !quantize_transform(m, &pos, NULL, true, &key)) { ass_cache_dec_ref(key.outline); return; } @@ -1288,7 +1301,8 @@ static void calc_transform_matrix(ASS_Renderer *render_priv, */ static void get_bitmap_glyph(ASS_Renderer *render_priv, GlyphInfo *info, - ASS_Vector *pos, ASS_Vector *pos_o, int flags) + ASS_Vector *pos, ASS_Vector *pos_o, + ASS_DVector *offset, bool first, int flags) { if (!info->outline || info->symbol == '\n' || info->symbol == 0 || info->skip) { ass_cache_dec_ref(info->outline); @@ -1307,7 +1321,7 @@ get_bitmap_glyph(ASS_Renderer *render_priv, GlyphInfo *info, BitmapHashKey key; key.outline = info->outline; - if (!quantize_transform(m, pos, &key)) { + if (!quantize_transform(m, pos, offset, first, &key)) { ass_cache_dec_ref(info->outline); return; } @@ -1424,7 +1438,8 @@ get_bitmap_glyph(ASS_Renderer *render_priv, GlyphInfo *info, } key.outline = ass_cache_get(render_priv->cache.outline_cache, &ol_key, render_priv); - if (!key.outline || !key.outline->valid || !quantize_transform(m, pos_o, &key)) { + if (!key.outline || !key.outline->valid || + !quantize_transform(m, pos_o, offset, false, &key)) { ass_cache_dec_ref(key.outline); return; } @@ -2209,6 +2224,7 @@ static void render_and_combine_glyphs(ASS_Renderer *render_priv, CombinedBitmapInfo *combined_info = text_info->combined_bitmaps; CombinedBitmapInfo *current_info = NULL; GlyphInfo *last_info = NULL; + ASS_DVector offset; for (int i = 0; i < text_info->length; i++) { GlyphInfo *info = text_info->glyphs + i; if (info->linebreak) linebreak = 1; @@ -2230,19 +2246,13 @@ static void render_and_combine_glyphs(ASS_Renderer *render_priv, if (flags == FILTER_NONZERO_SHADOW && (info->c[0] & 0xFF) == 0xFF) flags = 0; - ASS_Vector pos, pos_o; - info->pos.x = double_to_d6(device_x + d6_to_double(info->pos.x) * render_priv->font_scale_x); - info->pos.y = double_to_d6(device_y) + info->pos.y; - get_bitmap_glyph(render_priv, info, &pos, &pos_o, flags); - if (linebreak || is_new_bm_run(info, last_info)) { linebreak = 0; last_info = NULL; 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->bm); - ass_cache_dec_ref(info->bm_o); + ass_cache_dec_ref(info->outline); continue; } text_info->max_bitmaps = new_size; @@ -2277,8 +2287,7 @@ 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->bm); - ass_cache_dec_ref(info->bm_o); + ass_cache_dec_ref(info->outline); continue; } current_info->max_bitmap_count = MAX_SUB_BITMAPS_INITIAL; @@ -2287,6 +2296,12 @@ static void render_and_combine_glyphs(ASS_Renderer *render_priv, } last_info = info; + ASS_Vector pos, pos_o; + info->pos.x = double_to_d6(device_x + d6_to_double(info->pos.x) * render_priv->font_scale_x); + info->pos.y = double_to_d6(device_y) + info->pos.y; + get_bitmap_glyph(render_priv, info, &pos, &pos_o, + &offset, !current_info->bitmap_count, flags); + if (!current_info || (!info->bm && !info->bm_o)) { ass_cache_dec_ref(info->bm); ass_cache_dec_ref(info->bm_o); |