diff --git a/GNUmakefile b/GNUmakefile index 47fc98a..f9b53f8 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -31,11 +31,12 @@ L_CFLAGS = $(DEPINC) $(CFLAGS) -fPIC -D_MILSKO L_LDFLAGS = $(LDFLAGS) L_LIBS = $(LIBS) -L_OBJS = src/core.o src/default.o src/draw.o src/lowlevel.o src/font.o src/boldfont.o src/error.o src/unicode.o src/color.o src/messagebox.o src/directory.o src/string.o src/filechooser.o +L_OBJS = src/core.o src/default.o src/draw.o src/lowlevel.o src/boldfont.o src/error.o src/unicode.o src/color.o src/messagebox.o src/directory.o src/string.o src/filechooser.o L_OBJS += external/ds.o external/image.o L_OBJS += src/widget/window.o src/widget/button.o src/widget/frame.o src/widget/menu.o src/widget/submenu.o src/widget/image.o src/widget/scrollbar.o src/widget/checkbox.o src/widget/label.o src/widget/entry.o src/widget/numberentry.o src/widget/viewport.o src/widget/listbox.o L_OBJS += src/cursor/hidden.o src/cursor/default.o src/cursor/cross.o src/cursor/text.o L_OBJS += src/icon/question.o src/icon/warning.o src/icon/note.o src/icon/info.o src/icon/news.o src/icon/error.o src/icon/file.o src/icon/directory.o src/icon/back.o src/icon/forward.o src/icon/up.o src/icon/computer.o src/icon/search.o +L_OBJS += src/text/font.o src/text/draw.o E_CFLAGS = $(CFLAGS) E_LDFLAGS = $(LDFLAGS) -Lsrc -Wl,-rpath,$(shell pwd)/src @@ -144,6 +145,7 @@ L_OBJS += src/widget/vulkan.o EXAMPLES += examples/vkdemos/vulkan$(EXEC) endif + .PHONY: all install format clean lib examples all: lib examples diff --git a/compile_flags.txt b/compile_flags.txt index 261e265..f625a2d 100644 --- a/compile_flags.txt +++ b/compile_flags.txt @@ -1,3 +1,5 @@ -D_MILSKO -DUSE_X11 +-DHAS_FREETYPE +-I/usr/include/freetype2 -Iinclude diff --git a/include/Mw/Draw.h b/include/Mw/Draw.h index 7a993d1..b62930b 100644 --- a/include/Mw/Draw.h +++ b/include/Mw/Draw.h @@ -41,6 +41,14 @@ MWDECL MwLLColor MwLightenColor(MwWidget handle, MwLLColor color, int r, int g, */ MWDECL void MwDrawRect(MwWidget handle, MwRect* rect, MwLLColor color); +/*! + * %brief Draws a filled rectangle that fades to a darker color + * %param handle Widget + * %param rect Rectangle area + * %param color Color + */ +MWDECL void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color); + /*! * %brief Draws a frame * %param handle Widget @@ -51,6 +59,16 @@ MWDECL void MwDrawRect(MwWidget handle, MwRect* rect, MwLLColor color); */ MWDECL void MwDrawFrame(MwWidget handle, MwRect* rect, MwLLColor color, int invert); +/*! + * %brief Does the DrawFrame/DrawRect combo used for drawing widget. + * %param handle Widget + * %param rect Rectangle area + * %param color Color + * %param invert Invert the 3D border color or not + * %warning `rect` gets changed to the area of rectangle inside + */ +MWDECL void MwDrawWidgetBack(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int border); + /*! * %brief Draws a triangle * %param handle Widget diff --git a/src/backend/x11.h b/src/backend/x11.h index c05412d..26bb0ab 100644 --- a/src/backend/x11.h +++ b/src/backend/x11.h @@ -12,6 +12,11 @@ #include #include +#ifdef HAS_FREETYPE +#include +#include FT_FREETYPE_H +#endif + struct _MwLL { Display* display; Window window; @@ -42,6 +47,13 @@ struct _MwLL { unsigned long blue_mask; unsigned long blue_max; unsigned long blue_shift; + +#ifdef HAS_FREETYPE + void* ftLib; + FT_Library ftHandle; + MwBool ftOwns; + FT_Face ftFace; +#endif }; struct _MwLLColor { @@ -64,4 +76,19 @@ struct _MwLLPixmap { XImage* mask; }; +#ifdef HAS_FREETYPE +void print_ft_error(void* ftLib, FT_Error err); +#define MwFreeTypeFontSize 181388 +extern FT_Byte MwFreeTypeFontData[MwFreeTypeFontSize]; + +#define FT_WITH_FUNC(handle, func, block) \ + { \ + _##func = dlsym(handle->ftLib, #func); \ + if(_##func != NULL) { \ + block \ + } else \ + printf("[WARNING] Unable to resolve function " #func ".\n"); \ + } +#endif + #endif diff --git a/src/default.c b/src/default.c index e13f7ce..127cf98 100644 --- a/src/default.c +++ b/src/default.c @@ -1,6 +1,10 @@ /* $Id$ */ #include -const int MwDefaultBorderWidth = 2; -const char* MwDefaultBackground = "#ddd"; -const char* MwDefaultForeground = "#000"; +#ifdef MW_CLASSIC_THEME +const int MwDefaultBorderWidth = 2; +#else +const int MwDefaultBorderWidth = 1; +#endif +const char* MwDefaultBackground = "#ddd"; +const char* MwDefaultForeground = "#000"; diff --git a/src/draw.c b/src/draw.c index ba0ef21..7b7713b 100644 --- a/src/draw.c +++ b/src/draw.c @@ -11,10 +11,11 @@ #include "../external/stb_ds.h" -#define FontWidth 7 -#define FontHeight 14 +#ifdef MW_CLASSIC_THEME #define ColorDiff 128 - +#else +#define ColorDiff 48 +#endif static int hex(const char* txt, int len) { int i; int r = 0; @@ -90,10 +91,49 @@ void MwDrawRect(MwWidget handle, MwRect* rect, MwLLColor color) { MwLLPolygon(handle->lowlevel, p, 4, color); } +void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color) { + MwLLPixmap pixmap; + int y; + int x; + double darken = 0.; + double darkenStep = (ColorDiff / 2.) / rect->height; + +#define SIZE (rect->width * rect->height * 4) + unsigned char* data = malloc(SIZE); + memset(data, 0, SIZE); +#undef SIZE + + for(y = 0; y < rect->height; y++) { + MwLLColor col = MwLightenColor(handle, color, -darken, -darken, -darken); + for(x = 0; x < rect->width; x++) { + int idx = ((y * rect->width) + x) * 4; + data[idx] = col->red; + data[idx + 1] = col->green; + data[idx + 2] = col->blue; + data[idx + 3] = 255; + } + MwLLFreeColor(col); + darken += darkenStep; + } + + pixmap = MwLLCreatePixmap(handle->lowlevel, data, rect->width / 4, rect->height); + MwLLDrawPixmap(handle->lowlevel, rect, pixmap); + MwLLDestroyPixmap(pixmap); +} void MwDrawFrame(MwWidget handle, MwRect* rect, MwLLColor color, int invert) { MwDrawFrameEx(handle, rect, color, invert, MwDefaultBorderWidth); } +void MwDrawWidgetBack(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int border) { + if(border) { + MwDrawFrame(handle, rect, color, invert); + } +#ifdef MW_CLASSIC_THEME + MwDrawRect(handle, rect, color); +#else + MwDrawRectFading(handle, rect, color); +#endif +} void MwDrawFrameEx(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int border) { MwPoint p[6]; @@ -362,95 +402,6 @@ void MwDrawTriangle(MwWidget handle, MwRect* rect, MwLLColor color, int invert, MwLLFreeColor(darker); } -void MwDrawText(MwWidget handle, MwPoint* point, const char* text, int bold, int align, MwLLColor color) { - int i = 0, x, y, sx, sy; - int tw; - int 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); -} - -int MwTextWidth(MwWidget handle, const char* text) { - (void)handle; - - /* TODO: check newline */ - return strlen(text) * FontWidth; -} - -int MwTextHeight(MwWidget handle, const char* text) { - int c = 1; - int i = 0; - - (void)handle; - (void)text; - - while(text[i] != 0) { - int out; - i += MwUTF8ToUTF32(text + i, &out); - - if(out == '\n') c++; - } - - return FontHeight * c; -} - #ifndef USE_STB_IMAGE static void PNGCAPI user_error(png_structp png, const char* str) { (void)str; diff --git a/src/widget/button.c b/src/widget/button.c index f3404cd..bb6f360 100644 --- a/src/widget/button.c +++ b/src/widget/button.c @@ -22,8 +22,7 @@ static void draw(MwWidget handle) { r.width = MwGetInteger(handle, MwNwidth); r.height = MwGetInteger(handle, MwNheight); - MwDrawFrame(handle, &r, base, handle->pressed); - MwDrawRect(handle, &r, base); + MwDrawWidgetBack(handle, &r, base, handle->pressed, MwTRUE); if(px != NULL) { int ow = r.width; diff --git a/src/widget/checkbox.c b/src/widget/checkbox.c index 3562cb9..be15b57 100644 --- a/src/widget/checkbox.c +++ b/src/widget/checkbox.c @@ -18,8 +18,7 @@ static void draw(MwWidget handle) { r.width = MwGetInteger(handle, MwNwidth); r.height = MwGetInteger(handle, MwNheight); - MwDrawFrame(handle, &r, base, (handle->pressed || MwGetInteger(handle, MwNchecked)) ? 1 : 0); - MwDrawRect(handle, &r, base); + MwDrawWidgetBack(handle, &r, base, (handle->pressed || MwGetInteger(handle, MwNchecked)) ? 1 : 0, MwTRUE); if(handle->pressed || MwGetInteger(handle, MwNchecked)) { /* TODO: write check mark */ } diff --git a/src/widget/entry.c b/src/widget/entry.c index caab181..b5da4b1 100644 --- a/src/widget/entry.c +++ b/src/widget/entry.c @@ -32,8 +32,7 @@ static void draw(MwWidget handle) { r.width = MwGetInteger(handle, MwNwidth) - t->right; r.height = MwGetInteger(handle, MwNheight); - MwDrawFrame(handle, &r, base, (handle->pressed || MwGetInteger(handle, MwNchecked)) ? 1 : 0); - MwDrawRect(handle, &r, base); + MwDrawWidgetBack(handle, &r, base, (handle->pressed || MwGetInteger(handle, MwNchecked)) ? 1 : 0, MwTRUE); if(str != NULL) { int w = MwTextWidth(handle, "M"); int h = MwTextHeight(handle, "M"); diff --git a/src/widget/menu.c b/src/widget/menu.c index 2d982db..eccb126 100644 --- a/src/widget/menu.c +++ b/src/widget/menu.c @@ -2,6 +2,7 @@ #include #include "../../external/stb_ds.h" +#include "Mw/TypeDefs.h" static void set_xywh(MwWidget handle) { int height = 0; @@ -101,14 +102,13 @@ static void draw(MwWidget handle) { MwLLColor text = MwParseColor(handle, MwGetText(handle, MwNforeground)); MENU_LOOP_DECL; - MwDrawFrame(handle, &r, base, 0); - MwDrawRect(handle, &r, base); + MwDrawWidgetBack(handle, &r, base, 0, MwTRUE); BEGIN_MENU_LOOP; if(m->sub[i]->wsub != NULL) { - MwDrawFrame(handle, &r, base, 0); + MwDrawWidgetBack(handle, &r, base, 0, MwFALSE); } else if(in_area && handle->pressed) { - MwDrawFrame(handle, &r, base, 0); + MwDrawWidgetBack(handle, &r, base, 0, MwFALSE); } MwDrawText(handle, &p, m->sub[i]->name + incr, 1, MwALIGNMENT_BEGINNING, text); diff --git a/src/widget/numberentry.c b/src/widget/numberentry.c index 31051ba..1968d3a 100644 --- a/src/widget/numberentry.c +++ b/src/widget/numberentry.c @@ -34,8 +34,7 @@ static void draw(MwWidget handle) { r.y = 0; r.width = e->right; r.height = h / 2; - MwDrawFrame(handle, &r, base, pr); - MwDrawRect(handle, &r, base); + MwDrawWidgetBack(handle, &r, base, pr, MwTRUE); if(r.width > r.height) { r.width = r.height; @@ -51,8 +50,7 @@ static void draw(MwWidget handle) { r.y = h / 2; r.width = e->right; r.height = h / 2; - MwDrawFrame(handle, &r, base, pr); - MwDrawRect(handle, &r, base); + MwDrawWidgetBack(handle, &r, base, pr, MwTRUE); if(r.width > r.height) { r.width = r.height; diff --git a/src/widget/scrollbar.c b/src/widget/scrollbar.c index b471871..f0adcd2 100644 --- a/src/widget/scrollbar.c +++ b/src/widget/scrollbar.c @@ -78,8 +78,7 @@ static void draw(MwWidget handle) { ux = r.height; dx = r.width - r.height; - MwDrawFrame(handle, &r, dark, 1); - MwDrawRect(handle, &r, dark); + MwDrawWidgetBack(handle, &r, dark, 1, MwTRUE); rt = r; @@ -124,15 +123,14 @@ static void draw(MwWidget handle) { } } - MwDrawFrame(handle, &rbar, base, 0); - MwDrawRect(handle, &rbar, base); + MwDrawWidgetBack(handle, &rbar, base, 0, MwTRUE); MwLLFreeColor(dark); MwLLFreeColor(base); } static void mouse_move(MwWidget handle) { - int or = MwGetInteger(handle, MwNorientation); + int or = MwGetInteger(handle, MwNorientation); scrollbar_t* scr = handle->internal; if(!handle->pressed) return; @@ -160,9 +158,9 @@ static void mouse_move(MwWidget handle) { } static void mouse_down(MwWidget handle, void* ptr) { - int ww = MwGetInteger(handle, MwNwidth); - int wh = MwGetInteger(handle, MwNheight); - int or = MwGetInteger(handle, MwNorientation); + int ww = MwGetInteger(handle, MwNwidth); + int wh = MwGetInteger(handle, MwNheight); + int or = MwGetInteger(handle, MwNorientation); scrollbar_t* scr = handle->internal; MwLLMouse* m = ptr; diff --git a/src/widget/submenu.c b/src/widget/submenu.c index 94c8fd3..51a53cf 100644 --- a/src/widget/submenu.c +++ b/src/widget/submenu.c @@ -37,8 +37,7 @@ static void draw(MwWidget handle) { r.width = MwGetInteger(handle, MwNwidth); r.height = MwGetInteger(handle, MwNheight); - MwDrawFrame(handle, &r, base, 0); - MwDrawRect(handle, &r, base); + MwDrawWidgetBack(handle, &r, base, 0, MwTRUE); if(menu != NULL) { MwPoint p; @@ -56,7 +55,7 @@ static void draw(MwWidget handle) { r.y = p.y - 3; r.width = tw + 15 + 5 * 2; r.height = th + 3 * 2; - MwDrawFrame(handle, &r, base, 0); + MwDrawWidgetBack(handle, &r, base, 0, MwTRUE); } p.x = 5 + tw / 2;