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

Add the Gaussian function to blur a pixmap #58

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
55 changes: 50 additions & 5 deletions apps/multi.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@
#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 +39,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 +84,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 +127,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 +175,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 +221,49 @@ 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_window_set_name(window, "Test");
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,
screen->width, screen->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;
}

twin_stack_blur(window->pixmap, 5, window->client.left,
window->client.right, window->client.top,
window->client.bottom);
twin_window_show(window);
twin_pixmap_destroy(scaled_background);
}

void apps_multi_start(twin_screen_t *screen,
const char *name,
int x,
Expand All @@ -233,4 +277,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);
}
18 changes: 17 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,13 @@ void twin_fill(twin_pixmap_t *dst,

void twin_premultiply_alpha(twin_pixmap_t *px);

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);

/*
* event.c
*/
Expand Down Expand Up @@ -1121,14 +1134,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
147 changes: 147 additions & 0 deletions src/draw.c
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,153 @@ 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, 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)))

#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,
int radius,
int first_str,
int first_end,
int second_str,
int second_end,
bool horiz_span)
{
int den = (radius + 1) * (radius + 1);
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;
for (int first = first_str; first < first_end; first++) {
sumInR = sumOutR = sumR = sumInG = sumOutG = sumG = sumInB = sumOutB =
sumB = 0x00000000;

/* Initialize SumOut by padding */
if (horiz_span)
src_ptr = twin_pixmap_pointer(src_px, second_str, first);
else
src_ptr = twin_pixmap_pointer(src_px, first, second_str);
_src = *src_ptr.argb32;

for (int i = second_str; i < second_str + radius; i++) {
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 - second_str) + 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);
}
}

/* Initialize SumIn */
for (int i = second_str; i < second_str + 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 - second_str); 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 = second_str; cur < second_end; 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, second_str), first);
new_ptr = twin_pixmap_pointer(
src_px, min(cur + radius, second_end - 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, second_str));
new_ptr = twin_pixmap_pointer(
src_px, first, min(cur + radius, second_end - 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 / denominator */
*trg_ptr.argb32 =
(_twin_div(sumR, den, 0, t1) | _twin_div(sumG, den, 8, t2) |
_twin_div(sumB, den, 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 - 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,
int radius,
twin_coord_t left,
twin_coord_t right,
twin_coord_t top,
twin_coord_t bottom)
{
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, radius, top, bottom, left, right, true);
twin_stack(px, tmp_px, radius, left, right, top, bottom, 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
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