Skip to content

Commit dcbefd0

Browse files
committed
Implement the drop shadow
Add the stack blur function to blur the pixmap that is test on the test window. Add the shadow pixel map under the window which has shadow feature.
1 parent 182ebcf commit dcbefd0

File tree

7 files changed

+283
-12
lines changed

7 files changed

+283
-12
lines changed

apps/multi.c

+50-5
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@
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
{
1314
twin_window_t *window = twin_window_create(
14-
screen, TWIN_ARGB32, TwinWindowApplication, x, y, w, h);
15+
screen, TWIN_ARGB32, TwinWindowApplication, x, y, w, h, false);
1516
twin_pixmap_t *pixmap = window->pixmap;
1617
twin_path_t *stroke = twin_path_create();
1718
twin_fixed_t fy;
@@ -38,7 +39,7 @@ static void apps_circletext_start(twin_screen_t *screen,
3839
int h)
3940
{
4041
twin_window_t *window = twin_window_create(
41-
screen, TWIN_ARGB32, TwinWindowApplication, x, y, w, h);
42+
screen, TWIN_ARGB32, TwinWindowApplication, x, y, w, h, false);
4243
int wid = window->client.right - window->client.left;
4344
int hei = window->client.bottom - window->client.top;
4445
twin_pixmap_t *pixmap = window->pixmap;
@@ -83,7 +84,7 @@ static void apps_quickbrown_start(twin_screen_t *screen,
8384
int h)
8485
{
8586
twin_window_t *window = twin_window_create(
86-
screen, TWIN_ARGB32, TwinWindowApplication, x, y, w, h);
87+
screen, TWIN_ARGB32, TwinWindowApplication, x, y, w, h, false);
8788
int wid = window->client.right - window->client.left;
8889
int hei = window->client.bottom - window->client.top;
8990
twin_pixmap_t *pixmap = window->pixmap;
@@ -126,7 +127,7 @@ static void apps_quickbrown_start(twin_screen_t *screen,
126127
static void apps_ascii_start(twin_screen_t *screen, int x, int y, int w, int h)
127128
{
128129
twin_window_t *window = twin_window_create(
129-
screen, TWIN_ARGB32, TwinWindowApplication, x, y, w, h);
130+
screen, TWIN_ARGB32, TwinWindowApplication, x, y, w, h, false);
130131
int wid = window->client.right - window->client.left;
131132
int hei = window->client.bottom - window->client.top;
132133
twin_pixmap_t *pixmap = window->pixmap;
@@ -174,7 +175,7 @@ static void apps_ascii_start(twin_screen_t *screen, int x, int y, int w, int h)
174175
static void apps_jelly_start(twin_screen_t *screen, int x, int y, int w, int h)
175176
{
176177
twin_window_t *window = twin_window_create(
177-
screen, TWIN_ARGB32, TwinWindowApplication, x, y, w, h);
178+
screen, TWIN_ARGB32, TwinWindowApplication, x, y, w, h, false);
178179
int wid = window->client.right - window->client.left;
179180
int hei = window->client.bottom - window->client.top;
180181
twin_pixmap_t *pixmap = window->pixmap;
@@ -220,6 +221,49 @@ static void apps_jelly_start(twin_screen_t *screen, int x, int y, int w, int h)
220221
twin_window_show(window);
221222
}
222223

