rounded corners on select widgets #12

Merged
IoI_xD merged 15 commits from rounded into master 2026-03-27 11:08:43 +09:00
21 changed files with 321 additions and 99 deletions

View file

@ -53,7 +53,7 @@ MWDECL void MwDrawRect(MwWidget handle, MwRect* rect, MwLLColor color);
* @param rect Rectangle area
* @param color Color
*/
MWDECL void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color);
MWDECL void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color, int rounded);
/*!
* @brief Draws a frame
@ -63,7 +63,7 @@ MWDECL void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color);
* @param invert Invert the 3D border color or not
* @warning `rect` gets changed to the area of rectangle inside
*/
MWDECL void MwDrawFrame(MwWidget handle, MwRect* rect, MwLLColor color, int invert);
MWDECL void MwDrawFrame(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int rounded);
/*!
* @brief Does the DrawFrame/DrawRect combo used for drawing widget.
@ -95,7 +95,7 @@ MWDECL void MwDrawTriangle(MwWidget handle, MwRect* rect, MwLLColor color, int i
* @param same Same as dark color
* @warning `rect` gets changed to the area of rectangle inside
*/
MWDECL void MwDrawFrameEx(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int border, int diff, int same);
MWDECL void MwDrawFrameEx(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int border, int diff, int same, int rounded);
/*!
* @brief Creates a pixmap from image

View file

@ -34,10 +34,11 @@ enum MwLLBackends {
};
struct _MwLLCommon {
void* user;
int copy_buffer;
int type;
int coordinate_type;
void* user;
int copy_buffer;
int type;
int coordinate_type;
MwBool supports_transparency;
MwLLHandler handler;
};

View file

@ -123,6 +123,7 @@ typedef struct wayland_call_table {
void (*cairo_fill)(cairo_t* cr);
void (*cairo_pattern_set_filter)(cairo_pattern_t* pattern,
cairo_filter_t filter);
void (*cairo_set_antialias)(cairo_t*, cairo_antialias_t);
} wayland_call_table_t;
@ -201,6 +202,7 @@ MwInline int wayland_load_funcs() {
CAIRO_FUNC(cairo_rectangle);
CAIRO_FUNC(cairo_new_path);
CAIRO_FUNC(cairo_set_line_cap);
CAIRO_FUNC(cairo_set_antialias);
CAIRO_FUNC(cairo_set_source_rgba);
CAIRO_FUNC(cairo_set_source_rgb);
CAIRO_FUNC(cairo_reset_clip);
@ -257,6 +259,7 @@ MwInline int wayland_load_funcs() {
#define cairo_rectangle wl_call_tbl.cairo_rectangle
#define cairo_new_path wl_call_tbl.cairo_new_path
#define cairo_set_line_cap wl_call_tbl.cairo_set_line_cap
#define cairo_set_antialias wl_call_tbl.cairo_set_antialias
#define cairo_set_source_rgba wl_call_tbl.cairo_set_source_rgba
#define cairo_set_source_rgb wl_call_tbl.cairo_set_source_rgb
#define cairo_reset_clip wl_call_tbl.cairo_reset_clip
@ -343,12 +346,16 @@ struct _MwLLWaylandShmBuffer {
struct wl_shm* shm;
struct wl_shm_pool* shm_pool;
struct wl_buffer* shm_buffer;
struct wl_shm_pool* shm_pool_back;
struct wl_buffer* shm_buffer_back;
struct wl_surface* surface;
struct wl_output* output;
MwU8* buf;
MwU8* buf_back;
MwU64 buf_size;
int fd;
int fd_back;
MwBool setup;
};

View file

@ -39,6 +39,8 @@
#define MwNsevenSegment "IsevenSegment"
#define MwNlength "Ilength"
#define MwNforceInverted "IforceInverted"
#define MwNroundness "Iroundness"
#define MwNisRounded "IisRounded"
#define MwNtitle "Stitle"
#define MwNtext "Stext"

View file

@ -42,7 +42,9 @@
<!--
All widgets have:
- MwNbackground
- MwNsubBackground
- MwNforeground
- MwNsubForeground
- MwNx
- MwNy
- MwNwidth
@ -93,11 +95,15 @@
<integer name="sevenSegment" />
<integer name="length" />
<integer name="forceInverted" />
<integer name="roundness" />
<integer name="isRounded" />
<string name="title" />
<string name="text" />
<string name="background" />
<string name="subBackground" />
<string name="foreground" />
<string name="subForeground" />
<pixmap name="pixmap" />
<pixmap name="iconPixmap" />
@ -123,6 +129,7 @@
<handler name="colorChosen" />
<handler name="draw" />
<handler name="clipboard" />
<handler name="darkTheme" />
</properties>
<enumerations>
<enumeration name="MwDIRECTION">

View file

@ -46,7 +46,7 @@ static void buffer_destroy(struct _MwLLWaylandShmBuffer* buffer);
static void region_setup(MwLL handle);
static void region_invalidate(MwLL handle);
static void update_buffer(MwLL self, struct _MwLLWaylandShmBuffer* buffer);
/* Get the registered interface from r, or NULL if it doesn't currently have it. */
#define WAYLAND_GET_INTERFACE(handle, inter) shget(handle.wl_protocol_map, inter##_interface.name)
@ -65,8 +65,11 @@ static void new_protocol(void* data, struct wl_registry* registry,
char* inter = malloc(strlen(interface) + 1);
strcpy(inter, interface);
shput(self->wayland.wl_protocol_map, inter, cb->setup(name, data));
/* we don't care for adding this protocol, we just use it to know if the compositor will let us have transparent surfaces */
} else if(strcmp(interface, "wp_alpha_modifier_v1") == 0) {
self->common.supports_transparency = MwTRUE;
} else {
/* printf("unknown interface %s\n", interface); */
// printf("unknown interface %s\n", interface);
}
WAYLAND_EVENT_OP_END(self);
@ -1075,9 +1078,9 @@ static int event_loop(MwLL handle) {
if(!poll(&fd, 1, timeout.tv_nsec)) {
wl_display_cancel_read(wayland->display);
wl_surface_commit(wayland->framebuffer.surface);
update_buffer(handle, &wayland->framebuffer);
if(wayland->type == MWLL_WAYLAND_TOPLEVEL)
wl_surface_commit(wayland->backbuffer.surface);
update_buffer(handle, &wayland->backbuffer);
return 0;
}
wl_display_read_events(wayland->display);
@ -1163,8 +1166,8 @@ static void xdg_surface_configure(
xdg_surface_ack_configure(xdg_surface, serial);
if(self->wayland.configured) {
wl_surface_commit(self->wayland.framebuffer.surface);
wl_surface_commit(self->wayland.backbuffer.surface);
update_buffer(self, &self->wayland.framebuffer);
update_buffer(self, &self->wayland.backbuffer);
}
self->wayland.configured = MwTRUE;
@ -1186,41 +1189,60 @@ static void wl_shm_interface_destroy(struct _MwLLWayland* wayland, wayland_proto
static void update_buffer(MwLL self, struct _MwLLWaylandShmBuffer* buffer) {
(void)self; // for later, just in case.
memcpy(buffer->buf, buffer->buf_back, buffer->buf_size);
wl_surface_attach(buffer->surface, buffer->shm_buffer, 0, 0);
wl_surface_commit(buffer->surface);
}
static void buffer_setup(struct _MwLLWaylandShmBuffer* buffer, MwU32 width, MwU32 height) {
int stride = width * 4;
char temp_name[] = "/tmp/milsko-wl-shm-XXXXXX";
int stride = width * 4;
char temp_name[] = "/tmp/milsko-wl-shm-XXXXXX";
char temp_name_back[] = "/tmp/milsko-wl-shm-back-XXXXXX";
buffer->buf_size = width * height * 4;
buffer->fd = mkstemp(temp_name);
buffer->fd = mkstemp(temp_name);
buffer->fd_back = mkstemp(temp_name_back);
unlink(temp_name);
unlink(temp_name_back);
if(posix_fallocate(buffer->fd, 0, buffer->buf_size) != 0) {
printf("failure setting up wl_shm: could not fallocate. %s.\n", strerror(errno));
close(buffer->fd);
return;
}
if(posix_fallocate(buffer->fd_back, 0, buffer->buf_size) != 0) {
printf("failure setting up wl_shm: could not fallocate. %s.\n", strerror(errno));
close(buffer->fd_back);
return;
}
if(ftruncate(buffer->fd, buffer->buf_size) != 0) {
printf("failure setting up wl_shm: could not truncate. %s.\n", strerror(errno));
close(buffer->fd);
return;
}
if(ftruncate(buffer->fd_back, buffer->buf_size) != 0) {
printf("failure setting up wl_shm: could not truncate. %s.\n", strerror(errno));
close(buffer->fd_back);
return;
}
buffer->buf = mmap(NULL, buffer->buf_size, PROT_WRITE, MAP_SHARED, buffer->fd, 0);
buffer->buf = mmap(NULL, buffer->buf_size, PROT_WRITE, MAP_SHARED, buffer->fd, 0);
buffer->buf_back = mmap(NULL, buffer->buf_size, PROT_WRITE, MAP_SHARED, buffer->fd_back, 0);
fsync(buffer->fd);
fsync(buffer->fd_back);
if(!(buffer->shm_pool = wl_shm_create_pool(buffer->shm, buffer->fd, buffer->buf_size))) {
printf("failure setting up wl_shm: could not create pool.\n");
}
buffer->shm_buffer = wl_shm_pool_create_buffer(buffer->shm_pool, 0, width, height, stride, WL_SHM_FORMAT_ARGB8888);
buffer->setup = MwTRUE;
if(!(buffer->shm_pool_back = wl_shm_create_pool(buffer->shm, buffer->fd_back, buffer->buf_size))) {
printf("failure setting up wl_shm: could not create pool.\n");
}
buffer->shm_buffer = wl_shm_pool_create_buffer(buffer->shm_pool, 0, width, height, stride, WL_SHM_FORMAT_ARGB8888);
buffer->shm_buffer_back = wl_shm_pool_create_buffer(buffer->shm_pool_back, 0, width, height, stride, WL_SHM_FORMAT_ARGB8888);
buffer->setup = MwTRUE;
}
static void buffer_destroy(struct _MwLLWaylandShmBuffer* buffer) {
@ -1228,18 +1250,21 @@ static void buffer_destroy(struct _MwLLWaylandShmBuffer* buffer) {
return;
}
wl_buffer_destroy(buffer->shm_buffer);
wl_buffer_destroy(buffer->shm_buffer_back);
wl_shm_pool_destroy(buffer->shm_pool);
wl_shm_pool_destroy(buffer->shm_pool_back);
close(buffer->fd);
close(buffer->fd_back);
buffer->setup = MwFALSE;
}
static void framebuffer_setup(struct _MwLLWayland* wayland) {
buffer_setup(&wayland->framebuffer, wayland->ww, wayland->wh);
wayland->front_cs = cairo_image_surface_create_for_data(wayland->framebuffer.buf, CAIRO_FORMAT_ARGB32, wayland->ww, wayland->wh, 4 * wayland->ww);
wayland->front_cs = cairo_image_surface_create_for_data(wayland->framebuffer.buf_back, CAIRO_FORMAT_ARGB32, wayland->ww, wayland->wh, 4 * wayland->ww);
wayland->front_cairo = cairo_create(wayland->front_cs);
memset(wayland->framebuffer.buf, 0, wayland->framebuffer.buf_size);
memset(wayland->framebuffer.buf_back, 0, wayland->framebuffer.buf_size);
hang_until_configured((MwLL)wayland);
update_buffer((MwLL)wayland, &wayland->framebuffer);
};
@ -1261,10 +1286,10 @@ static void backbuffer_setup(struct _MwLLWayland* wayland) {
}
buffer_setup(&wayland->backbuffer, w, h);
wayland->back_cs = cairo_image_surface_create_for_data(wayland->backbuffer.buf, CAIRO_FORMAT_ARGB32, w, h, 4 * w);
wayland->back_cs = cairo_image_surface_create_for_data(wayland->backbuffer.buf_back, CAIRO_FORMAT_ARGB32, w, h, 4 * w);
wayland->back_cairo = cairo_create(wayland->back_cs);
memset(wayland->backbuffer.buf, 255, wayland->backbuffer.buf_size);
memset(wayland->backbuffer.buf_back, 255, wayland->backbuffer.buf_size);
hang_until_configured((MwLL)wayland);
update_buffer((MwLL)wayland, &wayland->backbuffer);
};
@ -1713,6 +1738,11 @@ static void widget_setup(MwLL r, MwLL parent, int x, int y, int width, int heigh
if(parent != NULL) {
MwLLForceRender(parent);
}
if(!r->wayland.has_decorations) {
MwLLBeginDraw(r);
MwLLEndDraw(r);
}
}
static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) {
MwLL r;
@ -1933,8 +1963,6 @@ static void MwLLBeginDrawImpl(MwLL handle) {
free(px);
}
update_buffer(handle, &handle->wayland.backbuffer);
wl_surface_commit(handle->wayland.backbuffer.surface);
}
handle->wayland.selected_cairo = handle->wayland.front_cairo;
}
@ -1953,7 +1981,7 @@ static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLL
clip(handle);
cairo_set_source_rgb(handle->wayland.front_cairo, color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0);
cairo_set_source_rgba(handle->wayland.front_cairo, color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0, 1.0);
cairo_new_path(handle->wayland.front_cairo);
for(i = 0; i < points_count; i++) {
if(i == 0) {
@ -1972,8 +2000,11 @@ static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count, MwLL
static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) {
int i;
clip(handle);
cairo_set_antialias(handle->wayland.front_cairo, CAIRO_ANTIALIAS_NONE);
cairo_set_line_cap(handle->wayland.front_cairo, CAIRO_LINE_CAP_SQUARE);
cairo_set_source_rgb(handle->wayland.front_cairo, color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0);
cairo_set_source_rgba(handle->wayland.front_cairo, color->common.red / 255.0, color->common.green / 255.0, color->common.blue / 255.0, 1.0);
cairo_new_path(handle->wayland.front_cairo);
for(i = 0; i < 2; i++) {
if(i == 0) {
@ -2083,6 +2114,8 @@ static void MwLLSetTitleImpl(MwLL handle, const char* title) {
}
if(!handle->wayland.has_decorations) {
strncpy(handle->wayland.title, title, 255);
MwLLBeginDraw(handle);
MwLLEndDraw(handle);
}
}
@ -2152,7 +2185,6 @@ static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) {
cairo_surface_destroy(cs);
MwLLForceRender(handle);
update_buffer(handle, &handle->wayland.framebuffer);
wl_surface_damage(handle->wayland.framebuffer.surface, 0, 0, handle->wayland.ww, handle->wayland.wh);
}
static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) {
@ -2178,15 +2210,15 @@ static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) {
buffer_setup(handle->wayland.icon, pixmap->common.width, pixmap->common.height);
for(; i < size; i += 2) {
handle->wayland.icon->buf[i] = pixmap->common.raw[i + 2];
handle->wayland.icon->buf[i + 1] = pixmap->common.raw[i + 1];
handle->wayland.icon->buf[i + 2] = pixmap->common.raw[i + 0];
handle->wayland.icon->buf[i + 3] = 255;
handle->wayland.icon->buf_back[i] = pixmap->common.raw[i + 2];
handle->wayland.icon->buf_back[i + 1] = pixmap->common.raw[i + 1];
handle->wayland.icon->buf_back[i + 2] = pixmap->common.raw[i + 0];
handle->wayland.icon->buf_back[i + 3] = 255;
}
if(handle->wayland.configured) update_buffer(handle, handle->wayland.icon);
xdg_toplevel_icon_v1_add_buffer(icon, handle->wayland.icon->shm_buffer, 1);
xdg_toplevel_icon_v1_add_buffer(icon, handle->wayland.icon->shm_buffer_back, 1);
xdg_toplevel_icon_manager_v1_set_icon(icon_manager, handle->wayland.toplevel->xdg_top_level, icon);
}
@ -2210,7 +2242,7 @@ static void MwLLSetCursorImpl(MwLL handle, MwCursor* image, MwCursor* mask) {
wl_surface_destroy(handle->wayland.cursor.surface);
}
buffer_setup(&handle->wayland.cursor, image->width, image->height);
memset(handle->wayland.cursor.buf, 0, handle->wayland.cursor.buf_size);
memset(handle->wayland.cursor.buf_back, 0, handle->wayland.cursor.buf_size);
xs = -mask->x + image->x;
ys = mask->height + mask->y;
@ -2222,7 +2254,7 @@ static void MwLLSetCursorImpl(MwLL handle, MwCursor* image, MwCursor* mask) {
int idx = ((y * image->width) + x) * 4;
if(d & 1) {
handle->wayland.cursor.buf[idx + 3] = 255;
handle->wayland.cursor.buf_back[idx + 3] = 255;
};
d = d >> 1;
}
@ -2237,16 +2269,16 @@ static void MwLLSetCursorImpl(MwLL handle, MwCursor* image, MwCursor* mask) {
px = 255;
};
handle->wayland.cursor.buf[idx] = px;
handle->wayland.cursor.buf[idx + 1] = px;
handle->wayland.cursor.buf[idx + 2] = px;
d = d >> 1;
handle->wayland.cursor.buf_back[idx] = px;
handle->wayland.cursor.buf_back[idx + 1] = px;
handle->wayland.cursor.buf_back[idx + 2] = px;
d = d >> 1;
}
}
handle->wayland.cursor.surface = wl_compositor_create_surface(handle->wayland.compositor);
wl_surface_attach(handle->wayland.cursor.surface, handle->wayland.cursor.shm_buffer, xs + image->x, ys + image->height + image->y);
wl_surface_attach(handle->wayland.cursor.surface, handle->wayland.cursor.shm_buffer_back, xs + image->x, ys + image->height + image->y);
wl_surface_commit(handle->wayland.cursor.surface);
/* If there's currently a pointer, set it up. (Otherwise, it'll be setup during the pointer enter event) */

