Fix for wordwrapping when there is a space then a newline
This commit is contained in:
parent
87ec4b7c77
commit
c41cbd05e9
@ -31,7 +31,7 @@ static bool get_wordlen(const struct mf_font_s *font, mf_str *text,
|
||||
struct wordlen_s *result)
|
||||
{
|
||||
mf_char c;
|
||||
mf_str prev;
|
||||
mf_str prev = *text;
|
||||
|
||||
result->word = 0;
|
||||
result->space = 0;
|
||||
@ -42,31 +42,35 @@ static bool get_wordlen(const struct mf_font_s *font, mf_str *text,
|
||||
{
|
||||
result->chars++;
|
||||
result->word += mf_character_width(font, c);
|
||||
|
||||
prev = *text;
|
||||
c = mf_getchar(text);
|
||||
}
|
||||
|
||||
prev = *text;
|
||||
|
||||
while (c && is_wrap_space(c))
|
||||
{
|
||||
result->chars++;
|
||||
|
||||
|
||||
if (c == ' ')
|
||||
result->space += mf_character_width(font, c);
|
||||
else if (c == '-')
|
||||
result->space += mf_character_width(font, '-');
|
||||
else if (c == '\t')
|
||||
result->space += mf_character_width(font, 'm') * MF_TABSIZE;
|
||||
else if (c == '\n')
|
||||
else if (c == '\n') {
|
||||
/* Special case for newlines, skip the character then break. */
|
||||
prev = *text;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
prev = *text;
|
||||
c = mf_getchar(text);
|
||||
}
|
||||
|
||||
|
||||
/* The last loop reads the first character of next word, put it back. */
|
||||
if (c)
|
||||
*text = prev;
|
||||
|
||||
|
||||
return (c == '\0' || c == '\n');
|
||||
}
|
||||
|
||||
@ -89,9 +93,9 @@ static bool append_word(const struct mf_font_s *font, int16_t width,
|
||||
mf_str tmp = *text;
|
||||
struct wordlen_s wordlen;
|
||||
bool linebreak;
|
||||
|
||||
|
||||
linebreak = get_wordlen(font, &tmp, &wordlen);
|
||||
|
||||
|
||||
if (current->width + wordlen.word <= width)
|
||||
{
|
||||
*text = tmp;
|
||||
@ -115,10 +119,10 @@ static bool append_char(const struct mf_font_s *font, int16_t width,
|
||||
mf_str tmp = *text;
|
||||
mf_char c;
|
||||
uint16_t w;
|
||||
|
||||
|
||||
c = mf_getchar(&tmp);
|
||||
w = mf_character_width(font, c);
|
||||
|
||||
|
||||
if (current->width + w <= width)
|
||||
{
|
||||
*text = tmp;
|
||||
@ -142,31 +146,31 @@ static void tune_lines(struct linelen_s *current, struct linelen_s *previous,
|
||||
int16_t curw1, prevw1;
|
||||
int16_t curw2, prevw2;
|
||||
int32_t delta1, delta2;
|
||||
|
||||
|
||||
/* If the lines are rendered as is */
|
||||
curw1 = current->width - current->last_word.space;
|
||||
prevw1 = previous->width - previous->last_word.space;
|
||||
delta1 = sq16(max_width - prevw1) + sq16(max_width - curw1);
|
||||
|
||||
|
||||
/* If the last word is moved */
|
||||
curw2 = current->width + previous->last_word.word;
|
||||
prevw2 = previous->width - previous->last_word.word
|
||||
- previous->last_word.space
|
||||
- previous->last_word_2.space;
|
||||
delta2 = sq16(max_width - prevw2) + sq16(max_width - curw2);
|
||||
|
||||
|
||||
if (delta1 > delta2 && curw2 <= max_width)
|
||||
{
|
||||
/* Do the change. */
|
||||
uint16_t chars;
|
||||
|
||||
|
||||
chars = previous->last_word.chars;
|
||||
previous->chars -= chars;
|
||||
current->chars += chars;
|
||||
previous->width -= previous->last_word.word + previous->last_word.space;
|
||||
current->width += previous->last_word.word + previous->last_word.space;
|
||||
previous->last_word = previous->last_word_2;
|
||||
|
||||
|
||||
while (chars--) mf_rewind(¤t->start);
|
||||
}
|
||||
}
|
||||
@ -177,13 +181,13 @@ void mf_wordwrap(const struct mf_font_s *font, int16_t width,
|
||||
struct linelen_s current = { 0 };
|
||||
struct linelen_s previous = { 0 };
|
||||
bool full;
|
||||
|
||||
|
||||
current.start = text;
|
||||
|
||||
|
||||
while (*text)
|
||||
{
|
||||
full = !append_word(font, width, ¤t, &text);
|
||||
|
||||
|
||||
if (full || current.linebreak)
|
||||
{
|
||||
if (!current.chars)
|
||||
@ -192,17 +196,17 @@ void mf_wordwrap(const struct mf_font_s *font, int16_t width,
|
||||
* point. */
|
||||
while (append_char(font, width, ¤t, &text));
|
||||
}
|
||||
|
||||
|
||||
if (previous.chars)
|
||||
{
|
||||
/* Tune the length and dispatch the previous line. */
|
||||
if (!previous.linebreak && !current.linebreak)
|
||||
tune_lines(¤t, &previous, width);
|
||||
|
||||
|
||||
if (!callback(previous.start, previous.chars, state))
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
previous = current;
|
||||
current.start = text;
|
||||
current.chars = 0;
|
||||
@ -213,14 +217,14 @@ void mf_wordwrap(const struct mf_font_s *font, int16_t width,
|
||||
current.last_word.chars = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Dispatch the last lines. */
|
||||
if (previous.chars)
|
||||
{
|
||||
if (!callback(previous.start, previous.chars, state))
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (current.chars)
|
||||
callback(current.start, current.chars, state);
|
||||
}
|
||||
@ -231,64 +235,64 @@ void mf_wordwrap(const struct mf_font_s *font, int16_t width,
|
||||
mf_str text, mf_line_callback_t callback, void *state)
|
||||
{
|
||||
mf_str linestart;
|
||||
|
||||
|
||||
/* Current line width and character count */
|
||||
int16_t lw_cur = 0, cc_cur = 0;
|
||||
|
||||
|
||||
/* Previous wrap point */
|
||||
int16_t cc_prev;
|
||||
mf_str ls_prev;
|
||||
|
||||
|
||||
linestart = text;
|
||||
|
||||
|
||||
while (*text)
|
||||
{
|
||||
cc_prev = 0;
|
||||
ls_prev = text;
|
||||
|
||||
|
||||
while (*text)
|
||||
{
|
||||
mf_char c;
|
||||
int16_t new_width;
|
||||
mf_str tmp;
|
||||
|
||||
|
||||
tmp = text;
|
||||
c = mf_getchar(&text);
|
||||
new_width = lw_cur + mf_character_width(font, c);
|
||||
|
||||
|
||||
if (c == '\n')
|
||||
{
|
||||
cc_prev = cc_cur + 1;
|
||||
ls_prev = text;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (new_width > width)
|
||||
{
|
||||
text = tmp;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
cc_cur++;
|
||||
lw_cur = new_width;
|
||||
|
||||
|
||||
if (is_wrap_space(c))
|
||||
{
|
||||
cc_prev = cc_cur;
|
||||
ls_prev = text;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Handle unbreakable words */
|
||||
if (cc_prev == 0)
|
||||
{
|
||||
cc_prev = cc_cur;
|
||||
ls_prev = text;
|
||||
}
|
||||
|
||||
|
||||
if (!callback(linestart, cc_prev, state))
|
||||
return;
|
||||
|
||||
|
||||
linestart = ls_prev;
|
||||
text = linestart;
|
||||
lw_cur = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user