Skip to content

Commit 5dda144

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 5dda144

File tree

7 files changed

+299
-12
lines changed

7 files changed

+299
-12
lines changed

apps/multi.c

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,16 @@
44
* All rights reserved.
55
*/
66

7+
#include <stdlib.h>
78
#include "apps_multi.h"
89

910
#define D(x) twin_double_to_fixed(x)
11+
#define ASSET_PATH "assets/"
1012

1113
static void apps_line_start(twin_screen_t *screen, int x, int y, int w, int h)
1214
{
1315
twin_window_t *window = twin_window_create(
14-
screen, TWIN_ARGB32, TwinWindowApplication, x, y, w, h);
16+
screen, TWIN_ARGB32, TwinWindowApplication, x, y, w, h, false);
1517
twin_pixmap_t *pixmap = window->pixmap;
1618
twin_path_t *stroke = twin_path_create();
1719
twin_fixed_t fy;
@@ -38,7 +40,7 @@ static void apps_circletext_start(twin_screen_t *screen,
3840
int h)
3941
{
4042
twin_window_t *window = twin_window_create(
41-
screen, TWIN_ARGB32, TwinWindowApplication, x, y, w, h);
43+
screen, TWIN_ARGB32, TwinWindowApplication, x, y, w, h, false);
4244
int wid = window->client.right - window->client.left;
4345
int hei = window->client.bottom - window->client.top;
4446
twin_pixmap_t *pixmap = window->pixmap;
@@ -83,7 +85,7 @@ static void apps_quickbrown_start(twin_screen_t *screen,
8385
int h)
8486
{
8587
twin_window_t *window = twin_window_create(
86-
screen, TWIN_ARGB32, TwinWindowApplication, x, y, w, h);
88+
screen, TWIN_ARGB32, TwinWindowApplication, x, y, w, h, false);
8789
int wid = window->client.right - window->client.left;
8890
int hei = window->client.bottom - window->client.top;
8991
twin_pixmap_t *pixmap = window->pixmap;
@@ -126,7 +128,7 @@ static void apps_quickbrown_start(twin_screen_t *screen,
126128
static void apps_ascii_start(twin_screen_t *screen, int x, int y, int w, int h)
127129
{
128130
twin_window_t *window = twin_window_create(
129-
screen, TWIN_ARGB32, TwinWindowApplication, x, y, w, h);
131+
screen, TWIN_ARGB32, TwinWindowApplication, x, y, w, h, false);
130132
int wid = window->client.right - window->client.left;
131133
int hei = window->client.bottom - window->client.top;
132134
twin_pixmap_t *pixmap = window->pixmap;
@@ -174,7 +176,7 @@ static void apps_ascii_start(twin_screen_t *screen, int x, int y, int w, int h)
174176
static void apps_jelly_start(twin_screen_t *screen, int x, int y, int w, int h)
175177
{
176178
twin_window_t *window = twin_window_create(
177-
screen, TWIN_ARGB32, TwinWindowApplication, x, y, w, h);
179+
screen, TWIN_ARGB32, TwinWindowApplication, x, y, w, h, false);
178180
int wid = window->client.right - window->client.left;
179181
int hei = window->client.bottom - window->client.top;
180182
twin_pixmap_t *pixmap = window->pixmap;
@@ -220,6 +222,42 @@ static void apps_jelly_start(twin_screen_t *screen, int x, int y, int w, int h)
220222
twin_window_show(window);
221223
}
222224

225+
static void apps_test(twin_screen_t *screen, int x, int y, int w, int h)
226+
{
227+
twin_pixmap_t *raw_background =
228+
twin_pixmap_from_file(ASSET_PATH "tux.png", TWIN_ARGB32);
229+
twin_window_t *window = twin_window_create(
230+
screen, TWIN_ARGB32, TwinWindowApplication, x, y, w, h, true);
231+
232+
twin_pixmap_t *scaled_background = twin_pixmap_create(
233+
TWIN_ARGB32, window->pixmap->width, window->pixmap->height);
234+
twin_fixed_t sx, sy;
235+
sx = twin_fixed_div(twin_int_to_fixed(raw_background->width),
236+
twin_int_to_fixed(window->pixmap->width));
237+
sy = twin_fixed_div(twin_int_to_fixed(raw_background->height),
238+
twin_int_to_fixed(window->pixmap->height));
239+
240+
twin_matrix_scale(&raw_background->transform, sx, sy);
241+
twin_operand_t srcop = {
242+
.source_kind = TWIN_PIXMAP,
243+
.u.pixmap = raw_background,
244+
};
245+
246+
twin_composite(scaled_background, 0, 0, &srcop, 0, 0, NULL, 0, 0,
247+
TWIN_SOURCE, screen->width, screen->height);
248+
twin_pointer_t src, dst;
249+
for (int y = 0; y < scaled_background->height; y++)
250+
for (int x = 0; x < scaled_background->width; x++) {
251+
src = twin_pixmap_pointer(scaled_background, x, y);
252+
dst = twin_pixmap_pointer(window->pixmap, x, y);
253+
*dst.argb32 = *src.argb32 | 0xff000000;
254+
}
255+
256+
twin_stack_blur(window->pixmap);
257+
twin_window_set_name(window, "Test");
258+
twin_window_show(window);
259+
}
260+
223261
void apps_multi_start(twin_screen_t *screen,
224262
const char *name,
225263
int x,
@@ -233,4 +271,5 @@ void apps_multi_start(twin_screen_t *screen,
233271
apps_quickbrown_start(screen, x += 20, y += 20, w, h);
234272
apps_ascii_start(screen, x += 20, y += 20, w, h);
235273
apps_jelly_start(screen, x += 20, y += 20, w / 2, h);
274+
apps_test(screen, x, y, w, h);
236275
}

include/twin.h

Lines changed: 12 additions & 1 deletion
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,8 @@ 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+
651659
/*
652660
* event.c
653661
*/
@@ -1121,14 +1129,17 @@ twin_window_t *twin_window_create(twin_screen_t *screen,
11211129
twin_coord_t x,
11221130
twin_coord_t y,
11231131
twin_coord_t width,
1124-
twin_coord_t height);
1132+
twin_coord_t height,
1133+
bool shadow);
11251134

