summaryrefslogtreecommitdiffstats
path: root/libass/ass_render.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2014-06-05 00:55:13 +0200
committerwm4 <wm4@nowhere>2014-06-05 01:15:14 +0200
commitdcecb9cba3ab2e9c1d082c9860aecb9e437e40f6 (patch)
treec366e02227a4814504f7911d0f6e2d48f5ec0ff4 /libass/ass_render.c
parent4a4e464d1dadce90bc91dce5448890e987019d89 (diff)
downloadlibass-dcecb9cba3ab2e9c1d082c9860aecb9e437e40f6.tar.bz2
libass-dcecb9cba3ab2e9c1d082c9860aecb9e437e40f6.tar.xz
Add a mechanism for selective style overrides
This adds 2 new API functions: ass_set_selective_style_override() ass_set_selective_style_override_enabled() They can be used to force dialog text to use a specific ASS_Style. It uses a fuzzy heuristic for that, and the quality of results may vary. It does style overriding selectively and tries not to override things that need explicit styling. The heuristic for that isn't set in stone either, and can change with future libass versions. Closes libass#88.
Diffstat (limited to 'libass/ass_render.c')
-rw-r--r--libass/ass_render.c101
1 files changed, 80 insertions, 21 deletions
diff --git a/libass/ass_render.c b/libass/ass_render.c
index 0cc1848..625a77d 100644
--- a/libass/ass_render.c
+++ b/libass/ass_render.c
@@ -208,6 +208,8 @@ void ass_renderer_done(ASS_Renderer *render_priv)
free(render_priv->settings.default_font);
free(render_priv->settings.default_family);
+ free(render_priv->user_override_style.FontName);
+
free_list_clear(render_priv);
free(render_priv);
}
@@ -763,14 +765,89 @@ static void compute_string_bbox(TextInfo *text, DBBox *bbox)
bbox->xMin = bbox->xMax = bbox->yMin = bbox->yMax = 0.;
}
+static ASS_Style *handle_selective_style_overrides(ASS_Renderer *render_priv,
+ ASS_Style *rstyle)
+{
+ // The script style is the one the event was declared with.
+ // The rstyle is either NULL, or the style used with a \r tag.
+ ASS_Style *script = render_priv->track->styles +
+ render_priv->state.event->Style;
+ ASS_Style *new = &render_priv->state.override_style_temp_storage;
+ int override = !event_is_positioned(render_priv->state.event->Text);
+ double scale;
+
+ if (!rstyle)
+ rstyle = script;
+
+ render_priv->state.style = script;
+
+ if (!override || !render_priv->settings.selective_style_overrides)
+ return rstyle;
+
+ // Create a new style that contains a mix of the original style and
+ // user_style (the user's override style). Copy only fields from the
+ // script's style that are deemed necessary.
+ *new = render_priv->user_override_style;
+
+ new->StrikeOut = rstyle->StrikeOut;
+ new->Underline = rstyle->Underline;
+ new->Angle = rstyle->Angle;
+
+ new->MarginL = script->MarginL;
+ new->MarginR = script->MarginR;
+ new->MarginV = script->MarginV;
+ new->Alignment = script->Alignment;
+ new->Encoding = script->Encoding;
+ new->treat_fontname_as_pattern = script->treat_fontname_as_pattern;
+
+ // The user style is supposed to be independent of the script resolution.
+ // Treat the user style's values as if they were specified for a script with
+ // PlayResY=288, and rescale the values to the current script.
+ scale = render_priv->track->PlayResY / 288.0;
+ new->FontSize *= scale;
+ new->Spacing *= scale;
+ new->Outline *= scale;
+ new->Shadow *= scale;
+
+ render_priv->state.style = new;
+
+ return new;
+}
+
+static void init_font_scale(ASS_Renderer *render_priv)
+{
+ ASS_Settings *settings_priv = &render_priv->settings;
+
+ render_priv->font_scale = ((double) render_priv->orig_height) /
+ render_priv->track->PlayResY;
+ if (settings_priv->storage_height)
+ render_priv->blur_scale = ((double) render_priv->orig_height) /
+ settings_priv->storage_height;
+ else
+ render_priv->blur_scale = 1.;
+ if (render_priv->track->ScaledBorderAndShadow)
+ render_priv->border_scale =
+ ((double) render_priv->orig_height) /
+ render_priv->track->PlayResY;
+ else
+ render_priv->border_scale = render_priv->blur_scale;
+ if (!settings_priv->storage_height)
+ render_priv->blur_scale = render_priv->border_scale;
+
+ render_priv->font_scale *= settings_priv->font_size_coeff;
+ render_priv->border_scale *= settings_priv->font_size_coeff;
+ render_priv->blur_scale *= settings_priv->font_size_coeff;
+}
+
/**
* \brief partially reset render_context to style values
* Works like {\r}: resets some style overrides
*/
void reset_render_context(ASS_Renderer *render_priv, ASS_Style *style)
{
- if (!style)
- style = render_priv->state.style;
+ style = handle_selective_style_overrides(render_priv, style);
+
+ init_font_scale(render_priv);
render_priv->state.c[0] = style->PrimaryColour;
render_priv->state.c[1] = style->SecondaryColour;
@@ -814,11 +891,10 @@ static void
init_render_context(ASS_Renderer *render_priv, ASS_Event *event)
{
render_priv->state.event = event;
- render_priv->state.style = render_priv->track->styles + event->Style;
render_priv->state.parsed_tags = 0;
render_priv->state.has_clips = 0;
- reset_render_context(render_priv, render_priv->state.style);
+ reset_render_context(render_priv, NULL);
render_priv->state.wrap_style = render_priv->track->WrapStyle;
render_priv->state.evt_type = EVENT_NORMAL;
@@ -2636,23 +2712,6 @@ ass_start_frame(ASS_Renderer *render_priv, ASS_Track *track,
ass_lazy_track_init(render_priv->library, render_priv->track);
- render_priv->font_scale = settings_priv->font_size_coeff *
- render_priv->orig_height / render_priv->track->PlayResY;
- if (settings_priv->storage_height)
- render_priv->blur_scale = ((double) render_priv->orig_height) /
- settings_priv->storage_height;
- else
- render_priv->blur_scale = 1.;
- if (render_priv->track->ScaledBorderAndShadow)
- render_priv->border_scale =
- ((double) render_priv->orig_height) /
- render_priv->track->PlayResY;
- else
- render_priv->border_scale = render_priv->blur_scale;
- if (!settings_priv->storage_height)
- render_priv->blur_scale = render_priv->border_scale;
- render_priv->border_scale *= settings_priv->font_size_coeff;
-
ass_shaper_set_kerning(render_priv->shaper, track->Kerning);
ass_shaper_set_language(render_priv->shaper, track->Language);
ass_shaper_set_level(render_priv->shaper, render_priv->settings.shaper);