]> granicus.if.org Git - libass/commitdiff
Eliminate render_context global; move it into ass_renderer.
authorgreg <greg@blackbox>
Thu, 18 Jun 2009 12:08:27 +0000 (14:08 +0200)
committergreg <greg@blackbox>
Fri, 19 Jun 2009 03:17:22 +0000 (05:17 +0200)
libass/ass_render.c

index 71f1300e03fd2f01f48a0e299b2844013bf52769..643db813c38b719025ce628a42eac2f36c9b52dc 100644 (file)
@@ -77,33 +77,6 @@ typedef struct event_images_s {
        ass_event_t* event;
 } event_images_t;
 
-struct ass_renderer_s {
-       ass_library_t* library;
-       FT_Library ftlibrary;
-       fc_instance_t* fontconfig_priv;
-       ass_settings_t settings;
-       int render_id;
-       ass_synth_priv_t* synth_priv;
-
-       ass_image_t* images_root; // rendering result is stored here
-       ass_image_t* prev_images_root;
-
-       event_images_t* eimg; // temporary buffer for sorting rendered events
-       int eimg_size; // allocated buffer size
-
-       // frame-global data
-       int width, height; // screen dimensions
-       int orig_height; // frame height ( = screen height - margins )
-       int orig_width; // frame width ( = screen width - margins )
-       int orig_height_nocrop; // frame height ( = screen height - margins + cropheight)
-       int orig_width_nocrop; // frame width ( = screen width - margins + cropwidth)
-       ass_track_t* track;
-       long long time; // frame's timestamp, ms
-       double font_scale;
-       double font_scale_x; // x scale applied to all glyphs to preserve text aspect ratio
-       double border_scale;
-};
-
 typedef enum {EF_NONE = 0, EF_KARAOKE, EF_KARAOKE_KF, EF_KARAOKE_KO} effect_t;
 
 // describes a glyph
@@ -201,7 +174,36 @@ typedef struct render_context_s {
 } render_context_t;
 
 static text_info_t text_info;
-static render_context_t render_context;
+
+struct ass_renderer_s {
+       ass_library_t* library;
+       FT_Library ftlibrary;
+       fc_instance_t* fontconfig_priv;
+       ass_settings_t settings;
+       int render_id;
+       ass_synth_priv_t* synth_priv;
+
+       ass_image_t* images_root; // rendering result is stored here
+       ass_image_t* prev_images_root;
+
+       event_images_t* eimg; // temporary buffer for sorting rendered events
+       int eimg_size; // allocated buffer size
+
+       // frame-global data
+       int width, height; // screen dimensions
+       int orig_height; // frame height ( = screen height - margins )
+       int orig_width; // frame width ( = screen width - margins )
+       int orig_height_nocrop; // frame height ( = screen height - margins + cropheight)
+       int orig_width_nocrop; // frame width ( = screen width - margins + cropwidth)
+       ass_track_t* track;
+       long long time; // frame's timestamp, ms
+       double font_scale;
+       double font_scale_x; // x scale applied to all glyphs to preserve text aspect ratio
+       double border_scale;
+       
+       render_context_t state;
+       text_info_t text_info;
+};
 
 struct render_priv_s {
        int top, height;
@@ -245,7 +247,6 @@ ass_renderer_t* ass_renderer_init(ass_library_t* library)
        ass_renderer_t* priv = 0;
        int vmajor, vminor, vpatch;
 
-       memset(&render_context, 0, sizeof(render_context));
        memset(&text_info, 0, sizeof(text_info));
 
        error = FT_Init_FreeType( &ft );
@@ -286,21 +287,21 @@ ass_init_exit:
        return priv;
 }
 
