Mirai's Miscellaneous Misadventures
M47 / core / text.c
#include <mimimi.h>
static unsigned char mimimi_paragraph_end(char ch)
{
if (ch == 0) return 1;
if (ch == 0x0A || ch == 0x0B) return 1;
if (ch == 0x0C || ch == 0x0D) return 1;
return 0;
}
static unsigned char mimimi_space(char ch)
{
if (mimimi_paragraph_end(ch)) return 1;
if (ch == 0x20 || ch == 0x09) return 1;
return 0;
}
int mimimi_measure_character(struct mimimi_font *font, char ch)
{
int width;
int i;
int x, y;
if (ch == 0x09) return 4;
if (ch == 0x20) return 4;
i = ch - 0x20;
width = 0;
for (x = 0 ; x < 8 ; x++)
for (y = 0 ; y < 16 ; y++)
{
if ((font->glyphs[i][y] >> (7 - x) & 1) != 0)
width = x + 1;
}
return width + 1;
}
int mimimi_draw_character(struct mimimi_font *font, char ch, struct mimimi_image *target, int x0, int y0, unsigned char color)
{
int width;
int x, y;
int x1, y1;
int i;
width = mimimi_measure_character(font, ch);
i = ch - 0x20;
for (x1 = 0 ; x1 < width ; x1++)
for (y1 = 0 ; y1 < 16 ; y1++)
{
x = x0 + x1;
y = y0 + y1;
if (x < 0) continue;
if (y < 0) continue;
if (x >= target->width) continue;
if (y >= target->height) continue;
if ((font->glyphs[i][y1] >> (7 - x1) & 1) == 0) continue;
target->colors[x + y * target->width] = color;
}
return x0 + width;
}
int mimimi_measure_segment(struct mimimi_font *font, char *text, int count)
{
int x;
char ch;
x = 0;
while (count-- > 0)
{
ch = *text++;
if (ch == 0) break;
x += mimimi_measure_character(font, ch);
}
return x;
}
int mimimi_draw_segment(struct mimimi_font *font, char *text, int count, struct mimimi_image *target, int x, int y, unsigned char color)
{
char ch;
while (count-- > 0)
{
ch = *text++;
if (ch == 0) break;
x = mimimi_draw_character(font, ch, target, x, y, color);
}
return x;
}
static char *mimimi_skip_nonspace(char *text)
{
while (mimimi_space(*text) == 0) text++;
return text;
}
static char *mimimi_skip_space(char *text)
{
while (mimimi_space(*text) != 0 && mimimi_paragraph_end(*text) == 0) text++;
return text;
}
static int mimimi_count_space(char *text)
{
return mimimi_skip_space(text) - text;
}
static int mimimi_measure_space(struct mimimi_font *font, char *text)
{
(void) font;
return 4 * mimimi_count_space(text);
}
char *mimimi_skip_word(char *text)
{
text = mimimi_skip_nonspace(text);
text = mimimi_skip_space(text);
return text;
}
int mimimi_count_word(char *text)
{
return mimimi_skip_nonspace(text) - text;
}
int mimimi_measure_word(struct mimimi_font *font, char *text)
{
return mimimi_measure_segment(font, text, mimimi_count_word(text));
}
int mimimi_draw_word(struct mimimi_font *font, char *text, struct mimimi_image *target, int x, int y, unsigned char color)
{
return mimimi_draw_segment(font, text, mimimi_count_word(text), target, x, y, color);
}
char *mimimi_skip_paragraph(char *text)
{
while (mimimi_paragraph_end(*text) == 0) text++;
if (text[0] == '\r' && text[1] == '\n') text++;
if (text[0] != 0) text++;
return text;
}
int mimimi_count_paragraph(char *text)
{
int n;
n = 0;
while (mimimi_paragraph_end(text[n]) == 0) n++;
return n;
}
int mimimi_measure_paragraph(struct mimimi_font *font, char *text)
{
return mimimi_measure_segment(font, text, mimimi_count_paragraph(text));
}
int mimimi_draw_paragraph(struct mimimi_font *font, char *text, struct mimimi_image *target, int x, int y, unsigned char color)
{
return mimimi_draw_segment(font, text, mimimi_count_paragraph(text), target, x, y, color);
}
static char *mimimi_skip_line_by_word(struct mimimi_font *font, char *text, int width)
{
for (;;)
{
if (mimimi_paragraph_end(*text)) return text;
width -= mimimi_measure_word(font, text);
if (width < 0) return text;
text += mimimi_count_word(text);
width -= mimimi_measure_space(font, text);
text = mimimi_skip_word(text);
}
}
static char *mimimi_skip_line_by_character(struct mimimi_font *font, char *text, int width)
{
for (;;)
{
if (mimimi_paragraph_end(*text)) return text;
width -= mimimi_measure_character(font, *text);
if (width < 0) return text;
text++;
}
}
int mimimi_count_line(struct mimimi_font *font, char *text0, int width)
{
char *text;
text = text0;
width++;
if (mimimi_measure_segment(font, text, mimimi_count_word(text)) > width)
text = mimimi_skip_line_by_character(font, text, width);
else
text = mimimi_skip_line_by_word(font, text, width);
text = mimimi_skip_space(text);
return text - text0;
}
char *mimimi_skip_line(struct mimimi_font *font, char *text, int width)
{
text += mimimi_count_line(font, text, width);
while (mimimi_paragraph_end(*text) != 0 && *text != 0) text++;
return text;
}
int mimimi_measure_line(struct mimimi_font *font, char *text, int width)
{
return mimimi_measure_segment(font, text, mimimi_count_line(font, text, width));
}
int mimimi_draw_line(struct mimimi_font *font, char *text, int width, struct mimimi_image *target, int x, int y, unsigned char color)
{
return mimimi_draw_segment(font, text, mimimi_count_line(font, text, width), target, x, y, color);
}
int mimimi_measure_text(struct mimimi_font *font, char *text, int width, int line_height)
{
int y;
y = 0;
while (*text != 0)
{
text = mimimi_skip_line(font, text, width);
y += line_height;
}
return y;
}
int mimimi_draw_text(struct mimimi_font *font, char *text, int width, int line_height, struct mimimi_image *target, int x, int y, unsigned char color)
{
while (*text != 0)
{
mimimi_draw_line(font, text, width, target, x, y, color);
text = mimimi_skip_line(font, text, width);
y += line_height;
}
return y;
}