Skip to content

Commit

Permalink
Implement the drop shadow
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
weihsinyeh committed Nov 12, 2024
1 parent 182ebcf commit 5dda144
Show file tree
Hide file tree
Showing 7 changed files with 299 additions and 12 deletions.
49 changes: 44 additions & 5 deletions apps/multi.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@
* All rights reserved.
*/

#include <stdlib.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)
{
twin_window_t *window = twin_window_create(
screen, TWIN_ARGB32, TwinWindowApplication, x, y, w, h);
screen, TWIN_ARGB32, TwinWindowApplication, x, y, w, h, false);
twin_pixmap_t *pixmap = window->pixmap;
twin_path_t *stroke = twin_path_create();
twin_fixed_t fy;
Expand All @@ -38,7 +40,7 @@ static void apps_circletext_start(twin_screen_t *screen,
int h)
{
twin_window_t *window = twin_window_create(
screen, TWIN_ARGB32, TwinWindowApplication, x, y, w, h);
screen, TWIN_ARGB32, TwinWindowApplication, x, y, w, h, false);
int wid = window->client.right - window->client.left;
int hei = window->client.bottom - window->client.top;
twin_pixmap_t *pixmap = window->pixmap;
Expand Down Expand Up @@ -83,7 +85,7 @@ static void apps_quickbrown_start(twin_screen_t *screen,
int h)
{
twin_window_t *window = twin_window_create(
screen, TWIN_ARGB32, TwinWindowApplication, x, y, w, h);
screen, TWIN_ARGB32, TwinWindowApplication, x, y, w, h, false);
int wid = window->client.right - window->client.left;
int hei = window->client.bottom - window->client.top;
twin_pixmap_t *pixmap = window->pixmap;
Expand Down Expand Up @@ -126,7 +128,7 @@ static void apps_quickbrown_start(twin_screen_t *screen,
static void apps_ascii_start(twin_screen_t *screen, int x, int y, int w, int h)
{
twin_window_t *window = twin_window_create(
screen, TWIN_ARGB32, TwinWindowApplication, x, y, w, h);
screen, TWIN_ARGB32, TwinWindowApplication, x, y, w, h, false);
int wid = window->client.right - window->client.left;
int hei = window->client.bottom - window->client.top;
twin_pixmap_t *pixmap = window->pixmap;
Expand Down Expand Up @@ -174,7 +176,7 @@ static void apps_ascii_start(twin_screen_t *screen, int x, int y, int w, int h)
static void apps_jelly_start(twin_screen_t *screen, int x, int y, int w, int h)
{
twin_window_t *window = twin_window_create(
screen, TWIN_ARGB32, TwinWindowApplication, x, y, w, h);
screen, TWIN_ARGB32, TwinWindowApplication, x, y, w, h, false);
int wid = window->client.right - window->client.left;
int hei = window->client.bottom - window->client.top;
twin_pixmap_t *pixmap = window->pixmap;
Expand Down Expand Up @@ -220,6 +222,42 @@ static void apps_jelly_start(twin_screen_t *screen, int x, int y, int w, int h)
twin_window_show(window);
}

static void apps_test(twin_screen_t *screen, int x, int y, int w, int h)
{
twin_pixmap_t *raw_background =
twin_pixmap_from_file(ASSET_PATH "tux.png", TWIN_ARGB32);
twin_window_t *window = twin_window_create(
screen, TWIN_ARGB32, TwinWindowApplication, x, y, w, h, true);

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->pixmap->width));
sy = twin_fixed_div(twin_int_to_fixed(raw_background->height),
twin_int_to_fixed(window->pixmap->height));

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, NULL, 0, 0,
TWIN_SOURCE, screen->width, screen->height);
twin_pointer_t src, dst;
for (int y = 0; y < scaled_background->height; y++)
for (int x = 0; x < scaled_background->width; x++) {
src = twin_pixmap_pointer(scaled_background, x, y);
dst = twin_pixmap_pointer(window->pixmap, x, y);
*dst.argb32 = *src.argb32 | 0xff000000;
}

