create abstract

git-svn-id: http://svn2.nishi.boats/svn/milsko/trunk@602 b9cfdab3-6d41-4d17-bbe4-086880011989
This commit is contained in:
NishiOwO
2025-11-05 04:15:35 +00:00
parent 82e10e6c94
commit 766b34ba34
8 changed files with 22 additions and 18 deletions

208
src/abstract/directory.c Normal file
View File

@@ -0,0 +1,208 @@
/* $Id$ */
#include <Mw/Milsko.h>
#ifdef _WIN32
#include <windows.h>
#endif
#ifdef _WIN32
typedef struct dir {
HANDLE hFind;
WIN32_FIND_DATA ffd;
int first;
} dir_t;
#else
typedef struct dir {
DIR* dir;
char* base;
} dir_t;
#endif
void* MwDirectoryOpen(const char* path) {
dir_t* dir = malloc(sizeof(*dir));
#ifdef _WIN32
char* p = malloc(strlen(path) + 2 + 1);
strcpy(p, path);
strcat(p, "/*");
if((dir->hFind = FindFirstFile(p, &dir->ffd)) == INVALID_HANDLE_VALUE) {
free(p);
free(dir);
return NULL;
}
free(p);
dir->first = 1;
#else
if((dir->dir = opendir(path)) == NULL) {
free(dir);
return NULL;
}
dir->base = malloc(strlen(path) + 1);
strcpy(dir->base, path);
#endif
return dir;
}
void MwDirectoryClose(void* handle) {
dir_t* dir = handle;
#ifdef _WIN32
FindClose(dir->hFind);
#else
closedir(dir->dir);
free(dir->base);
#endif
free(handle);
}
MwDirectoryEntry* MwDirectoryRead(void* handle) {
dir_t* dir = handle;
MwDirectoryEntry* entry = malloc(sizeof(*entry));
#ifdef _WIN32
if(dir->first) {
dir->first = 0;
} else if(FindNextFile(dir->hFind, &dir->ffd) == 0) {
free(entry);
return NULL;
}
entry->name = MwStringDupliacte(dir->ffd.cFileName);
if(dir->ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
entry->type = MwDIRECTORY_DIRECTORY;
} else {
entry->type = MwDIRECTORY_FILE;
}
entry->size = 0;
entry->size = entry->size << 32;
entry->size |= dir->ffd.nFileSizeHigh;
entry->size = entry->size << 32;
entry->size |= dir->ffd.nFileSizeLow;
#else
struct dirent* d;
struct stat s;
char* p;
if((d = readdir(dir->dir)) == NULL) {
free(entry);
return NULL;
}
entry->name = MwStringDupliacte(d->d_name);
p = malloc(strlen(dir->base) + 1 + strlen(d->d_name) + 1);
strcpy(p, dir->base);
strcat(p, "/");
strcat(p, d->d_name);
stat(p, &s);
if(S_ISDIR(s.st_mode)) {
entry->type = MwDIRECTORY_DIRECTORY;
} else {
entry->type = MwDIRECTORY_FILE;
}
entry->size = s.st_size;
entry->mtime = s.st_mtime;
free(p);
#endif
return entry;
}
void MwDirectoryFreeEntry(MwDirectoryEntry* entry) {
free(entry->name);
free(entry);
}
char* MwDirectoryCurrent(void) {
#ifdef _WIN32
int len = GetCurrentDirectory(0, NULL);
char* out = malloc(len);
GetCurrentDirectory(len, out);
return out;
#else
return getcwd(NULL, 0);
#endif
}
#ifdef _WIN32
#define DIRSEP '\\'
#else
#define DIRSEP '/'
#endif
static void MwDirectoryJoinSingle(char* target, char* p) {
int i;
if(strcmp(p, ".") == 0) return;
for(i = strlen(target) - 1; i >= 0; i--) {
if(target[i] == DIRSEP) {
target[i] = 0;
} else {
break;
}
}
if(strcmp(p, "..") == 0) {
for(i = strlen(target) - 1; i >= 0; i--) {
if(target[i] != DIRSEP) {
target[i] = 0;
} else {
break;
}
}
} else {
char b[2];
b[0] = DIRSEP;
b[1] = 0;
strcat(target, b);
strcat(target, p);
}
for(i = strlen(target) - 1; i >= 0; i--) {
if(target[i] == DIRSEP) {
target[i] = 0;
} else {
break;
}
}
if(strchr(target, DIRSEP) == NULL) {
char b[2];
b[0] = DIRSEP;
b[1] = 0;
strcat(target, b);
}
}
char* MwDirectoryJoin(char* a, char* b) {
char* p = malloc(strlen(a) + 1 + strlen(b) + 1);
char* bdup = MwStringDupliacte(b);
char* b2 = bdup;
int i;
strcpy(p, a);
for(i = strlen(p) - 1; i >= 0; i--) {
if(p[i] == DIRSEP) {
p[i] = 0;
} else {
break;
}
}
while(b2 != NULL) {
char* current = b2;
b2 = strchr(b2, DIRSEP);
if(b2 != NULL) {
b2[0] = 0;
}
MwDirectoryJoinSingle(p, current);
if(b2 != NULL) b2++;
}
free(bdup);
return p;
}

360
src/abstract/text.c Normal file
View File

@@ -0,0 +1,360 @@
/* $Id$ */
#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 >= 0x80) 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->red;
ppx[1] = color->green;
ppx[2] = color->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;
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);
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 = (ttf->ascent * ttf->scale) + y0 + cy;
unsigned char* opx = &px[(oy * tw + ox) * 4];
opx[0] = color->red;
opx[1] = color->green;
opx[2] = color->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;
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;
text += MwUTF8ToUTF32(text, &c);
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 = th - 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->red;
opx[1] = color->green;
opx[2] = color->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;
if(ttf == NULL) return -1;
while(text[0] != 0) {
int c;
text += MwUTF8ToUTF32(text, &c);
FT_Load_Char(ttf->face, c, FT_LOAD_RENDER);
tw += ttf->face->glyph->metrics.horiAdvance / 64;
}
return tw;
}
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) {
#ifdef TTF
if(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((st = ttf_MwTextWidth(handle, text)) != -1) return st;
#else
(void)handle;
#endif
return strlen(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;
i += MwUTF8ToUTF32(text + i, &out);
if(out == '\n') c++;
}
#ifdef TTF
if((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
}