Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Render drop shadow for active window #58

Merged
merged 1 commit into from
Feb 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions apps/multi.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
* All rights reserved.
*/

#include <stddef.h>
#include "apps_multi.h"

#define D(x) twin_double_to_fixed(x)
#define ASSET_PATH "assets/"

static void apps_line_start(twin_screen_t *screen, int x, int y, int w, int h)
{
Expand Down Expand Up @@ -272,6 +274,55 @@ static void apps_flower_start(twin_screen_t *screen, int x, int y, int w, int h)
twin_window_show(window);
}

static void apps_blur(twin_screen_t *screen, int x, int y, int w, int h)
jserv marked this conversation as resolved.
Show resolved Hide resolved
{
twin_pixmap_t *raw_background = NULL;
#if defined(CONFIG_LOADER_PNG)
raw_background = twin_pixmap_from_file(ASSET_PATH "tux.png", TWIN_ARGB32);
#endif
if (!raw_background)
return;
twin_window_t *window = twin_window_create(
screen, TWIN_ARGB32, TwinWindowApplication, x, y, w, h);
twin_window_set_name(window, "Blur");
twin_pixmap_t *scaled_background = twin_pixmap_create(
TWIN_ARGB32, window->pixmap->width, window->pixmap->height);
twin_fixed_t sx, sy;
sx = twin_fixed_div(
twin_int_to_fixed(raw_background->width),
twin_int_to_fixed(window->client.right - window->client.left));
sy = twin_fixed_div(
twin_int_to_fixed(raw_background->height),
twin_int_to_fixed(window->client.bottom - window->client.top));

twin_matrix_scale(&raw_background->transform, sx, sy);
twin_operand_t srcop = {
.source_kind = TWIN_PIXMAP,
.u.pixmap = raw_background,
};

twin_composite(scaled_background, 0, 0, &srcop, 0, 0, 0, 0, 0, TWIN_SOURCE,
scaled_background->width, scaled_background->height);

twin_pointer_t src, dst;
for (int y = window->client.top; y < window->client.bottom; y++)
for (int x = window->client.left; x < window->client.right; x++) {
src =
twin_pixmap_pointer(scaled_background, x - window->client.left,
y - window->client.top);
dst = twin_pixmap_pointer(window->pixmap, x, y);
*dst.argb32 = *src.argb32 | 0xff000000;
jserv marked this conversation as resolved.
Show resolved Hide resolved
}
twin_stack_blur(window->pixmap, 5, window->client.left,
window->client.right, window->client.top,
window->client.bottom);
jserv marked this conversation as resolved.
Show resolved Hide resolved
jserv marked this conversation as resolved.
Show resolved Hide resolved

twin_pixmap_destroy(scaled_background);
twin_pixmap_destroy(raw_background);
jserv marked this conversation as resolved.
Show resolved Hide resolved
twin_window_show(window);
return;
}

void apps_multi_start(twin_screen_t *screen,
const char *name,
int x,
Expand All @@ -286,4 +337,5 @@ void apps_multi_start(twin_screen_t *screen,
apps_ascii_start(screen, x += 20, y += 20, w, h);
apps_jelly_start(screen, x += 20, y += 20, w / 2, h);
apps_flower_start(screen, x += 20, y += 20, w, h);
apps_blur(screen, x += 20, y += 20, w / 2, h / 2);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it is worthy to have an application for stack blur. Any idea to keep it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The apps_blur() function currently only resizes tux.png. This function isn't worthwhile to show by creating a standalone window feature. If it is still not worthy to have an application by adding another function, "blur," the apps_blur() function could be removed entirely.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The drop shadow feature's availability depends on configuration settings, so it should not expose any public functions.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The drop shadow functionality relies on the blur effect, but the blur effect is designed to be used independently as well. This is why in draw.c, the function twin_shadow_border() is conditionally built, while the function twin_stack_blur() is not.

jserv marked this conversation as resolved.
Show resolved Hide resolved
}
22 changes: 22 additions & 0 deletions configs/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,28 @@ config CURSOR
default n
depends on !BACKEND_VNC

config DROP_SHADOW
bool "Render drop shadow for active window"
default y

config HORIZONTAL_OFFSET
int "Horizontal offset"
default 1
range 1 10
depends on DROP_SHADOW

config VERTICAL_OFFSET
int "Vertical offset"
default 1
range 1 10
depends on DROP_SHADOW
jserv marked this conversation as resolved.
Show resolved Hide resolved

config SHADOW_BLUR
int "Shadow blur radius"
default 10
range 1 10
depends on DROP_SHADOW
jserv marked this conversation as resolved.
Show resolved Hide resolved

endmenu

menu "Image Loaders"
Expand Down
34 changes: 34 additions & 0 deletions include/twin.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,15 @@ typedef struct _twin_pixmap {
* Pixels
*/
twin_animation_t *animation;

#if defined(CONFIG_DROP_SHADOW)
/*
* When the pixel map is within the active window, it will have a drop
* shadow to enhance its visual distinction.
*/
bool shadow;
jserv marked this conversation as resolved.
Show resolved Hide resolved
jserv marked this conversation as resolved.
Show resolved Hide resolved
#endif

twin_pointer_t p;
/*
* When representing a window, this point
Expand Down Expand Up @@ -423,6 +432,13 @@ typedef void (*twin_destroy_func_t)(twin_window_t *window);
struct _twin_window {
twin_screen_t *screen;
twin_pixmap_t *pixmap;

#if defined(CONFIG_DROP_SHADOW)
/* Set the shadow range for horizontal and vertical directions. */
twin_coord_t shadow_x;
twin_coord_t shadow_y;
#endif

twin_window_style_t style;
twin_rect_t client;
twin_rect_t damage;
Expand Down Expand Up @@ -652,8 +668,26 @@ void twin_fill(twin_pixmap_t *dst,
* draw-common.c
*/

/* Blur the specified area in the pixel map. */
void twin_stack_blur(twin_pixmap_t *px,
int radius,
twin_coord_t left,
twin_coord_t right,
twin_coord_t top,
twin_coord_t bottom);

void twin_premultiply_alpha(twin_pixmap_t *px);

/*
* Overwrite the original pixel values for a specified number of pixels in
* width.
*/
void twin_cover(twin_pixmap_t *dst,
jserv marked this conversation as resolved.
Show resolved Hide resolved
twin_argb32_t color,
twin_coord_t x,
twin_coord_t y,
twin_coord_t width);

/*
* event.c
*/
Expand Down
55 changes: 54 additions & 1 deletion include/twin_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -181,13 +181,51 @@ typedef int64_t twin_xfixed_t;
(((t) = twin_get_8(d, i) + twin_get_8(s, i)), (twin_argb32_t) twin_sat(t) \
<< (i))

#define _twin_add_ARGB(s, d, i, t) (((t) = (s) + twin_get_8(d, i)))
#define _twin_add(s, d, t) (((t) = (s) + (d)))
#define _twin_div(d, den, i, t) \
(((t) = (d) / (den)), (t) = twin_get_8((t), 0), \
(twin_argb32_t) twin_sat(t) << (i))
#define _twin_sub_ARGB(s, d, i, t) (((t) = (s) - twin_get_8(d, i)))
#define _twin_sub(s, d, t) (((t) = (s) - (d)))
#define twin_put_8(d, i, t) (((t) = (d) << (i)))
jserv marked this conversation as resolved.
Show resolved Hide resolved

#define twin_argb32_to_rgb16(s) \
((((s) >> 3) & 0x001f) | (((s) >> 5) & 0x07e0) | (((s) >> 8) & 0xf800))
#define twin_rgb16_to_argb32(s) \
(((((s) << 3) & 0xf8) | (((s) >> 2) & 0x7)) | \
((((s) << 5) & 0xfc00) | (((s) >> 1) & 0x300)) | \
((((s) << 8) & 0xf80000) | (((s) << 3) & 0x70000)) | 0xff000000)

#ifndef min
#if defined(__GNUC__) || defined(__clang__)
#define min(x, y) \
({ \
typeof(x) _x = (x); \
typeof(y) _y = (y); \
(void) (&_x == &_y); \
_x < _y ? _x : _y; \
})
#else
/* Generic implementation: potential side effects */
#define min(x, y) ((x) < (y) ? (x) : (y))
#endif
#endif
#ifndef max
#if defined(__GNUC__) || defined(__clang__)
#define max(x, y) \
({ \
typeof(x) _x = (x); \
typeof(y) _y = (y); \
(void) (&_x == &_y); \
jserv marked this conversation as resolved.
Show resolved Hide resolved
_x > _y ? _x : _y; \
})
#else
/* Generic implementation: potential side effects */
#define max(x, y) ((x) > (y) ? (x) : (y))
#endif
#endif

typedef union {
twin_pointer_t p;
twin_argb32_t c;
Expand Down Expand Up @@ -468,7 +506,7 @@ void _twin_path_sfinish(twin_path_t *path);
#define twin_glyph_snap_y(g) (twin_glyph_snap_x(g) + twin_glyph_n_snap_x(g))

/*
* dispatch stuff
* Dispatch stuff
*/
typedef struct _twin_queue {
struct _twin_queue *next;
Expand Down Expand Up @@ -593,6 +631,21 @@ void _twin_button_init(twin_button_t *button,
twin_style_t font_style,
twin_dispatch_proc_t dispatch);

/*
* Visual effect stuff
*/

#if defined(CONFIG_DROP_SHADOW)
/*
* Add a shadow with the specified color, horizontal offset, and vertical
* offset.
*/
void twin_shadow_border(twin_pixmap_t *shadow,
twin_argb32_t color,
twin_coord_t shift_x,
twin_coord_t shift_y);
#endif

/* utility */

#ifdef _MSC_VER
Expand Down
Loading