8 #include "mf_wordwrap.h"
13 static bool is_wrap_space(gU16 c)
15 return c ==
' ' || c ==
'\n' || c ==
'\t' || c ==
'\r' || c ==
'-';
18 #if MF_USE_ADVANCED_WORDWRAP
30 static bool get_wordlen(
const struct mf_font_s *font, mf_str *text,
31 struct wordlen_s *result)
41 while (c && !is_wrap_space(c))
44 result->word += mf_character_width(font, c);
50 while (c && is_wrap_space(c))
54 if (c ==
' ' || c ==
'-')
55 result->space += mf_character_width(font, c);
57 result->space += mf_character_width(font,
'm') * MF_TABSIZE;
72 return (c ==
'\0' || c ==
'\n');
82 struct wordlen_s last_word;
83 struct wordlen_s last_word_2;
88 static bool append_word(
const struct mf_font_s *font, gI16 width,
89 struct linelen_s *current, mf_str *text)
92 struct wordlen_s wordlen;
95 linebreak = get_wordlen(font, &tmp, &wordlen);
97 if (current->width + wordlen.word <= width)
100 current->last_word_2 = current->last_word;
101 current->last_word = wordlen;
102 current->linebreak = linebreak;
103 current->chars += wordlen.chars;
104 current->width += wordlen.word + wordlen.space;
114 static bool append_char(
const struct mf_font_s *font, gI16 width,
115 struct linelen_s *current, mf_str *text)
121 c = mf_getchar(&tmp);
122 w = mf_character_width(font, c);
124 if (current->width + w <= width)
137 static gI32 sq16(gI16 x) {
return (gI32)x * x; }
141 static void tune_lines(
struct linelen_s *current,
struct linelen_s *previous,
149 curw1 = current->width - current->last_word.space;
150 prevw1 = previous->width - previous->last_word.space;
151 delta1 = sq16(max_width - prevw1) + sq16(max_width - curw1);
154 curw2 = current->width + previous->last_word.word;
155 prevw2 = previous->width - previous->last_word.word
156 - previous->last_word.space
157 - previous->last_word_2.space;
158 delta2 = sq16(max_width - prevw2) + sq16(max_width - curw2);
160 if (delta1 > delta2 && curw2 <= max_width)
165 chars = previous->last_word.chars;
166 previous->chars -= chars;
167 current->chars += chars;
168 previous->width -= previous->last_word.word + previous->last_word.space;
169 current->width += previous->last_word.word + previous->last_word.space;
170 previous->last_word = previous->last_word_2;
172 while (chars--) mf_rewind(¤t->start);
176 void mf_wordwrap(
const struct mf_font_s *font, gI16 width,
177 mf_str text, mf_line_callback_t callback,
void *state)
179 struct linelen_s current = { 0 };
180 struct linelen_s previous = { 0 };
184 current.start = text;
188 full = !append_word(font, width, ¤t, &text);
190 if (full || current.linebreak)
196 while (append_char(font, width, ¤t, &text));
202 if (!previous.linebreak && !current.linebreak)
203 tune_lines(¤t, &previous, width);
205 if (!callback(previous.start, previous.chars, state))
210 current.start = text;
213 current.linebreak =
false;
214 current.last_word.word = 0;
215 current.last_word.space = 0;
216 current.last_word.chars = 0;
229 if (!callback(previous.start, previous.chars, state))
234 callback(current.start, current.chars, state);
239 void mf_wordwrap(
const struct mf_font_s *font, gI16 width,
240 mf_str text, mf_line_callback_t callback,
void *state)
245 gI16 lw_cur = 0, cc_cur = 0;
265 c = mf_getchar(&text);
266 new_width = lw_cur + mf_character_width(font, c);
270 cc_prev = cc_cur + 1;
275 if (new_width > width)
284 if (is_wrap_space(c))
298 if (!callback(linestart, cc_prev, state))