11261135
void twin_window_destroy(twin_window_t *window);
11271136

11281137
void twin_window_show(twin_window_t *window);
11291138

11301139
void twin_window_hide(twin_window_t *window);
11311140

1141+
void twin_shadow_visible(twin_pixmap_t *pixmap, twin_window_t *window);
1142+
11321143
void twin_window_configure(twin_window_t *window,
11331144
twin_window_style_t style,
11341145
twin_coord_t x,

src/draw.c

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,141 @@ 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, i, t) \
308+
(((t) = (d) / 9), (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, twin_pixmap_t *src_px, bool horiz_span)
330+
{
331+
int first_num, second_num, radius = 2;
332+
twin_pointer_t src_ptr, trg_ptr, old_ptr, new_ptr;
333+
twin_argb32_t sumInR, sumOutR, sumR, sumInG, sumOutG, sumG, sumInB, sumOutB,
334+
sumB, _cur, _old, _new, _src;
335+
uint16_t t1, t2, t3, t4;
336+
first_num = src_px->height, second_num = src_px->width;
337+
for (int first = 0; first < first_num; first++) {
338+
/* padding sum_out */
339+
sumInR = sumOutR = sumR = sumInG = sumOutG = sumG = sumInB = sumOutB =
340+
sumB = 0x00000000;
341+
342+
for (int i = 0; i < radius; i++) {
343+
if (horiz_span)
344+
src_ptr = twin_pixmap_pointer(src_px, 0, first);
345+
else
346+
src_ptr = twin_pixmap_pointer(src_px, first, 0);
347+
_src = *src_ptr.argb32;
348+
sumOutR = _twin_add_ARGB(sumOutR, _src, 0, t1);
349+
sumOutG = _twin_add_ARGB(sumOutG, _src, 8, t2);
350+
sumOutB = _twin_add_ARGB(sumOutB, _src, 16, t3);
351+
for (int j = 0; j < i + 1; j++) {
352+
sumR = _twin_add_ARGB(sumR, _src, 0, t1);
353+
sumG = _twin_add_ARGB(sumG, _src, 8, t2);
354+
sumB = _twin_add_ARGB(sumB, _src, 16, t3);
355+
}
356+
}
357+
358+
for (int i = 0; i < radius; i++) {
359+
if (horiz_span)
360+
src_ptr = twin_pixmap_pointer(src_px, i, first);
361+
else
362+
src_ptr = twin_pixmap_pointer(src_px, first, i);
363+
_src = *src_ptr.argb32;
364+
sumInR = _twin_add_ARGB(sumInR, _src, 0, t1);
365+
sumInG = _twin_add_ARGB(sumInG, _src, 8, t2);
366+
sumInB = _twin_add_ARGB(sumInB, _src, 16, t3);
367+
for (int j = 0; j < radius - i; j++) {
368+
sumR = _twin_add_ARGB(sumR, _src, 0, t1);
369+
sumG = _twin_add_ARGB(sumG, _src, 8, t2);
370+
sumB = _twin_add_ARGB(sumB, _src, 16, t3);
371+
}
372+
}
373+
374+
for (int cur = 0; cur < second_num; cur++) {
375+
if (horiz_span) {
376+
src_ptr = twin_pixmap_pointer(src_px, cur, first);
377+
trg_ptr = twin_pixmap_pointer(trg_px, cur, first);
378+
old_ptr =
379+
twin_pixmap_pointer(src_px, max(cur - radius, 0), first);
380+
new_ptr = twin_pixmap_pointer(
381+
src_px, min(cur + radius, second_num - 1), first);
382+
} else {
383+
src_ptr = twin_pixmap_pointer(src_px, first, cur);
384+
trg_ptr = twin_pixmap_pointer(trg_px, first, cur);
385+
old_ptr =
386+
twin_pixmap_pointer(src_px, first, max(cur - radius, 0));
387+
new_ptr = twin_pixmap_pointer(
388+
src_px, first, min(cur + radius, second_num - 1));
389+
}
390+
_cur = *src_ptr.argb32;
391+
_old = *old_ptr.argb32;
392+
_new = *new_ptr.argb32;
393+
/* STEP 1 : sum_out + current */
394+
sumOutR = _twin_add_ARGB(sumOutR, _cur, 0, t1);
395+
sumOutG = _twin_add_ARGB(sumOutG, _cur, 8, t2);
396+
sumOutB = _twin_add_ARGB(sumOutB, _cur, 16, t3);
397+
/* STEP 2 : sum_in + new */
398+
sumInR = _twin_add_ARGB(sumInR, _new, 0, t1);
399+
sumInG = _twin_add_ARGB(sumInG, _new, 8, t2);
400+
sumInB = _twin_add_ARGB(sumInB, _new, 16, t3);
401+
/* STEP 3: sum + sum_in */
402+
sumR = _twin_add(sumR, sumInR, t1);
403+
sumG = _twin_add(sumG, sumInG, t2);
404+
sumB = _twin_add(sumB, sumInB, t3);
405+
/* STEP 4 : sum / 9 */
406+
*trg_ptr.argb32 =
407+
(_twin_div(sumR, 0, t1) | _twin_div(sumG, 8, t2) |
408+
_twin_div(sumB, 16, t3) | (*src_ptr.argb32 & 0xff000000));
409+
/* STEP 5 : sum - sum_out */
410+
sumR = _twin_sub(sumR, sumOutR, t1);
411+
sumG = _twin_sub(sumG, sumOutG, t2);
412+
sumB = _twin_sub(sumB, sumOutB, t3);
413+
/* STEP 6 : sum_out - old */
414+
sumOutR = _twin_sub_ARGB(sumOutR, _old, 0, t1);
415+
sumOutG = _twin_sub_ARGB(sumOutG, _old, 8, t2);
416+
sumOutB = _twin_sub_ARGB(sumOutB, _old, 16, t3);
417+
/* STEP 7 : sum_in - source_current */
418+
sumInR = _twin_sub_ARGB(sumInR, _cur, 0, t1);
419+
sumInG = _twin_sub_ARGB(sumInG, _cur, 8, t2);
420+
sumInB = _twin_sub_ARGB(sumInB, _cur, 16, t3);
421+
}
422+
}
423+
}
424+
425+
void twin_stack_blur(twin_pixmap_t *px)
426+
{
427+
if (px->format != TWIN_ARGB32)
428+
return;
429+
twin_pixmap_t *tmp_px =
430+
twin_pixmap_create(px->format, px->width, px->height);
431+
memcpy(tmp_px->p.v, px->p.v,
432+
px->width * px->height * twin_bytes_per_pixel(px->format));
433+
434+
twin_stack(tmp_px, px, true);
435+
twin_stack(px, tmp_px, false);
436+
twin_pixmap_destroy(tmp_px);
437+
return;
438+
}
439+
305440
/* FIXME: source clipping is busted */
306441
static void _twin_composite_simple(twin_pixmap_t *dst,
307442
twin_coord_t dst_x,
@@ -777,3 +912,41 @@ void twin_fill(twin_pixmap_t *dst,
777912
(*op)(twin_pixmap_pointer(dst, left, iy), src, right - left);
778913
twin_pixmap_damage(dst, left, top, right, bottom);
779914
}
915+
916+
void twin_glass_fill(twin_pixmap_t *dst,
917+
twin_argb32_t pixel,
918+
twin_operator_t operator,
919+
twin_coord_t left,
920+
twin_coord_t top,
921+
twin_coord_t right,
922+
twin_coord_t bottom)
923+
{
924+
twin_src_op op;
925+
twin_source_u src;
926+
twin_coord_t iy, ix;
927+
928+
/* offset */
929+
left += dst->origin_x;
930+
top += dst->origin_y;
931+
right += dst->origin_x;
932+
bottom += dst->origin_y;
933+
934+
/* clip */
935+
if (left < dst->clip.left)
936+
left = dst->clip.left;
937+
if (right > dst->clip.right)
938+
right = dst->clip.right;
939+
if (top < dst->clip.top)
940+
top = dst->clip.top;
941+
if (bottom > dst->clip.bottom)
942+
bottom = dst->clip.bottom;
943+
if (left >= right || top >= bottom)
944+
return;
945+
946+
src.c = pixel;
947+
op = fill[operator][dst->format];
948+
949+
for (iy = 0; iy < dst->height; iy++)
950+
for (ix = 0; ix < dst->width; ix++)
951+
(*op)(twin_pixmap_pointer(dst, ix, iy), src, 1);
952+
}

src/pixmap.c

Lines changed: 1 addition & 0 deletions
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

Lines changed: 5 additions & 3 deletions
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

Lines changed: 1 addition & 1 deletion
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)