View file

@ -516,6 +516,7 @@ int MwGetInteger(MwWidget handle, const char* key) {
#else
if(strcmp(key, MwNmodernLook) == 0) return inherit_integer(handle, key, 1);
#endif
if(strcmp(key, MwNisRounded) == 0) return inherit_integer(handle, key, 1);
}
return shget(handle->integer, key);
}

View file

@ -11,9 +11,13 @@
#include "../external/stb_ds.h"
#define DEFAULT_ROUNDNESS 5
#define MAX_ROUNDNESS 30
#define BORDER_SMOOTHNESS 50
static int get_color_diff(MwWidget handle) {
if(MwGetInteger(handle, MwNmodernLook)) {
return 46;
return 23;
} else {
return 80;
}
@ -29,7 +33,7 @@ static int hex(const char* txt, int len) {
n = c - 'a' + 10;
} else if('A' <= c && c <= 'F') {
n = c - 'A' + 10;
} else if('0' <= c && c <= '9') {
} else if('0' <= c && c <= 'g') {
n = c - '0';
}
r = r << 4;
@ -102,14 +106,20 @@ void MwDrawRect(MwWidget handle, MwRect* rect, MwLLColor color) {
MwLLPolygon(handle->lowlevel, p, 4, color);
}
void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color) {
void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color, int rounded) {
MwLLPixmap pixmap;
int y;
int y, i;
double darken = 0.;
int ColorDiff = get_color_diff(handle);
double darkenStep = (ColorDiff / 4.) / rect->height;
double darkenStep = (ColorDiff / 2.) / rect->height;
unsigned long sz = 1 * rect->height * 4;
unsigned char* data = malloc(sz);
MwRect r = *rect;
int roundness = MwGetInteger(handle, MwNroundness);
double div;
if(roundness == MwDEFAULT) roundness = DEFAULT_ROUNDNESS;
if(roundness >= MAX_ROUNDNESS) roundness = MAX_ROUNDNESS;
div = (roundness <= 10) ? 7. : 10.;
memset(data, 0, sz);
for(y = 0; y < rect->height; y++) {
@ -124,18 +134,61 @@ void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color) {
}
pixmap = MwLLCreatePixmap(handle->lowlevel, data, 1, rect->height);
MwLLDrawPixmap(handle->lowlevel, rect, pixmap);
if(rounded && rect->height >= (roundness * 2) && rect->width >= (roundness * 2) && roundness > 0) {
int x = rect->x + (roundness + 1);
int y = rect->y + (roundness + 1);
for(i = 0; i < roundness; i++) {
double point = ((i + (M_PI * 4)) / div);
double point2 = (((i + 1) + (M_PI * 4)) / div);
int x2 = x - (sin(point2) * roundness);
r.x = x - (sin(point) * roundness);
r.y = y + (cos(point) * roundness);
r.width = (x - (sin(point + 1) * roundness)) - r.x;
r.height = (rect->height - ((r.y - rect->y) * 2) - 1);
MwLLDrawPixmap(handle->lowlevel, &r, pixmap);
r.y = y + (cos(point2) * roundness);
for(r.x = x; r.x < x2; r.x++) {
r.height = (rect->height - ((r.y - rect->y)) - 1);
MwLLDrawPixmap(handle->lowlevel, &r, pixmap);
}
}
r = *rect;
r.x += roundness - 1;
r.width -= (roundness * 2) + 1;
r.height -= 2;
MwLLDrawPixmap(handle->lowlevel, &r, pixmap);
r = *rect;
x = (rect->x + rect->width) - (roundness + 3);
y = rect->y + (roundness + 1);
for(i = 0; i < roundness; i++) {
double point = ((i + (M_PI * 4)) / div);
double point2 = (((i + 1) + (M_PI * 4)) / div);
int x2 = x + (sin(point2) * roundness);
r.x = x + (sin(point) * roundness);
r.y = y + (cos(point) * roundness);
r.width = 1;
r.height = (rect->height - ((r.y - rect->y) * 2) - 1);
MwLLDrawPixmap(handle->lowlevel, &r, pixmap);
r.y = y + (cos(point2) * roundness);
for(r.x = x; r.x < x2; r.x++) {
r.height = (rect->height - ((r.y - rect->y) * 2) - 1);
MwLLDrawPixmap(handle->lowlevel, &r, pixmap);
}
}
} else {
MwLLDrawPixmap(handle->lowlevel, &r, pixmap);
}
MwLLDestroyPixmap(pixmap);
free(data);
}
void MwDrawFrame(MwWidget handle, MwRect* rect, MwLLColor color, int invert) {
void MwDrawFrame(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int rounded) {
int inv;
if((inv = MwGetInteger(handle, MwNforceInverted)) != MwDEFAULT && inv) invert = 1;
if(MwGetInteger(handle, MwNmodernLook)) {
MwDrawFrameEx(handle, rect, color, invert, MwDefaultBorderWidth(handle), 0, 0);
MwDrawFrameEx(handle, rect, color, invert, MwDefaultBorderWidth(handle), 0, 0, rounded);
} else {
int diff = get_color_diff(handle) / 3 * 2;
@ -143,24 +196,34 @@ void MwDrawFrame(MwWidget handle, MwRect* rect, MwLLColor color, int invert) {
int i;
int st = invert ? 1 : 0;
for(i = st; i < st + 2; i++) {
if((i % 2) == 0) MwDrawFrameEx(handle, rect, color, invert, MwDefaultBorderWidth(handle) - 1, -diff, (handle->parent == NULL || handle->parent->lowlevel == NULL) ? 1 : 0);
if((i % 2) == 1) MwDrawFrameEx(handle, rect, color, invert, 1, diff, 0);
if((i % 2) == 0) MwDrawFrameEx(handle, rect, color, invert, MwDefaultBorderWidth(handle) - 1, -diff, (handle->parent == NULL || handle->parent->lowlevel == NULL) ? 1 : 0, 0);
if((i % 2) == 1) MwDrawFrameEx(handle, rect, color, invert, 1, diff, 0, 0);
}
} else {
MwDrawFrameEx(handle, rect, color, invert, 1, 0, 0);
MwDrawFrameEx(handle, rect, color, invert, 1, 0, 0, 0);
}
}
}
void MwDrawWidgetBack(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int border) {
MwLLColor col;
MwBool rounded = MwGetInteger(handle, MwNroundness) != MwDEFAULT && MwGetInteger(handle, MwNisRounded) != 0;
if(border) {
MwDrawFrame(handle, rect, color, invert);
if(!handle->lowlevel->common.supports_transparency) {
MwLLColor c = handle->parent == NULL ? NULL : MwParseColor(handle->parent, MwGetText(handle->parent, MwNbackground));
if(c != NULL) {
MwDrawRect(handle, rect, c);
MwLLFreeColor(c);
}
}
MwDrawFrame(handle, rect, color, invert, rounded);
}
col = invert ? MwLightenColor(handle, color, -8, -8, -8) : color;
if(MwGetInteger(handle, MwNmodernLook)) {
MwDrawRectFading(handle, rect, col);
MwDrawRectFading(handle, rect, col, rounded);
} else {
MwDrawRect(handle, rect, col);
}
@ -170,7 +233,7 @@ void MwDrawWidgetBack(MwWidget handle, MwRect* rect, MwLLColor color, int invert
void MwDrawDiamond(MwWidget handle, MwRect* rect, MwLLColor color, int invert) {
MwPoint p[6];
int border = MwDefaultBorderWidth(handle);
int ColorDiff = get_color_diff(handle);
int ColorDiff = get_color_diff(handle) + (MwGetInteger(handle, MwNmodernLook) ? 48 : 0);
MwLLColor darker = MwLightenColor(handle, color, -ColorDiff, -ColorDiff, -ColorDiff);
MwLLColor lighter = MwLightenColor(handle, color, ColorDiff, ColorDiff, ColorDiff);
MwLLColor col = invert ? MwLightenColor(handle, color, -8, -8, -8) : color;
@ -234,54 +297,161 @@ void MwDrawDiamond(MwWidget handle, MwRect* rect, MwLLColor color, int invert) {
MwLLFreeColor(darker);
}
void MwDrawFrameEx(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int border, int diff, int same) {
MwPoint p[6];
void MwDrawFrameEx(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int border, int diff, int same, int rounded) {
MwPoint p[7];
int ColorDiff = get_color_diff(handle);
MwLLColor darker = MwLightenColor(handle, color, -ColorDiff * 3 / 2 + diff, -ColorDiff * 3 / 2 + diff, -ColorDiff * 3 / 2 + diff);
MwLLColor lighter = same ? MwLightenColor(handle, darker, 0, 0, 0) : MwLightenColor(handle, color, ColorDiff - diff, ColorDiff - diff, ColorDiff - diff);
int i;
MwLLColor middle = MwLLAllocColor(handle->lowlevel,
(lighter->common.red * darker->common.red) / 255,
(lighter->common.green * darker->common.green) / 255,
(lighter->common.blue * darker->common.blue) / 255);
int roundness = MwGetInteger(handle, MwNroundness);
p[0].x = rect->x;
p[0].y = rect->y;
if(roundness == MwDEFAULT) roundness = DEFAULT_ROUNDNESS;
if(roundness >= MAX_ROUNDNESS) roundness = MAX_ROUNDNESS;
if(rounded && rect->height >= (roundness * 2) && rect->width >= (roundness * 2) && roundness > 0) {
/* top left edge */
for(i = 0; i < BORDER_SMOOTHNESS; i += 2) {
MwPoint line[2];
double point = ((i + (M_PI * (BORDER_SMOOTHNESS / 2.))) / (BORDER_SMOOTHNESS));
int x = rect->x + (roundness + 2);
int y = rect->y + (roundness + 2);
p[1].x = rect->x + rect->width;
p[1].y = rect->y;
line[0].x = x - (sin(point) * roundness);
line[0].y = y + (cos(point) * roundness);
line[1].x = x - (sin(point + 1) * roundness);
line[1].y = y + (cos(point + 1) * roundness);
MwLLLine(handle->lowlevel, line, invert ? darker : lighter);
}
p[2].x = rect->x + rect->width - border;
p[2].y = rect->y + border;
p[0].x = rect->x + roundness;
p[0].y = rect->y;
p[3].x = rect->x + border;
p[3].y = rect->y + border;
p[1].x = rect->x + rect->width - border - roundness - 2;
p[1].y = rect->y;
p[4].x = rect->x + border;
p[4].y = rect->y + rect->height - border;
p[2].x = rect->x + rect->width - border - roundness - 2;
p[2].y = rect->y + border;
p[5].x = rect->x;
p[5].y = rect->y + rect->height;
p[3].x = rect->x + border - roundness;
p[3].y = rect->y + border + roundness;
p[4].x = rect->x + border - roundness;
p[4].y = rect->y + rect->height - border - roundness;
p[5].x = rect->x + roundness;
p[5].y = rect->y + rect->height - roundness;
MwLLPolygon(handle->lowlevel, p, 6, invert ? darker : lighter);
/* top right edge */
for(i = 0; i < BORDER_SMOOTHNESS; i += 2) {
MwPoint line[2];
double point = ((i + (M_PI * (BORDER_SMOOTHNESS / 2.))) / (BORDER_SMOOTHNESS));
int x = (rect->x + rect->width) - (roundness + 2);
int y = rect->y + (roundness + 2);
double placeholder = (sin(point) * roundness);
line[0].x = x + placeholder;
line[0].y = y + (cos(point) * roundness);
line[1].x = x + (sin(point + 1) * roundness);
line[1].y = y + (cos(point + 1) * roundness);
MwLLLine(handle->lowlevel, line, middle);
}
} else {
p[0].x = rect->x;
p[0].y = rect->y;
p[1].x = rect->x + rect->width;
p[1].y = rect->y;
p[2].x = rect->x + rect->width - border;
p[2].y = rect->y + border;
p[3].x = rect->x + border;
p[3].y = rect->y + border;
p[4].x = rect->x + border;
p[4].y = rect->y + rect->height - border;
p[5].x = rect->x;
p[5].y = rect->y + rect->height;
}
MwLLPolygon(handle->lowlevel, p, 6, invert ? darker : lighter);
p[0].x = rect->x + rect->width;
p[0].y = rect->y;
if(rounded && rect->height >= (roundness * 2) && rect->width >= (roundness * 2) && roundness > 0) {
/* bottom left edge */
for(i = 0; i < BORDER_SMOOTHNESS; i += 2) {
MwPoint line[2];
double point = ((i + (M_PI * (BORDER_SMOOTHNESS / 2.))) / (BORDER_SMOOTHNESS));
int x = rect->x + (roundness + 2);
int y = (rect->y + rect->height) - (roundness + 2);
p[1].x = rect->x + rect->width - border;
p[1].y = rect->y + border;
line[0].x = x - (sin(point) * roundness);
line[0].y = y - (cos(point) * roundness);
line[1].x = x - (sin(point + 1) * roundness);
line[1].y = y - (cos(point + 1) * roundness);
MwLLLine(handle->lowlevel, line, middle);
}
p[0].x = rect->x + roundness;
p[0].y = rect->y + 1;
p[2].x = rect->x + rect->width - border;
p[2].y = rect->y + rect->height - border;
p[1].x = rect->x + rect->width - border;
p[1].y = rect->y + border + roundness;
p[3].x = rect->x + border;
p[3].y = rect->y + rect->height - border;
p[2].x = rect->x + rect->width - border;
p[2].y = rect->y + rect->height - border - roundness;
p[4].x = rect->x;
p[4].y = rect->y + rect->height;
p[3].x = rect->x + rect->width - border - roundness;
p[3].y = rect->y + rect->height - border;
p[5].x = rect->x + rect->width;
p[5].y = rect->y + rect->height;
p[4].x = rect->x + border + roundness;
p[4].y = rect->y + rect->height - border;
MwLLPolygon(handle->lowlevel, p, 6, invert ? lighter : darker);
p[5].x = rect->x + roundness;
p[5].y = rect->y + rect->height - roundness;
p[6].x = rect->x + rect->width - border - roundness;
p[6].y = rect->y + rect->height - roundness;
MwLLPolygon(handle->lowlevel, p, 7, invert ? lighter : darker);
/* bottom right edge */
for(i = 0; i < BORDER_SMOOTHNESS; i += 2) {
MwPoint line[2];
double point = ((i + (M_PI * (BORDER_SMOOTHNESS / 2.))) / (BORDER_SMOOTHNESS));
int x = (rect->x + rect->width) - (roundness + 2);
int y = (rect->y + rect->height) - (roundness + 2);
line[0].x = x + (sin(point) * roundness);
line[0].y = y - (cos(point) * roundness);
line[1].x = x + (sin(point + 1) * roundness);
line[1].y = y - (cos(point + 1) * roundness);
MwLLLine(handle->lowlevel, line, middle);
}
} else {
p[0].x = rect->x + rect->width;
p[0].y = rect->y;
p[1].x = rect->x + rect->width - border;
p[1].y = rect->y + border;
p[2].x = rect->x + rect->width - border;
p[2].y = rect->y + rect->height - border;
p[3].x = rect->x + border;
p[3].y = rect->y + rect->height - border;
p[4].x = rect->x;
p[4].y = rect->y + rect->height;
p[5].x = rect->x + rect->width;
p[5].y = rect->y + rect->height;
MwLLPolygon(handle->lowlevel, p, 6, invert ? lighter : darker);
}
MwLLFreeColor(lighter);
MwLLFreeColor(darker);
MwLLFreeColor(middle);
rect->x += border;
rect->y += border;

View file

@ -24,7 +24,7 @@ static void draw(MwWidget handle) {
r.height = MwGetInteger(handle, MwNheight);
if(MwGetInteger(handle, MwNhasBorder)) {
MwDrawFrame(handle, &r, base, MwGetInteger(handle, MwNinverted));
MwDrawFrame(handle, &r, base, MwGetInteger(handle, MwNinverted), 0);
}
MwDrawRect(handle, &r, base);

View file

@ -8,6 +8,7 @@ static int create(MwWidget handle) {
MwSetInteger(handle, MwNflat, 0);
MwSetInteger(handle, MwNpadding, 0);
MwSetInteger(handle, MwNfillArea, 1);
MwSetInteger(handle, MwNroundness, 5);
return 0;
}

View file

@ -72,7 +72,7 @@ static void draw(MwWidget handle) {
r.y += r.height;
r.height = MwDefaultBorderWidth(handle) * 2;
MwDrawFrame(handle, &r, base, 0);
MwDrawFrame(handle, &r, base, 0, 0);
MwLLFreeColor(text);
MwLLFreeColor(base);

View file

@ -11,6 +11,7 @@ static int create(MwWidget handle) {
MwSetDefault(handle);
MwLLSetCursor(handle->lowlevel, &MwCursorText, &MwCursorTextMask);
MwSetInteger(handle, MwNroundness, 5);
return 0;
}

View file

@ -22,7 +22,7 @@ static void draw(MwWidget handle) {
fr.y = 0;
fr.width = MwGetInteger(handle, MwNwidth);
fr.height = MwGetInteger(handle, MwNheight);
MwDrawFrame(handle, &fr, base, inverted);
MwDrawFrame(handle, &fr, base, inverted, 0);
rr.x = MwDefaultBorderWidth(handle);
rr.y = MwDefaultBorderWidth(handle);

View file

@ -20,7 +20,7 @@ static void draw(MwWidget handle) {
r.width = MwGetInteger(handle, MwNwidth);
r.height = MwGetInteger(handle, MwNheight);
if(MwGetInteger(handle, MwNhasBorder)) MwDrawFrame(handle, &r, base, MwGetInteger(handle, MwNinverted));
if(MwGetInteger(handle, MwNhasBorder)) MwDrawFrame(handle, &r, base, MwGetInteger(handle, MwNinverted), 0);
MwDrawRect(handle, &r, base);
if(px != NULL) {

View file

@ -208,7 +208,7 @@ static void frame_draw(MwWidget handle) {
p.x = MwDefaultBorderWidth(handle);
p.y = MwDefaultBorderWidth(handle);
MwDrawFrame(handle, &r, base, 1);
MwDrawFrame(handle, &r, base, 1, 0);
MwDrawRect(handle, &r, base2);
r = r2;
@ -282,7 +282,7 @@ static void frame_draw(MwWidget handle) {
handle->bgcolor = NULL;
}
MwDrawFrame(handle, &r, base, 1);
MwDrawFrame(handle, &r, base, 1, 0);
MwLLFreeColor(text2);
MwLLFreeColor(text);
@ -401,7 +401,7 @@ static void draw(MwWidget handle) {
r.y = 0;
r.width = get_col_width(lb, i);
r.height = MwDefaultBorderWidth(handle) * 2 + MwTextHeight(handle, "M");
MwDrawFrame(handle, &r, base, 0);
MwDrawFrame(handle, &r, base, 0, 0);
x += MwDefaultBorderWidth(handle);

View file

@ -100,7 +100,7 @@ static void draw(MwWidget handle) {
BEGIN_MENU_LOOP;
if(m->sub[i]->wsub != NULL || (in_area && handle->pressed)) {
MwDrawFrame(handle, &r, base, MwFALSE);
MwDrawFrame(handle, &r, base, MwFALSE, 0);
MwDrawWidgetBack(handle, &r, base, 0, MwFALSE);
}

View file

@ -23,7 +23,7 @@ static void draw(MwWidget handle) {
r.width = MwGetInteger(handle, MwNwidth);
r.height = MwGetInteger(handle, MwNheight);
MwDrawFrame(handle, &r, base, 1);
MwDrawFrame(handle, &r, base, 1, 0);
MwDrawRect(handle, &r, base);
w = MwGetInteger(handle, MwNvalue) - MwGetInteger(handle, MwNminValue);
w = w / (MwGetInteger(handle, MwNmaxValue) - MwGetInteger(handle, MwNminValue));

View file

@ -25,7 +25,7 @@ static void draw(MwWidget handle) {
r.y = (r.height - 2) / 2;
r.height = 2;
}
MwDrawFrameEx(handle, &r, base, 1, 1, 0, 0);
MwDrawFrameEx(handle, &r, base, 1, 1, 0, 0, MwGetInteger(handle, MwNmodernLook));
MwLLFreeColor(base);
}

View file

@ -59,7 +59,7 @@ static void draw(MwWidget handle) {
rc.x += MwGetInteger(handle, MwNleftPadding);
MwDrawFrameEx(handle, &rc, base, 1, 1, 0, 0);
MwDrawFrameEx(handle, &rc, base, 1, 1, 0, 0, 0);
p.y += 2 + 1;
} else {

View file

@ -64,7 +64,7 @@ static void recursion(MwWidget handle, MwTreeViewEntry* tree, MwTreeViewEntry**
const int len = 4;
MwDrawRect(handle, &r, col);
MwDrawFrame(handle, &r, base, tree->opened);
MwDrawFrame(handle, &r, base, tree->opened, 0);
if(tree->opened) {
l[0].x = r.x + (r.width - len) / 2;
l[0].y = r.y + r.height / 2;
@ -91,7 +91,7 @@ static void recursion(MwWidget handle, MwTreeViewEntry* tree, MwTreeViewEntry**
MwLLLine(handle->lowlevel, &l[0], text);
}
r = r2;
MwDrawFrame(handle, &r, base, tree->opened);
MwDrawFrame(handle, &r, base, tree->opened, 0);
if(col != base) MwLLFreeColor(col);
} else {
@ -183,7 +183,7 @@ static void frame_draw(MwWidget handle) {
p.x = MwDefaultBorderWidth(handle);
p.y = MwDefaultBorderWidth(handle);
MwDrawFrame(handle, &r, base, 1);
MwDrawFrame(handle, &r, base, 1, 0);
MwDrawRect(handle, &r, base2);
r = r2;
@ -193,7 +193,7 @@ static void frame_draw(MwWidget handle) {
recursion(handle, tv->tree[i], tv->tree, base, text, base2, text2, &p, 0, LineSpace, &skip, &shared, 1, NULL);
}
MwDrawFrame(handle, &r, base, 1);
MwDrawFrame(handle, &r, base, 1, 0);
MwLLFreeColor(text2);
MwLLFreeColor(text);

View file

@ -18,7 +18,7 @@ static void draw(MwWidget handle) {
r.width = MwGetInteger(handle, MwNwidth);
r.height = MwGetInteger(handle, MwNheight);
if(MwGetInteger(handle, MwNhasBorder)) MwDrawFrame(handle, &r, c, MwGetInteger(handle, MwNinverted));
if(MwGetInteger(handle, MwNhasBorder)) MwDrawFrame(handle, &r, c, MwGetInteger(handle, MwNinverted), 0);
MwDrawRect(handle, &r, c);