diff options
author | Oneric <oneric@oneric.stub> | 2021-03-13 19:59:34 +0100 |
---|---|---|
committer | Oneric <oneric@oneric.stub> | 2022-08-19 19:03:35 +0200 |
commit | c610332853b6581802f07229101c0889ed731ee5 (patch) | |
tree | 40379368d66ebce65510f98bbdae99643d6a40ed | |
parent | b890df23eb8931728acdf240fd5d29e53401b4f2 (diff) | |
download | libass-c610332853b6581802f07229101c0889ed731ee5.tar.bz2 libass-c610332853b6581802f07229101c0889ed731ee5.tar.xz |
refactor: split up wrap_lines_smart
The 3 stages had no interdependencies besides text_info and using some
common variable names and names only. Split each stage into its own
function to make it a bit easier to understand and also rename
last_space to last_breakable.
-rw-r--r-- | libass/ass_render.c | 115 |
1 files changed, 63 insertions, 52 deletions
diff --git a/libass/ass_render.c b/libass/ass_render.c index bbc8070..c0451a3 100644 --- a/libass/ass_render.c +++ b/libass/ass_render.c @@ -1627,40 +1627,23 @@ static void trim_whitespace(ASS_Renderer *render_priv) } #undef IS_WHITESPACE -/** - * \brief rearrange text between lines - * \param max_text_width maximal text line width in pixels - * The algo is similar to the one in libvo/sub.c: - * 1. Place text, wrapping it when current line is full - * 2. Try moving words from the end of a line to the beginning of the next one while it reduces - * the difference in lengths between this two lines. - * The result may not be optimal, but usually is good enough. - * - * FIXME: implement style 0 and 3 correctly +/* + * Starts a new line on the first breakable character after overflow */ static void -wrap_lines_smart(ASS_Renderer *render_priv, double max_text_width) +wrap_lines_naive(ASS_Renderer *render_priv, double max_text_width) { - int i; - GlyphInfo *cur, *s1, *e1, *s2, *s3; - int last_space; - int break_type; - int exit; - double pen_shift_x; - double pen_shift_y; - int cur_line; TextInfo *text_info = &render_priv->text_info; + GlyphInfo *s1 = text_info->glyphs; // current line start + int last_breakable = -1; + int break_type = 0; - last_space = -1; text_info->n_lines = 1; - break_type = 0; - s1 = text_info->glyphs; // current line start - for (i = 0; i < text_info->length; ++i) { + for (int i = 0; i < text_info->length; ++i) { + GlyphInfo *cur = text_info->glyphs + i; int break_at = -1; - double s_offset, len; - cur = text_info->glyphs + i; - s_offset = d6_to_double(s1->bbox.x_min + s1->pos.x); - len = d6_to_double(cur->bbox.x_max + cur->pos.x) - s_offset; + double s_offset = d6_to_double(s1->bbox.x_min + s1->pos.x); + double len = d6_to_double(cur->bbox.x_max + cur->pos.x) - s_offset; if (cur->symbol == '\n') { break_type = 2; @@ -1668,11 +1651,11 @@ wrap_lines_smart(ASS_Renderer *render_priv, double max_text_width) ass_msg(render_priv->library, MSGL_DBG2, "forced line break at %d", break_at); } else if (cur->symbol == ' ') { - last_space = i; + last_breakable = i; } else if (len >= max_text_width && (render_priv->state.wrap_style != 2)) { break_type = 1; - break_at = last_space; + break_at = last_breakable; if (break_at >= 0) ass_msg(render_priv->library, MSGL_DBG2, "line break at %d", break_at); @@ -1691,20 +1674,33 @@ wrap_lines_smart(ASS_Renderer *render_priv, double max_text_width) } if (lead < text_info->length) { text_info->glyphs[lead].linebreak = break_type; - last_space = -1; + last_breakable = -1; s1 = text_info->glyphs + lead; text_info->n_lines++; } } } +} + +/* + * Shift soft linebreaks to balance out line lengths + * May remove but never add linebreaks + * FIXME: implement style 0 and 3 correctly + */ +static void +wrap_lines_rebalance(ASS_Renderer *render_priv, double max_text_width) +{ + TextInfo *text_info = &render_priv->text_info; + int exit = 0; + #define DIFF(x,y) (((x) < (y)) ? (y - x) : (x - y)) - exit = 0; while (!exit && render_priv->state.wrap_style != 1) { exit = 1; + GlyphInfo *s1, *s2, *s3; s3 = text_info->glyphs; s1 = s2 = 0; - for (i = 0; i <= text_info->length; ++i) { - cur = text_info->glyphs + i; + for (int i = 0; i <= text_info->length; ++i) { + GlyphInfo *cur = text_info->glyphs + i; if ((i == text_info->length) || cur->linebreak) { s1 = s2; s2 = s3; @@ -1719,7 +1715,7 @@ wrap_lines_smart(ASS_Renderer *render_priv, double max_text_width) while ((w > s1) && (w->symbol != ' ')) { --w; } - e1 = w; + GlyphInfo *e1 = w; while ((e1 > s1) && (e1->symbol == ' ')) { --e1; } @@ -1754,21 +1750,22 @@ wrap_lines_smart(ASS_Renderer *render_priv, double max_text_width) } assert(text_info->n_lines >= 1); #undef DIFF +} - trim_whitespace(render_priv); - measure_text(render_priv); - - cur_line = 1; +static void +wrap_lines_measure(ASS_Renderer *render_priv) +{ + TextInfo *text_info = &render_priv->text_info; + int cur_line = 1; + int i = 0; - i = 0; - cur = text_info->glyphs + i; - while (i < text_info->length && cur->skip) - cur = text_info->glyphs + ++i; - pen_shift_x = d6_to_double(-cur->pos.x); - pen_shift_y = 0.; + while (i < text_info->length && text_info->glyphs[i].skip) + ++i; + double pen_shift_x = d6_to_double(-text_info->glyphs[i].pos.x); + double pen_shift_y = 0.; for (i = 0; i < text_info->length; ++i) { - cur = text_info->glyphs + i; + GlyphInfo *cur = text_info->glyphs + i; if (cur->linebreak) { while (i < text_info->length && cur->skip && cur->symbol != '\n') cur = text_info->glyphs + ++i; @@ -1787,14 +1784,28 @@ wrap_lines_smart(ASS_Renderer *render_priv, double max_text_width) } text_info->lines[cur_line - 1].len = text_info->length - text_info->lines[cur_line - 1].offset; +} -#if 0 - // print line info - for (i = 0; i < text_info->n_lines; i++) { - printf("line %d offset %d length %d\n", i, text_info->lines[i].offset, - text_info->lines[i].len); - } -#endif +/** + * \brief rearrange text between lines + * \param max_text_width maximal text line width in pixels + * The algo is similar to the one in libvo/sub.c: + * 1. Place text, wrapping it when current line is full + * 2. Try moving words from the end of a line to the beginning of the next one while it reduces + * the difference in lengths between this two lines. + * The result may not be optimal, but usually is good enough. + * + * FIXME: implement style 0 and 3 correctly + */ +static void +wrap_lines_smart(ASS_Renderer *render_priv, double max_text_width) +{ + wrap_lines_naive(render_priv, max_text_width); + wrap_lines_rebalance(render_priv, max_text_width); + + trim_whitespace(render_priv); + measure_text(render_priv); + wrap_lines_measure(render_priv); } /** |