twin_stack_blur(window->pixmap);
twin_window_set_name(window, "Test");
twin_window_show(window);
}

void apps_multi_start(twin_screen_t *screen,
const char *name,
int x,
Expand All @@ -233,4 +271,5 @@ void apps_multi_start(twin_screen_t *screen,
apps_quickbrown_start(screen, x += 20, y += 20, w, h);
apps_ascii_start(screen, x += 20, y += 20, w, h);
apps_jelly_start(screen, x += 20, y += 20, w / 2, h);
apps_test(screen, x, y, w, h);
}
13 changes: 12 additions & 1 deletion include/twin.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ typedef struct _twin_pixmap {
* Pixels
*/
twin_animation_t *animation;
bool shadow;
twin_pointer_t p;
/*
* When representing a window, this point
Expand Down Expand Up @@ -422,6 +423,11 @@ typedef void (*twin_destroy_func_t)(twin_window_t *window);
struct _twin_window {
twin_screen_t *screen;
twin_pixmap_t *pixmap;
bool shadow;
twin_pixmap_t *shadow_pixmap;
twin_coord_t shadow_offset_x;
twin_coord_t shadow_offset_y;
twin_argb32_t shadow_color;
twin_window_style_t style;
twin_rect_t client;
twin_rect_t damage;
Expand Down Expand Up @@ -648,6 +654,8 @@ void twin_fill(twin_pixmap_t *dst,

void twin_premultiply_alpha(twin_pixmap_t *px);

void twin_stack_blur(twin_pixmap_t *px);

/*
* event.c
*/
Expand Down Expand Up @@ -1121,14 +1129,17 @@ twin_window_t *twin_window_create(twin_screen_t *screen,
twin_coord_t x,
twin_coord_t y,
twin_coord_t width,
twin_coord_t height);
twin_coord_t height,
bool shadow);

void twin_window_destroy(twin_window_t *window);

void twin_window_show(twin_window_t *window);

void twin_window_hide(twin_window_t *window);

void twin_shadow_visible(twin_pixmap_t *pixmap, twin_window_t *window);

void twin_window_configure(twin_window_t *window,
twin_window_style_t style,
twin_coord_t x,
Expand Down
173 changes: 173 additions & 0 deletions src/draw.c
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,141 @@ static const twin_src_msk_op comp3[2][4][4][3] = {
#define operand_index(o) \
((o)->source_kind == TWIN_SOLID ? 3 : o->u.pixmap->format)

#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, i, t) \
(((t) = (d) / 9), (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)))

#define min(x, y) \
({ \
typeof(x) _x = (x); \
typeof(y) _y = (y); \
(void) (&_x == &_y); \
_x < _y ? _x : _y; \
})
#define max(x, y) \
({ \
typeof(x) _x = (x); \
typeof(y) _y = (y); \
(void) (&_x == &_y); \
_x > _y ? _x : _y; \
})

void twin_stack(twin_pixmap_t *trg_px, twin_pixmap_t *src_px, bool horiz_span)
{
int first_num, second_num, radius = 2;
twin_pointer_t src_ptr, trg_ptr, old_ptr, new_ptr;
twin_argb32_t sumInR, sumOutR, sumR, sumInG, sumOutG, sumG, sumInB, sumOutB,
sumB, _cur, _old, _new, _src;
uint16_t t1, t2, t3, t4;
first_num = src_px->height, second_num = src_px->width;
for (int first = 0; first < first_num; first++) {
/* padding sum_out */
sumInR = sumOutR = sumR = sumInG = sumOutG = sumG = sumInB = sumOutB =
sumB = 0x00000000;

for (int i = 0; i < radius; i++) {
if (horiz_span)
src_ptr = twin_pixmap_pointer(src_px, 0, first);
else
src_ptr = twin_pixmap_pointer(src_px, first, 0);
_src = *src_ptr.argb32;
sumOutR = _twin_add_ARGB(sumOutR, _src, 0, t1);
sumOutG = _twin_add_ARGB(sumOutG, _src, 8, t2);
sumOutB = _twin_add_ARGB(sumOutB, _src, 16, t3);
for (int j = 0; j < i + 1; j++) {
sumR = _twin_add_ARGB(sumR, _src, 0, t1);
sumG = _twin_add_ARGB(sumG, _src, 8, t2);
sumB = _twin_add_ARGB(sumB, _src, 16, t3);
}
}

for (int i = 0; i < radius; i++) {
if (horiz_span)
src_ptr = twin_pixmap_pointer(src_px, i, first);
else
src_ptr = twin_pixmap_pointer(src_px, first, i);
_src = *src_ptr.argb32;
sumInR = _twin_add_ARGB(sumInR, _src, 0, t1);
sumInG = _twin_add_ARGB(sumInG, _src, 8, t2);
sumInB = _twin_add_ARGB(sumInB, _src, 16, t3);
for (int j = 0; j < radius - i; j++) {
sumR = _twin_add_ARGB(sumR, _src, 0, t1);
sumG = _twin_add_ARGB(sumG, _src, 8, t2);
sumB = _twin_add_ARGB(sumB, _src, 16, t3);
}
}

for (int cur = 0; cur < second_num; cur++) {
if (horiz_span) {
src_ptr = twin_pixmap_pointer(src_px, cur, first);
trg_ptr = twin_pixmap_pointer(trg_px, cur, first);
old_ptr =
twin_pixmap_pointer(src_px, max(cur - radius, 0), first);
new_ptr = twin_pixmap_pointer(
src_px, min(cur + radius, second_num - 1), first);
} else {
src_ptr = twin_pixmap_pointer(src_px, first, cur);
trg_ptr = twin_pixmap_pointer(trg_px, first, cur);
old_ptr =
twin_pixmap_pointer(src_px, first, max(cur - radius, 0));
new_ptr = twin_pixmap_pointer(
src_px, first, min(cur + radius, second_num - 1));
}
_cur = *src_ptr.argb32;
_old = *old_ptr.argb32;
_new = *new_ptr.argb32;
/* STEP 1 : sum_out + current */
sumOutR = _twin_add_ARGB(sumOutR, _cur, 0, t1);
sumOutG = _twin_add_ARGB(sumOutG, _cur, 8, t2);
sumOutB = _twin_add_ARGB(sumOutB, _cur, 16, t3);
/* STEP 2 : sum_in + new */
sumInR = _twin_add_ARGB(sumInR, _new, 0, t1);
sumInG = _twin_add_ARGB(sumInG, _new, 8, t2);
sumInB = _twin_add_ARGB(sumInB, _new, 16, t3);
/* STEP 3: sum + sum_in */
sumR = _twin_add(sumR, sumInR, t1);
sumG = _twin_add(sumG, sumInG, t2);
sumB = _twin_add(sumB, sumInB, t3);
/* STEP 4 : sum / 9 */
*trg_ptr.argb32 =
(_twin_div(sumR, 0, t1) | _twin_div(sumG, 8, t2) |
_twin_div(sumB, 16, t3) | (*src_ptr.argb32 & 0xff000000));
/* STEP 5 : sum - sum_out */
sumR = _twin_sub(sumR, sumOutR, t1);
sumG = _twin_sub(sumG, sumOutG, t2);
sumB = _twin_sub(sumB, sumOutB, t3);
/* STEP 6 : sum_out - old */
sumOutR = _twin_sub_ARGB(sumOutR, _old, 0, t1);
sumOutG = _twin_sub_ARGB(sumOutG, _old, 8, t2);
sumOutB = _twin_sub_ARGB(sumOutB, _old, 16, t3);
/* STEP 7 : sum_in - source_current */
sumInR = _twin_sub_ARGB(sumInR, _cur, 0, t1);
sumInG = _twin_sub_ARGB(sumInG, _cur, 8, t2);
sumInB = _twin_sub_ARGB(sumInB, _cur, 16, t3);
}
}
}

void twin_stack_blur(twin_pixmap_t *px)
{
if (px->format != TWIN_ARGB32)
return;
twin_pixmap_t *tmp_px =
twin_pixmap_create(px->format, px->width, px->height);
memcpy(tmp_px->p.v, px->p.v,
px->width * px->height * twin_bytes_per_pixel(px->format));

twin_stack(tmp_px, px, true);
twin_stack(px, tmp_px, false);
twin_pixmap_destroy(tmp_px);
return;
}

/* FIXME: source clipping is busted */
static void _twin_composite_simple(twin_pixmap_t *dst,
twin_coord_t dst_x,
Expand Down Expand Up @@ -777,3 +912,41 @@ void twin_fill(twin_pixmap_t *dst,
(*op)(twin_pixmap_pointer(dst, left, iy), src, right - left);
twin_pixmap_damage(dst, left, top, right, bottom);
}

void twin_glass_fill(twin_pixmap_t *dst,
twin_argb32_t pixel,
twin_operator_t operator,
twin_coord_t left,
twin_coord_t top,
twin_coord_t right,
twin_coord_t bottom)
{
twin_src_op op;
twin_source_u src;
twin_coord_t iy, ix;

/* offset */
left += dst->origin_x;
top += dst->origin_y;
right += dst->origin_x;
bottom += dst->origin_y;

/* clip */
if (left < dst->clip.left)
left = dst->clip.left;
if (right > dst->clip.right)
right = dst->clip.right;
if (top < dst->clip.top)
top = dst->clip.top;
if (bottom > dst->clip.bottom)
bottom = dst->clip.bottom;
if (left >= right || top >= bottom)
return;

src.c = pixel;
op = fill[operator][dst->format];

for (iy = 0; iy < dst->height; iy++)
for (ix = 0; ix < dst->width; ix++)
(*op)(twin_pixmap_pointer(dst, ix, iy), src, 1);
}
1 change: 1 addition & 0 deletions src/pixmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ twin_pixmap_t *twin_pixmap_create(twin_format_t format,
pixmap->stride = stride;
pixmap->disable = 0;
pixmap->animation = NULL;
pixmap->shadow = false;
pixmap->p.v = pixmap + 1;
memset(pixmap->p.v, '\0', space);
return pixmap;
Expand Down
8 changes: 5 additions & 3 deletions src/screen.c
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,8 @@ bool twin_screen_dispatch(twin_screen_t *screen, twin_event_t *event)
evt = *event;
evt.kind = TwinEventLeave;
_twin_adj_mouse_evt(&evt, pixmap);
twin_pixmap_dispatch(pixmap, &evt);
if (!pixmap->shadow)
twin_pixmap_dispatch(pixmap, &evt);
}

pixmap = screen->target = ntarget;
Expand All @@ -365,7 +366,8 @@ bool twin_screen_dispatch(twin_screen_t *screen, twin_event_t *event)
evt = *event;
_twin_adj_mouse_evt(&evt, pixmap);
evt.kind = TwinEventEnter;
twin_pixmap_dispatch(pixmap, &evt);
if (!pixmap->shadow)
twin_pixmap_dispatch(pixmap, &evt);
}
}

Expand All @@ -389,7 +391,7 @@ bool twin_screen_dispatch(twin_screen_t *screen, twin_event_t *event)
pixmap = NULL;
break;
}
if (pixmap)
if (pixmap && !pixmap->shadow)
return twin_pixmap_dispatch(pixmap, event);
return false;
}
2 changes: 1 addition & 1 deletion src/toplevel.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ twin_toplevel_t *twin_toplevel_create(twin_screen_t *screen,
{
twin_toplevel_t *toplevel;
twin_window_t *window =
twin_window_create(screen, format, style, x, y, width, height);
twin_window_create(screen, format, style, x, y, width, height, false);

if (!window)
return NULL;
Expand Down
Loading

0 comments on commit 5dda144

Please sign in to comment.