From f1d3d38dc81cc07b432d93bb2346f3b8c24c920a Mon Sep 17 00:00:00 2001 From: Grigori Goronzy Date: Sat, 21 Apr 2012 03:52:54 +0200 Subject: Refactor and fix border generation Make sure to update the border appropriately in the second pass, after parsing. --- libass/ass_parse.c | 49 ++++++++++++++++++++++++++++++------------------- libass/ass_parse.h | 1 + libass/ass_render.c | 4 +++- libass/ass_render.h | 1 + 4 files changed, 35 insertions(+), 20 deletions(-) diff --git a/libass/ass_parse.c b/libass/ass_parse.c index d505dd5..7f1c8f0 100644 --- a/libass/ass_parse.c +++ b/libass/ass_parse.c @@ -105,28 +105,36 @@ void update_font(ASS_Renderer *render_priv) } /** - * \brief Change border width - * negative value resets border to style value + * \brief Calculate valid border size. Makes sure the border sizes make sense. + * + * \param priv renderer state object + * \param border_x requested x border size + * \param border_y requested y border size */ -void change_border(ASS_Renderer *render_priv, double border_x, - double border_y) +void calc_border(ASS_Renderer *priv, double border_x, double border_y) { - int bord; - if (!render_priv->state.font) - return; - if (border_x < 0 && border_y < 0) { - if (render_priv->state.style->BorderStyle == 1 || - render_priv->state.style->BorderStyle == 3) - border_x = border_y = render_priv->state.style->Outline; + if (priv->state.style->BorderStyle == 1 || + priv->state.style->BorderStyle == 3) + border_x = border_y = priv->state.style->Outline; else border_x = border_y = 1.; } - render_priv->state.border_x = border_x; - render_priv->state.border_y = border_y; + priv->state.border_x = border_x; + priv->state.border_y = border_y; +} + +/** + * \brief Change border width + * + * \param render_priv renderer state object + * \param info glyph state object + */ +void change_border(ASS_Renderer *render_priv, double border_x, double border_y) +{ + int bord = 64 * border_x * render_priv->border_scale; - bord = 64 * border_x * render_priv->border_scale; if (bord > 0 && border_x == border_y) { if (!render_priv->state.stroker) { int error; @@ -138,11 +146,14 @@ void change_border(ASS_Renderer *render_priv, double border_x, "failed to get stroker"); render_priv->state.stroker = 0; } + render_priv->state.stroker_radius = -1.0; } - if (render_priv->state.stroker) + if (render_priv->state.stroker && render_priv->state.stroker_radius != bord) { FT_Stroker_Set(render_priv->state.stroker, bord, FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0); + render_priv->state.stroker_radius = bord; + } } else { FT_Stroker_Done(render_priv->state.stroker); render_priv->state.stroker = 0; @@ -256,7 +267,7 @@ static char *parse_tag(ASS_Renderer *render_priv, char *p, double pwr) val = render_priv->state.border_x * (1 - pwr) + val * pwr; else val = -1.; - change_border(render_priv, val, render_priv->state.border_y); + calc_border(render_priv, val, render_priv->state.border_y); render_priv->state.bm_run_id++; } else if (mystrcmp(&p, "ybord")) { double val; @@ -264,7 +275,8 @@ static char *parse_tag(ASS_Renderer *render_priv, char *p, double pwr) val = render_priv->state.border_y * (1 - pwr) + val * pwr; else val = -1.; - change_border(render_priv, render_priv->state.border_x, val); + calc_border(render_priv, render_priv->state.border_x, val); + render_priv->state.bm_run_id++; } else if (mystrcmp(&p, "xshad")) { double val; if (mystrtod(&p, &val)) @@ -388,11 +400,10 @@ static char *parse_tag(ASS_Renderer *render_priv, char *p, double pwr) } else if (mystrcmp(&p, "bord")) { double val; if (mystrtod(&p, &val)) { - if (render_priv->state.border_x == render_priv->state.border_y) val = render_priv->state.border_x * (1 - pwr) + val * pwr; } else val = -1.; // reset to default - change_border(render_priv, val, val); + calc_border(render_priv, val, val); render_priv->state.bm_run_id++; } else if (mystrcmp(&p, "move")) { double x1, x2, y1, y2; diff --git a/libass/ass_parse.h b/libass/ass_parse.h index 2e145dc..fd4fd66 100644 --- a/libass/ass_parse.h +++ b/libass/ass_parse.h @@ -28,6 +28,7 @@ void update_font(ASS_Renderer *render_priv); double ensure_font_size(ASS_Renderer *priv, double size); +void calc_border(ASS_Renderer *priv, double border_x, double border_y); void change_border(ASS_Renderer *render_priv, double border_x, double border_y); void apply_transition_effects(ASS_Renderer *render_priv, ASS_Event *event); diff --git a/libass/ass_render.c b/libass/ass_render.c index f89c930..98064e3 100644 --- a/libass/ass_render.c +++ b/libass/ass_render.c @@ -862,7 +862,8 @@ void reset_render_context(ASS_Renderer *render_priv, ASS_Style *style) render_priv->state.italic = style->Italic; update_font(render_priv); - change_border(render_priv, -1., -1.); + calc_border(render_priv, style->Outline, style->Outline); + change_border(render_priv, render_priv->state.border_x, render_priv->state.border_y); render_priv->state.scale_x = style->ScaleX; render_priv->state.scale_y = style->ScaleY; render_priv->state.hspacing = style->Spacing; @@ -1142,6 +1143,7 @@ get_outline_glyph(ASS_Renderer *priv, GlyphInfo *info) } else if ((info->border_x > 0 || info->border_y > 0) && double_to_d6(info->scale_x) && double_to_d6(info->scale_y)) { + change_border(priv, info->border_x, info->border_y); outline_copy(priv->ftlibrary, v.outline, &v.border); stroke_outline(priv, v.border, double_to_d6(info->border_x * priv->border_scale), diff --git a/libass/ass_render.h b/libass/ass_render.h index 6dca2a2..2ee7f1e 100644 --- a/libass/ass_render.h +++ b/libass/ass_render.h @@ -175,6 +175,7 @@ typedef struct { int flags; // decoration flags (underline/strike-through) FT_Stroker stroker; + int stroker_radius; // last stroker radius, for caching stroker objects int alignment; // alignment overrides go here; if zero, style value will be used double frx, fry, frz; double fax, fay; // text shearing -- cgit v1.2.3