summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRodger Combs <rodger.combs@gmail.com>2014-06-06 15:50:47 -0500
committerRodger Combs <rodger.combs@gmail.com>2014-07-20 00:05:33 -0500
commit67966b6f64690dbfb18ea34b99ed8b26c158a2d0 (patch)
treee824a8827f0809d194389aa20931290b201c7493
parent079769c5717278971ba9115cbf074434574dfc75 (diff)
downloadlibass-67966b6f64690dbfb18ea34b99ed8b26c158a2d0.tar.bz2
libass-67966b6f64690dbfb18ea34b99ed8b26c158a2d0.tar.xz
Render each event on a separate thread using pthreads
-rw-r--r--.gitignore1
-rw-r--r--configure.ac12
-rw-r--r--libass/Makefile.am2
-rw-r--r--libass/ass_bitmap.c21
-rw-r--r--libass/ass_bitmap.h8
-rw-r--r--libass/ass_cache.c95
-rw-r--r--libass/ass_cache.h4
-rw-r--r--libass/ass_font.c2
-rw-r--r--libass/ass_fontconfig.c22
-rw-r--r--libass/ass_library.c9
-rw-r--r--libass/ass_library.h11
-rw-r--r--libass/ass_parse.c463
-rw-r--r--libass/ass_parse.h18
-rw-r--r--libass/ass_render.c1028
-rw-r--r--libass/ass_render.h86
-rw-r--r--libass/ass_render_api.c29
-rw-r--r--libass/ass_shaper.c51
-rw-r--r--libass/ass_shaper.h26
-rw-r--r--libass/stdatomic.h367
-rw-r--r--m4/ax_pthread.m4332
20 files changed, 1861 insertions, 726 deletions
diff --git a/.gitignore b/.gitignore
index 8df5344..648295a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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)