diff options
Diffstat (limited to 'libass/ass_render.c')
-rw-r--r-- | libass/ass_render.c | 274 |
1 files changed, 141 insertions, 133 deletions
diff --git a/libass/ass_render.c b/libass/ass_render.c index b4c43ac4..177c9f5c 100644 --- a/libass/ass_render.c +++ b/libass/ass_render.c @@ -205,16 +205,15 @@ typedef struct frame_context_s { static text_info_t text_info; static render_context_t render_context; -static frame_context_t frame_context; struct render_priv_s { int top, height; int render_id; }; -static void ass_lazy_track_init(ass_settings_t* settings_priv) +static void ass_lazy_track_init(frame_context_t* frame_priv, ass_settings_t* settings_priv) { - ass_track_t* track = frame_context.track; + ass_track_t* track = frame_priv->track; if (track->PlayResX && track->PlayResY) return; if (!track->PlayResX && !track->PlayResY) { @@ -222,8 +221,8 @@ static void ass_lazy_track_init(ass_settings_t* settings_priv) track->PlayResX = 384; track->PlayResY = 288; } else { - double orig_aspect = (settings_priv->aspect * frame_context.height * frame_context.orig_width) / - frame_context.orig_height / frame_context.width; + double orig_aspect = (settings_priv->aspect * frame_priv->height * frame_priv->orig_width) / + frame_priv->orig_height / frame_priv->width; if (!track->PlayResY && track->PlayResX == 1280) { track->PlayResY = 1024; mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_PlayResYUndefinedSettingY, track->PlayResY); @@ -245,10 +244,10 @@ ass_renderer_t* ass_renderer_init(ass_library_t* library) int error; FT_Library ft; ass_renderer_t* priv = 0; + frame_context_t* frame_priv = 0; int vmajor, vminor, vpatch; memset(&render_context, 0, sizeof(render_context)); - memset(&frame_context, 0, sizeof(frame_context)); memset(&text_info, 0, sizeof(text_info)); error = FT_Init_FreeType( &ft ); @@ -268,6 +267,12 @@ ass_renderer_t* ass_renderer_init(ass_library_t* library) FT_Done_FreeType(ft); goto ass_init_exit; } + + frame_priv = calloc(1, sizeof(frame_context_t)); + if (!frame_priv) { + FT_Done_FreeType(ft); + goto ass_init_exit; + } priv->synth_priv = ass_synth_init(BLUR_MAX_RADIUS); @@ -502,7 +507,7 @@ static void render_overlap(ass_image_t** last_tail, ass_image_t** tail, bitmap_h * \brief Convert text_info_t struct to ass_image_t list * Splits glyphs in halves when needed (for \kf karaoke). */ -static ass_image_t* render_text(text_info_t* text_info, int dst_x, int dst_y) +static ass_image_t* render_text(frame_context_t* frame_priv, text_info_t* text_info, int dst_x, int dst_y) { int pen_x, pen_y; int i; @@ -518,8 +523,8 @@ static ass_image_t* render_text(text_info_t* text_info, int dst_x, int dst_y) if ((info->symbol == 0) || (info->symbol == '\n') || !info->bm_s || (info->shadow == 0)) continue; - pen_x = dst_x + info->pos.x + ROUND(info->shadow * frame_context.border_scale); - pen_y = dst_y + info->pos.y + ROUND(info->shadow * frame_context.border_scale); + pen_x = dst_x + info->pos.x + ROUND(info->shadow * frame_priv->border_scale); + pen_y = dst_y + info->pos.y + ROUND(info->shadow * frame_priv->border_scale); bm = info->bm_s; here_tail = tail; @@ -578,42 +583,42 @@ static ass_image_t* render_text(text_info_t* text_info, int dst_x, int dst_y) /** * \brief Mapping between script and screen coordinates */ -static int x2scr(ass_settings_t* priv, double x) { - return x*frame_context.orig_width_nocrop / frame_context.track->PlayResX + +static int x2scr(frame_context_t* frame_priv, ass_settings_t* priv, double x) { + return x*frame_priv->orig_width_nocrop / frame_priv->track->PlayResX + FFMAX(priv->left_margin, 0); } -static double x2scr_pos(ass_settings_t* priv, double x) { - return x*frame_context.orig_width / frame_context.track->PlayResX + +static double x2scr_pos(frame_context_t* frame_priv, ass_settings_t* priv, double x) { + return x*frame_priv->orig_width / frame_priv->track->PlayResX + priv->left_margin; } /** * \brief Mapping between script and screen coordinates */ -static double y2scr(ass_settings_t* priv, double y) { - return y * frame_context.orig_height_nocrop / frame_context.track->PlayResY + +static double y2scr(frame_context_t* frame_priv, ass_settings_t* priv, double y) { + return y * frame_priv->orig_height_nocrop / frame_priv->track->PlayResY + FFMAX(priv->top_margin, 0); } -static double y2scr_pos(ass_settings_t* priv, double y) { - return y * frame_context.orig_height / frame_context.track->PlayResY + +static double y2scr_pos(frame_context_t* frame_priv, ass_settings_t* priv, double y) { + return y * frame_priv->orig_height / frame_priv->track->PlayResY + priv->top_margin; } // the same for toptitles -static int y2scr_top(ass_settings_t* priv, double y) { +static int y2scr_top(frame_context_t* frame_priv, ass_settings_t* priv, double y) { if (priv->use_margins) - return y * frame_context.orig_height_nocrop / frame_context.track->PlayResY; + return y * frame_priv->orig_height_nocrop / frame_priv->track->PlayResY; else - return y * frame_context.orig_height_nocrop / frame_context.track->PlayResY + + return y * frame_priv->orig_height_nocrop / frame_priv->track->PlayResY + FFMAX(priv->top_margin, 0); } // the same for subtitles -static int y2scr_sub(ass_settings_t* priv, double y) { +static int y2scr_sub(frame_context_t* frame_priv, ass_settings_t* priv, double y) { if (priv->use_margins) - return y * frame_context.orig_height_nocrop / frame_context.track->PlayResY + + return y * frame_priv->orig_height_nocrop / frame_priv->track->PlayResY + FFMAX(priv->top_margin, 0) + FFMAX(priv->bottom_margin, 0); else - return y * frame_context.orig_height_nocrop / frame_context.track->PlayResY + + return y * frame_priv->orig_height_nocrop / frame_priv->track->PlayResY + FFMAX(priv->top_margin, 0); } @@ -653,14 +658,14 @@ static inline int mystrcmp(char** p, const char* sample) { return 0; } -static void change_font_size(double sz) +static void change_font_size(frame_context_t* frame_priv, double sz) { - double size = sz * frame_context.font_scale; + double size = sz * frame_priv->font_scale; if (size < 1) size = 1; - else if (size > frame_context.height * 2) - size = frame_context.height * 2; + else if (size > frame_priv->height * 2) + size = frame_priv->height * 2; ass_font_set_size(render_context.font, size); @@ -670,10 +675,10 @@ static void change_font_size(double sz) /** * \brief Change current font, using setting from render_context. */ -static void update_font(void) +static void update_font(frame_context_t* frame_priv) { unsigned val; - ass_renderer_t* priv = frame_context.ass_priv; + ass_renderer_t* priv = frame_priv->ass_priv; ass_font_desc_t desc; desc.family = strdup(render_context.family); desc.treat_family_as_pattern = render_context.treat_family_as_pattern; @@ -693,14 +698,14 @@ static void update_font(void) free(desc.family); if (render_context.font) - change_font_size(render_context.font_size); + change_font_size(frame_priv, render_context.font_size); } /** * \brief Change border width * negative value resets border to style value */ -static void change_border(ass_renderer_t* render_priv, double border) +static void change_border(frame_context_t* frame_priv, ass_renderer_t* render_priv, double border) { int b; if (!render_context.font) return; @@ -713,7 +718,7 @@ static void change_border(ass_renderer_t* render_priv, double border) } render_context.border = border; - b = 64 * border * frame_context.border_scale; + b = 64 * border * frame_priv->border_scale; if (b > 0) { if (!render_context.stroker) { int error; @@ -800,14 +805,14 @@ static unsigned interpolate_alpha(long long now, return a; } -static void reset_render_context(ass_renderer_t*); +static void reset_render_context(frame_context_t*, ass_renderer_t*); /** * \brief Parse style override tag. * \param p string to parse * \param pwr multiplier for some tag effects (comes from \t tags) */ -static char* parse_tag(ass_renderer_t* render_priv, char* p, double pwr) { +static char* parse_tag(frame_context_t* frame_priv, ass_renderer_t* render_priv, char* p, double pwr) { #define skip_to(x) while ((*p != (x)) && (*p != '}') && (*p != 0)) { ++p;} #define skip(x) if (*p == (x)) ++p; else { return p; } @@ -892,14 +897,14 @@ static char* parse_tag(ass_renderer_t* render_priv, char* p, double pwr) { else val = render_context.style->FontSize; if (render_context.font) - change_font_size(val); + change_font_size(frame_priv, val); } else if (mystrcmp(&p, "bord")) { double val; if (mystrtod(&p, &val)) val = render_context.border * ( 1 - pwr ) + val * pwr; else val = -1.; // reset to default - change_border(render_priv, val); + change_border(frame_priv, render_priv, val); } else if (mystrcmp(&p, "move")) { double x1, x2, y1, y2; long long t1, t2, delta_t, t; @@ -927,7 +932,7 @@ static char* parse_tag(ass_renderer_t* render_priv, char* p, double pwr) { } skip(')'); delta_t = t2 - t1; - t = frame_context.time - render_context.event->Start; + t = frame_priv->time - render_context.event->Start; if (t < t1) k = 0.; else if (t > t2) @@ -975,7 +980,7 @@ static char* parse_tag(ass_renderer_t* render_priv, char* p, double pwr) { if (render_context.family) free(render_context.family); render_context.family = family; - update_font(); + update_font(frame_priv); } else if (mystrcmp(&p, "alpha")) { uint32_t val; int i; @@ -1058,7 +1063,7 @@ static char* parse_tag(ass_renderer_t* render_priv, char* p, double pwr) { mystrtoll(&p, &t4); } skip(')'); - render_context.fade = interpolate_alpha(frame_context.time - render_context.event->Start, t1, t2, t3, t4, a1, a2, a3); + render_context.fade = interpolate_alpha(frame_priv->time - render_context.event->Start, t1, t2, t3, t4, a1, a2, a3); } else if (mystrcmp(&p, "org")) { int v1, v2; skip('('); @@ -1103,7 +1108,7 @@ static char* parse_tag(ass_renderer_t* render_priv, char* p, double pwr) { delta_t = v2 - v1; if (v3 < 0.) v3 = 0.; - t = frame_context.time - render_context.event->Start; // FIXME: move to render_context + t = frame_priv->time - render_context.event->Start; // FIXME: move to render_context if (t <= t1) k = 0.; else if (t >= t2) @@ -1113,7 +1118,7 @@ static char* parse_tag(ass_renderer_t* render_priv, char* p, double pwr) { k = pow(((double)(t - t1)) / delta_t, v3); } while (*p == '\\') - p = parse_tag(render_priv, p, k); // maybe k*pwr ? no, specs forbid nested \t's + p = parse_tag(frame_priv, render_priv, p, k); // maybe k*pwr ? no, specs forbid nested \t's skip_to(')'); // in case there is some unknown tag or a comment skip(')'); } else if (mystrcmp(&p, "clip")) { @@ -1136,8 +1141,8 @@ static char* parse_tag(ass_renderer_t* render_priv, char* p, double pwr) { } else { render_context.clip_x0 = 0; render_context.clip_y0 = 0; - render_context.clip_x1 = frame_context.track->PlayResX; - render_context.clip_y1 = frame_context.track->PlayResY; + render_context.clip_x1 = frame_priv->track->PlayResX; + render_context.clip_y1 = frame_priv->track->PlayResY; } } else if (mystrcmp(&p, "c")) { uint32_t val; @@ -1166,7 +1171,7 @@ static char* parse_tag(ass_renderer_t* render_priv, char* p, double pwr) { } mp_msg(MSGT_ASS, MSGL_DBG2, "single c/a at %f: %c%c = %X \n", pwr, n, cmd, render_context.c[cidx]); } else if (mystrcmp(&p, "r")) { - reset_render_context(render_priv); + reset_render_context(frame_priv, render_priv); } else if (mystrcmp(&p, "be")) { int val; if (mystrtoi(&p, &val)) { @@ -1183,7 +1188,7 @@ static char* parse_tag(ass_renderer_t* render_priv, char* p, double pwr) { render_context.bold = b; } else render_context.bold = render_context.style->Bold; - update_font(); + update_font(frame_priv); } else if (mystrcmp(&p, "i")) { int i; if (mystrtoi(&p, &i)) { @@ -1191,7 +1196,7 @@ static char* parse_tag(ass_renderer_t* render_priv, char* p, double pwr) { render_context.italic = i; } else render_context.italic = render_context.style->Italic; - update_font(); + update_font(frame_priv); } else if (mystrcmp(&p, "kf") || mystrcmp(&p, "K")) { int val = 0; mystrtoi(&p, &val); @@ -1241,14 +1246,14 @@ static char* parse_tag(ass_renderer_t* render_priv, char* p, double pwr) { * \return ucs4 code of the next char * On return str points to the unparsed part of the string */ -static unsigned get_next_char(ass_renderer_t* render_priv, char** str) +static unsigned get_next_char(frame_context_t* frame_priv, ass_renderer_t* render_priv, char** str) { char* p = *str; unsigned chr; if (*p == '{') { // '\0' goes here p++; while (1) { - p = parse_tag(render_priv, p, 1.); + p = parse_tag(frame_priv, render_priv, p, 1.); if (*p == '}') { // end of tag p++; if (*p == '{') { @@ -1268,7 +1273,7 @@ static unsigned get_next_char(ass_renderer_t* render_priv, char** str) return ' '; } if (*p == '\\') { - if ((*(p+1) == 'N') || ((*(p+1) == 'n') && (frame_context.track->WrapStyle == 2))) { + if ((*(p+1) == 'N') || ((*(p+1) == 'n') && (frame_priv->track->WrapStyle == 2))) { p += 2; *str = p; return '\n'; @@ -1283,7 +1288,7 @@ static unsigned get_next_char(ass_renderer_t* render_priv, char** str) return chr; } -static void apply_transition_effects(ass_event_t* event) +static void apply_transition_effects(frame_context_t* frame_priv, ass_event_t* event) { int v[4]; int cnt; @@ -1309,7 +1314,7 @@ static void apply_transition_effects(ass_event_t* event) delay = v[0]; if (delay == 0) delay = 1; // ? - render_context.scroll_shift = (frame_context.time - render_context.event->Start) / delay; + render_context.scroll_shift = (frame_priv->time - render_context.event->Start) / delay; render_context.evt_type = EVENT_HSCROLL; return; } @@ -1332,14 +1337,14 @@ static void apply_transition_effects(ass_event_t* event) } delay = v[2]; if (delay == 0) delay = 1; // ? - render_context.scroll_shift = (frame_context.time - render_context.event->Start) / delay; + render_context.scroll_shift = (frame_priv->time - render_context.event->Start) / delay; if (v[0] < v[1]) { y0 = v[0]; y1 = v[1]; } else { y0 = v[1]; y1 = v[0]; } if (y1 == 0) - y1 = frame_context.track->PlayResY; // y0=y1=0 means fullscreen scrolling + y1 = frame_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; @@ -1352,7 +1357,7 @@ static void apply_transition_effects(ass_event_t* event) * \brief partially reset render_context to style values * Works like {\r}: resets some style overrides */ -static void reset_render_context(ass_renderer_t* render_priv) +static void reset_render_context(frame_context_t* frame_priv, ass_renderer_t* render_priv) { render_context.c[0] = render_context.style->PrimaryColour; render_context.c[1] = render_context.style->SecondaryColour; @@ -1366,9 +1371,9 @@ static void reset_render_context(ass_renderer_t* render_priv) 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; - update_font(); + update_font(frame_priv); - change_border(render_priv, -1.); + change_border(frame_priv, 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; @@ -1384,12 +1389,12 @@ static void reset_render_context(ass_renderer_t* render_priv) /** * \brief Start new event. Reset render_context. */ -static void init_render_context(ass_renderer_t* render_priv, ass_event_t* event) +static void init_render_context(frame_context_t *frame_priv, ass_renderer_t* render_priv, ass_event_t* event) { render_context.event = event; - render_context.style = frame_context.track->styles + event->Style; + render_context.style = frame_priv->track->styles + event->Style; - reset_render_context(render_priv); + reset_render_context(frame_priv, render_priv); render_context.evt_type = EVENT_NORMAL; render_context.alignment = render_context.style->Alignment; @@ -1400,8 +1405,8 @@ static void init_render_context(ass_renderer_t* render_priv, ass_event_t* event) render_context.have_origin = 0; render_context.clip_x0 = 0; render_context.clip_y0 = 0; - render_context.clip_x1 = frame_context.track->PlayResX; - render_context.clip_y1 = frame_context.track->PlayResY; + render_context.clip_x1 = frame_priv->track->PlayResX; + render_context.clip_y1 = frame_priv->track->PlayResY; render_context.detect_collisions = 1; render_context.fade = 0; render_context.drawing_mode = 0; @@ -1409,7 +1414,7 @@ static void init_render_context(ass_renderer_t* render_priv, ass_event_t* event) render_context.effect_timing = 0; render_context.effect_skip_timing = 0; - apply_transition_effects(event); + apply_transition_effects(frame_priv, event); } static void free_render_context(void) @@ -1426,7 +1431,7 @@ static void free_render_context(void) * and add them to cache. * The glyphs are returned in info->glyph and info->outline_glyph */ -static void get_outline_glyph(ass_settings_t* priv, int symbol, glyph_info_t* info, FT_Vector* advance) +static void get_outline_glyph(frame_context_t* frame_priv, ass_settings_t* priv, int symbol, glyph_info_t* info, FT_Vector* advance) { int error; glyph_hash_val_t* val; @@ -1454,7 +1459,7 @@ static void get_outline_glyph(ass_settings_t* priv, int symbol, glyph_info_t* in info->advance.y = val->advance.y; } else { glyph_hash_val_t v; - info->glyph = ass_font_get_glyph(frame_context.ass_priv->fontconfig_priv, render_context.font, symbol, priv->hinting); + info->glyph = ass_font_get_glyph(frame_priv->ass_priv->fontconfig_priv, render_context.font, symbol, priv->hinting); if (!info->glyph) return; info->advance.x = d16_to_d6(info->glyph->advance.x); @@ -1489,7 +1494,7 @@ static void transform_3d(FT_Vector shift, FT_Glyph* glyph, FT_Glyph* glyph2, dou * After that, bitmaps are added to the cache. * They are returned in info->bm (glyph), info->bm_o (outline) and info->bm_s (shadow). */ -static void get_bitmap_glyph(ass_renderer_t* render_priv, glyph_info_t* info) +static void get_bitmap_glyph(frame_context_t* frame_priv, ass_renderer_t* render_priv, glyph_info_t* info) { bitmap_hash_val_t* val; bitmap_hash_key_t* key = &info->hash_key; @@ -1517,7 +1522,7 @@ static void get_bitmap_glyph(ass_renderer_t* render_priv, glyph_info_t* info) error = glyph_to_bitmap(render_priv->synth_priv, info->glyph, info->outline_glyph, &info->bm, &info->bm_o, - &info->bm_s, info->be, info->blur * frame_context.border_scale); + &info->bm_s, info->be, info->blur * frame_priv->border_scale); if (error) info->symbol = 0; @@ -1604,7 +1609,7 @@ static void wrap_lines_smart(ass_settings_t* priv, int max_text_width) mp_msg(MSGT_ASS, MSGL_DBG2, "forced line break at %d\n", break_at); } - if ((len >= max_text_width) && (frame_context.track->WrapStyle != 2)) { + if ((len >= max_text_width) && (render_priv->track->WrapStyle != 2)) { break_type = 1; break_at = last_space; if (break_at == -1) @@ -1714,7 +1719,7 @@ static void wrap_lines_smart(ass_settings_t* priv, int max_text_width) * 2. sets effect_timing for all glyphs to x coordinate of the border line between the left and right karaoke parts * (left part is filled with PrimaryColour, right one - with SecondaryColour). */ -static void process_karaoke_effects(void) +static void process_karaoke_effects(frame_context_t* frame_priv) { glyph_info_t *cur, *cur2; glyph_info_t *s1, *e1; // start and end of the current word @@ -1727,7 +1732,7 @@ static void process_karaoke_effects(void) int x; int x_start, x_end; - tm_current = frame_context.time - render_context.event->Start; + tm_current = frame_priv->time - render_context.event->Start; timing = 0; s1 = s2 = 0; for (i = 0; i <= text_info.length; ++i) { @@ -1879,7 +1884,7 @@ static void transform_3d(FT_Vector shift, FT_Glyph* glyph, FT_Glyph* glyph2, dou * \param event_images struct containing resulting images, will also be initialized * Process event, appending resulting ass_image_t's to images_root. */ -static int ass_render_event(ass_renderer_t* render_priv, ass_event_t* event, event_images_t* event_images) +static int ass_render_event(frame_context_t* frame_priv, ass_renderer_t* render_priv, ass_event_t* event, event_images_t* event_images) { char* p; FT_UInt previous; @@ -1895,7 +1900,7 @@ static int ass_render_event(ass_renderer_t* render_priv, ass_event_t* event, eve int device_x = 0, device_y = 0; ass_settings_t* settings_priv = &render_priv->settings; - if (event->Style >= frame_context.track->n_styles) { + if (event->Style >= frame_priv->track->n_styles) { mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_NoStyleFound); return 1; } @@ -1904,7 +1909,7 @@ static int ass_render_event(ass_renderer_t* render_priv, ass_event_t* event, eve return 1; } - init_render_context(render_priv, event); + init_render_context(frame_priv, render_priv, event); text_info.length = 0; pen.x = 0; @@ -1917,7 +1922,7 @@ static int ass_render_event(ass_renderer_t* render_priv, ass_event_t* event, eve // get next char, executing style override // this affects render_context do { - code = get_next_char(render_priv, &p); + code = get_next_char(frame_priv, render_priv, &p); } while (code && render_context.drawing_mode); // skip everything in drawing mode // face could have been changed in get_next_char @@ -1931,7 +1936,7 @@ static int ass_render_event(ass_renderer_t* render_priv, ass_event_t* event, eve if (text_info.length >= MAX_GLYPHS) { mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_MAX_GLYPHS_Reached, - (int)(event - frame_context.track->events), event->Start, event->Duration, event->Text); + (int)(event - frame_priv->track->events), event->Start, event->Duration, event->Text); break; } @@ -1946,16 +1951,16 @@ static int ass_render_event(ass_renderer_t* render_priv, ass_event_t* event, eve shift.y = pen.y & SUBPIXEL_MASK; if (render_context.evt_type == EVENT_POSITIONED) { - shift.x += double_to_d6(x2scr_pos(settings_priv, render_context.pos_x)) & SUBPIXEL_MASK; - shift.y -= double_to_d6(y2scr_pos(settings_priv, render_context.pos_y)) & SUBPIXEL_MASK; + shift.x += double_to_d6(x2scr_pos(frame_priv, settings_priv, render_context.pos_x)) & SUBPIXEL_MASK; + shift.y -= double_to_d6(y2scr_pos(frame_priv, settings_priv, render_context.pos_y)) & SUBPIXEL_MASK; } ass_font_set_transform(render_context.font, - render_context.scale_x * frame_context.font_scale_x, + render_context.scale_x * frame_priv->font_scale_x, render_context.scale_y, &shift ); - get_outline_glyph(settings_priv, code, text_info.glyphs + text_info.length, &shift); + get_outline_glyph(frame_priv, settings_priv, code, text_info.glyphs + text_info.length, &shift); text_info.glyphs[text_info.length].pos.x = pen.x >> 6; text_info.glyphs[text_info.length].pos.y = pen.y >> 6; @@ -2018,7 +2023,7 @@ static int ass_render_event(ass_renderer_t* render_priv, ass_event_t* event, eve } // depends on glyph x coordinates being monotonous, so it should be done before line wrap - process_karaoke_effects(); + process_karaoke_effects(frame_priv); // alignments alignment = render_context.alignment; @@ -2033,7 +2038,7 @@ static int ass_render_event(ass_renderer_t* render_priv, ass_event_t* event, eve int max_text_width; // calculate max length of a line - max_text_width = x2scr(settings_priv, frame_context.track->PlayResX - MarginR) - x2scr(settings_priv, MarginL); + max_text_width = x2scr(frame_priv, settings_priv, frame_priv->track->PlayResX - MarginR) - x2scr(frame_priv, settings_priv, MarginL); // rearrange text in several lines wrap_lines_smart(settings_priv, max_text_width); @@ -2075,36 +2080,36 @@ static int ass_render_event(ass_renderer_t* render_priv, ass_event_t* event, eve // x coordinate for everything except positioned events if (render_context.evt_type == EVENT_NORMAL || render_context.evt_type == EVENT_VSCROLL) { - device_x = x2scr(settings_priv, MarginL); + device_x = x2scr(frame_priv, settings_priv, MarginL); } else if (render_context.evt_type == EVENT_HSCROLL) { if (render_context.scroll_direction == SCROLL_RL) - device_x = x2scr(settings_priv, frame_context.track->PlayResX - render_context.scroll_shift); + device_x = x2scr(frame_priv, settings_priv, frame_priv->track->PlayResX - render_context.scroll_shift); else if (render_context.scroll_direction == SCROLL_LR) - device_x = x2scr(settings_priv, render_context.scroll_shift) - (bbox.xMax - bbox.xMin); + device_x = x2scr(frame_priv, settings_priv, render_context.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 (valign == VALIGN_TOP) { // toptitle - device_y = y2scr_top(settings_priv, MarginV) + d6_to_int(text_info.lines[0].asc); + device_y = y2scr_top(frame_priv, settings_priv, MarginV) + d6_to_int(text_info.lines[0].asc); } else if (valign == VALIGN_CENTER) { // midtitle - int scr_y = y2scr(settings_priv, frame_context.track->PlayResY / 2); + int scr_y = y2scr(frame_priv, settings_priv, frame_priv->track->PlayResY / 2); device_y = scr_y - (bbox.yMax - bbox.yMin) / 2; } else { // subtitle int scr_y; if (valign != VALIGN_SUB) mp_msg(MSGT_ASS, MSGL_V, "Invalid valign, supposing 0 (subtitle)\n"); - scr_y = y2scr_sub(settings_priv, frame_context.track->PlayResY - MarginV); + scr_y = y2scr_sub(frame_priv, settings_priv, frame_priv->track->PlayResY - MarginV); device_y = scr_y; 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(settings_priv, render_context.clip_y0 + render_context.scroll_shift) - (bbox.yMax - bbox.yMin); + device_y = y2scr(frame_priv, settings_priv, render_context.clip_y0 + render_context.scroll_shift) - (bbox.yMax - bbox.yMin); else if (render_context.scroll_direction == SCROLL_BT) - device_y = y2scr(settings_priv, render_context.clip_y1 - render_context.scroll_shift); + device_y = y2scr(frame_priv, settings_priv, render_context.clip_y1 - render_context.scroll_shift); } // positioned events are totally different @@ -2113,31 +2118,31 @@ static int ass_render_event(ass_renderer_t* render_priv, ass_event_t* event, eve int base_y = 0; mp_msg(MSGT_ASS, MSGL_DBG2, "positioned event at %f, %f\n", render_context.pos_x, render_context.pos_y); get_base_point(bbox, alignment, &base_x, &base_y); - device_x = x2scr_pos(settings_priv, render_context.pos_x) - base_x; - device_y = y2scr_pos(settings_priv, render_context.pos_y) - base_y; + device_x = x2scr_pos(frame_priv, settings_priv, render_context.pos_x) - base_x; + device_y = y2scr_pos(frame_priv, settings_priv, render_context.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(settings_priv, render_context.clip_x0); - render_context.clip_x1 = x2scr(settings_priv, render_context.clip_x1); + render_context.clip_x0 = x2scr(frame_priv, settings_priv, render_context.clip_x0); + render_context.clip_x1 = x2scr(frame_priv, settings_priv, render_context.clip_x1); if (valign == VALIGN_TOP) { - render_context.clip_y0 = y2scr_top(settings_priv, render_context.clip_y0); - render_context.clip_y1 = y2scr_top(settings_priv, render_context.clip_y1); + render_context.clip_y0 = y2scr_top(frame_priv, settings_priv, render_context.clip_y0); + render_context.clip_y1 = y2scr_top(frame_priv, settings_priv, render_context.clip_y1); } else if (valign == VALIGN_CENTER) { - render_context.clip_y0 = y2scr(settings_priv, render_context.clip_y0); - render_context.clip_y1 = y2scr(settings_priv, render_context.clip_y1); + render_context.clip_y0 = y2scr(frame_priv, settings_priv, render_context.clip_y0); + render_context.clip_y1 = y2scr(frame_priv, settings_priv, render_context.clip_y1); } else if (valign == VALIGN_SUB) { - render_context.clip_y0 = y2scr_sub(settings_priv, render_context.clip_y0); - render_context.clip_y1 = y2scr_sub(settings_priv, render_context.clip_y1); + render_context.clip_y0 = y2scr_sub(frame_priv, settings_priv, render_context.clip_y0); + render_context.clip_y1 = y2scr_sub(frame_priv, settings_priv, render_context.clip_y1); } } else if (render_context.evt_type == EVENT_POSITIONED) { - render_context.clip_x0 = x2scr_pos(settings_priv, render_context.clip_x0); - render_context.clip_x1 = x2scr_pos(settings_priv, render_context.clip_x1); - render_context.clip_y0 = y2scr_pos(settings_priv, render_context.clip_y0); - render_context.clip_y1 = y2scr_pos(settings_priv, render_context.clip_y1); + render_context.clip_x0 = x2scr_pos(frame_priv, settings_priv, render_context.clip_x0); + render_context.clip_x1 = x2scr_pos(frame_priv, settings_priv, render_context.clip_x1); + render_context.clip_y0 = y2scr_pos(frame_priv, settings_priv, render_context.clip_y0); + render_context.clip_y1 = y2scr_pos(frame_priv, settings_priv, render_context.clip_y1); } // calculate rotation parameters @@ -2145,8 +2150,8 @@ static int ass_render_event(ass_renderer_t* render_priv, ass_event_t* event, eve FT_Vector center; if (render_context.have_origin) { - center.x = x2scr(settings_priv, render_context.org_x); - center.y = y2scr(settings_priv, render_context.org_y); + center.x = x2scr(frame_priv, settings_priv, render_context.org_x); + center.y = y2scr(frame_priv, settings_priv, render_context.org_y); } else { int bx = 0, by = 0; get_base_point(bbox, alignment, &bx, &by); @@ -2169,7 +2174,7 @@ static int ass_render_event(ass_renderer_t* render_priv, ass_event_t* event, eve // convert glyphs to bitmaps for (i = 0; i < text_info.length; ++i) - get_bitmap_glyph(render_priv, text_info.glyphs + i); + get_bitmap_glyph(frame_priv, render_priv, text_info.glyphs + i); memset(event_images, 0, sizeof(*event_images)); event_images->top = device_y - d6_to_int(text_info.lines[0].asc); @@ -2177,7 +2182,7 @@ static int ass_render_event(ass_renderer_t* render_priv, ass_event_t* event, eve event_images->detect_collisions = render_context.detect_collisions; event_images->shift_direction = (valign == VALIGN_TOP) ? 1 : -1; event_images->event = event; - event_images->imgs = render_text(&text_info, device_x, device_y); + event_images->imgs = render_text(frame_priv, &text_info, device_x, device_y); free_render_context(); @@ -2296,7 +2301,7 @@ int ass_set_fonts_nofc(ass_renderer_t* priv, const char* default_font, const cha /** * \brief Start a new frame */ -static int ass_start_frame(ass_renderer_t *priv, ass_track_t* track, long long now) +static int ass_start_frame(frame_context_t* frame_priv, ass_renderer_t *priv, ass_track_t* track, long long now) { ass_settings_t* settings_priv = &priv->settings; @@ -2306,30 +2311,30 @@ static int ass_start_frame(ass_renderer_t *priv, ass_track_t* track, long long n if (track->n_events == 0) return 1; // nothing to do - frame_context.ass_priv = priv; - frame_context.width = settings_priv->frame_width; - frame_context.height = settings_priv->frame_height; - frame_context.orig_width = settings_priv->frame_width - settings_priv->left_margin - settings_priv->right_margin; - frame_context.orig_height = settings_priv->frame_height - settings_priv->top_margin - settings_priv->bottom_margin; - frame_context.orig_width_nocrop = settings_priv->frame_width - + frame_priv->ass_priv = priv; + frame_priv->width = settings_priv->frame_width; + frame_priv->height = settings_priv->frame_height; + frame_priv->orig_width = settings_priv->frame_width - settings_priv->left_margin - settings_priv->right_margin; + frame_priv->orig_height = settings_priv->frame_height - settings_priv->top_margin - settings_priv->bottom_margin; + frame_priv->orig_width_nocrop = settings_priv->frame_width - FFMAX(settings_priv->left_margin, 0) - FFMAX(settings_priv->right_margin, 0); - frame_context.orig_height_nocrop = settings_priv->frame_height - + frame_priv->orig_height_nocrop = settings_priv->frame_height - FFMAX(settings_priv->top_margin, 0) - FFMAX(settings_priv->bottom_margin, 0); - frame_context.track = track; - frame_context.time = now; + frame_priv->track = track; + frame_priv->time = now; - ass_lazy_track_init(settings_priv); + ass_lazy_track_init(frame_priv, settings_priv); - frame_context.font_scale = settings_priv->font_size_coeff * - frame_context.orig_height / frame_context.track->PlayResY; - if (frame_context.track->ScaledBorderAndShadow) - frame_context.border_scale = ((double)frame_context.orig_height) / frame_context.track->PlayResY; + frame_priv->font_scale = settings_priv->font_size_coeff * + frame_priv->orig_height / frame_priv->track->PlayResY; + if (frame_priv->track->ScaledBorderAndShadow) + frame_priv->border_scale = ((double)frame_priv->orig_height) / frame_priv->track->PlayResY; else - frame_context.border_scale = 1.; + frame_priv->border_scale = 1.; - frame_context.font_scale_x = 1.; + frame_priv->font_scale_x = 1.; priv->prev_images_root = priv->images_root; priv->images_root = 0; @@ -2382,7 +2387,7 @@ static int cmp_segment(const void* p1, const void* p2) return ((segment_t*)p1)->a - ((segment_t*)p2)->a; } -static void shift_event(event_images_t* ei, int shift) +static void shift_event(frame_context_t* frame_priv, event_images_t* ei, int shift) { ass_image_t* cur = ei->imgs; while (cur) { @@ -2394,8 +2399,8 @@ static void shift_event(event_images_t* ei, int shift) cur->bitmap += clip * cur->stride; cur->dst_y = 0; } - if (cur->dst_y + cur->h >= frame_context.height) { - int clip = cur->dst_y + cur->h - frame_context.height; + if (cur->dst_y + cur->h >= frame_priv->height) { + int clip = cur->dst_y + cur->h - frame_priv->height; cur->h -= clip; } if (cur->h <= 0) { @@ -2435,7 +2440,7 @@ static int fit_segment(segment_t* s, segment_t* fixed, int* cnt, int dir) return shift; } -static void fix_collisions(ass_renderer_t* render_priv, event_images_t* imgs, int cnt) +static void fix_collisions(frame_context_t* frame_priv, ass_renderer_t* render_priv, event_images_t* imgs, int cnt) { segment_t used[MAX_EVENTS]; int cnt_used = 0; @@ -2464,7 +2469,7 @@ static void fix_collisions(ass_renderer_t* render_priv, event_images_t* imgs, in used[cnt_used].a = priv->top; used[cnt_used].b = priv->top + priv->height; cnt_used ++; - shift_event(imgs + i, priv->top - imgs[i].top); + shift_event(frame_priv, imgs + i, priv->top - imgs[i].top); } } } @@ -2481,7 +2486,7 @@ static void fix_collisions(ass_renderer_t* render_priv, event_images_t* imgs, in s.a = imgs[i].top; s.b = imgs[i].top + imgs[i].height; shift = fit_segment(&s, used, &cnt_used, imgs[i].shift_direction); - if (shift) shift_event(imgs + i, shift); + if (shift) shift_event(frame_priv, imgs + i, shift); // make it fixed priv->top = imgs[i].top; priv->height = imgs[i].height; @@ -2560,8 +2565,11 @@ ass_image_t* ass_render_frame(ass_renderer_t *priv, ass_track_t* track, long lon event_images_t* last; ass_image_t** tail; + // FIXME: XXX: BROKEN BEYOND REPAIR + frame_context_t* frame_priv = 0; + // init frame - rc = ass_start_frame(priv, track, now); + rc = ass_start_frame(frame_priv, priv, track, now); if (rc != 0) return 0; @@ -2574,7 +2582,7 @@ ass_image_t* ass_render_frame(ass_renderer_t *priv, ass_track_t* track, long lon priv->eimg_size += 100; priv->eimg = realloc(priv->eimg, priv->eimg_size * sizeof(event_images_t)); } - rc = ass_render_event(priv, event, priv->eimg + cnt); + rc = ass_render_event(frame_priv, priv, event, priv->eimg + cnt); if (!rc) ++cnt; } } @@ -2586,11 +2594,11 @@ ass_image_t* ass_render_frame(ass_renderer_t *priv, ass_track_t* track, long lon last = priv->eimg; for (i = 1; i < cnt; ++i) if (last->event->Layer != priv->eimg[i].event->Layer) { - fix_collisions(priv, last, priv->eimg + i - last); + fix_collisions(frame_priv, priv, last, priv->eimg + i - last); last = priv->eimg + i; } if (cnt > 0) - fix_collisions(priv, last, priv->eimg + cnt - last); + fix_collisions(frame_priv, priv, last, priv->eimg + cnt - last); // concat lists tail = &priv->images_root; |