Mirai's Miscellaneous Misadventures
M34 / core / text.c
#include <mimimi/chapters.h>
#include <mimimi/fonts.h>
#include <mimimi/assets.h>
static int mimimi_stamp_glyph(int stamp, struct mimimi_image *target, int x0, int y0, struct mimimi_font *font, unsigned char color, unsigned long int cp)
{
if (cp == 0x20) return 4;
unsigned long int a = cp >> 8;
unsigned long int b = cp & 0xFF;
unsigned long int i = font->indices[a] * 0x100 + b;
int width = 0;
for (int x = 0 ; x < 8 ; x++)
for (int y = 0 ; y < 16 ; y++)
{
if ((font->glyphs[i][y] >> (8 - x) & 1) != 0)
width = x + 1;
}
if (stamp == 0) return width;
for (int x1 = 0 ; x1 < width ; x1++)
for (int y1 = 0 ; y1 < 16 ; y1++)
{
int x = x0 + x1 - 1;
int y = y0 + y1 - 10;
if (x < 0) continue;
if (y < 0) continue;
if (x >= target->width) break;
if (y >= target->height) return width;
if ((font->glyphs[i][y1] >> (8 - x1) & 1) == 0) continue;
target->colors[x + y * target->width] = color;
}
return width;
}
static unsigned long int mimimi_utf8(char **text)
{
unsigned char ch = text[0][0];
if ((ch & 0x80) == 0x00)
{
text[0] += 1;
return ch;
}
unsigned char ch1 = text[0][1];
if ((ch & 0xE0) == 0xC0)
{
unsigned long int cp = ch;
cp &= ~0xC0;
cp <<= 6;
cp |= ch1 & ~0x80;
text[0] += 2;
return cp;
}
unsigned char ch2 = text[0][2];
if ((ch & 0xF0) == 0xE0)
{
unsigned long int cp = ch;
cp &= ~0xE0;
cp <<= 6;
cp |= ch1 & ~0x80;
cp <<= 6;
cp |= ch2 & ~0x80;
text[0] += 3;
return cp;
}
unsigned char ch3 = text[0][3];
if ((ch & 0xF8) == 0xF0)
{
unsigned long int cp = ch;
cp &= ~0xF0;
cp <<= 6;
cp |= ch1 & ~0x80;
cp <<= 6;
cp |= ch2 & ~0x80;
cp <<= 6;
cp |= ch3 & ~0x80;
text[0] += 4;
return cp;
}
return 0;
}
static int mimimi_measure_text_until(struct mimimi_font *font, char **text, unsigned long int last, unsigned long int last2)
{
int x = 0;
for (;;)
{
if (**text == 0) break;
unsigned long int cp = mimimi_utf8(text);
if (cp == last) break;
if (cp == last2) break;
x += mimimi_stamp_glyph(0, 0, x, 0, font, 0, cp);
}
return x;
}
int mimimi_text_until(struct mimimi_image *image, struct mimimi_font *font, unsigned char color, int x, int y, char **text, unsigned long int last, unsigned long int last2)
{
for (;;)
{
if (**text == 0) break;
unsigned long int cp = mimimi_utf8(text);
if (cp == last) break;
if (cp == last2) break;
x += mimimi_stamp_glyph(1, image, x, y, font, color, cp);
}
return x;
}
int mimimi_measure_text(struct mimimi_font *font, char *text)
{
return mimimi_measure_text_until(font, &text, 0, 0);
}
int mimimi_text(struct mimimi_image *image, struct mimimi_font *font, unsigned char color, int x, int y, char *text)
{
return mimimi_text_until(image, font, color, x, y, &text, 0, 0);
}
int mimimi_measure_word(struct mimimi_font *font, char **text)
{
return mimimi_measure_text_until(font, text, 0x20, 0x0A);
}
int mimimi_word(struct mimimi_image *image, struct mimimi_font *font, unsigned char color, int x, int y, char **text)
{
return mimimi_text_until(image, font, color, x, y, text, 0x20, 0x0A);
}
static int mimimi_stamp_line(int stamp, struct mimimi_image *image, struct mimimi_font *font, unsigned char color, int x, int y, int width, char **text)
{
width += x;
int sp = mimimi_measure_text(font, " ");
for (;;)
{
char *text1 = *text;
int n = mimimi_measure_text_until(font, &text1, 0x20, 0x0A);
if (x + n > width) return x;
if (stamp == 0) *text = text1;
else mimimi_text_until(image, font, color, x, y, text, 0x20, 0x0A);
if (**text == 0) return x + n;
if ((*text)[-1] == 0x0A) return x + n;
while (**text == 0x20) mimimi_utf8(text);
x += n + sp;
}
}
int mimimi_measure_line(struct mimimi_font *font, int width, char **text)
{
return mimimi_stamp_line(0, 0, font, 0, 0, 0, width, text);
}
int mimimi_line(struct mimimi_image *image, struct mimimi_font *font, unsigned char color, int x, int y, int width, char **text)
{
return mimimi_stamp_line(1, image, font, color, x, y, width, text);
}
int mimimi_count_lines(struct mimimi_font *font, int width, char *text)
{
int count = 0;
for (;;)
{
char *text1 = text;
mimimi_measure_line(font, width, &text);
if (text == text1) mimimi_measure_word(font, &text);
if (*text == 0) return count;
count++;
}
}
void mimimi_lines(struct mimimi_image *image, struct mimimi_font *font, unsigned char color, int x, int y, int width, int height, char *text)
{
for (;;)
{
char *text1 = text;
mimimi_line(image, font, color, x, y, width, &text);
if (text == text1) mimimi_word(image, font, color, x, y, &text);
if (*text == 0) return;
y += height;
}
}