diff options
author | Rodger Combs <rodger.combs@gmail.com> | 2014-06-06 15:50:47 -0500 |
---|---|---|
committer | Rodger Combs <rodger.combs@gmail.com> | 2014-07-20 00:05:33 -0500 |
commit | 67966b6f64690dbfb18ea34b99ed8b26c158a2d0 (patch) | |
tree | e824a8827f0809d194389aa20931290b201c7493 | |
parent | 079769c5717278971ba9115cbf074434574dfc75 (diff) | |
download | libass-67966b6f64690dbfb18ea34b99ed8b26c158a2d0.tar.bz2 libass-67966b6f64690dbfb18ea34b99ed8b26c158a2d0.tar.xz |
Render each event on a separate thread using pthreads
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | configure.ac | 12 | ||||
-rw-r--r-- | libass/Makefile.am | 2 | ||||
-rw-r--r-- | libass/ass_bitmap.c | 21 | ||||
-rw-r--r-- | libass/ass_bitmap.h | 8 | ||||
-rw-r--r-- | libass/ass_cache.c | 95 | ||||
-rw-r--r-- | libass/ass_cache.h | 4 | ||||
-rw-r--r-- | libass/ass_font.c | 2 | ||||
-rw-r--r-- | libass/ass_fontconfig.c | 22 | ||||
-rw-r--r-- | libass/ass_library.c | 9 | ||||
-rw-r--r-- | libass/ass_library.h | 11 | ||||
-rw-r--r-- | libass/ass_parse.c | 463 | ||||
-rw-r--r-- | libass/ass_parse.h | 18 | ||||
-rw-r--r-- | libass/ass_render.c | 1028 | ||||
-rw-r--r-- | libass/ass_render.h | 86 | ||||
-rw-r--r-- | libass/ass_render_api.c | 29 | ||||
-rw-r--r-- | libass/ass_shaper.c | 51 | ||||
-rw-r--r-- | libass/ass_shaper.h | 26 | ||||
-rw-r--r-- | libass/stdatomic.h | 367 | ||||
-rw-r--r-- | m4/ax_pthread.m4 | 332 |
20 files changed, 1861 insertions, 726 deletions
@@ -18,4 +18,3 @@ Makefile.in /missing /compile /libass.pc -/m4 diff --git a/configure.ac b/configure.ac index 3d10ef9..e712597 100644 --- a/configure.ac +++ b/configure.ac @@ -51,6 +51,8 @@ AC_ARG_ENABLE([rasterizer], AS_HELP_STRING([--disable-rasterizer], [disable internal rasterizer @<:@default=enabled@:>@])) AC_ARG_ENABLE([large-tiles], AS_HELP_STRING([--enable-large-tiles], [use larger tiles in the rasterizer (better performance, slightly worse quality) @<:@default=disabled@:>@])) +AC_ARG_ENABLE([pthreads], AS_HELP_STRING([--disable-pthreads], + [disable threading support @<:@default=enabled@:>@])) AS_IF([test x$enable_asm != xno], [ AS_CASE([$host], @@ -142,6 +144,16 @@ PKG_CHECK_MODULES([FRIBIDI], fribidi >= 0.19.0, [ AC_DEFINE(CONFIG_FRIBIDI, 1, [found fribidi via pkg-config]) ]) +if test x$enable_pthreads != xno; then +AX_PTHREAD([ + CC="$PTHREAD_CC" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$LIBS $PTHREAD_LIBS" + AC_DEFINE(CONFIG_PTHREAD, 1, [found pthreads via AX_PTHREAD]) + pthread=true + ]) +fi + if test x$enable_fontconfig != xno; then PKG_CHECK_MODULES([FONTCONFIG], fontconfig >= 2.4.2, [ CFLAGS="$CFLAGS $FONTCONFIG_CFLAGS" diff --git a/libass/Makefile.am b/libass/Makefile.am index bc5345b..eee0a90 100644 --- a/libass/Makefile.am +++ b/libass/Makefile.am @@ -1,4 +1,4 @@ -AM_CFLAGS = -std=gnu99 -Wall -Wextra -Wno-sign-compare -Wno-unused-parameter \ +AM_CFLAGS = -std=gnu11 -Wall -Wextra -Wno-sign-compare -Wno-unused-parameter \ -Werror-implicit-function-declaration -Wstrict-prototypes \ -Wpointer-arith -Wredundant-decls diff --git a/libass/ass_bitmap.c b/libass/ass_bitmap.c index a2dc293..178d172 100644 --- a/libass/ass_bitmap.c +++ b/libass/ass_bitmap.c @@ -110,9 +110,9 @@ void resize_tmp(ASS_SynthPriv *priv, int w, int h) ass_aligned_alloc(32, (priv->tmp_w + 1) * priv->tmp_h * sizeof(unsigned)); } -ASS_SynthPriv *ass_synth_init(double radius) +ASS_SynthPriv *ass_synth_init(double radius, unsigned count) { - ASS_SynthPriv *priv = calloc(1, sizeof(ASS_SynthPriv)); + ASS_SynthPriv *priv = calloc(count, sizeof(ASS_SynthPriv)); generate_tables(priv, radius); return priv; } @@ -123,7 +123,6 @@ void ass_synth_done(ASS_SynthPriv *priv) free(priv->g0); free(priv->g); free(priv->gt2); - free(priv); } static Bitmap *alloc_bitmap_raw(int w, int h) @@ -168,10 +167,10 @@ Bitmap *copy_bitmap(const Bitmap *src) #if CONFIG_RASTERIZER -Bitmap *outline_to_bitmap(ASS_Renderer *render_priv, - FT_Outline *outline, int bord) +Bitmap *outline_to_bitmap(ASS_Renderer *render_priv, FT_Outline *outline, + int bord, void *rast) { - ASS_Rasterizer *rst = &render_priv->rasterizer; + ASS_Rasterizer *rst = rast; if (!rasterizer_set_outline(rst, outline)) { ass_msg(render_priv->library, MSGL_WARN, "Failed to process glyph outline!\n"); return NULL; @@ -222,8 +221,8 @@ Bitmap *outline_to_bitmap(ASS_Renderer *render_priv, #else -Bitmap *outline_to_bitmap(ASS_Renderer *render_priv, - FT_Outline *outline, int bord) +Bitmap *outline_to_bitmap(ASS_Renderer *render_priv, FT_Outline *outline, + int bord, void *rast) { Bitmap *bm; int w, h; @@ -566,7 +565,7 @@ void be_blur_c(uint8_t *buf, intptr_t w, int outline_to_bitmap3(ASS_Renderer *render_priv, FT_Outline *outline, FT_Outline *border, Bitmap **bm_g, Bitmap **bm_o, Bitmap **bm_s, int be, double blur_radius, FT_Vector shadow_offset, - int border_style, int border_visible) + int border_style, int border_visible, void *rast) { blur_radius *= 2; int bbord = be > 0 ? sqrt(2 * be) : 0; @@ -580,12 +579,12 @@ int outline_to_bitmap3(ASS_Renderer *render_priv, FT_Outline *outline, FT_Outlin *bm_g = *bm_o = *bm_s = 0; if (outline) - *bm_g = outline_to_bitmap(render_priv, outline, bord); + *bm_g = outline_to_bitmap(render_priv, outline, bord, rast); if (!*bm_g) return 1; if (border) { - *bm_o = outline_to_bitmap(render_priv, border, bord); + *bm_o = outline_to_bitmap(render_priv, border, bord, rast); if (!*bm_o) { return 1; } diff --git a/libass/ass_bitmap.h b/libass/ass_bitmap.h index 852cb0b..5ca62e7 100644 --- a/libass/ass_bitmap.h +++ b/libass/ass_bitmap.h @@ -38,7 +38,7 @@ typedef struct ass_synth_priv { double radius; } ASS_SynthPriv; -ASS_SynthPriv *ass_synth_init(double); +ASS_SynthPriv *ass_synth_init(double radius, unsigned count); void ass_synth_done(ASS_SynthPriv *priv); typedef struct { @@ -48,8 +48,8 @@ typedef struct { unsigned char *buffer; // h * stride buffer } Bitmap; -Bitmap *outline_to_bitmap(ASS_Renderer *render_priv, - FT_Outline *outline, int bord); +Bitmap *outline_to_bitmap(ASS_Renderer *render_priv, FT_Outline *outline, + int bord, void *rast); Bitmap *alloc_bitmap(int w, int h); /** @@ -65,7 +65,7 @@ Bitmap *alloc_bitmap(int w, int h); int outline_to_bitmap3(ASS_Renderer *render_priv, FT_Outline *outline, FT_Outline *border, Bitmap **bm_g, Bitmap **bm_o, Bitmap **bm_s, int be, double blur_radius, FT_Vector shadow_offset, - int border_style, int border_visible); + int border_style, int border_visible, void *rast); void ass_free_bitmap(Bitmap *bm); void ass_gauss_blur(unsigned char *buffer, unsigned *tmp2, diff --git a/libass/ass_cache.c b/libass/ass_cache.c index 6baa924..15a0b6b 100644 --- a/libass/ass_cache.c +++ b/libass/ass_cache.c @@ -209,6 +209,8 @@ struct cache { unsigned hits; unsigned misses; unsigned items; + + CacheItem *add_items; }; // Hash for a simple (single value or array) type @@ -230,6 +232,16 @@ static void destruct_simple(void *key, void *value) free(value); } +Cache *ass_cache_clone(Cache *src) +{ + Cache *cache = calloc(1, sizeof(*cache)); + if (!cache || !src) + return NULL; + memcpy(cache, src, sizeof(Cache)); + + cache->add_items = NULL; + return cache; +} // Create a cache with type-specific hash/compare/destruct/size functions Cache *ass_cache_create(HashFunction hash_func, HashCompare compare_func, @@ -237,6 +249,8 @@ Cache *ass_cache_create(HashFunction hash_func, HashCompare compare_func, size_t key_size, size_t value_size) { Cache *cache = calloc(1, sizeof(*cache)); + if (!cache) + return NULL; cache->buckets = 0xFFFF; cache->hash_func = hash_simple; cache->compare_func = compare_simple; @@ -251,33 +265,72 @@ Cache *ass_cache_create(HashFunction hash_func, HashCompare compare_func, cache->key_size = key_size; cache->value_size = value_size; cache->map = calloc(cache->buckets, sizeof(CacheItem *)); + if (!cache->map) { + free(cache); + return NULL; + } return cache; } -void *ass_cache_put(Cache *cache, void *key, void *value) +static void *ass_cache_put_real(Cache *cache, CacheItem *item) { - unsigned bucket = cache->hash_func(key, cache->key_size) % cache->buckets; + unsigned bucket = + cache->hash_func(item->key, cache->key_size) % cache->buckets; CacheItem **bucketptr = &cache->map[bucket]; - CacheItem *item = calloc(1, sizeof(CacheItem)); - item->key = malloc(cache->key_size); - item->value = malloc(cache->value_size); - memcpy(item->key, key, cache->key_size); - memcpy(item->value, value, cache->value_size); - item->next = *bucketptr; *bucketptr = item; cache->items++; if (cache->size_func) - cache->cache_size += cache->size_func(value, cache->value_size); + cache->cache_size += cache->size_func(item->value, cache->value_size); else cache->cache_size++; return item->value; } +void ass_cache_merge(Cache *dst, Cache *src) +{ + CacheItem *item = src->add_items; + while (item) { + CacheItem *next = item->next; + ass_cache_put_real(dst, item); + item = next; + } + src->add_items = NULL; +} + +static CacheItem *create_item(Cache *cache, void *key, void *value) +{ + CacheItem *item = calloc(1, sizeof(CacheItem)); + if (!item) + return NULL; + item->key = malloc(cache->key_size); + item->value = malloc(cache->value_size); + memcpy(item->key, key, cache->key_size); + memcpy(item->value, value, cache->value_size); + return item; +} + +void *ass_cache_put(Cache *cache, void *key, void *value) +{ + CacheItem *item = create_item(cache, key, value); + + item->next = cache->add_items; + cache->add_items = item; + + return item->value; +} + +void *ass_cache_put_now(Cache *cache, void *key, void *value) +{ + CacheItem *item = create_item(cache, key, value); + + return ass_cache_put_real(cache, item); +} + void *ass_cache_get(Cache *cache, void *key) { unsigned bucket = cache->hash_func(key, cache->key_size) % cache->buckets; @@ -289,6 +342,14 @@ void *ass_cache_get(Cache *cache, void *key) } item = item->next; } + item = cache->add_items; + while (item) { + if (cache->compare_func(key, item->key, cache->key_size)) { + cache->hits++; + return item->value; + } + item = item->next; + } cache->misses++; return NULL; } @@ -297,8 +358,9 @@ int ass_cache_empty(Cache *cache, size_t max_size) { int i; - if (cache->cache_size < max_size) + if (cache->cache_size < max_size) { return 0; + } for (i = 0; i < cache->buckets; i++) { CacheItem *item = cache->map[i]; @@ -336,6 +398,19 @@ void ass_cache_done(Cache *cache) free(cache); } +void ass_cache_dupe_done(Cache *cache) +{ + CacheItem *item = cache->add_items; + while (item) { + CacheItem *next = item->next; + cache->destruct_func(item->key, item->value); + free(item); + item = next; + } + cache->add_items = NULL; + free(cache); +} + // Type-specific creation function Cache *ass_font_cache_create(void) { diff --git a/libass/ass_cache.h b/libass/ass_cache.h index 677b705..1671b23 100644 --- a/libass/ass_cache.h +++ b/libass/ass_cache.h @@ -91,12 +91,16 @@ typedef struct bitmap_hash_key { Cache *ass_cache_create(HashFunction hash_func, HashCompare compare_func, CacheItemDestructor destruct_func, ItemSize size_func, size_t key_size, size_t value_size); +Cache *ass_cache_clone(Cache *src); void *ass_cache_put(Cache *cache, void *key, void *value); +void *ass_cache_put_now(Cache *cache, void *key, void *value); +void ass_cache_merge(Cache *dst, Cache *src); void *ass_cache_get(Cache *cache, void *key); int ass_cache_empty(Cache *cache, size_t max_size); void ass_cache_stats(Cache *cache, size_t *size, unsigned *hits, unsigned *misses, unsigned *count); void ass_cache_done(Cache *cache); +void ass_cache_dupe_done(Cache *cache); Cache *ass_font_cache_create(void); Cache *ass_outline_cache_create(void); Cache *ass_glyph_metrics_cache_create(void); diff --git a/libass/ass_font.c b/libass/ass_font.c index 6e2f400..b20cbea 100644 --- a/libass/ass_font.c +++ b/libass/ass_font.c @@ -211,7 +211,7 @@ ASS_Font *ass_font_new(Cache *font_cache, ASS_Library *library, free(font.desc.family); return 0; } else - return ass_cache_put(font_cache, &font.desc, &font); + return ass_cache_put_now(font_cache, &font.desc, &font); } /** diff --git a/libass/ass_fontconfig.c b/libass/ass_fontconfig.c index dcb0bcf..ad02937 100644 --- a/libass/ass_fontconfig.c +++ b/libass/ass_fontconfig.c @@ -39,6 +39,10 @@ #include <fontconfig/fcfreetype.h> #endif +#ifdef CONFIG_PTHREAD +#include <pthread.h> +#endif + struct fc_instance { #ifdef CONFIG_FONTCONFIG FcConfig *config; @@ -46,6 +50,9 @@ struct fc_instance { char *family_default; char *path_default; int index_default; +#ifdef CONFIG_PTHREAD + pthread_mutex_t mutex; +#endif }; #ifdef CONFIG_FONTCONFIG @@ -328,6 +335,9 @@ char *fontconfig_select(ASS_Library *library, FCInstance *priv, res = priv->path_default ? strdup(priv->path_default) : 0; return res; } +#ifdef CONFIG_PTHREAD + pthread_mutex_lock(&priv->mutex); +#endif if (family && *family) res = select_font(library, priv, family, treat_family_as_pattern, @@ -360,6 +370,9 @@ char *fontconfig_select(ASS_Library *library, FCInstance *priv, ass_msg(library, MSGL_V, "fontconfig_select: (%s, %d, %d) -> %s, %d", family, bold, italic, res, *index); +#ifdef CONFIG_PTHREAD + pthread_mutex_unlock(&priv->mutex); +#endif return res; } @@ -482,6 +495,10 @@ FCInstance *fontconfig_init(ASS_Library *library, } } +#ifdef CONFIG_PTHREAD + pthread_mutex_init(&priv->mutex, &library->pthread_mutexattr); +#endif + priv->family_default = family ? strdup(family) : NULL; exit: priv->path_default = path ? strdup(path) : NULL; @@ -542,6 +559,9 @@ void fontconfig_done(FCInstance *priv) #endif free(priv->path_default); free(priv->family_default); +#ifdef CONFIG_PTHREAD + pthread_mutex_destroy(&priv->mutex); +#endif + free(priv); } - free(priv); } diff --git a/libass/ass_library.c b/libass/ass_library.c index b33ca55..5fb5a18 100644 --- a/libass/ass_library.c +++ b/libass/ass_library.c @@ -42,6 +42,12 @@ ASS_Library *ass_library_init(void) ASS_Library* lib = calloc(1, sizeof(*lib)); lib->msg_callback = ass_msg_handler; +#ifdef CONFIG_PTHREAD + pthread_attr_init(&lib->pthread_attr); + pthread_mutexattr_init(&lib->pthread_mutexattr); + pthread_condattr_init(&lib->pthread_condattr); +#endif + return lib; } @@ -51,6 +57,9 @@ void ass_library_done(ASS_Library *priv) ass_set_fonts_dir(priv, NULL); ass_set_style_overrides(priv, NULL); ass_clear_fonts(priv); +#ifdef CONFIG_PTHREAD + pthread_attr_destroy(&priv->pthread_attr); +#endif free(priv); } } diff --git a/libass/ass_library.h b/libass/ass_library.h index 8faf15e..9b056ff 100644 --- a/libass/ass_library.h +++ b/libass/ass_library.h @@ -19,6 +19,12 @@ #ifndef LIBASS_LIBRARY_H #define LIBASS_LIBRARY_H +#include "config.h" + +#ifdef CONFIG_PTHREAD +#include <pthread.h> +#endif + #include <stdarg.h> typedef struct { @@ -36,6 +42,11 @@ struct ass_library { int num_fontdata; void (*msg_callback)(int, const char *, va_list, void *); void *msg_callback_data; +#ifdef CONFIG_PTHREAD + pthread_attr_t pthread_attr; + pthread_mutexattr_t pthread_mutexattr; + pthread_condattr_t pthread_condattr; +#endif }; #endif /* LIBASS_LIBRARY_H */ diff --git a/libass/ass_parse.c b/libass/ass_parse.c index e256b53..5058a41 100644 --- a/libass/ass_parse.c +++ b/libass/ass_parse.c @@ -90,29 +90,29 @@ double ensure_font_size(ASS_Renderer *priv, double size) return size; } -static void change_font_size(ASS_Renderer *render_priv, double sz) +static void change_font_size(RenderContext *state, double sz) { - render_priv->state.font_size = sz; + state->font_size = sz; } /** - * \brief Change current font, using setting from render_priv->state. + * \brief Change current font, using setting from state-> */ -void update_font(ASS_Renderer *render_priv) +void update_font(ASS_Renderer *render_priv, RenderContext *state) { unsigned val; ASS_FontDesc desc; - desc.treat_family_as_pattern = render_priv->state.treat_family_as_pattern; + desc.treat_family_as_pattern = state->treat_family_as_pattern; - if (render_priv->state.family[0] == '@') { + if (state->family[0] == '@') { desc.vertical = 1; - desc.family = strdup(render_priv->state.family + 1); + desc.family = strdup(state->family + 1); } else { desc.vertical = 0; - desc.family = strdup(render_priv->state.family); + desc.family = strdup(state->family); } - val = render_priv->state.bold; + val = state->bold; // 0 = normal, 1 = bold, >1 = exact weight if (val == 1) val = 200; // bold @@ -120,21 +120,18 @@ void update_font(ASS_Renderer *render_priv) val = 80; // normal desc.bold = val; - val = render_priv->state.italic; + val = state->italic; if (val == 1) val = 110; // italic else if (val <= 0) val = 0; // normal desc.italic = val; - render_priv->state.font = - ass_font_new(render_priv->cache.font_cache, render_priv->library, - render_priv->ftlibrary, render_priv->fontconfig_priv, + state->font = + ass_font_new(state->cache->font_cache, render_priv->library, + state->ftlibrary, render_priv->fontconfig_priv, &desc); free(desc.family); - - if (render_priv->state.font) - change_font_size(render_priv, render_priv->state.font_size); } /** @@ -143,32 +140,33 @@ void update_font(ASS_Renderer *render_priv) * \param render_priv renderer state object * \param info glyph state object */ -void change_border(ASS_Renderer *render_priv, double border_x, double border_y) +void change_border(ASS_Renderer *render_priv, double border_x, double border_y, + RenderContext *state) { int bord = 64 * border_x * render_priv->border_scale; if (bord > 0 && border_x == border_y) { - if (!render_priv->state.stroker) { + if (!state->stroker) { int error; error = - FT_Stroker_New(render_priv->ftlibrary, - &render_priv->state.stroker); + FT_Stroker_New(state->ftlibrary, + &state->stroker); if (error) { ass_msg(render_priv->library, MSGL_V, "failed to get stroker"); - render_priv->state.stroker = 0; + state->stroker = 0; } - render_priv->state.stroker_radius = -1.0; + state->stroker_radius = -1.0; } - if (render_priv->state.stroker && render_priv->state.stroker_radius != bord) { - FT_Stroker_Set(render_priv->state.stroker, bord, + if (state->stroker && state->stroker_radius != bord) { + FT_Stroker_Set(state->stroker, bord, FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0); - render_priv->state.stroker_radius = bord; + state->stroker_radius = bord; } } else { - FT_Stroker_Done(render_priv->state.stroker); - render_priv->state.stroker = 0; + FT_Stroker_Done(state->stroker); + state->stroker = 0; } } @@ -236,19 +234,19 @@ interpolate_alpha(long long now, long long t1, long long t2, long long t3, * parameters. Translate it to correct for screen borders, if needed. */ static int parse_vector_clip(ASS_Renderer *render_priv, - struct arg *args, int nargs) + struct arg *args, int nargs, RenderContext *state) { int scale = 1; - ASS_Drawing *drawing = render_priv->state.clip_drawing; + ASS_Drawing *drawing = state->clip_drawing; struct arg text; if (nargs != 1 && nargs != 2) return 0; ass_drawing_free(drawing); - render_priv->state.clip_drawing = - ass_drawing_new(render_priv->library, render_priv->ftlibrary); - drawing = render_priv->state.clip_drawing; + state->clip_drawing = + ass_drawing_new(render_priv->library, state->ftlibrary); + drawing = state->clip_drawing; if (nargs == 2) scale = argtoi(args[0]); drawing->scale = scale; @@ -266,7 +264,8 @@ static int parse_vector_clip(ASS_Renderer *render_priv, * \param end end of string to parse, which must be '}' or ')' * \param pwr multiplier for some tag effects (comes from \t tags) */ -char *parse_tag(ASS_Renderer *render_priv, char *p, char *end, double pwr) +char *parse_tag(ASS_Renderer *render_priv, char *p, char *end, double pwr, + RenderContext *state) { while (*p != '\\' && p != end) ++p; @@ -331,52 +330,52 @@ char *parse_tag(ASS_Renderer *render_priv, char *p, char *end, double pwr) double val; if (nargs) { val = argtod(*args); - val = render_priv->state.border_x * (1 - pwr) + val * pwr; + val = state->border_x * (1 - pwr) + val * pwr; val = (val < 0) ? 0 : val; } else - val = render_priv->state.style->Outline; - render_priv->state.border_x = val; + val = state->style->Outline; + state->border_x = val; } else if (tag("ybord")) { double val; if (nargs) { val = argtod(*args); - val = render_priv->state.border_y * (1 - pwr) + val * pwr; + val = state->border_y * (1 - pwr) + val * pwr; val = (val < 0) ? 0 : val; } else - val = render_priv->state.style->Outline; - render_priv->state.border_y = val; + val = state->style->Outline; + state->border_y = val; } else if (tag("xshad")) { double val; if (nargs) { val = argtod(*args); - val = render_priv->state.shadow_x * (1 - pwr) + val * pwr; + val = state->shadow_x * (1 - pwr) + val * pwr; } else - val = render_priv->state.style->Shadow; - render_priv->state.shadow_x = val; + val = state->style->Shadow; + state->shadow_x = val; } else if (tag("yshad")) { double val; if (nargs) { val = argtod(*args); - val = render_priv->state.shadow_y * (1 - pwr) + val * pwr; + val = state->shadow_y * (1 - pwr) + val * pwr; } else - val = render_priv->state.style->Shadow; - render_priv->state.shadow_y = val; + val = state->style->Shadow; + state->shadow_y = val; } else if (tag("fax")) { double val; if (nargs) { val = argtod(*args); - render_priv->state.fax = - val * pwr + render_priv->state.fax * (1 - pwr); + state->fax = + val * pwr + state->fax * (1 - pwr); } else - render_priv->state.fax = 0.; + state->fax = 0.; } else if (tag("fay")) { double val; if (nargs) { val = argtod(*args); - render_priv->state.fay = - val * pwr + render_priv->state.fay * (1 - pwr); + state->fay = + val * pwr + state->fay * (1 - pwr); } else - render_priv->state.fay = 0.; + state->fay = 0.; } else if (complex_tag("iclip")) { if (nargs == 4) { int x0, y0, x1, y1; @@ -384,84 +383,84 @@ char *parse_tag(ASS_Renderer *render_priv, char *p, char *end, double pwr) y0 = argtoi(args[1]); x1 = argtoi(args[2]); y1 = argtoi(args[3]); - render_priv->state.clip_x0 = - render_priv->state.clip_x0 * (1 - pwr) + x0 * pwr; - render_priv->state.clip_x1 = - render_priv->state.clip_x1 * (1 - pwr) + x1 * pwr; - render_priv->state.clip_y0 = - render_priv->state.clip_y0 * (1 - pwr) + y0 * pwr; - render_priv->state.clip_y1 = - render_priv->state.clip_y1 * (1 - pwr) + y1 * pwr; - render_priv->state.clip_mode = 1; - } else if (!render_priv->state.clip_drawing) { - if (parse_vector_clip(render_priv, args, nargs)) - render_priv->state.clip_drawing_mode = 1; + state->clip_x0 = + state->clip_x0 * (1 - pwr) + x0 * pwr; + state->clip_x1 = + state->clip_x1 * (1 - pwr) + x1 * pwr; + state->clip_y0 = + state->clip_y0 * (1 - pwr) + y0 * pwr; + state->clip_y1 = + state->clip_y1 * (1 - pwr) + y1 * pwr; + state->clip_mode = 1; + } else if (!state->clip_drawing) { + if (parse_vector_clip(render_priv, args, nargs, state)) + state->clip_drawing_mode = 1; } } else if (tag("blur")) { double val; if (nargs) { val = argtod(*args); - val = render_priv->state.blur * (1 - pwr) + val * pwr; + val = state->blur * (1 - pwr) + val * pwr; val = (val < 0) ? 0 : val; val = (val > BLUR_MAX_RADIUS) ? BLUR_MAX_RADIUS : val; - render_priv->state.blur = val; + state->blur = val; } else - render_priv->state.blur = 0.0; + state->blur = 0.0; // ASS standard tags } else if (tag("fscx")) { double val; if (nargs) { val = argtod(*args) / 100; - val = render_priv->state.scale_x * (1 - pwr) + val * pwr; + val = state->scale_x * (1 - pwr) + val * pwr; val = (val < 0) ? 0 : val; } else - val = render_priv->state.style->ScaleX; - render_priv->state.scale_x = val; + val = state->style->ScaleX; + state->scale_x = val; } else if (tag("fscy")) { double val; if (nargs) { val = argtod(*args) / 100; - val = render_priv->state.scale_y * (1 - pwr) + val * pwr; + val = state->scale_y * (1 - pwr) + val * pwr; val = (val < 0) ? 0 : val; } else - val = render_priv->state.style->ScaleY; - render_priv->state.scale_y = val; + val = state->style->ScaleY; + state->scale_y = val; } else if (tag("fsc")) { - render_priv->state.scale_x = render_priv->state.style->ScaleX; - render_priv->state.scale_y = render_priv->state.style->ScaleY; + state->scale_x = state->style->ScaleX; + state->scale_y = state->style->ScaleY; } else if (tag("fsp")) { double val; if (nargs) { val = argtod(*args); - render_priv->state.hspacing = - render_priv->state.hspacing * (1 - pwr) + val * pwr; + state->hspacing = + state->hspacing * (1 - pwr) + val * pwr; } else - render_priv->state.hspacing = render_priv->state.style->Spacing; + state->hspacing = state->style->Spacing; } else if (tag("fs")) { double val = 0; if (nargs) { val = argtod(*args); if (*args->start == '+' || *args->start == '-') - val = render_priv->state.font_size * (1 + pwr * val / 10); + val = state->font_size * (1 + pwr * val / 10); else - val = render_priv->state.font_size * (1 - pwr) + val * pwr; + val = state->font_size * (1 - pwr) + val * pwr; } if (val <= 0) - val = render_priv->state.style->FontSize; - if (render_priv->state.font) - change_font_size(render_priv, val); + val = state->style->FontSize; + if (state->font) + change_font_size(state, val); } else if (tag("bord")) { double val, xval, yval; if (nargs) { val = argtod(*args); - xval = render_priv->state.border_x * (1 - pwr) + val * pwr; - yval = render_priv->state.border_y * (1 - pwr) + val * pwr; + xval = state->border_x * (1 - pwr) + val * pwr; + yval = state->border_y * (1 - pwr) + val * pwr; xval = (xval < 0) ? 0 : xval; yval = (yval < 0) ? 0 : yval; } else - xval = yval = render_priv->state.style->Outline; - render_priv->state.border_x = xval; - render_priv->state.border_y = yval; + xval = yval = state->style->Outline; + state->border_x = xval; + state->border_y = yval; } else if (complex_tag("move")) { double x1, x2, y1, y2; long long t1, t2, delta_t, t; @@ -486,10 +485,10 @@ char *parse_tag(ASS_Renderer *render_priv, char *p, char *end, double pwr) return q; if (t1 <= 0 && t2 <= 0) { t1 = 0; - t2 = render_priv->state.event->Duration; + t2 = state->event->Duration; } delta_t = t2 - t1; - t = render_priv->time - render_priv->state.event->Start; + t = render_priv->time - state->event->Start; if (t <= t1) k = 0.; else if (t >= t2) @@ -498,40 +497,40 @@ char *parse_tag(ASS_Renderer *render_priv, char *p, char *end, double pwr) k = ((double) |