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