-void ass_renderer_done(ass_renderer_t* priv)
+void ass_renderer_done(ass_renderer_t* render_priv)
 {
        ass_font_cache_done();
        ass_bitmap_cache_done();
        ass_composite_cache_done();
        ass_glyph_cache_done();
-       if (render_context.stroker) {
-               FT_Stroker_Done(render_context.stroker);
-               render_context.stroker = 0;
+       if (render_priv->state.stroker) {
+               FT_Stroker_Done(render_priv->state.stroker);
+               render_priv->state.stroker = 0;
        }
-       if (priv && priv->ftlibrary) FT_Done_FreeType(priv->ftlibrary);
-       if (priv && priv->fontconfig_priv) fontconfig_done(priv->fontconfig_priv);
-       if (priv && priv->synth_priv) ass_synth_done(priv->synth_priv);
-       if (priv && priv->eimg) free(priv->eimg);
-       free(priv);
+       if (render_priv && render_priv->ftlibrary) FT_Done_FreeType(render_priv->ftlibrary);
+       if (render_priv && render_priv->fontconfig_priv) fontconfig_done(render_priv->fontconfig_priv);
+       if (render_priv && render_priv->synth_priv) ass_synth_done(render_priv->synth_priv);
+       if (render_priv && render_priv->eimg) free(render_priv->eimg);
+       free(render_priv);
        if (text_info.glyphs) free(text_info.glyphs);
 }
 
@@ -335,7 +336,7 @@ static ass_image_t* my_draw_bitmap(unsigned char* bitmap, int bitmap_w, int bitm
  * \return pointer to the new list tail
  * Performs clipping. Uses my_draw_bitmap for actual bitmap convertion.
  */
-static ass_image_t** render_glyph(bitmap_t* bm, int dst_x, int dst_y, uint32_t color, uint32_t color2, int brk, ass_image_t** tail)
+static ass_image_t** render_glyph(ass_renderer_t* render_priv, bitmap_t* bm, int dst_x, int dst_y, uint32_t color, uint32_t color2, int brk, ass_image_t** tail)
 {
        // brk is relative to dst_x
        // color = color left of brk
@@ -350,10 +351,10 @@ static ass_image_t** render_glyph(bitmap_t* bm, int dst_x, int dst_y, uint32_t c
        brk -= bm->left;
 
        // clipping
-       clip_x0 = render_context.clip_x0;
-       clip_y0 = render_context.clip_y0;
-       clip_x1 = render_context.clip_x1;
-       clip_y1 = render_context.clip_y1;
+       clip_x0 = render_priv->state.clip_x0;
+       clip_y0 = render_priv->state.clip_y0;
+       clip_x1 = render_priv->state.clip_x1;
+       clip_y1 = render_priv->state.clip_y1;
        b_x0 = 0;
        b_y0 = 0;
        b_x1 = bm->w;
@@ -520,7 +521,7 @@ static ass_image_t* render_text(ass_renderer_t* render_priv, text_info_t* text_i
                bm = info->bm_s;
 
                here_tail = tail;
-               tail = render_glyph(bm, pen_x, pen_y, info->c[3], 0, 1000000, tail);
+               tail = render_glyph(render_priv, bm, pen_x, pen_y, info->c[3], 0, 1000000, tail);
                if (last_tail && tail != here_tail && ((info->c[3] & 0xff) > 0))
                        render_overlap(last_tail, here_tail, last_hash, &info->hash_key);
                last_tail = here_tail;
@@ -541,7 +542,7 @@ static ass_image_t* render_text(ass_renderer_t* render_priv, text_info_t* text_i
                        // do nothing
                } else {
                        here_tail = tail;
-                       tail = render_glyph(bm, pen_x, pen_y, info->c[2], 0, 1000000, tail);
+                       tail = render_glyph(render_priv, bm, pen_x, pen_y, info->c[2], 0, 1000000, tail);
                        if (last_tail && tail != here_tail && ((info->c[2] & 0xff) > 0))
                                render_overlap(last_tail, here_tail, last_hash, &info->hash_key);
                        last_tail = here_tail;
@@ -559,13 +560,13 @@ static ass_image_t* render_text(ass_renderer_t* render_priv, text_info_t* text_i
 
                if ((info->effect_type == EF_KARAOKE) || (info->effect_type == EF_KARAOKE_KO)) {
                        if (info->effect_timing > info->bbox.xMax)
-                               tail = render_glyph(bm, pen_x, pen_y, info->c[0], 0, 1000000, tail);
+                               tail = render_glyph(render_priv, bm, pen_x, pen_y, info->c[0], 0, 1000000, tail);
                        else
-                               tail = render_glyph(bm, pen_x, pen_y, info->c[1], 0, 1000000, tail);
+                               tail = render_glyph(render_priv, bm, pen_x, pen_y, info->c[1], 0, 1000000, tail);
                } else if (info->effect_type == EF_KARAOKE_KF) {
-                       tail = render_glyph(bm, pen_x, pen_y, info->c[0], info->c[1], info->effect_timing, tail);
+                       tail = render_glyph(render_priv, bm, pen_x, pen_y, info->c[0], info->c[1], info->effect_timing, tail);
                } else
-                       tail = render_glyph(bm, pen_x, pen_y, info->c[0], 0, 1000000, tail);
+                       tail = render_glyph(render_priv, bm, pen_x, pen_y, info->c[0], 0, 1000000, tail);
        }
 
        *tail = 0;
@@ -659,37 +660,37 @@ static void change_font_size(ass_renderer_t* render_priv, double sz)
        else if (size > render_priv->height * 2)
                size = render_priv->height * 2;
 
-       ass_font_set_size(render_context.font, size);
+       ass_font_set_size(render_priv->state.font, size);
 
-       render_context.font_size = sz;
+       render_priv->state.font_size = sz;
 }
 
 /**
- * \brief Change current font, using setting from render_context.
+ * \brief Change current font, using setting from render_priv->state.
  */
 static void update_font(ass_renderer_t* render_priv)
 {
        unsigned val;
        ass_font_desc_t desc;
-       desc.family = strdup(render_context.family);
-       desc.treat_family_as_pattern = render_context.treat_family_as_pattern;
+       desc.family = strdup(render_priv->state.family);
+       desc.treat_family_as_pattern = render_priv->state.treat_family_as_pattern;
 
-       val = render_context.bold;
+       val = render_priv->state.bold;
        // 0 = normal, 1 = bold, >1 = exact weight
        if (val == 0) val = 80; // normal
        else if (val == 1) val = 200; // bold
        desc.bold = val;
 
-       val = render_context.italic;
+       val = render_priv->state.italic;
        if (val == 0) val = 0; // normal
        else if (val == 1) val = 110; //italic
        desc.italic = val;
 
-       render_context.font = ass_font_new(render_priv->library, render_priv->ftlibrary, render_priv->fontconfig_priv, &desc);
+       render_priv->state.font = ass_font_new(render_priv->library, render_priv->ftlibrary, render_priv->fontconfig_priv, &desc);
        free(desc.family);
 
-       if (render_context.font)
-               change_font_size(render_priv, render_context.font_size);
+       if (render_priv->state.font)
+               change_font_size(render_priv, render_priv->state.font_size);
 }
 
 /**
@@ -699,38 +700,38 @@ static void update_font(ass_renderer_t* render_priv)
 static void change_border(ass_renderer_t* render_priv, double border)
 {
        int b;
-       if (!render_context.font) return;
+       if (!render_priv->state.font) return;
 
        if (border < 0) {
-               if (render_context.style->BorderStyle == 1)
-                       border = render_context.style->Outline;
+               if (render_priv->state.style->BorderStyle == 1)
+                       border = render_priv->state.style->Outline;
                else
                        border = 1.;
        }
-       render_context.border = border;
+       render_priv->state.border = border;
 
        b = 64 * border * render_priv->border_scale;
        if (b > 0) {
-               if (!render_context.stroker) {
+               if (!render_priv->state.stroker) {
                        int error;
 #if (FREETYPE_MAJOR > 2) || ((FREETYPE_MAJOR == 2) && (FREETYPE_MINOR > 1))
-                       error = FT_Stroker_New( render_priv->ftlibrary, &render_context.stroker );
+                       error = FT_Stroker_New( render_priv->ftlibrary, &render_priv->state.stroker );
 #else // < 2.2
-                       error = FT_Stroker_New( render_context.font->faces[0]->memory, &render_context.stroker );
+                       error = FT_Stroker_New( render_priv->state.font->faces[0]->memory, &render_priv->state.stroker );
 #endif
                        if (error) {
                                mp_msg(MSGT_ASS, MSGL_V, "failed to get stroker\n");
-                               render_context.stroker = 0;
+                               render_priv->state.stroker = 0;
                        }
                }
-               if (render_context.stroker)
-                       FT_Stroker_Set( render_context.stroker, b,
+               if (render_priv->state.stroker)
+                       FT_Stroker_Set( render_priv->state.stroker, b,
                                        FT_STROKER_LINECAP_ROUND,
                                        FT_STROKER_LINEJOIN_ROUND,
                                        0 );
        } else {
-               FT_Stroker_Done(render_context.stroker);
-               render_context.stroker = 0;
+               FT_Stroker_Done(render_priv->state.stroker);
+               render_priv->state.stroker = 0;
        }
 }
 
@@ -855,9 +856,9 @@ static char* parse_tag(ass_renderer_t* render_priv, char* p, double pwr) {
                if (mystrtod(&p, &val)) {
                        val = (val < 0) ? 0 : val;
                        val = (val > BLUR_MAX_RADIUS) ? BLUR_MAX_RADIUS : val;
-                       render_context.blur = val;
+                       render_priv->state.blur = val;
                } else
-                       render_context.blur = 0.0;
+                       render_priv->state.blur = 0.0;
        // ASS standard tags
        } else if (mystrcmp(&p, "fsc")) {
                char tp = *p++;
@@ -865,34 +866,34 @@ static char* parse_tag(ass_renderer_t* render_priv, char* p, double pwr) {
                if (tp == 'x') {
                        if (mystrtod(&p, &val)) {
                                val /= 100;
-                               render_context.scale_x = render_context.scale_x * ( 1 - pwr) + val * pwr;
+                               render_priv->state.scale_x = render_priv->state.scale_x * ( 1 - pwr) + val * pwr;
                        } else
-                               render_context.scale_x = render_context.style->ScaleX;
+                               render_priv->state.scale_x = render_priv->state.style->ScaleX;
                } else if (tp == 'y') {
                        if (mystrtod(&p, &val)) {
                                val /= 100;
-                               render_context.scale_y = render_context.scale_y * ( 1 - pwr) + val * pwr;
+                               render_priv->state.scale_y = render_priv->state.scale_y * ( 1 - pwr) + val * pwr;
                        } else
-                               render_context.scale_y = render_context.style->ScaleY;
+                               render_priv->state.scale_y = render_priv->state.style->ScaleY;
                }
        } else if (mystrcmp(&p, "fsp")) {
                double val;
                if (mystrtod(&p, &val))
-                       render_context.hspacing = render_context.hspacing * ( 1 - pwr ) + val * pwr;
+                       render_priv->state.hspacing = render_priv->state.hspacing * ( 1 - pwr ) + val * pwr;
                else
-                       render_context.hspacing = render_context.style->Spacing;
+                       render_priv->state.hspacing = render_priv->state.style->Spacing;
        } else if (mystrcmp(&p, "fs")) {
                double val;
                if (mystrtod(&p, &val))
-                       val = render_context.font_size * ( 1 - pwr ) + val * pwr;
+                       val = render_priv->state.font_size * ( 1 - pwr ) + val * pwr;
                else
-                       val = render_context.style->FontSize;
-               if (render_context.font)
+                       val = render_priv->state.style->FontSize;
+               if (render_priv->state.font)
                        change_font_size(render_priv, val);
        } else if (mystrcmp(&p, "bord")) {
                double val;
                if (mystrtod(&p, &val))
-                       val = render_context.border * ( 1 - pwr ) + val * pwr;
+                       val = render_priv->state.border * ( 1 - pwr ) + val * pwr;
                else
                        val = -1.; // reset to default
                change_border(render_priv, val);
@@ -918,12 +919,12 @@ static char* parse_tag(ass_renderer_t* render_priv, char* p, double pwr) {
                                x1, y1, x2, y2, (int64_t)t1, (int64_t)t2);
                } else {
                        t1 = 0;
-                       t2 = render_context.event->Duration;
+                       t2 = render_priv->state.event->Duration;
                        mp_msg(MSGT_ASS, MSGL_DBG2, "movement: (%f, %f) -> (%f, %f)\n", x1, y1, x2, y2);
                }
                skip(')');
                delta_t = t2 - t1;
-               t = render_priv->time - render_context.event->Start;
+               t = render_priv->time - render_priv->state.event->Start;
                if (t < t1)
                        k = 0.;
                else if (t > t2)
@@ -931,33 +932,33 @@ static char* parse_tag(ass_renderer_t* render_priv, char* p, double pwr) {
                else k = ((double)(t - t1)) / delta_t;
                x = k * (x2 - x1) + x1;
                y = k * (y2 - y1) + y1;
-               if (render_context.evt_type != EVENT_POSITIONED) {
-                       render_context.pos_x = x;
-                       render_context.pos_y = y;
-                       render_context.detect_collisions = 0;
-                       render_context.evt_type = EVENT_POSITIONED;
+               if (render_priv->state.evt_type != EVENT_POSITIONED) {
+                       render_priv->state.pos_x = x;
+                       render_priv->state.pos_y = y;
+                       render_priv->state.detect_collisions = 0;
+                       render_priv->state.evt_type = EVENT_POSITIONED;
                }
        } else if (mystrcmp(&p, "frx")) {
                double val;
                if (mystrtod(&p, &val)) {
                        val *= M_PI / 180;
-                       render_context.frx = val * pwr + render_context.frx * (1-pwr);
+                       render_priv->state.frx = val * pwr + render_priv->state.frx * (1-pwr);
                } else
-                       render_context.frx = 0.;
+                       render_priv->state.frx = 0.;
        } else if (mystrcmp(&p, "fry")) {
                double val;
                if (mystrtod(&p, &val)) {
                        val *= M_PI / 180;
-                       render_context.fry = val * pwr + render_context.fry * (1-pwr);
+                       render_priv->state.fry = val * pwr + render_priv->state.fry * (1-pwr);
                } else
-                       render_context.fry = 0.;
+                       render_priv->state.fry = 0.;
        } else if (mystrcmp(&p, "frz") || mystrcmp(&p, "fr")) {
                double val;
                if (mystrtod(&p, &val)) {
                        val *= M_PI / 180;
-                       render_context.frz = val * pwr + render_context.frz * (1-pwr);
+                       render_priv->state.frz = val * pwr + render_priv->state.frz * (1-pwr);
                } else
-                       render_context.frz = M_PI * render_context.style->Angle / 180.;
+                       render_priv->state.frz = M_PI * render_priv->state.style->Angle / 180.;
        } else if (mystrcmp(&p, "fn")) {
                char* start = p;
                char* family;
@@ -967,10 +968,10 @@ static char* parse_tag(ass_renderer_t* render_priv, char* p, double pwr) {
                        strncpy(family, start, p - start);
                        family[p - start] = '\0';
                } else
-                       family = strdup(render_context.style->FontName);
-               if (render_context.family)
-                       free(render_context.family);
-               render_context.family = family;
+                       family = strdup(render_priv->state.style->FontName);
+               if (render_priv->state.family)
+                       free(render_priv->state.family);
+               render_priv->state.family = family;
                update_font(render_priv);
        } else if (mystrcmp(&p, "alpha")) {
                uint32_t val;
@@ -978,12 +979,12 @@ static char* parse_tag(ass_renderer_t* render_priv, char* p, double pwr) {
                if (strtocolor(&p, &val)) {
                        unsigned char a = val >> 24;
                        for (i = 0; i < 4; ++i)
-                               change_alpha(&render_context.c[i], a, pwr);
+                               change_alpha(&render_priv->state.c[i], a, pwr);
                } else {
-                       change_alpha(&render_context.c[0], render_context.style->PrimaryColour, pwr);
-                       change_alpha(&render_context.c[1], render_context.style->SecondaryColour, pwr);
-                       change_alpha(&render_context.c[2], render_context.style->OutlineColour, pwr);
-                       change_alpha(&render_context.c[3], render_context.style->BackColour, pwr);
+                       change_alpha(&render_priv->state.c[0], render_priv->state.style->PrimaryColour, pwr);
+                       change_alpha(&render_priv->state.c[1], render_priv->state.style->SecondaryColour, pwr);
+                       change_alpha(&render_priv->state.c[2], render_priv->state.style->OutlineColour, pwr);
+                       change_alpha(&render_priv->state.c[3], render_priv->state.style->BackColour, pwr);
                }
                // FIXME: simplify
        } else if (mystrcmp(&p, "an")) {
@@ -995,15 +996,15 @@ static char* parse_tag(ass_renderer_t* render_priv, char* p, double pwr) {
                        val = ((val - 1) % 3) + 1; // horizontal alignment
                        val += v*4;
                        mp_msg(MSGT_ASS, MSGL_DBG2, "align %d\n", val);
-                       render_context.alignment = val;
+                       render_priv->state.alignment = val;
                } else
-                       render_context.alignment = render_context.style->Alignment;
+                       render_priv->state.alignment = render_priv->state.style->Alignment;
        } else if (mystrcmp(&p, "a")) {
                int val;
                if (mystrtoi(&p, &val) && val)
-                       render_context.alignment = val;
+                       render_priv->state.alignment = val;
                else
-                       render_context.alignment = render_context.style->Alignment;
+                       render_priv->state.alignment = render_priv->state.style->Alignment;
        } else if (mystrcmp(&p, "pos")) {
                double v1, v2;
                skip('(');
@@ -1012,14 +1013,14 @@ static char* parse_tag(ass_renderer_t* render_priv, char* p, double pwr) {
                mystrtod(&p, &v2);
                skip(')');
                mp_msg(MSGT_ASS, MSGL_DBG2, "pos(%f, %f)\n", v1, v2);
-               if (render_context.evt_type == EVENT_POSITIONED) {
+               if (render_priv->state.evt_type == EVENT_POSITIONED) {
                        mp_msg(MSGT_ASS, MSGL_V, "Subtitle has a new \\pos "
                               "after \\move or \\pos, ignoring\n");
                } else {
-                       render_context.evt_type = EVENT_POSITIONED;
-                       render_context.detect_collisions = 0;
-                       render_context.pos_x = v1;
-                       render_context.pos_y = v2;
+                       render_priv->state.evt_type = EVENT_POSITIONED;
+                       render_priv->state.detect_collisions = 0;
+                       render_priv->state.pos_x = v1;
+                       render_priv->state.pos_y = v2;
                }
        } else if (mystrcmp(&p, "fad")) {
                int a1, a2, a3;
@@ -1033,7 +1034,7 @@ static char* parse_tag(ass_renderer_t* render_priv, char* p, double pwr) {
                        // 2-argument version (\fad, according to specs)
                        // a1 and a2 are fade-in and fade-out durations
                        t1 = 0;
-                       t4 = render_context.event->Duration;
+                       t4 = render_priv->state.event->Duration;
                        t2 = a1;
                        t3 = t4 - a2;
                        a1 = 0xFF;
@@ -1054,7 +1055,7 @@ static char* parse_tag(ass_renderer_t* render_priv, char* p, double pwr) {
                        mystrtoll(&p, &t4);
                }
                skip(')');
-               render_context.fade = interpolate_alpha(render_priv->time - render_context.event->Start, t1, t2, t3, t4, a1, a2, a3);
+               render_priv->state.fade = interpolate_alpha(render_priv->time - render_priv->state.event->Start, t1, t2, t3, t4, a1, a2, a3);
        } else if (mystrcmp(&p, "org")) {
                int v1, v2;
                skip('(');
@@ -1063,12 +1064,12 @@ static char* parse_tag(ass_renderer_t* render_priv, char* p, double pwr) {
                mystrtoi(&p, &v2);
                skip(')');
                mp_msg(MSGT_ASS, MSGL_DBG2, "org(%d, %d)\n", v1, v2);
-               //                              render_context.evt_type = EVENT_POSITIONED;
-               if (!render_context.have_origin) {
-                       render_context.org_x = v1;
-                       render_context.org_y = v2;
-                       render_context.have_origin = 1;
-                       render_context.detect_collisions = 0;
+               //                              render_priv->state.evt_type = EVENT_POSITIONED;
+               if (!render_priv->state.have_origin) {
+                       render_priv->state.org_x = v1;
+                       render_priv->state.org_y = v2;
+                       render_priv->state.have_origin = 1;
+                       render_priv->state.detect_collisions = 0;
                }
        } else if (mystrcmp(&p, "t")) {
                double v[3];
@@ -1089,17 +1090,17 @@ static char* parse_tag(ass_renderer_t* render_priv, char* p, double pwr) {
                } else if (cnt == 2) {
                        v1 = v[0]; v2 = v[1]; v3 = 1.;
                } else if (cnt == 1) {
-                       v1 = 0; v2 = render_context.event->Duration; v3 = v[0];
+                       v1 = 0; v2 = render_priv->state.event->Duration; v3 = v[0];
                } else { // cnt == 0
-                       v1 = 0; v2 = render_context.event->Duration; v3 = 1.;
+                       v1 = 0; v2 = render_priv->state.event->Duration; v3 = 1.;
                }
-               render_context.detect_collisions = 0;
+               render_priv->state.detect_collisions = 0;
                t1 = v1;
                t2 = v2;
                delta_t = v2 - v1;
                if (v3 < 0.)
                        v3 = 0.;
-               t = render_priv->time - render_context.event->Start; // FIXME: move to render_context
+               t = render_priv->time - render_priv->state.event->Start; // FIXME: move to render_context
                if (t <= t1)
                        k = 0.;
                else if (t >= t2)
@@ -1125,22 +1126,22 @@ static char* parse_tag(ass_renderer_t* render_priv, char* p, double pwr) {
                res &= mystrtoi(&p, &y1);
                skip(')');
                if (res) {
-                       render_context.clip_x0 = render_context.clip_x0 * (1-pwr) + x0 * pwr;
-                       render_context.clip_x1 = render_context.clip_x1 * (1-pwr) + x1 * pwr;
-                       render_context.clip_y0 = render_context.clip_y0 * (1-pwr) + y0 * pwr;
-                       render_context.clip_y1 = render_context.clip_y1 * (1-pwr) + y1 * pwr;
+                       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;
                } else {
-                       render_context.clip_x0 = 0;
-                       render_context.clip_y0 = 0;
-                       render_context.clip_x1 = render_priv->track->PlayResX;
-                       render_context.clip_y1 = render_priv->track->PlayResY;
+                       render_priv->state.clip_x0 = 0;
+                       render_priv->state.clip_y0 = 0;
+                       render_priv->state.clip_x1 = render_priv->track->PlayResX;
+                       render_priv->state.clip_y1 = render_priv->track->PlayResY;
                }
        } else if (mystrcmp(&p, "c")) {
                uint32_t val;
                if (!strtocolor(&p, &val))
-                       val = render_context.style->PrimaryColour;
+                       val = render_priv->state.style->PrimaryColour;
                mp_msg(MSGT_ASS, MSGL_DBG2, "color: %X\n", val);
-               change_color(&render_context.c[0], val, pwr);
+               change_color(&render_priv->state.c[0], val, pwr);
        } else if ((*p >= '1') && (*p <= '4') && (++p) && (mystrcmp(&p, "c") || mystrcmp(&p, "a"))) {
                char n = *(p-2);
                int cidx = n - '1';
@@ -1149,18 +1150,18 @@ static char* parse_tag(ass_renderer_t* render_priv, char* p, double pwr) {
                assert((n >= '1') && (n <= '4'));
                if (!strtocolor(&p, &val))
                        switch(n) {
-                               case '1': val = render_context.style->PrimaryColour; break;
-                               case '2': val = render_context.style->SecondaryColour; break;
-                               case '3': val = render_context.style->OutlineColour; break;
-                               case '4': val = render_context.style->BackColour; break;
+                               case '1': val = render_priv->state.style->PrimaryColour; break;
+                               case '2': val = render_priv->state.style->SecondaryColour; break;
+                               case '3': val = render_priv->state.style->OutlineColour; break;
+                               case '4': val = render_priv->state.style->BackColour; break;
                                default : val = 0; break; // impossible due to assert; avoid compilation warning
                        }
                switch (cmd) {
-                       case 'c': change_color(render_context.c + cidx, val, pwr); break;
-                       case 'a': change_alpha(render_context.c + cidx, val >> 24, pwr); break;
+                       case 'c': change_color(render_priv->state.c + cidx, val, pwr); break;
+                       case 'a': change_alpha(render_priv->state.c + cidx, val >> 24, pwr); break;
                        default: mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_BadCommand, n, cmd); break;
                }
-               mp_msg(MSGT_ASS, MSGL_DBG2, "single c/a at %f: %c%c = %X   \n", pwr, n, cmd, render_context.c[cidx]);
+               mp_msg(MSGT_ASS, MSGL_DBG2, "single c/a at %f: %c%c = %X   \n", pwr, n, cmd, render_priv->state.c[cidx]);
        } else if (mystrcmp(&p, "r")) {
                reset_render_context(render_priv);
        } else if (mystrcmp(&p, "be")) {
@@ -1169,52 +1170,52 @@ static char* parse_tag(ass_renderer_t* render_priv, char* p, double pwr) {
                        // Clamp to a safe upper limit, since high values need excessive CPU
                        val = (val < 0) ? 0 : val;
                        val = (val > MAX_BE) ? MAX_BE : val;
-                       render_context.be = val;
+                       render_priv->state.be = val;
                } else
-                       render_context.be = 0;
+                       render_priv->state.be = 0;
        } else if (mystrcmp(&p, "b")) {
                int b;
                if (mystrtoi(&p, &b)) {
                        if (pwr >= .5)
-                               render_context.bold = b;
+                               render_priv->state.bold = b;
                } else
-                       render_context.bold = render_context.style->Bold;
+                       render_priv->state.bold = render_priv->state.style->Bold;
                update_font(render_priv);
        } else if (mystrcmp(&p, "i")) {
                int i;
                if (mystrtoi(&p, &i)) {
                        if (pwr >= .5)
-                               render_context.italic = i;
+                               render_priv->state.italic = i;
                } else
-                       render_context.italic = render_context.style->Italic;
+                       render_priv->state.italic = render_priv->state.style->Italic;
                update_font(render_priv);
        } else if (mystrcmp(&p, "kf") || mystrcmp(&p, "K")) {
                int val = 0;
                mystrtoi(&p, &val);
-               render_context.effect_type = EF_KARAOKE_KF;
-               if (render_context.effect_timing)
-                       render_context.effect_skip_timing += render_context.effect_timing;
-               render_context.effect_timing = val * 10;
+               render_priv->state.effect_type = EF_KARAOKE_KF;
+               if (render_priv->state.effect_timing)
+                       render_priv->state.effect_skip_timing += render_priv->state.effect_timing;
+               render_priv->state.effect_timing = val * 10;
        } else if (mystrcmp(&p, "ko")) {
                int val = 0;
                mystrtoi(&p, &val);
-               render_context.effect_type = EF_KARAOKE_KO;
-               if (render_context.effect_timing)
-                       render_context.effect_skip_timing += render_context.effect_timing;
-               render_context.effect_timing = val * 10;
+               render_priv->state.effect_type = EF_KARAOKE_KO;
+               if (render_priv->state.effect_timing)
+                       render_priv->state.effect_skip_timing += render_priv->state.effect_timing;
+               render_priv->state.effect_timing = val * 10;
        } else if (mystrcmp(&p, "k")) {
                int val = 0;
                mystrtoi(&p, &val);
-               render_context.effect_type = EF_KARAOKE;
-               if (render_context.effect_timing)
-                       render_context.effect_skip_timing += render_context.effect_timing;
-               render_context.effect_timing = val * 10;
+               render_priv->state.effect_type = EF_KARAOKE;
+               if (render_priv->state.effect_timing)
+                       render_priv->state.effect_skip_timing += render_priv->state.effect_timing;
+               render_priv->state.effect_timing = val * 10;
        } else if (mystrcmp(&p, "shad")) {
                int val;
                if (mystrtoi(&p, &val))
-                       render_context.shadow = val;
+                       render_priv->state.shadow = val;
                else
-                       render_context.shadow = render_context.style->Shadow;
+                       render_priv->state.shadow = render_priv->state.style->Shadow;
        } else if (mystrcmp(&p, "pbo")) {
                int val = 0;
                mystrtoi(&p, &val); // ignored
@@ -1222,7 +1223,7 @@ static char* parse_tag(ass_renderer_t* render_priv, char* p, double pwr) {
                int val;
                if (!mystrtoi(&p, &val))
                        val = 0;
-               render_context.drawing_mode = !!val;
+               render_priv->state.drawing_mode = !!val;
        }
 
        return p;
@@ -1299,21 +1300,21 @@ static void apply_transition_effects(ass_renderer_t* render_priv, ass_event_t* e
                        return;
                }
                if (cnt >= 2 && v[1] == 0) // right-to-left
-                       render_context.scroll_direction = SCROLL_RL;
+                       render_priv->state.scroll_direction = SCROLL_RL;
                else // left-to-right
-                       render_context.scroll_direction = SCROLL_LR;
+                       render_priv->state.scroll_direction = SCROLL_LR;
 
                delay = v[0];
                if (delay == 0) delay = 1; // ?
-               render_context.scroll_shift = (render_priv->time - render_context.event->Start) / delay;
-               render_context.evt_type = EVENT_HSCROLL;
+               render_priv->state.scroll_shift = (render_priv->time - render_priv->state.event->Start) / delay;
+               render_priv->state.evt_type = EVENT_HSCROLL;
                return;
        }
 
        if (strncmp(event->Effect, "Scroll up;", 10) == 0) {
-               render_context.scroll_direction = SCROLL_BT;
+               render_priv->state.scroll_direction = SCROLL_BT;
        } else if (strncmp(event->Effect, "Scroll down;", 12) == 0) {
-               render_context.scroll_direction = SCROLL_TB;
+               render_priv->state.scroll_direction = SCROLL_TB;
        } else {
                mp_msg(MSGT_ASS, MSGL_V, "Unknown transition effect: %s \n", event->Effect);
                return;
@@ -1328,7 +1329,7 @@ static void apply_transition_effects(ass_renderer_t* render_priv, ass_event_t* e
                }
                delay = v[2];
                if (delay == 0) delay = 1; // ?
-               render_context.scroll_shift = (render_priv->time - render_context.event->Start) / delay;
+               render_priv->state.scroll_shift = (render_priv->time - render_priv->state.event->Start) / delay;
                if (v[0] < v[1]) {
                        y0 = v[0]; y1 = v[1];
                } else {
@@ -1336,10 +1337,10 @@ static void apply_transition_effects(ass_renderer_t* render_priv, ass_event_t* e
                }
                if (y1 == 0)
                        y1 = render_priv->track->PlayResY; // y0=y1=0 means fullscreen scrolling
-               render_context.clip_y0 = y0;
-               render_context.clip_y1 = y1;
-               render_context.evt_type = EVENT_VSCROLL;
-               render_context.detect_collisions = 0;
+               render_priv->state.clip_y0 = y0;
+               render_priv->state.clip_y1 = y1;
+               render_priv->state.evt_type = EVENT_VSCROLL;
+               render_priv->state.detect_collisions = 0;
        }
 
 }
@@ -1350,60 +1351,60 @@ static void apply_transition_effects(ass_renderer_t* render_priv, ass_event_t* e
  */
 static void reset_render_context(ass_renderer_t* render_priv)
 {
-       render_context.c[0] = render_context.style->PrimaryColour;
-       render_context.c[1] = render_context.style->SecondaryColour;
-       render_context.c[2] = render_context.style->OutlineColour;
-       render_context.c[3] = render_context.style->BackColour;
-       render_context.font_size = render_context.style->FontSize;
-
-       if (render_context.family)
-               free(render_context.family);
-       render_context.family = strdup(render_context.style->FontName);
-       render_context.treat_family_as_pattern = render_context.style->treat_fontname_as_pattern;
-       render_context.bold = render_context.style->Bold;
-       render_context.italic = render_context.style->Italic;
+       render_priv->state.c[0] = render_priv->state.style->PrimaryColour;
+       render_priv->state.c[1] = render_priv->state.style->SecondaryColour;
+       render_priv->state.c[2] = render_priv->state.style->OutlineColour;
+       render_priv->state.c[3] = render_priv->state.style->BackColour;
+       render_priv->state.font_size = render_priv->state.style->FontSize;
+
+       if (render_priv->state.family)
+               free(render_priv->state.family);
+       render_priv->state.family = strdup(render_priv->state.style->FontName);
+       render_priv->state.treat_family_as_pattern = render_priv->state.style->treat_fontname_as_pattern;
+       render_priv->state.bold = render_priv->state.style->Bold;
+       render_priv->state.italic = render_priv->state.style->Italic;
        update_font(render_priv);
 
        change_border(render_priv, -1.);
-       render_context.scale_x = render_context.style->ScaleX;
-       render_context.scale_y = render_context.style->ScaleY;
-       render_context.hspacing = render_context.style->Spacing;
-       render_context.be = 0;
-       render_context.blur = 0.0;
-       render_context.shadow = render_context.style->Shadow;
-       render_context.frx = render_context.fry = 0.;
-       render_context.frz = M_PI * render_context.style->Angle / 180.;
+       render_priv->state.scale_x = render_priv->state.style->ScaleX;
+       render_priv->state.scale_y = render_priv->state.style->ScaleY;
+       render_priv->state.hspacing = render_priv->state.style->Spacing;
+       render_priv->state.be = 0;
+       render_priv->state.blur = 0.0;
+       render_priv->state.shadow = render_priv->state.style->Shadow;
+       render_priv->state.frx = render_priv->state.fry = 0.;
+       render_priv->state.frz = M_PI * render_priv->state.style->Angle / 180.;
 
        // FIXME: does not reset unsupported attributes.
 }
 
 /**
- * \brief Start new event. Reset render_context.
+ * \brief Start new event. Reset render_priv->state.
  */
 static void init_render_context(ass_renderer_t* render_priv, ass_event_t* event)
 {
-       render_context.event = event;
-       render_context.style = render_priv->track->styles + event->Style;
+       render_priv->state.event = event;
+       render_priv->state.style = render_priv->track->styles + event->Style;
 
        reset_render_context(render_priv);
 
-       render_context.evt_type = EVENT_NORMAL;
-       render_context.alignment = render_context.style->Alignment;
-       render_context.pos_x = 0;
-       render_context.pos_y = 0;
-       render_context.org_x = 0;
-       render_context.org_y = 0;
-       render_context.have_origin = 0;
-       render_context.clip_x0 = 0;
-       render_context.clip_y0 = 0;
-       render_context.clip_x1 = render_priv->track->PlayResX;
-       render_context.clip_y1 = render_priv->track->PlayResY;
-       render_context.detect_collisions = 1;
-       render_context.fade = 0;
-       render_context.drawing_mode = 0;
-       render_context.effect_type = EF_NONE;
-       render_context.effect_timing = 0;
-       render_context.effect_skip_timing = 0;
+       render_priv->state.evt_type = EVENT_NORMAL;
+       render_priv->state.alignment = render_priv->state.style->Alignment;
+       render_priv->state.pos_x = 0;
+       render_priv->state.pos_y = 0;
+       render_priv->state.org_x = 0;
+       render_priv->state.org_y = 0;
+       render_priv->state.have_origin = 0;
+       render_priv->state.clip_x0 = 0;
+       render_priv->state.clip_y0 = 0;
+       render_priv->state.clip_x1 = render_priv->track->PlayResX;
+       render_priv->state.clip_y1 = render_priv->track->PlayResY;
+       render_priv->state.detect_collisions = 1;
+       render_priv->state.fade = 0;
+       render_priv->state.drawing_mode = 0;
+       render_priv->state.effect_type = EF_NONE;
+       render_priv->state.effect_timing = 0;
+       render_priv->state.effect_skip_timing = 0;
 
        apply_transition_effects(render_priv, event);
 }
@@ -1428,15 +1429,15 @@ static void get_outline_glyph(ass_renderer_t* render_priv, int symbol, glyph_inf
        glyph_hash_val_t* val;
        glyph_hash_key_t key;
        memset(&key, 0, sizeof(key));
-       key.font = render_context.font;
-       key.size = render_context.font_size;
+       key.font = render_priv->state.font;
+       key.size = render_priv->state.font_size;
        key.ch = symbol;
-       key.scale_x = (render_context.scale_x * 0xFFFF);
-       key.scale_y = (render_context.scale_y * 0xFFFF);
+       key.scale_x = (render_priv->state.scale_x * 0xFFFF);
+       key.scale_y = (render_priv->state.scale_y * 0xFFFF);
        key.advance = *advance;
-       key.bold = render_context.bold;
-       key.italic = render_context.italic;
-       key.outline = render_context.border * 0xFFFF;
+       key.bold = render_priv->state.bold;
+       key.italic = render_priv->state.italic;
+       key.outline = render_priv->state.border * 0xFFFF;
 
        memset(info, 0, sizeof(glyph_info_t));
 
@@ -1450,16 +1451,16 @@ static void get_outline_glyph(ass_renderer_t* render_priv, int symbol, glyph_inf
                info->advance.y = val->advance.y;
        } else {
                glyph_hash_val_t v;
-               info->glyph = ass_font_get_glyph(render_priv->fontconfig_priv, render_context.font, symbol, render_priv->settings.hinting);
+               info->glyph = ass_font_get_glyph(render_priv->fontconfig_priv, render_priv->state.font, symbol, render_priv->settings.hinting);
                if (!info->glyph)
                        return;
                info->advance.x = d16_to_d6(info->glyph->advance.x);
                info->advance.y = d16_to_d6(info->glyph->advance.y);
                FT_Glyph_Get_CBox( info->glyph, FT_GLYPH_BBOX_PIXELS, &info->bbox);
 
-               if (render_context.stroker) {
+               if (render_priv->state.stroker) {
                        info->outline_glyph = info->glyph;
-                       error = FT_Glyph_StrokeBorder( &(info->outline_glyph), render_context.stroker, 0 , 0 ); // don't destroy original
+                       error = FT_Glyph_StrokeBorder( &(info->outline_glyph), render_priv->state.stroker, 0 , 0 ); // don't destroy original
                        if (error) {
                                mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_FT_Glyph_Stroke_Error, error);
                        }
@@ -1723,7 +1724,7 @@ static void process_karaoke_effects(ass_renderer_t* render_priv)
        int x;
        int x_start, x_end;
 
-       tm_current = render_priv->time - render_context.event->Start;
+       tm_current = render_priv->time - render_priv->state.event->Start;
        timing = 0;
        s1 = s2 = 0;
        for (i = 0; i <= text_info.length; ++i) {
@@ -1914,10 +1915,10 @@ static int ass_render_event(ass_renderer_t* render_priv, ass_event_t* event, eve
                // this affects render_context
                do {
                        code = get_next_char(render_priv, &p);
-               } while (code && render_context.drawing_mode); // skip everything in drawing mode
+               } while (code && render_priv->state.drawing_mode); // skip everything in drawing mode
 
                // face could have been changed in get_next_char
-               if (!render_context.font) {
+               if (!render_priv->state.font) {
                        free_render_context();
                        return 1;
                }
@@ -1933,22 +1934,22 @@ static int ass_render_event(ass_renderer_t* render_priv, ass_event_t* event, eve
 
                if ( previous && code ) {
                        FT_Vector delta;
-                       delta = ass_font_get_kerning(render_context.font, previous, code);
-                       pen.x += delta.x * render_context.scale_x;
-                       pen.y += delta.y * render_context.scale_y;
+                       delta = ass_font_get_kerning(render_priv->state.font, previous, code);
+                       pen.x += delta.x * render_priv->state.scale_x;
+                       pen.y += delta.y * render_priv->state.scale_y;
                }
 
                shift.x = pen.x & SUBPIXEL_MASK;
                shift.y = pen.y & SUBPIXEL_MASK;
 
-               if (render_context.evt_type == EVENT_POSITIONED) {
-                       shift.x += double_to_d6(x2scr_pos(render_priv, render_context.pos_x)) & SUBPIXEL_MASK;
-                       shift.y -= double_to_d6(y2scr_pos(render_priv, render_context.pos_y)) & SUBPIXEL_MASK;
+               if (render_priv->state.evt_type == EVENT_POSITIONED) {
+                       shift.x += double_to_d6(x2scr_pos(render_priv, render_priv->state.pos_x)) & SUBPIXEL_MASK;
+                       shift.y -= double_to_d6(y2scr_pos(render_priv, render_priv->state.pos_y)) & SUBPIXEL_MASK;
                }
 
-               ass_font_set_transform(render_context.font,
-                                      render_context.scale_x * render_priv->font_scale_x,
-                                      render_context.scale_y,
+               ass_font_set_transform(render_priv->state.font,
+                                      render_priv->state.scale_x * render_priv->font_scale_x,
+                                      render_priv->state.scale_y,
                                       &shift );
 
                get_outline_glyph(render_priv, code, text_info.glyphs + text_info.length, &shift);
@@ -1957,7 +1958,7 @@ static int ass_render_event(ass_renderer_t* render_priv, ass_event_t* event, eve
                text_info.glyphs[text_info.length].pos.y = pen.y >> 6;
 
                pen.x += text_info.glyphs[text_info.length].advance.x;
-               pen.x += double_to_d6(render_context.hspacing);
+               pen.x += double_to_d6(render_priv->state.hspacing);
                pen.y += text_info.glyphs[text_info.length].advance.y;
 
                previous = code;
@@ -1965,46 +1966,46 @@ static int ass_render_event(ass_renderer_t* render_priv, ass_event_t* event, eve
                text_info.glyphs[text_info.length].symbol = code;
                text_info.glyphs[text_info.length].linebreak = 0;
                for (i = 0; i < 4; ++i) {
-                       uint32_t clr = render_context.c[i];
-                       change_alpha(&clr, mult_alpha(_a(clr), render_context.fade), 1.);
+                       uint32_t clr = render_priv->state.c[i];
+                       change_alpha(&clr, mult_alpha(_a(clr), render_priv->state.fade), 1.);
                        text_info.glyphs[text_info.length].c[i] = clr;
                }
-               text_info.glyphs[text_info.length].effect_type = render_context.effect_type;
-               text_info.glyphs[text_info.length].effect_timing = render_context.effect_timing;
-               text_info.glyphs[text_info.length].effect_skip_timing = render_context.effect_skip_timing;
-               text_info.glyphs[text_info.length].be = render_context.be;
-               text_info.glyphs[text_info.length].blur = render_context.blur;
-               text_info.glyphs[text_info.length].shadow = render_context.shadow;
-               text_info.glyphs[text_info.length].frx = render_context.frx;
-               text_info.glyphs[text_info.length].fry = render_context.fry;
-               text_info.glyphs[text_info.length].frz = render_context.frz;
-               ass_font_get_asc_desc(render_context.font, code,
+               text_info.glyphs[text_info.length].effect_type = render_priv->state.effect_type;
+               text_info.glyphs[text_info.length].effect_timing = render_priv->state.effect_timing;
+               text_info.glyphs[text_info.length].effect_skip_timing = render_priv->state.effect_skip_timing;
+               text_info.glyphs[text_info.length].be = render_priv->state.be;
+               text_info.glyphs[text_info.length].blur = render_priv->state.blur;
+               text_info.glyphs[text_info.length].shadow = render_priv->state.shadow;
+               text_info.glyphs[text_info.length].frx = render_priv->state.frx;
+               text_info.glyphs[text_info.length].fry = render_priv->state.fry;
+               text_info.glyphs[text_info.length].frz = render_priv->state.frz;
+               ass_font_get_asc_desc(render_priv->state.font, code,
                                      &text_info.glyphs[text_info.length].asc,
                                      &text_info.glyphs[text_info.length].desc);
-               text_info.glyphs[text_info.length].asc *= render_context.scale_y;
-               text_info.glyphs[text_info.length].desc *= render_context.scale_y;
+               text_info.glyphs[text_info.length].asc *= render_priv->state.scale_y;
+               text_info.glyphs[text_info.length].desc *= render_priv->state.scale_y;
 
                // fill bitmap_hash_key
-               text_info.glyphs[text_info.length].hash_key.font = render_context.font;
-               text_info.glyphs[text_info.length].hash_key.size = render_context.font_size;
-               text_info.glyphs[text_info.length].hash_key.outline = render_context.border * 0xFFFF;
-               text_info.glyphs[text_info.length].hash_key.scale_x = render_context.scale_x * 0xFFFF;
-               text_info.glyphs[text_info.length].hash_key.scale_y = render_context.scale_y * 0xFFFF;
-               text_info.glyphs[text_info.length].hash_key.frx = render_context.frx * 0xFFFF;
-               text_info.glyphs[text_info.length].hash_key.fry = render_context.fry * 0xFFFF;
-               text_info.glyphs[text_info.length].hash_key.frz = render_context.frz * 0xFFFF;
-               text_info.glyphs[text_info.length].hash_key.bold = render_context.bold;
-               text_info.glyphs[text_info.length].hash_key.italic = render_context.italic;
+               text_info.glyphs[text_info.length].hash_key.font = render_priv->state.font;
+               text_info.glyphs[text_info.length].hash_key.size = render_priv->state.font_size;
+               text_info.glyphs[text_info.length].hash_key.outline = render_priv->state.border * 0xFFFF;
+               text_info.glyphs[text_info.length].hash_key.scale_x = render_priv->state.scale_x * 0xFFFF;
+               text_info.glyphs[text_info.length].hash_key.scale_y = render_priv->state.scale_y * 0xFFFF;
+               text_info.glyphs[text_info.length].hash_key.frx = render_priv->state.frx * 0xFFFF;
+               text_info.glyphs[text_info.length].hash_key.fry = render_priv->state.fry * 0xFFFF;
+               text_info.glyphs[text_info.length].hash_key.frz = render_priv->state.frz * 0xFFFF;
+               text_info.glyphs[text_info.length].hash_key.bold = render_priv->state.bold;
+               text_info.glyphs[text_info.length].hash_key.italic = render_priv->state.italic;
                text_info.glyphs[text_info.length].hash_key.ch = code;
                text_info.glyphs[text_info.length].hash_key.advance = shift;
-               text_info.glyphs[text_info.length].hash_key.be = render_context.be;
-               text_info.glyphs[text_info.length].hash_key.blur = render_context.blur;
+               text_info.glyphs[text_info.length].hash_key.be = render_priv->state.be;
+               text_info.glyphs[text_info.length].hash_key.blur = render_priv->state.blur;
 
                text_info.length++;
 
-               render_context.effect_type = EF_NONE;
-               render_context.effect_timing = 0;
-               render_context.effect_skip_timing = 0;
+               render_priv->state.effect_type = EF_NONE;
+               render_priv->state.effect_timing = 0;
+               render_priv->state.effect_skip_timing = 0;
        }
 
        if (text_info.length == 0) {
@@ -2017,15 +2018,15 @@ static int ass_render_event(ass_renderer_t* render_priv, ass_event_t* event, eve
        process_karaoke_effects(render_priv);
 
        // alignments
-       alignment = render_context.alignment;
+       alignment = render_priv->state.alignment;
        halign = alignment & 3;
        valign = alignment & 12;
 
-       MarginL = (event->MarginL) ? event->MarginL : render_context.style->MarginL;
-       MarginR = (event->MarginR) ? event->MarginR : render_context.style->MarginR;
-       MarginV = (event->MarginV) ? event->MarginV : render_context.style->MarginV;
+       MarginL = (event->MarginL) ? event->MarginL : render_priv->state.style->MarginL; 
+       MarginR = (event->MarginR) ? event->MarginR : render_priv->state.style->MarginR; 
+       MarginV = (event->MarginV) ? event->MarginV : render_priv->state.style->MarginV;
 
-       if (render_context.evt_type != EVENT_HSCROLL) {
+       if (render_priv->state.evt_type != EVENT_HSCROLL) {
                int max_text_width;
 
                // calculate max length of a line
@@ -2059,7 +2060,7 @@ static int ass_render_event(ass_renderer_t* render_priv, ass_event_t* event, eve
                                last_break = i - 1;
                        }
                }
-       } else { // render_context.evt_type == EVENT_HSCROLL
+       } else { // render_priv->state.evt_type == EVENT_HSCROLL
                measure_text(settings_priv);
        }
 
@@ -2069,19 +2070,19 @@ static int ass_render_event(ass_renderer_t* render_priv, ass_event_t* event, eve
        // determine device coordinates for text
 
        // x coordinate for everything except positioned events
-       if (render_context.evt_type == EVENT_NORMAL ||
-           render_context.evt_type == EVENT_VSCROLL) {
+       if (render_priv->state.evt_type == EVENT_NORMAL ||
+           render_priv->state.evt_type == EVENT_VSCROLL) {
                device_x = x2scr(render_priv, MarginL);
-       } else if (render_context.evt_type == EVENT_HSCROLL) {
-               if (render_context.scroll_direction == SCROLL_RL)
-                       device_x = x2scr(render_priv, render_priv->track->PlayResX - render_context.scroll_shift);
-               else if (render_context.scroll_direction == SCROLL_LR)
-                       device_x = x2scr(render_priv, render_context.scroll_shift) - (bbox.xMax - bbox.xMin);
+       } else if (render_priv->state.evt_type == EVENT_HSCROLL) {
+               if (render_priv->state.scroll_direction == SCROLL_RL)
+                       device_x = x2scr(render_priv, render_priv->track->PlayResX - render_priv->state.scroll_shift);
+               else if (render_priv->state.scroll_direction == SCROLL_LR)
+                       device_x = x2scr(render_priv, render_priv->state.scroll_shift) - (bbox.xMax - bbox.xMin);
        }
 
        // y coordinate for everything except positioned events
-       if (render_context.evt_type == EVENT_NORMAL ||
-           render_context.evt_type == EVENT_HSCROLL) {
+       if (render_priv->state.evt_type == EVENT_NORMAL ||
+           render_priv->state.evt_type == EVENT_HSCROLL) {
                if (valign == VALIGN_TOP) { // toptitle
                        device_y = y2scr_top(render_priv, MarginV) + d6_to_int(text_info.lines[0].asc);
                } else if (valign == VALIGN_CENTER) { // midtitle
@@ -2096,53 +2097,53 @@ static int ass_render_event(ass_renderer_t* render_priv, ass_event_t* event, eve
                        device_y -= d6_to_int(text_info.height);
                        device_y += d6_to_int(text_info.lines[0].asc);
                }
-       } else if (render_context.evt_type == EVENT_VSCROLL) {
-               if (render_context.scroll_direction == SCROLL_TB)
-                       device_y = y2scr(render_priv, render_context.clip_y0 + render_context.scroll_shift) - (bbox.yMax - bbox.yMin);
-               else if (render_context.scroll_direction == SCROLL_BT)
-                       device_y = y2scr(render_priv, render_context.clip_y1 - render_context.scroll_shift);
+       } else if (render_priv->state.evt_type == EVENT_VSCROLL) {
+               if (render_priv->state.scroll_direction == SCROLL_TB)
+                       device_y = y2scr(render_priv, render_priv->state.clip_y0 + render_priv->state.scroll_shift) - (bbox.yMax - bbox.yMin);
+               else if (render_priv->state.scroll_direction == SCROLL_BT)
+                       device_y = y2scr(render_priv, render_priv->state.clip_y1 - render_priv->state.scroll_shift);
        }
 
        // positioned events are totally different
-       if (render_context.evt_type == EVENT_POSITIONED) {
+       if (render_priv->state.evt_type == EVENT_POSITIONED) {
                int base_x = 0;
                int base_y = 0;
-               mp_msg(MSGT_ASS, MSGL_DBG2, "positioned event at %f, %f\n", render_context.pos_x, render_context.pos_y);
+               mp_msg(MSGT_ASS, MSGL_DBG2, "positioned event at %f, %f\n", render_priv->state.pos_x, render_priv->state.pos_y);
                get_base_point(bbox, alignment, &base_x, &base_y);
-               device_x = x2scr_pos(render_priv, render_context.pos_x) - base_x;
-               device_y = y2scr_pos(render_priv, render_context.pos_y) - base_y;
+               device_x = x2scr_pos(render_priv, render_priv->state.pos_x) - base_x;
+               device_y = y2scr_pos(render_priv, render_priv->state.pos_y) - base_y;
        }
 
        // fix clip coordinates (they depend on alignment)
-       if (render_context.evt_type == EVENT_NORMAL ||
-           render_context.evt_type == EVENT_HSCROLL ||
-           render_context.evt_type == EVENT_VSCROLL) {
-               render_context.clip_x0 = x2scr(render_priv, render_context.clip_x0);
-               render_context.clip_x1 = x2scr(render_priv, render_context.clip_x1);
+       if (render_priv->state.evt_type == EVENT_NORMAL ||
+           render_priv->state.evt_type == EVENT_HSCROLL ||
+           render_priv->state.evt_type == EVENT_VSCROLL) {
+               render_priv->state.clip_x0 = x2scr(render_priv, render_priv->state.clip_x0);
+               render_priv->state.clip_x1 = x2scr(render_priv, render_priv->state.clip_x1);
                if (valign == VALIGN_TOP) {
-                       render_context.clip_y0 = y2scr_top(render_priv, render_context.clip_y0);
-                       render_context.clip_y1 = y2scr_top(render_priv, render_context.clip_y1);
+                       render_priv->state.clip_y0 = y2scr_top(render_priv, render_priv->state.clip_y0);
+                       render_priv->state.clip_y1 = y2scr_top(render_priv, render_priv->state.clip_y1);
                } else if (valign == VALIGN_CENTER) {
-                       render_context.clip_y0 = y2scr(render_priv, render_context.clip_y0);
-                       render_context.clip_y1 = y2scr(render_priv, render_context.clip_y1);
+                       render_priv->state.clip_y0 = y2scr(render_priv, render_priv->state.clip_y0);
+                       render_priv->state.clip_y1 = y2scr(render_priv, render_priv->state.clip_y1);
                } else if (valign == VALIGN_SUB) {
-                       render_context.clip_y0 = y2scr_sub(render_priv, render_context.clip_y0);
-                       render_context.clip_y1 = y2scr_sub(render_priv, render_context.clip_y1);
+                       render_priv->state.clip_y0 = y2scr_sub(render_priv, render_priv->state.clip_y0);
+                       render_priv->state.clip_y1 = y2scr_sub(render_priv, render_priv->state.clip_y1);
                }
-       } else if (render_context.evt_type == EVENT_POSITIONED) {
-               render_context.clip_x0 = x2scr_pos(render_priv, render_context.clip_x0);
-               render_context.clip_x1 = x2scr_pos(render_priv, render_context.clip_x1);
-               render_context.clip_y0 = y2scr_pos(render_priv, render_context.clip_y0);
-               render_context.clip_y1 = y2scr_pos(render_priv, render_context.clip_y1);
+       } else if (render_priv->state.evt_type == EVENT_POSITIONED) {
+               render_priv->state.clip_x0 = x2scr_pos(render_priv, render_priv->state.clip_x0);
+               render_priv->state.clip_x1 = x2scr_pos(render_priv, render_priv->state.clip_x1);
+               render_priv->state.clip_y0 = y2scr_pos(render_priv, render_priv->state.clip_y0);
+               render_priv->state.clip_y1 = y2scr_pos(render_priv, render_priv->state.clip_y1);
        }
 
        // calculate rotation parameters
        {
                FT_Vector center;
 
-               if (render_context.have_origin) {
-                       center.x = x2scr(render_priv, render_context.org_x);
-                       center.y = y2scr(render_priv, render_context.org_y);
+               if (render_priv->state.have_origin) {
+                       center.x = x2scr(render_priv, render_priv->state.org_x);
+                       center.y = y2scr(render_priv, render_priv->state.org_y);
                } else {
                        int bx = 0, by = 0;
                        get_base_point(bbox, alignment, &bx, &by);
@@ -2170,7 +2171,7 @@ static int ass_render_event(ass_renderer_t* render_priv, ass_event_t* event, eve
        memset(event_images, 0, sizeof(*event_images));
        event_images->top = device_y - d6_to_int(text_info.lines[0].asc);
        event_images->height = d6_to_int(text_info.height);
-       event_images->detect_collisions = render_context.detect_collisions;
+       event_images->detect_collisions = render_priv->state.detect_collisions;
        event_images->shift_direction = (valign == VALIGN_TOP) ? 1 : -1;
        event_images->event = event;
        event_images->imgs = render_text(render_priv, &text_info, device_x, device_y);