diff --git a/libass/ass.c b/libass/ass.c index f42fd4b98..1cb0d4ce7 100644 --- a/libass/ass.c +++ b/libass/ass.c @@ -449,6 +449,7 @@ void ass_process_force_style(ASS_Track *track) FPVAL(Angle) INTVAL(BorderStyle) INTVAL(Alignment) + INTVAL(Justify) INTVAL(MarginL) INTVAL(MarginR) INTVAL(MarginV) diff --git a/libass/ass.h b/libass/ass.h index 24a461883..912a7a1a0 100644 --- a/libass/ass.h +++ b/libass/ass.h @@ -166,6 +166,10 @@ typedef enum { * resolution given by the ASS_Track. */ ASS_OVERRIDE_FULL_STYLE = 1 << 9, + /** + * On dialogue events override: Justify + */ + ASS_OVERRIDE_BIT_JUSTIFY = 1 << 10, } ASS_OverrideBits; /** diff --git a/libass/ass_render.c b/libass/ass_render.c index d57bdac3b..d0f827d35 100644 --- a/libass/ass_render.c +++ b/libass/ass_render.c @@ -784,6 +784,9 @@ static ASS_Style *handle_selective_style_overrides(ASS_Renderer *render_priv, if (requested & ASS_OVERRIDE_BIT_ALIGNMENT) new->Alignment = user->Alignment; + if (requested & ASS_OVERRIDE_BIT_JUSTIFY) + new->Justify = user->Justify; + if (requested & ASS_OVERRIDE_BIT_MARGINS) { new->MarginL = user->MarginL; new->MarginR = user->MarginR; @@ -886,6 +889,7 @@ init_render_context(ASS_Renderer *render_priv, ASS_Event *event) render_priv->state.wrap_style = render_priv->track->WrapStyle; render_priv->state.alignment = render_priv->state.style->Alignment; + render_priv->state.justify = render_priv->state.style->Justify; render_priv->state.pos_x = 0; render_priv->state.pos_y = 0; render_priv->state.org_x = 0; @@ -2071,19 +2075,49 @@ static void align_lines(ASS_Renderer *render_priv, double max_text_width) double width = 0; int last_break = -1; int halign = render_priv->state.alignment & 3; + int justify = render_priv->state.justify; + double max_width = 0; if (render_priv->state.evt_type == EVENT_HSCROLL) return; + for (i = 0; i <= text_info->length; ++i) { // (text_info->length + 1) is the end of the last line + if ((i == text_info->length) || glyphs[i].linebreak) { + max_width = FFMAX(max_width,width); + width = 0; + } + if (i < text_info->length && !glyphs[i].skip && + glyphs[i].symbol != '\n' && glyphs[i].symbol != 0) { + width += d6_to_double(glyphs[i].cluster_advance.x); + } + } for (i = 0; i <= text_info->length; ++i) { // (text_info->length + 1) is the end of the last line if ((i == text_info->length) || glyphs[i].linebreak) { double shift = 0; if (halign == HALIGN_LEFT) { // left aligned, no action - shift = 0; + if (justify == ASS_JUSTIFY_RIGHT) { + shift = max_width - width; + } else if (justify == ASS_JUSTIFY_CENTER) { + shift = (max_width - width) / 2.0; + } else { + shift = 0; + } } else if (halign == HALIGN_RIGHT) { // right aligned - shift = max_text_width - width; + if (justify == ASS_JUSTIFY_LEFT) { + shift = max_text_width - max_width; + } else if (justify == ASS_JUSTIFY_CENTER) { + shift = max_text_width - max_width + (max_width - width) / 2.0; + } else { + shift = max_text_width - width; + } } else if (halign == HALIGN_CENTER) { // centered - shift = (max_text_width - width) / 2.0; + if (justify == ASS_JUSTIFY_LEFT) { + shift = (max_text_width - max_width) / 2.0; + } else if (justify == ASS_JUSTIFY_RIGHT) { + shift = (max_text_width - max_width) / 2.0 + max_width - width; + } else { + shift = (max_text_width - width) / 2.0; + } } for (j = last_break + 1; j < i; ++j) { GlyphInfo *info = glyphs + j; diff --git a/libass/ass_render.h b/libass/ass_render.h index 6e3963ebf..fad554b9e 100644 --- a/libass/ass_render.h +++ b/libass/ass_render.h @@ -220,6 +220,7 @@ typedef struct { 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 + int justify; // justify instructions double frx, fry, frz; double fax, fay; // text shearing enum { diff --git a/libass/ass_types.h b/libass/ass_types.h index f4a6ae5ec..88951a790 100644 --- a/libass/ass_types.h +++ b/libass/ass_types.h @@ -28,6 +28,10 @@ #define HALIGN_LEFT 1 #define HALIGN_CENTER 2 #define HALIGN_RIGHT 3 +#define ASS_JUSTIFY_AUTO 0 +#define ASS_JUSTIFY_LEFT 1 +#define ASS_JUSTIFY_CENTER 2 +#define ASS_JUSTIFY_RIGHT 3 #define FONT_WEIGHT_LIGHT 300 #define FONT_WEIGHT_MEDIUM 400 @@ -73,6 +77,7 @@ typedef struct ass_style { int Encoding; int treat_fontname_as_pattern; double Blur; + int Justify; } ASS_Style;