refactor font.c into an MwFL section
Some checks failed
pyrite-dev/milsko/pipeline/head There was a failure building this commit
Some checks failed
pyrite-dev/milsko/pipeline/head There was a failure building this commit
This commit is contained in:
parent
cc2d3008d0
commit
fea0fc9c32
11 changed files with 468 additions and 385 deletions
|
|
@ -18,10 +18,12 @@ typedef struct _MwLLCommonPixmap* MwLLCommonPixmap;
|
|||
typedef union _MwLL* MwLL;
|
||||
typedef union _MwLLColor* MwLLColor;
|
||||
typedef union _MwLLPixmap* MwLLPixmap;
|
||||
typedef struct _MwFLFont* MwFLFont;
|
||||
#else
|
||||
typedef void* MwLL;
|
||||
typedef void* MwLLColor;
|
||||
typedef void* MwLLPixmap;
|
||||
typedef void* MwFLFont;
|
||||
#endif
|
||||
|
||||
enum MwLLBackends {
|
||||
|
|
@ -166,6 +168,14 @@ struct _MwLLHandler {
|
|||
void (*dark_theme)(MwLL handle, void* data);
|
||||
};
|
||||
|
||||
struct _MwLLTextDispatchTable {
|
||||
int (*drawText)(MwWidget handle, MwPoint* point, const char* text, int bold, int align, MwLLColor color);
|
||||
int (*textWidth)(MwWidget handle, const char* text);
|
||||
int (*textHeight)(MwWidget handle, int count);
|
||||
void* (*fontLoad)(unsigned char* data, unsigned int size);
|
||||
void (*fontFree)(void* handle);
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
|
@ -225,6 +235,22 @@ MWDECL void (*MwLLGetClipboard)(MwLL handle);
|
|||
MWDECL void (*MwLLGetCursorCoord)(MwLL handle, MwPoint* point);
|
||||
MWDECL void (*MwLLGetScreenSize)(MwLL handle, MwRect* rect);
|
||||
|
||||
/*font renderer */
|
||||
MWDECL void MwFLSetup();
|
||||
|
||||
#ifdef USE_FREETYPE2
|
||||
MWDECL int MWFL_FT2Setup();
|
||||
#endif
|
||||
#ifdef USE_STB_TRUETYPE
|
||||
MWDECL int MwFL_STBTTSetup();
|
||||
#endif
|
||||
|
||||
MWDECL int (*MwFLDrawText)(MwWidget handle, MwPoint* point, const char* text, int bold, int align, MwLLColor color);
|
||||
MWDECL int (*MwFLTextWidth)(MwWidget handle, const char* text);
|
||||
MWDECL int (*MwFLTextHeight)(MwWidget handle, int count);
|
||||
MWDECL void* (*MwFLFontLoad)(unsigned char* data, unsigned int size);
|
||||
MWDECL void (*MwFLFontFree)(void* handle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -76,8 +76,9 @@ if (param_get("vulkan") && param_get("vulkan-string-helper")) {
|
|||
}
|
||||
|
||||
new_object("src/icon/*.c");
|
||||
new_object("src/font/*.c");
|
||||
new_object("src/cursor/*.c");
|
||||
new_object("src/text/*.c");
|
||||
new_object("src/text/font/*.c");
|
||||
|
||||
new_object("src/widget/box.c");
|
||||
new_object("src/widget/button.c");
|
||||
|
|
|
|||
|
|
@ -784,6 +784,8 @@ int MwLibraryInit(void) {
|
|||
NULL};
|
||||
int i;
|
||||
|
||||
MwFLSetup();
|
||||
|
||||
for(i = 0; calls[i] != NULL; i++) {
|
||||
if(calls[i]() == 0) return 0;
|
||||
}
|
||||
|
|
|
|||
384
src/text.c
384
src/text.c
|
|
@ -1,384 +0,0 @@
|
|||
#include <Mw/Milsko.h>
|
||||
|
||||
#if defined(USE_FREETYPE2)
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
typedef struct ttf {
|
||||
FT_Library library;
|
||||
FT_Face face;
|
||||
void* data;
|
||||
} ttf_t;
|
||||
|
||||
#define TTF
|
||||
#elif defined(USE_STB_TRUETYPE)
|
||||
#include "../external/stb_truetype.h"
|
||||
|
||||
typedef struct ttf {
|
||||
stbtt_fontinfo font;
|
||||
void* data;
|
||||
float scale;
|
||||
int ascent;
|
||||
int descent;
|
||||
} ttf_t;
|
||||
|
||||
#define TTF
|
||||
#endif
|
||||
|
||||
#define FontWidth 7
|
||||
#define FontHeight 14
|
||||
|
||||
static void bitmap_MwDrawText(MwWidget handle, MwPoint* point, const char* text, int bold, int align, MwLLColor color) {
|
||||
int i = 0, x, y, sx, sy;
|
||||
int tw, th;
|
||||
unsigned char* px;
|
||||
MwRect r;
|
||||
MwLLPixmap p;
|
||||
|
||||
if(strlen(text) == 0) text = " ";
|
||||
tw = MwTextWidth(handle, text);
|
||||
th = MwTextHeight(handle, 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;
|
||||
|
||||
if(align == MwALIGNMENT_CENTER) {
|
||||
r.x -= tw / 2;
|
||||
} else if(align == MwALIGNMENT_END) {
|
||||
r.x -= tw;
|
||||
}
|
||||
|
||||
MwLLDrawPixmap(handle->lowlevel, &r, p);
|
||||
MwLLDestroyPixmap(p);
|
||||
free(px);
|
||||
}
|
||||
|
||||
#if defined(USE_STB_TRUETYPE)
|
||||
static int ttf_MwDrawText(MwWidget handle, MwPoint* point, const char* text, int bold, int align, MwLLColor color) {
|
||||
ttf_t* ttf = MwGetVoid(handle, bold ? MwNboldFont : MwNfont);
|
||||
unsigned char* px;
|
||||
int tw, th;
|
||||
MwRect r;
|
||||
MwLLPixmap p;
|
||||
int ax, lsb;
|
||||
int x = 0, y = 0;
|
||||
if(ttf == NULL) return 1;
|
||||
|
||||
tw = MwTextWidth(handle, text);
|
||||
th = MwTextHeight(handle, text);
|
||||
px = malloc(tw * th * 4);
|
||||
|
||||
memset(px, 0, tw * th * 4);
|
||||
while(text[0] != 0) {
|
||||
int c;
|
||||
int x0, y0, x1, y1, cx, cy;
|
||||
int ow, oh;
|
||||
unsigned char* out;
|
||||
|
||||
text += MwUTF8ToUTF32(text, &c);
|
||||
if(c == '\n') {
|
||||
x = 0;
|
||||
y += (ttf->ascent - ttf->descent) * ttf->scale;
|
||||
continue;
|
||||
}
|
||||
|
||||
stbtt_GetCodepointHMetrics(&ttf->font, c, &ax, &lsb);
|
||||
|
||||
stbtt_GetCodepointBitmapBox(&ttf->font, c, ttf->scale, ttf->scale, &x0, &y0, &x1, &y1);
|
||||
ow = x1 - x0;
|
||||
oh = y1 - y0;
|
||||
out = malloc(ow * oh);
|
||||
stbtt_MakeCodepointBitmap(&ttf->font, out, ow, oh, ow, ttf->scale, ttf->scale, c);
|
||||
|
||||
for(cy = 0; cy < oh; cy++) {
|
||||
for(cx = 0; cx < ow; cx++) {
|
||||
int ox = x + (lsb * ttf->scale) + cx;
|
||||
int oy = y + (ttf->ascent * ttf->scale) + y0 + cy;
|
||||
unsigned char* opx = &px[(oy * tw + ox) * 4];
|
||||
|
||||
opx[0] = color->common.red;
|
||||
opx[1] = color->common.green;
|
||||
opx[2] = color->common.blue;
|
||||
opx[3] = out[cy * ow + cx];
|
||||
}
|
||||
}
|
||||
|
||||
x += ax * ttf->scale;
|
||||
|
||||
free(out);
|
||||
}
|
||||
|
||||
p = MwLoadRaw(handle, px, tw, th);
|
||||
r.x = point->x;
|
||||
r.y = point->y - th / 2;
|
||||
r.width = tw;
|
||||
r.height = th;
|
||||
|
||||
if(align == MwALIGNMENT_CENTER) {
|
||||
r.x -= tw / 2;
|
||||
} else if(align == MwALIGNMENT_END) {
|
||||
r.x -= tw;
|
||||
}
|
||||
|
||||
MwLLDrawPixmap(handle->lowlevel, &r, p);
|
||||
MwLLDestroyPixmap(p);
|
||||
free(px);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ttf_MwTextWidth(MwWidget handle, const char* text) {
|
||||
ttf_t* ttf = MwGetVoid(handle, MwNfont);
|
||||
int ax, lsb;
|
||||
int tw = 0;
|
||||
if(ttf == NULL) return -1;
|
||||
|
||||
while(text[0] != 0) {
|
||||
int c;
|
||||
text += MwUTF8ToUTF32(text, &c);
|
||||
|
||||
stbtt_GetCodepointHMetrics(&ttf->font, c, &ax, &lsb);
|
||||
|
||||
tw += ax * ttf->scale;
|
||||
}
|
||||
|
||||
return tw;
|
||||
}
|
||||
|
||||
static int ttf_MwTextHeight(MwWidget handle, int count) {
|
||||
ttf_t* ttf = MwGetVoid(handle, MwNfont);
|
||||
if(ttf == NULL) return -1;
|
||||
|
||||
return (ttf->ascent - ttf->descent) * ttf->scale * count;
|
||||
}
|
||||
#elif defined(USE_FREETYPE2)
|
||||
static int ttf_MwDrawText(MwWidget handle, MwPoint* point, const char* text, int bold, int align, MwLLColor color) {
|
||||
ttf_t* ttf = MwGetVoid(handle, bold ? MwNboldFont : MwNfont);
|
||||
int tw, th;
|
||||
unsigned char* px;
|
||||
MwLLPixmap p;
|
||||
MwRect r;
|
||||
int x = 0, y = 0;
|
||||
if(ttf == NULL) return 1;
|
||||
|
||||
tw = MwTextWidth(handle, text);
|
||||
th = MwTextHeight(handle, text);
|
||||
px = malloc(tw * th * 4);
|
||||
|
||||
memset(px, 0, tw * th * 4);
|
||||
while(text[0] != 0) {
|
||||
int c;
|
||||
FT_Bitmap* bmp;
|
||||
int cy, cx;
|
||||
int l = MwUTF8ToUTF32(text, &c);
|
||||
if(l <= 0) break;
|
||||
text += l;
|
||||
|
||||
if(c == '\n') {
|
||||
x = 0;
|
||||
y += ttf->face->height * 14 / ttf->face->units_per_EM;
|
||||
continue;
|
||||
}
|
||||
|
||||
FT_Load_Char(ttf->face, c, FT_LOAD_RENDER);
|
||||
bmp = &ttf->face->glyph->bitmap;
|
||||
|
||||
for(cy = 0; cy < bmp->rows; cy++) {
|
||||
for(cx = 0; cx < bmp->width; cx++) {
|
||||
int ox = x + cx + ttf->face->glyph->bitmap_left;
|
||||
int oy = y + (ttf->face->height * 14 / ttf->face->units_per_EM) - ttf->face->glyph->bitmap_top + cy + (ttf->face->descender * 14 / ttf->face->units_per_EM);
|
||||
unsigned char* opx = &px[(oy * tw + ox) * 4];
|
||||
|
||||
opx[0] = color->common.red;
|
||||
opx[1] = color->common.green;
|
||||
opx[2] = color->common.blue;
|
||||
opx[3] = bmp->buffer[cy * bmp->pitch + cx];
|
||||
}
|
||||
}
|
||||
|
||||
x += ttf->face->glyph->metrics.horiAdvance / 64;
|
||||
}
|
||||
|
||||
p = MwLoadRaw(handle, px, tw, th);
|
||||
r.x = point->x;
|
||||
r.y = point->y - th / 2;
|
||||
r.width = tw;
|
||||
r.height = th;
|
||||
|
||||
if(align == MwALIGNMENT_CENTER) {
|
||||
r.x -= tw / 2;
|
||||
} else if(align == MwALIGNMENT_END) {
|
||||
r.x -= tw;
|
||||
}
|
||||
|
||||
MwLLDrawPixmap(handle->lowlevel, &r, p);
|
||||
MwLLDestroyPixmap(p);
|
||||
free(px);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ttf_MwTextWidth(MwWidget handle, const char* text) {
|
||||
ttf_t* ttf = MwGetVoid(handle, MwNfont);
|
||||
int tw = 0, mtw = 0;
|
||||
if(ttf == NULL) return -1;
|
||||
|
||||
while(text[0] != 0) {
|
||||
int c;
|
||||
int l = MwUTF8ToUTF32(text, &c);
|
||||
if(l <= 0) break;
|
||||
text += l;
|
||||
if(c == '\n') {
|
||||
tw = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
FT_Load_Char(ttf->face, c, FT_LOAD_RENDER);
|
||||
|
||||
tw += ttf->face->glyph->metrics.horiAdvance / 64;
|
||||
if(tw > mtw) mtw = tw;
|
||||
}
|
||||
|
||||
return mtw;
|
||||
}
|
||||
|
||||
static int ttf_MwTextHeight(MwWidget handle, int count) {
|
||||
ttf_t* ttf = MwGetVoid(handle, MwNfont);
|
||||
if(ttf == NULL) return -1;
|
||||
|
||||
return (ttf->face->height * 14 / ttf->face->units_per_EM) * count;
|
||||
}
|
||||
#endif
|
||||
|
||||
void MwDrawText(MwWidget handle, MwPoint* point, const char* text, int bold, int align, MwLLColor color) {
|
||||
if(strlen(text) == 0) return;
|
||||
#ifdef TTF
|
||||
if(MwGetInteger(handle, MwNbitmapFont) || ttf_MwDrawText(handle, point, text, bold, align, color))
|
||||
#endif
|
||||
bitmap_MwDrawText(handle, point, text, bold, align, color);
|
||||
}
|
||||
|
||||
int MwTextWidth(MwWidget handle, const char* text) {
|
||||
/* TODO: check newline */
|
||||
#ifdef TTF
|
||||
int st;
|
||||
|
||||
if(!MwGetInteger(handle, MwNbitmapFont) && (st = ttf_MwTextWidth(handle, text)) != -1) return st;
|
||||
#else
|
||||
(void)handle;
|
||||
|
||||
#endif
|
||||
return MwUTF8Length(text) * FontWidth;
|
||||
}
|
||||
|
||||
int MwTextHeight(MwWidget handle, const char* text) {
|
||||
int c = 1;
|
||||
int i = 0;
|
||||
#ifdef TTF
|
||||
int st;
|
||||
#endif
|
||||
|
||||
(void)handle;
|
||||
(void)text;
|
||||
|
||||
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(!MwGetInteger(handle, MwNbitmapFont) && (st = ttf_MwTextHeight(handle, c)) != -1) return st;
|
||||
#endif
|
||||
return FontHeight * c;
|
||||
}
|
||||
|
||||
void* MwFontLoad(unsigned char* data, unsigned int size) {
|
||||
#if defined(USE_FREETYPE2)
|
||||
ttf_t* ttf = malloc(sizeof(*ttf));
|
||||
ttf->data = malloc(size);
|
||||
memcpy(ttf->data, data, size);
|
||||
FT_Init_FreeType(&ttf->library);
|
||||
FT_New_Memory_Face(ttf->library, ttf->data, size, 0, &ttf->face);
|
||||
|
||||
FT_Set_Pixel_Sizes(ttf->face, 0, 14);
|
||||
|
||||
return ttf;
|
||||
#elif defined(USE_STB_TRUETYPE)
|
||||
ttf_t* ttf = malloc(sizeof(*ttf));
|
||||
ttf->data = malloc(size);
|
||||
memcpy(ttf->data, data, size);
|
||||
stbtt_InitFont(&ttf->font, ttf->data, 0);
|
||||
|
||||
ttf->scale = stbtt_ScaleForPixelHeight(&ttf->font, 16);
|
||||
stbtt_GetFontVMetrics(&ttf->font, &ttf->ascent, &ttf->descent, 0);
|
||||
|
||||
return ttf;
|
||||
#else
|
||||
(void)data;
|
||||
(void)size;
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
void MwFontFree(void* handle) {
|
||||
#if defined(USE_FREETYPE2)
|
||||
ttf_t* ttf = handle;
|
||||
|
||||
FT_Done_Face(ttf->face);
|
||||
FT_Done_FreeType(ttf->library);
|
||||
|
||||
free(ttf->data);
|
||||
free(ttf);
|
||||
#elif defined(USE_STB_TRUETYPE)
|
||||
ttf_t* ttf = handle;
|
||||
|
||||
free(ttf->data);
|
||||
free(ttf);
|
||||
#else
|
||||
(void)handle;
|
||||
#endif
|
||||
}
|
||||
139
src/text/ft2.c
Normal file
139
src/text/ft2.c
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
#ifdef USE_FREETYPE2
|
||||
#include <Mw/Milsko.h>
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
struct _MwFLFont {
|
||||
FT_Library library;
|
||||
FT_Face face;
|
||||
void* data;
|
||||
};
|
||||
static int ft2_MwDrawText(MwWidget handle, MwPoint* point, const char* text, int bold, int align, MwLLColor color) {
|
||||
MwFLFont ttf = MwGetVoid(handle, bold ? MwNboldFont : MwNfont);
|
||||
int tw, th;
|
||||
unsigned char* px;
|
||||
MwLLPixmap p;
|
||||
MwRect r;
|
||||
int x = 0, y = 0;
|
||||
if(ttf == NULL) return 1;
|
||||
|
||||
tw = MwTextWidth(handle, text);
|
||||
th = MwTextHeight(handle, text);
|
||||
px = malloc(tw * th * 4);
|
||||
|
||||
memset(px, 0, tw * th * 4);
|
||||
while(text[0] != 0) {
|
||||
int c;
|
||||
FT_Bitmap* bmp;
|
||||
int cy, cx;
|
||||
int l = MwUTF8ToUTF32(text, &c);
|
||||
if(l <= 0) break;
|
||||
text += l;
|
||||
|
||||
if(c == '\n') {
|
||||
x = 0;
|
||||
y += ttf->face->height * 14 / ttf->face->units_per_EM;
|
||||
continue;
|
||||
}
|
||||
|
||||
FT_Load_Char(ttf->face, c, FT_LOAD_RENDER);
|
||||
bmp = &ttf->face->glyph->bitmap;
|
||||
|
||||
for(cy = 0; cy < bmp->rows; cy++) {
|
||||
for(cx = 0; cx < bmp->width; cx++) {
|
||||
int ox = x + cx + ttf->face->glyph->bitmap_left;
|
||||
int oy = y + (ttf->face->height * 14 / ttf->face->units_per_EM) - ttf->face->glyph->bitmap_top + cy + (ttf->face->descender * 14 / ttf->face->units_per_EM);
|
||||
unsigned char* opx = &px[(oy * tw + ox) * 4];
|
||||
|
||||
opx[0] = color->common.red;
|
||||
opx[1] = color->common.green;
|
||||
opx[2] = color->common.blue;
|
||||
opx[3] = bmp->buffer[cy * bmp->pitch + cx];
|
||||
}
|
||||
}
|
||||
|
||||
x += ttf->face->glyph->metrics.horiAdvance / 64;
|
||||
}
|
||||
|
||||
p = MwLoadRaw(handle, px, tw, th);
|
||||
r.x = point->x;
|
||||
r.y = point->y - th / 2;
|
||||
r.width = tw;
|
||||
r.height = th;
|
||||
|
||||
if(align == MwALIGNMENT_CENTER) {
|
||||
r.x -= tw / 2;
|
||||
} else if(align == MwALIGNMENT_END) {
|
||||
r.x -= tw;
|
||||
}
|
||||
|
||||
MwLLDrawPixmap(handle->lowlevel, &r, p);
|
||||
MwLLDestroyPixmap(p);
|
||||
free(px);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ft2_MwTextWidth(MwWidget handle, const char* text) {
|
||||
MwFLFont ttf = MwGetVoid(handle, MwNfont);
|
||||
int tw = 0, mtw = 0;
|
||||
if(ttf == NULL) return -1;
|
||||
|
||||
while(text[0] != 0) {
|
||||
int c;
|
||||
int l = MwUTF8ToUTF32(text, &c);
|
||||
if(l <= 0) break;
|
||||
text += l;
|
||||
if(c == '\n') {
|
||||
tw = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
FT_Load_Char(ttf->face, c, FT_LOAD_RENDER);
|
||||
|
||||
tw += ttf->face->glyph->metrics.horiAdvance / 64;
|
||||
if(tw > mtw) mtw = tw;
|
||||
}
|
||||
|
||||
return mtw;
|
||||
}
|
||||
|
||||
static int ft2_MwTextHeight(MwWidget handle, int count) {
|
||||
MwFLFont ttf = MwGetVoid(handle, MwNfont);
|
||||
if(ttf == NULL) return -1;
|
||||
|
||||
return (ttf->face->height * 14 / ttf->face->units_per_EM) * count;
|
||||
}
|
||||
|
||||
static void* ft2_MwFontLoad(unsigned char* data, unsigned int size) {
|
||||
MwFLFont ttf = malloc(sizeof(*ttf));
|
||||
ttf->data = malloc(size);
|
||||
memcpy(ttf->data, data, size);
|
||||
FT_Init_FreeType(&ttf->library);
|
||||
FT_New_Memory_Face(ttf->library, ttf->data, size, 0, &ttf->face);
|
||||
|
||||
FT_Set_Pixel_Sizes(ttf->face, 0, 14);
|
||||
|
||||
return ttf;
|
||||
}
|
||||
|
||||
static void ft2_MwFontFree(void* handle) {
|
||||
MwFLFont ttf = handle;
|
||||
|
||||
FT_Done_Face(ttf->face);
|
||||
FT_Done_FreeType(ttf->library);
|
||||
|
||||
free(ttf->data);
|
||||
free(ttf);
|
||||
}
|
||||
|
||||
int MWFL_FT2Setup() {
|
||||
MwFLDrawText = ft2_MwDrawText;
|
||||
MwFLTextWidth = ft2_MwTextWidth;
|
||||
MwFLTextHeight = ft2_MwTextHeight;
|
||||
MwFLFontLoad = ft2_MwFontLoad;
|
||||
MwFLFontFree = ft2_MwFontFree;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
141
src/text/stbtt.c
Normal file
141
src/text/stbtt.c
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
#ifdef USE_STB_TRUETYPE
|
||||
#include <stdlib.h>
|
||||
#include <Mw/Milsko.h>
|
||||
|
||||
#include "../../external/stb_truetype.h"
|
||||
|
||||
struct _MwFLFont {
|
||||
stbtt_fontinfo font;
|
||||
void* data;
|
||||
float scale;
|
||||
int ascent;
|
||||
int descent;
|
||||
};
|
||||
|
||||
static int stbtt_MwDrawText(MwWidget handle, MwPoint* point, const char* text, int bold, int align, MwLLColor color) {
|
||||
MwFLFont ttf = MwGetVoid(handle, bold ? MwNboldFont : MwNfont);
|
||||
unsigned char* px;
|
||||
int tw, th;
|
||||
MwRect r;
|
||||
MwLLPixmap p;
|
||||
int ax, lsb;
|
||||
int x = 0, y = 0;
|
||||
if(ttf == NULL) return 1;
|
||||
|
||||
tw = MwTextWidth(handle, text);
|
||||
th = MwTextHeight(handle, text);
|
||||
px = malloc(tw * th * 4);
|
||||
|
||||
memset(px, 0, tw * th * 4);
|
||||
while(text[0] != 0) {
|
||||
int c;
|
||||
int x0, y0, x1, y1, cx, cy;
|
||||
int ow, oh;
|
||||
unsigned char* out;
|
||||
|
||||
text += MwUTF8ToUTF32(text, &c);
|
||||
if(c == '\n') {
|
||||
x = 0;
|
||||
y += (ttf->ascent - ttf->descent) * ttf->scale;
|
||||
continue;
|
||||
}
|
||||
|
||||
stbtt_GetCodepointHMetrics(&ttf->font, c, &ax, &lsb);
|
||||
|
||||
stbtt_GetCodepointBitmapBox(&ttf->font, c, ttf->scale, ttf->scale, &x0, &y0, &x1, &y1);
|
||||
ow = x1 - x0;
|
||||
oh = y1 - y0;
|
||||
out = malloc(ow * oh);
|
||||
stbtt_MakeCodepointBitmap(&ttf->font, out, ow, oh, ow, ttf->scale, ttf->scale, c);
|
||||
|
||||
for(cy = 0; cy < oh; cy++) {
|
||||
for(cx = 0; cx < ow; cx++) {
|
||||
int ox = x + (lsb * ttf->scale) + cx;
|
||||
int oy = y + (ttf->ascent * ttf->scale) + y0 + cy;
|
||||
unsigned char* opx = &px[(oy * tw + ox) * 4];
|
||||
|
||||
opx[0] = color->common.red;
|
||||
opx[1] = color->common.green;
|
||||
opx[2] = color->common.blue;
|
||||
opx[3] = out[cy * ow + cx];
|
||||
}
|
||||
}
|
||||
|
||||
x += ax * ttf->scale;
|
||||
|
||||
free(out);
|
||||
}
|
||||
|
||||
p = MwLoadRaw(handle, px, tw, th);
|
||||
r.x = point->x;
|
||||
r.y = point->y - th / 2;
|
||||
r.width = tw;
|
||||
r.height = th;
|
||||
|
||||
if(align == MwALIGNMENT_CENTER) {
|
||||
r.x -= tw / 2;
|
||||
} else if(align == MwALIGNMENT_END) {
|
||||
r.x -= tw;
|
||||
}
|
||||
|
||||
MwLLDrawPixmap(handle->lowlevel, &r, p);
|
||||
MwLLDestroyPixmap(p);
|
||||
free(px);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stbtt_MwTextWidth(MwWidget handle, const char* text) {
|
||||
MwFLFont ttf = MwGetVoid(handle, MwNfont);
|
||||
int ax, lsb;
|
||||
int tw = 0;
|
||||
if(ttf == NULL) return -1;
|
||||
|
||||
while(text[0] != 0) {
|
||||
int c;
|
||||
text += MwUTF8ToUTF32(text, &c);
|
||||
|
||||
stbtt_GetCodepointHMetrics(&ttf->font, c, &ax, &lsb);
|
||||
|
||||
tw += ax * ttf->scale;
|
||||
}
|
||||
|
||||
return tw;
|
||||
}
|
||||
|
||||
static int stbtt_MwTextHeight(MwWidget handle, int count) {
|
||||
MwFLFont ttf = MwGetVoid(handle, MwNfont);
|
||||
if(ttf == NULL) return -1;
|
||||
|
||||
return (ttf->ascent - ttf->descent) * ttf->scale * count;
|
||||
}
|
||||
|
||||
static void* stbtt_MwFontLoad(unsigned char* data, unsigned int size) {
|
||||
MwFLFont ttf = malloc(sizeof(*ttf));
|
||||
ttf->data = malloc(size);
|
||||
memcpy(ttf->data, data, size);
|
||||
stbtt_InitFont(&ttf->font, ttf->data, 0);
|
||||
|
||||
ttf->scale = stbtt_ScaleForPixelHeight(&ttf->font, 16);
|
||||
stbtt_GetFontVMetrics(&ttf->font, &ttf->ascent, &ttf->descent, 0);
|
||||
|
||||
return ttf;
|
||||
}
|
||||
|
||||
static void stbtt_MwFontFree(void* handle) {
|
||||
MwFLFont ttf = handle;
|
||||
|
||||
free(ttf->data);
|
||||
free(ttf);
|
||||
}
|
||||
|
||||
int MwFL_STBTTSetup() {
|
||||
MwFLDrawText = stbtt_MwDrawText;
|
||||
MwFLTextWidth = stbtt_MwTextWidth;
|
||||
MwFLTextHeight = stbtt_MwTextHeight;
|
||||
MwFLFontLoad = stbtt_MwFontLoad;
|
||||
MwFLFontFree = stbtt_MwFontFree;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
158
src/text/text.c
Normal file
158
src/text/text.c
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
#include <Mw/Milsko.h>
|
||||
|
||||
int (*MwFLDrawText)(MwWidget handle, MwPoint* point, const char* text, int bold, int align, MwLLColor color) = NULL;
|
||||
int (*MwFLTextWidth)(MwWidget handle, const char* text) = NULL;
|
||||
int (*MwFLTextHeight)(MwWidget handle, int count) = NULL;
|
||||
void* (*MwFLFontLoad)(unsigned char* data, unsigned int size) = NULL;
|
||||
void (*MwFLFontFree)(void* handle) = NULL;
|
||||
|
||||
#if defined(USE_FREETYPE2) || defined(USE_STB_TRUETYPE)
|
||||
#define TTF
|
||||
#endif
|
||||
|
||||
#define FontWidth 7
|
||||
#define FontHeight 14
|
||||
|
||||
static void bitmap_MwDrawText(MwWidget handle, MwPoint* point, const char* text, int bold, int align, MwLLColor color);
|
||||
|
||||
void MwDrawText(MwWidget handle, MwPoint* point, const char* text, int bold, int align, MwLLColor color) {
|
||||
if(strlen(text) == 0) return;
|
||||
#ifdef TTF
|
||||
if(MwFLDrawText)
|
||||
if(MwGetInteger(handle, MwNbitmapFont) || MwFLDrawText(handle, point, text, bold, align, color))
|
||||
#endif
|
||||
bitmap_MwDrawText(handle, point, text, bold, align, color);
|
||||
}
|
||||
|
||||
int MwTextWidth(MwWidget handle, const char* text) {
|
||||
/* TODO: check newline */
|
||||
#ifdef TTF
|
||||
int st;
|
||||
|
||||
if(MwFLTextWidth)
|
||||
if(!MwGetInteger(handle, MwNbitmapFont) && (st = MwFLTextWidth(handle, text)) != -1) return st;
|
||||
#else
|
||||
(void)handle;
|
||||
|
||||
#endif
|
||||
return MwUTF8Length(text) * FontWidth;
|
||||
}
|
||||
|
||||
int MwTextHeight(MwWidget handle, const char* text) {
|
||||
int c = 1;
|
||||
int i = 0;
|
||||
#ifdef TTF
|
||||
int st;
|
||||
#endif
|
||||
|
||||
(void)handle;
|
||||
(void)text;
|
||||
|
||||
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)
|
||||
if(!MwGetInteger(handle, MwNbitmapFont) && (st = MwFLTextHeight(handle, c)) != -1) return st;
|
||||
#endif
|
||||
return FontHeight * c;
|
||||
}
|
||||
|
||||
void* MwFontLoad(unsigned char* data, unsigned int size) {
|
||||
if(MwFLFontLoad)
|
||||
return MwFLFontLoad(data, size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void MwFontFree(void* handle) {
|
||||
if(MwFLFontFree)
|
||||
return MwFLFontFree(handle);
|
||||
}
|
||||
|
||||
static void bitmap_MwDrawText(MwWidget handle, MwPoint* point, const char* text, int bold, int align, MwLLColor color) {
|
||||
int i = 0, x, y, sx, sy;
|
||||
int tw, th;
|
||||
unsigned char* px;
|
||||
MwRect r;
|
||||
MwLLPixmap p;
|
||||
|
||||
if(strlen(text) == 0) text = " ";
|
||||
tw = MwTextWidth(handle, text);
|
||||
th = MwTextHeight(handle, 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;
|
||||
|
||||
if(align == MwALIGNMENT_CENTER) {
|
||||
r.x -= tw / 2;
|
||||
} else if(align == MwALIGNMENT_END) {
|
||||
r.x -= tw;
|
||||
}
|
||||
|
||||
MwLLDrawPixmap(handle->lowlevel, &r, p);
|
||||
MwLLDestroyPixmap(p);
|
||||
free(px);
|
||||
}
|
||||
|
||||
typedef int (*call_t)();
|
||||
void MwFLSetup() {
|
||||
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;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue