Skip to content

Commit ed659ba

Browse files
committed
Render drop shadow for active window
Implement the twin_window_drop_shadow() function to handle the pixels within the drop shadow area of the active window's pixel map. The drop shadow effect of the window is only visible when the window is on the top layer, ensuring the active window stands out visually. Add the twin_stack_blur() function to implement Mario's Stack Blur algorithm, which blurs the target pixel map. Additionally, create a blur window in apps_blur() to show the effect of twin_stack_blur(). Implement the twin_shadow_border() function to create a darker border of the active window that gives a more dimensional appearance. The function twin_window_drop_shadow() will first apply the twin_shadow_border() and then apply twin_stack_blur() to blur the darker border. Furthermore, implement the twin_cover() function to cover the target pixels with the desired color. Ref: https://melatonin.dev/blog/implementing-marios-stack-blur-15-times-in-cpp/ Close #34 Signed-off-by: Wei-Hsin Yeh <[email protected]>
1 parent 122f696 commit ed659ba

File tree

9 files changed

+460
-9
lines changed

9 files changed

+460
-9
lines changed

apps/multi.c

+50
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "apps_multi.h"
88

99
#define D(x) twin_double_to_fixed(x)
10+
#define ASSET_PATH "assets/"
1011

1112
static void apps_line_start(twin_screen_t *screen, int x, int y, int w, int h)
1213
{
@@ -272,6 +273,52 @@ static void apps_flower_start(twin_screen_t *screen, int x, int y, int w, int h)
272273
twin_window_show(window);
273274
}
274275

276+
#if defined(CONFIG_LOADER_PNG)
277+
static void apps_blur(twin_screen_t *screen, int x, int y, int w, int h)
278+
{
279+
twin_pixmap_t *raw_background =
280+
twin_pixmap_from_file(ASSET_PATH "tux.png", TWIN_ARGB32);
281+
twin_window_t *window = twin_window_create(
282+
screen, TWIN_ARGB32, TwinWindowApplication, x, y, w, h);
283+
twin_window_set_name(window, "Blur");
284+
twin_pixmap_t *scaled_background = twin_pixmap_create(
285+
TWIN_ARGB32, window->pixmap->width, window->pixmap->height);
286+
twin_fixed_t sx, sy;
287+
sx = twin_fixed_div(
288+
twin_int_to_fixed(raw_background->width),
289+
twin_int_to_fixed(window->client.right - window->client.left));
290+
sy = twin_fixed_div(
291+
twin_int_to_fixed(raw_background->height),
292+
twin_int_to_fixed(window->client.bottom - window->client.top));
293+
294+
twin_matrix_scale(&raw_background->transform, sx, sy);
295+
twin_operand_t srcop = {
296+
.source_kind = TWIN_PIXMAP,
297+
.u.pixmap = raw_background,
298+
};
299+
300+
twin_composite(scaled_background, 0, 0, &srcop, 0, 0, 0, 0, 0, TWIN_SOURCE,
301+
screen->width, screen->height);
302+
303+
twin_pointer_t src, dst;
304+
for (int y = window->client.top; y < window->client.bottom; y++)
305+
for (int x = window->client.left; x < window->client.right; x++) {
306+
src =
307+
twin_pixmap_pointer(scaled_background, x - window->client.left,
308+
y - window->client.top);
309+
dst = twin_pixmap_pointer(window->pixmap, x, y);
310+
*dst.argb32 = *src.argb32 | 0xff000000;
311+
}
312+
twin_stack_blur(window->pixmap, 5, window->client.left,
313+
window->client.right, window->client.top,
314+
window->client.bottom);
315+
316+
twin_pixmap_destroy(scaled_background);
317+
twin_pixmap_destroy(raw_background);
318+
twin_window_show(window);
319+
}
320+
#endif
321+
275322
void apps_multi_start(twin_screen_t *screen,
276323
const char *name,
277324
int x,
@@ -286,4 +333,7 @@ void apps_multi_start(twin_screen_t *screen,
286333
apps_ascii_start(screen, x += 20, y += 20, w, h);
287334
apps_jelly_start(screen, x += 20, y += 20, w / 2, h);
288335
apps_flower_start(screen, x += 20, y += 20, w, h);
336+
#if defined(CONFIG_LOADER_PNG)
337+
apps_blur(screen, x += 20, y += 20, w / 2, h / 2);
338+
#endif
289339
}

configs/Kconfig

+22
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,28 @@ config CURSOR
5555
default n
5656
depends on !BACKEND_VNC
5757

58+
config DROP_SHADOW
59+
bool "Render drop shadow for active window"
60+
default y
61+
62+
config HORIZONTAL_OFFSET
63+
int "Horizontal offset"
64+
default 1
65+
range 1 10
66+
depends on DROP_SHADOW
67+
68+
config VERTICAL_OFFSET
69+
int "Vertical offset"
70+
default 1
71+
range 1 10
72+
depends on DROP_SHADOW
73+
74+
config BLUR
75+
int "Blur"
76+
default 10
77+
range 1 10
78+
depends on DROP_SHADOW
79+
5880
endmenu
5981

6082
menu "Image Loaders"

include/twin.h

+34
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,15 @@ typedef struct _twin_pixmap {
195195
* Pixels
196196
*/
197197
twin_animation_t *animation;
198+
199+
#if defined(CONFIG_DROP_SHADOW)
200+
/*
201+
* When the pixel map is within the active window, it will have a drop
202+
* shadow to enhance its visual distinction.
203+
*/
204+
bool shadow;
205+
#endif
206+
198207
twin_pointer_t p;
199208
/*
200209
* When representing a window, this point
@@ -423,6 +432,13 @@ typedef void (*twin_destroy_func_t)(twin_window_t *window);
423432
struct _twin_window {
424433
twin_screen_t *screen;
425434
twin_pixmap_t *pixmap;
435+
436+
#if defined(CONFIG_DROP_SHADOW)
437+
/* Set the shadow range for horizontal and vertical directions. */
438+
twin_coord_t shadow_x;
439+
twin_coord_t shadow_y;
440+
#endif
441+
426442
twin_window_style_t style;
427443
twin_rect_t client;
428444
twin_rect_t damage;
@@ -652,8 +668,26 @@ void twin_fill(twin_pixmap_t *dst,
652668
* draw-common.c
653669
*/
654670

671+
/* Blur the specified area in the pixel map. */
672+
void twin_stack_blur(twin_pixmap_t *px,
673+
int radius,
674+
twin_coord_t left,
675+
twin_coord_t right,
676+
twin_coord_t top,
677+
twin_coord_t bottom);
678+
655679
void twin_premultiply_alpha(twin_pixmap_t *px);
656680

681+
/*
682+
* Overwrite the original pixel values for a specified number of pixels in
683+
* width.
684+
*/
685+
void twin_cover(twin_pixmap_t *dst,
686+
twin_argb32_t color,
687+
twin_coord_t x,
688+
twin_coord_t y,
689+
twin_coord_t width);
690+
657691
/*
658692
* event.c
659693
*/

include/twin_private.h

+44-1
Original file line numberDiff line numberDiff line change
@@ -181,13 +181,41 @@ typedef int64_t twin_xfixed_t;
181181
(((t) = twin_get_8(d, i) + twin_get_8(s, i)), (twin_argb32_t) twin_sat(t) \
182182
<< (i))
183183

184+
#define _twin_add_ARGB(s, d, i, t) (((t) = (s) + twin_get_8(d, i)))
185+
#define _twin_add(s, d, t) (((t) = (s) + (d)))
186+
#define _twin_div(d, den, i, t) \
187+
(((t) = (d) / (den)), (t) = twin_get_8((t), 0), \
188+
(twin_argb32_t) twin_sat(t) << (i))
189+
#define _twin_sub_ARGB(s, d, i, t) (((t) = (s) - twin_get_8(d, i)))
190+
#define _twin_sub(s, d, t) (((t) = (s) - (d)))
191+
#define twin_put_8(d, i, t) (((t) = (d) << (i)))
192+
184193
#define twin_argb32_to_rgb16(s) \
185194
((((s) >> 3) & 0x001f) | (((s) >> 5) & 0x07e0) | (((s) >> 8) & 0xf800))
186195
#define twin_rgb16_to_argb32(s) \
187196
(((((s) << 3) & 0xf8) | (((s) >> 2) & 0x7)) | \
188197
((((s) << 5) & 0xfc00) | (((s) >> 1) & 0x300)) | \
189198
((((s) << 8) & 0xf80000) | (((s) << 3) & 0x70000)) | 0xff000000)
190199

200+
#ifndef min
201+
#define min(x, y) \
202+
({ \
203+
typeof(x) _x = (x); \
204+
typeof(y) _y = (y); \
205+
(void) (&_x == &_y); \
206+
_x < _y ? _x : _y; \
207+
})
208+
#endif
209+
#ifndef max
210+
#define max(x, y) \
211+
({ \
212+
typeof(x) _x = (x); \
213+
typeof(y) _y = (y); \
214+
(void) (&_x == &_y); \
215+
_x > _y ? _x : _y; \
216+
})
217+
#endif
218+
191219
typedef union {
192220
twin_pointer_t p;
193221
twin_argb32_t c;
@@ -468,7 +496,7 @@ void _twin_path_sfinish(twin_path_t *path);
468496
#define twin_glyph_snap_y(g) (twin_glyph_snap_x(g) + twin_glyph_n_snap_x(g))
469497

470498
/*
471-
* dispatch stuff
499+
* Dispatch stuff
472500
*/
473501
typedef struct _twin_queue {
474502
struct _twin_queue *next;
@@ -593,6 +621,21 @@ void _twin_button_init(twin_button_t *button,
593621
twin_style_t font_style,
594622
twin_dispatch_proc_t dispatch);
595623

624+
/*
625+
* Visual effect stuff
626+
*/
627+
628+
#if defined(CONFIG_DROP_SHADOW)
629+
/*
630+
* Add a shadow with the specified color, horizontal offset, and vertical
631+
* offset.
632+
*/
633+
void twin_shadow_border(twin_pixmap_t *shadow,
634+
twin_argb32_t color,
635+
twin_coord_t shift_x,
636+
twin_coord_t shift_y);
637+
#endif
638+
596639
/* utility */
597640

598641
#ifdef _MSC_VER

0 commit comments

Comments
 (0)