summaryrefslogtreecommitdiffstats
path: root/libass
diff options
context:
space:
mode:
authorDr.Smile <vabnick@gmail.com>2018-12-02 23:26:08 +0300
committerDr.Smile <vabnick@gmail.com>2019-05-20 01:09:11 +0300
commit4c45b6f79fcdd82b30ecc55df6572776a051d363 (patch)
tree280b64289a6c8fd8b6e79976318de6d3dd7b97b3 /libass
parent891ada89c9cb91c468ea6e829ed9760d11cabf85 (diff)
downloadlibass-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.c43
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);