224+
static void apps_test(twin_screen_t *screen, int x, int y, int w, int h)
225+
{
226+
twin_pixmap_t *raw_background =
227+
twin_pixmap_from_file(ASSET_PATH "tux.png", TWIN_ARGB32);
228+
twin_window_t *window = twin_window_create(
229+
screen, TWIN_ARGB32, TwinWindowApplication, x, y, w, h, true);
230+
twin_window_set_name(window, "Test");
231+
twin_pixmap_t *scaled_background = twin_pixmap_create(
232+
TWIN_ARGB32, window->pixmap->width, window->pixmap->height);
233+
twin_fixed_t sx, sy;
234+
sx = twin_fixed_div(
235+
twin_int_to_fixed(raw_background->width),
236+
twin_int_to_fixed(window->client.right - window->client.left));
237+
sy = twin_fixed_div(
238+
twin_int_to_fixed(raw_background->height),
239+
twin_int_to_fixed(window->client.bottom - window->client.top));
240+
241+
twin_matrix_scale(&raw_background->transform, sx, sy);
242+
twin_operand_t srcop = {
243+
.source_kind = TWIN_PIXMAP,
244+
.u.pixmap = raw_background,
245+
};
246+
247+
twin_composite(scaled_background, 0, 0, &srcop, 0, 0, 0, 0, 0, TWIN_SOURCE,
248+
screen->width, screen->height);
249+
250+
twin_pointer_t src, dst;
251+
for (int y = window->client.top; y < window->client.bottom; y++)
252+
for (int x = window->client.left; x < window->client.right; x++) {
253+
src =
254+
twin_pixmap_pointer(scaled_background, x - window->client.left,
255+
y - window->client.top);
256+
dst = twin_pixmap_pointer(window->pixmap, x, y);
257+
*dst.argb32 = *src.argb32 | 0xff000000;
258+
}
259+
260+
twin_stack_blur(window->pixmap, 5, window->client.left,
261+
window->client.right, window->client.top,
262+
window->client.bottom);
263+
twin_window_show(window);
264+
twin_pixmap_destroy(scaled_background);
265+
}
266+
223267
void apps_multi_start(twin_screen_t *screen,
224268
const char *name,
225269
int x,
@@ -233,4 +277,5 @@ void apps_multi_start(twin_screen_t *screen,
233277
apps_quickbrown_start(screen, x += 20, y += 20, w, h);
234278
apps_ascii_start(screen, x += 20, y += 20, w, h);
235279
apps_jelly_start(screen, x += 20, y += 20, w / 2, h);
280+
apps_test(screen, x, y, w, h);
236281
}

include/twin.h

+17-1
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ typedef struct _twin_pixmap {
194194
* Pixels
195195
*/
196196
twin_animation_t *animation;
197+
bool shadow;
197198
twin_pointer_t p;
198199
/*
199200
* When representing a window, this point
@@ -422,6 +423,11 @@ typedef void (*twin_destroy_func_t)(twin_window_t *window);
422423
struct _twin_window {
423424
twin_screen_t *screen;
424425
twin_pixmap_t *pixmap;
426+
bool shadow;
427+
twin_pixmap_t *shadow_pixmap;
428+
twin_coord_t shadow_offset_x;
429+
twin_coord_t shadow_offset_y;
430+
twin_argb32_t shadow_color;
425431
twin_window_style_t style;
426432
twin_rect_t client;
427433
twin_rect_t damage;
@@ -648,6 +654,13 @@ void twin_fill(twin_pixmap_t *dst,
648654

649655
void twin_premultiply_alpha(twin_pixmap_t *px);
650656

657+
void twin_stack_blur(twin_pixmap_t *px,
658+
int radius,
659+
twin_coord_t left,
660+
twin_coord_t right,
661+
twin_coord_t top,
662+
twin_coord_t bottom);
663+
651664
/*
652665
* event.c
653666
*/
@@ -1121,14 +1134,17 @@ twin_window_t *twin_window_create(twin_screen_t *screen,
11211134
twin_coord_t x,
11221135
twin_coord_t y,
11231136
twin_coord_t width,
1124-
twin_coord_t height);
1137+
twin_coord_t height,
1138+
bool shadow);
11251139

11261140
void twin_window_destroy(twin_window_t *window);
11271141

11281142
void twin_window_show(twin_window_t *window);
11291143

11301144
void twin_window_hide(twin_window_t *window);
11311145

1146+
void twin_shadow_visible(twin_pixmap_t *pixmap, twin_window_t *window);
1147+
11321148
void twin_window_configure(twin_window_t *window,
11331149
twin_window_style_t style,
11341150
twin_coord_t x,

src/draw.c

+147
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,153 @@ static const twin_src_msk_op comp3[2][4][4][3] = {
302302
#define operand_index(o) \
303303
((o)->source_kind == TWIN_SOLID ? 3 : o->u.pixmap->format)
304304

305+
#define _twin_add_ARGB(s, d, i, t) (((t) = (s) + twin_get_8(d, i)))
306+
#define _twin_add(s, d, t) (((t) = (s) + (d)))
307+
#define _twin_div(d, den, i, t) \
308+
(((t) = (d) / (den)), (t) = twin_get_8((t), 0), \
309+
(twin_argb32_t) twin_sat(t) << (i))
310+
#define _twin_sub_ARGB(s, d, i, t) (((t) = (s) - twin_get_8(d, i)))
311+
#define _twin_sub(s, d, t) (((t) = (s) - (d)))
312+
#define twin_put_8(d, i, t) (((t) = (d) << (i)))
313+
314+
#define min(x, y) \
315+
({ \
316+
typeof(x) _x = (x); \
317+
typeof(y) _y = (y); \
318+
(void) (&_x == &_y); \
319+
_x < _y ? _x : _y; \
320+
})
321+
#define max(x, y) \
322+
({ \
323+
typeof(x) _x = (x); \
324+
typeof(y) _y = (y); \
325+
(void) (&_x == &_y); \
326+
_x > _y ? _x : _y; \
327+
})
328+
329+
void twin_stack(twin_pixmap_t *trg_px,
330+
twin_pixmap_t *src_px,
331+
int radius,
332+
int first_str,
333+
int first_end,
334+
int second_str,
335+
int second_end,
336+
bool horiz_span)
337+
{
338+
int den = (radius + 1) * (radius + 1);
339+
twin_pointer_t src_ptr, trg_ptr, old_ptr, new_ptr;
340+
twin_argb32_t sumInR, sumOutR, sumR, sumInG, sumOutG, sumG, sumInB, sumOutB,
341+
sumB, _cur, _old, _new, _src;
342+
uint16_t t1, t2, t3;
343+
for (int first = first_str; first < first_end; first++) {
344+
sumInR = sumOutR = sumR = sumInG = sumOutG = sumG = sumInB = sumOutB =
345+
sumB = 0x00000000;
346+
347+
/* Initialize SumOut by padding */
348+
if (horiz_span)
349+
src_ptr = twin_pixmap_pointer(src_px, second_str, first);
350+
else
351+
src_ptr = twin_pixmap_pointer(src_px, first, second_str);
352+
_src = *src_ptr.argb32;
353+
354+
for (int i = second_str; i < second_str + radius; i++) {
355+
sumOutR = _twin_add_ARGB(sumOutR, _src, 0, t1);
356+
sumOutG = _twin_add_ARGB(sumOutG, _src, 8, t2);
357+
sumOutB = _twin_add_ARGB(sumOutB, _src, 16, t3);
358+
for (int j = 0; j < (i - second_str) + 1; j++) {
359+
sumR = _twin_add_ARGB(sumR, _src, 0, t1);
360+
sumG = _twin_add_ARGB(sumG, _src, 8, t2);
361+
sumB = _twin_add_ARGB(sumB, _src, 16, t3);
362+
}
363+
}
364+
365+
/* Initialize SumIn */
366+
for (int i = second_str; i < second_str + radius; i++) {
367+
if (horiz_span)
368+
src_ptr = twin_pixmap_pointer(src_px, i, first);
369+
else
370+
src_ptr = twin_pixmap_pointer(src_px, first, i);
371+
_src = *src_ptr.argb32;
372+
sumInR = _twin_add_ARGB(sumInR, _src, 0, t1);
373+
sumInG = _twin_add_ARGB(sumInG, _src, 8, t2);
374+
sumInB = _twin_add_ARGB(sumInB, _src, 16, t3);
375+
for (int j = 0; j < radius - (i - second_str); j++) {
376+
sumR = _twin_add_ARGB(sumR, _src, 0, t1);
377+
sumG = _twin_add_ARGB(sumG, _src, 8, t2);
378+
sumB = _twin_add_ARGB(sumB, _src, 16, t3);
379+
}
380+
}
381+
382+
for (int cur = second_str; cur < second_end; cur++) {
383+
if (horiz_span) {
384+
src_ptr = twin_pixmap_pointer(src_px, cur, first);
385+
trg_ptr = twin_pixmap_pointer(trg_px, cur, first);
386+
old_ptr = twin_pixmap_pointer(
387+
src_px, max(cur - radius, second_str), first);
388+
new_ptr = twin_pixmap_pointer(
389+
src_px, min(cur + radius, second_end - 1), first);
390+
} else {
391+
src_ptr = twin_pixmap_pointer(src_px, first, cur);
392+
trg_ptr = twin_pixmap_pointer(trg_px, first, cur);
393+
old_ptr = twin_pixmap_pointer(src_px, first,
394+
max(cur - radius, second_str));
395+
new_ptr = twin_pixmap_pointer(
396+
src_px, first, min(cur + radius, second_end - 1));
397+
}
398+
_cur = *src_ptr.argb32;
399+
_old = *old_ptr.argb32;
400+
_new = *new_ptr.argb32;
401+
/* STEP 1 : sum_out + current */
402+
sumOutR = _twin_add_ARGB(sumOutR, _cur, 0, t1);
403+
sumOutG = _twin_add_ARGB(sumOutG, _cur, 8, t2);
404+
sumOutB = _twin_add_ARGB(sumOutB, _cur, 16, t3);
405+
/* STEP 2 : sum_in + new */
406+
sumInR = _twin_add_ARGB(sumInR, _new, 0, t1);
407+
sumInG = _twin_add_ARGB(sumInG, _new, 8, t2);
408+
sumInB = _twin_add_ARGB(sumInB, _new, 16, t3);
409+
/* STEP 3 : sum + sum_in */
410+
sumR = _twin_add(sumR, sumInR, t1);
411+
sumG = _twin_add(sumG, sumInG, t2);
412+
sumB = _twin_add(sumB, sumInB, t3);
413+
/* STEP 4 : sum / denominator */
414+
*trg_ptr.argb32 =
415+
(_twin_div(sumR, den, 0, t1) | _twin_div(sumG, den, 8, t2) |
416+
_twin_div(sumB, den, 16, t3) | (*src_ptr.argb32 & 0xff000000));
417+
/* STEP 5 : sum - sum_out */
418+
sumR = _twin_sub(sumR, sumOutR, t1);
419+
sumG = _twin_sub(sumG, sumOutG, t2);
420+
sumB = _twin_sub(sumB, sumOutB, t3);
421+
/* STEP 6 : sum_out - old */
422+
sumOutR = _twin_sub_ARGB(sumOutR, _old, 0, t1);
423+
sumOutG = _twin_sub_ARGB(sumOutG, _old, 8, t2);
424+
sumOutB = _twin_sub_ARGB(sumOutB, _old, 16, t3);
425+
/* STEP 7 : sum_in - current */
426+
sumInR = _twin_sub_ARGB(sumInR, _cur, 0, t1);
427+
sumInG = _twin_sub_ARGB(sumInG, _cur, 8, t2);
428+
sumInB = _twin_sub_ARGB(sumInB, _cur, 16, t3);
429+
}
430+
}
431+
}
432+
433+
void twin_stack_blur(twin_pixmap_t *px,
434+
int radius,
435+
twin_coord_t left,
436+
twin_coord_t right,
437+
twin_coord_t top,
438+
twin_coord_t bottom)
439+
{
440+
if (px->format != TWIN_ARGB32)
441+
return;
442+
twin_pixmap_t *tmp_px =
443+
twin_pixmap_create(px->format, px->width, px->height);
444+
memcpy(tmp_px->p.v, px->p.v,
445+
px->width * px->height * twin_bytes_per_pixel(px->format));
446+
twin_stack(tmp_px, px, radius, top, bottom, left, right, true);
447+
twin_stack(px, tmp_px, radius, left, right, top, bottom, false);
448+
twin_pixmap_destroy(tmp_px);
449+
return;
450+
}
451+
305452
/* FIXME: source clipping is busted */
306453
static void _twin_composite_simple(twin_pixmap_t *dst,
307454
twin_coord_t dst_x,

src/pixmap.c

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ twin_pixmap_t *twin_pixmap_create(twin_format_t format,
4343
pixmap->stride = stride;
4444
pixmap->disable = 0;
4545
pixmap->animation = NULL;
46+
pixmap->shadow = false;
4647
pixmap->p.v = pixmap + 1;
4748
memset(pixmap->p.v, '\0', space);
4849
return pixmap;

src/screen.c

+5-3
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,8 @@ bool twin_screen_dispatch(twin_screen_t *screen, twin_event_t *event)
356356
evt = *event;
357357
evt.kind = TwinEventLeave;
358358
_twin_adj_mouse_evt(&evt, pixmap);
359-
twin_pixmap_dispatch(pixmap, &evt);
359+
if (!pixmap->shadow)
360+
twin_pixmap_dispatch(pixmap, &evt);
360361
}
361362

362363
pixmap = screen->target = ntarget;
@@ -365,7 +366,8 @@ bool twin_screen_dispatch(twin_screen_t *screen, twin_event_t *event)
365366
evt = *event;
366367
_twin_adj_mouse_evt(&evt, pixmap);
367368
evt.kind = TwinEventEnter;
368-
twin_pixmap_dispatch(pixmap, &evt);
369+
if (!pixmap->shadow)
370+
twin_pixmap_dispatch(pixmap, &evt);
369371
}
370372
}
371373

@@ -389,7 +391,7 @@ bool twin_screen_dispatch(twin_screen_t *screen, twin_event_t *event)
389391
pixmap = NULL;
390392
break;
391393
}
392-
if (pixmap)
394+
if (pixmap && !pixmap->shadow)
393395
return twin_pixmap_dispatch(pixmap, event);
394396
return false;
395397
}

src/toplevel.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ twin_toplevel_t *twin_toplevel_create(twin_screen_t *screen,
8181
{
8282
twin_toplevel_t *toplevel;
8383
twin_window_t *window =
84-
twin_window_create(screen, format, style, x, y, width, height);
84+
twin_window_create(screen, format, style, x, y, width, height, false);
8585

8686
if (!window)
8787
return NULL;

0 commit comments

Comments
 (0)