milsko/src/text/text.c

202 lines
4.6 KiB
C
Raw Normal View History

#include <Mw/Milsko.h>
2026-04-06 17:29:09 +09:00
int (*MwFLDrawText)(MwWidget handle, MwFLFont font, MwPoint* point, const char* text, MwLLColor color) = NULL;
int (*MwFLTextWidth)(MwFLFont font, const char* text) = NULL;
int (*MwFLTextHeight)(MwFLFont font, int count) = NULL;
2026-04-06 23:27:27 +09:00
void* (*MwFLFontLoad)(unsigned char* data, unsigned int size, int px) = NULL;
2026-04-06 17:29:09 +09:00
void (*MwFLFontFree)(void* handle) = NULL;
#if defined(USE_FREETYPE2) || defined(USE_STB_TRUETYPE)
#define TTF
#endif
#define FontWidth 7
#define FontHeight 14
2026-04-06 17:29:09 +09:00
static void bitmap_MwDrawText(MwWidget handle, MwPoint* point, const char* text, int bold, MwLLColor color);
static int is_bold(MwWidget handle, MwFLFont ttf) {
size_t u = (size_t)ttf;
int s;
if(u & MwFLFlagBold) return 1;
s = MwGetInteger(handle, MwNbold);
if(s == MwDEFAULT) return 0;
return s;
}
static int is_monospace(MwWidget handle, MwFLFont ttf) {
size_t u = (size_t)ttf;
int s;
if(u & MwFLFlagMonospace) return 1;
s = MwGetInteger(handle, MwNuseMonospace);
if(s == MwDEFAULT) return 0;
return s;
}
#ifdef TTF
static MwFLFont assume_ttf(MwWidget handle, MwFLFont ttf) {
if(MwGetInteger(handle, MwNbitmapFont)) return NULL;
if(is_monospace(handle, ttf)) return is_bold(handle, ttf) ? MwGetVoid(handle, MwNboldMonospaceFont) : MwGetVoid(handle, MwNmonospaceFont);
return is_bold(handle, ttf) ? MwGetVoid(handle, MwNboldFont) : MwGetVoid(handle, MwNfont);
}
#endif
void MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const char* text, int align, MwLLColor color) {
MwPoint p = *point;
if(strlen(text) == 0) return;
2026-04-06 17:29:09 +09:00
#ifdef TTF
if(ttf <= MwFLBuildFont(0xff)) ttf = assume_ttf(handle, ttf);
#endif
if(align == MwALIGNMENT_CENTER) {
p.x -= MwTextWidth(handle, ttf, text) / 2;
} else if(align == MwALIGNMENT_END) {
p.x -= MwTextWidth(handle, ttf, text);
}
#ifdef TTF
if(MwFLDrawText)
2026-04-06 17:29:09 +09:00
if(MwGetInteger(handle, MwNbitmapFont) || ttf == NULL || MwFLDrawText(handle, ttf, &p, text, color))
#endif
2026-04-06 17:29:09 +09:00
bitmap_MwDrawText(handle, &p, text, is_bold(handle, ttf), color);
}
2026-04-06 17:29:09 +09:00
int MwTextWidth(MwWidget handle, MwFLFont ttf, const char* text) {
/* TODO: check newline */
#ifdef TTF
int st;
2026-04-06 17:29:09 +09:00
if(ttf <= MwFLBuildFont(0xff)) ttf = assume_ttf(handle, ttf);
if(MwFLTextWidth)
2026-04-06 17:29:09 +09:00
if(!MwGetInteger(handle, MwNbitmapFont) && ttf != NULL && (st = MwFLTextWidth(ttf, text)) != -1) return st;
#else
(void)handle;
2026-04-06 17:29:09 +09:00
(void)ttf;
#endif
return MwUTF8Length(text) * FontWidth;
}
2026-04-06 17:29:09 +09:00
int MwTextHeight(MwWidget handle, MwFLFont ttf, const char* text) {
int c = 1;
int i = 0;
#ifdef TTF
int st;
#endif
2026-04-06 17:29:09 +09:00
#ifdef TTF
if(ttf <= MwFLBuildFont(0xff)) ttf = assume_ttf(handle, ttf);
#else
(void)handle;
(void)text;
2026-04-06 17:29:09 +09:00
(void)ttf;
#endif
while(text[i] != 0) {
int out;
int l = MwUTF8ToUTF32(text + i, &out);
if(l == 0) break;
i += l;
if(out == '\n') c++;
}
#ifdef TTF
if(MwFLTextHeight)
2026-04-06 17:29:09 +09:00
if(!MwGetInteger(handle, MwNbitmapFont) && ttf != NULL && (st = MwFLTextHeight(ttf, c)) != -1) return st;
#endif
return FontHeight * c;
}
void* MwFontLoad(unsigned char* data, unsigned int size) {
if(MwFLFontLoad)
2026-04-06 23:27:27 +09:00
return MwFLFontLoad(data, size, 16);
return NULL;
}
void MwFontFree(void* handle) {
2026-03-24 04:27:57 +09:00
if(MwFLFontFree) MwFLFontFree(handle);
}
2026-04-06 17:29:09 +09:00
static void bitmap_MwDrawText(MwWidget handle, MwPoint* point, const char* text, int bold, MwLLColor color) {
int i = 0, x, y, sx, sy;
int tw, th;
unsigned char* px;
MwRect r;
MwLLPixmap p;
if(strlen(text) == 0) text = " ";
2026-04-06 17:29:09 +09:00
tw = MwTextWidth(handle, NULL, text);
th = MwTextHeight(handle, NULL, text);
px = malloc(tw * th * 4);
memset(px, 0, tw * th * 4);
sx = 0;
sy = 0;
while(text[i] != 0) {
int out;
i += MwUTF8ToUTF32(text + i, &out);
if(out > 0xff) {
out = 0;
}
if(out == '\n') {
sx = 0;
sy += FontHeight;
} else {
for(y = 0; y < FontHeight; y++) {
for(x = 0; x < FontWidth; x++) {
unsigned char* ppx = &px[((sy + y) * tw + sx + x) * 4];
if((bold ? MwBoldFontData : MwFontData)[out].data[y] & (1 << ((FontWidth - 1) - x))) {
ppx[0] = color->common.red;
ppx[1] = color->common.green;
ppx[2] = color->common.blue;
ppx[3] = 255;
} else {
ppx[0] = 0;
ppx[1] = 0;
ppx[2] = 0;
ppx[3] = 0;
}
}
}
sx += FontWidth;
}
}
p = MwLoadRaw(handle, px, tw, th);
r.x = point->x;
r.y = point->y - th / 2;
r.width = tw;
r.height = th;
MwLLDrawPixmap(handle->lowlevel, &r, p);
MwLLDestroyPixmap(p);
free(px);
}
2026-03-08 07:06:12 +09:00
typedef int (*call_t)(void);
void MwFLSetup(void) {
call_t calls[] = {
#ifdef USE_FREETYPE2
MWFL_FT2Setup,
#endif
#ifdef USE_STB_TRUETYPE
MwFL_STBTTSetup,
#endif
NULL};
int i;
for(i = 0; calls[i] != NULL; i++) {
if(calls[i]() == 0) return;
}
}