summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOneric <oneric@oneric.stub>2021-03-13 19:59:34 +0100
committerOneric <oneric@oneric.stub>2022-08-19 19:03:35 +0200
commitc610332853b6581802f07229101c0889ed731ee5 (patch)
tree40379368d66ebce65510f98bbdae99643d6a40ed
parentb890df23eb8931728acdf240fd5d29e53401b4f2 (diff)
downloadlibass-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.c115
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);
}
/**