diff --git a/README.md b/README.md
index ebf757f..9eb462e 100644
--- a/README.md
+++ b/README.md
@@ -59,12 +59,14 @@ The following lines can be used as swappy's default:
```
[Default]
save_dir=$HOME/Desktop
+ blur_level=80
line_size=5
text_size=20
text_font=sans-serif
```
- `save_dir` is where swappshots will be saved, can contain env variables and must exist in your filesystem
+- `blur_level` is the default blur level (must be between 1 and 500)
- `line_size` is the default line size (must be between 1 and 50)
- `text_size` is the default text size (must be between 10 and 50)
- `text_font` is the font used to render text, its format is pango friendly
diff --git a/include/application.h b/include/application.h
index 3a162c5..4f63aa2 100644
--- a/include/application.h
+++ b/include/application.h
@@ -27,11 +27,9 @@ void draw_area_button_release_handler(GtkWidget *widget, GdkEventButton *event,
void draw_area_motion_notify_handler(GtkWidget *widget, GdkEventMotion *event,
struct swappy_state *state);
-void blur_radius_decrease_handler(GtkWidget *widget,
- struct swappy_state *state);
-void blur_radius_increase_handler(GtkWidget *widget,
- struct swappy_state *state);
-void blur_radius_reset_handler(GtkWidget *widget, struct swappy_state *state);
+void blur_level_decrease_handler(GtkWidget *widget, struct swappy_state *state);
+void blur_level_increase_handler(GtkWidget *widget, struct swappy_state *state);
+void blur_level_reset_handler(GtkWidget *widget, struct swappy_state *state);
void brush_clicked_handler(GtkWidget *widget, struct swappy_state *state);
void text_clicked_handler(GtkWidget *widget, struct swappy_state *state);
diff --git a/include/config.h b/include/config.h
index 841443d..78e31b3 100644
--- a/include/config.h
+++ b/include/config.h
@@ -1,6 +1,6 @@
#include "swappy.h"
-#define CONFIG_BLUR_RADIUS_DEFAULT 15
+#define CONFIG_BLUR_LEVEL_DEFAULT 80
#define CONFIG_LINE_SIZE_DEFAULT 5
#define CONFIG_TEXT_FONT_DEFAULT "sans-serif"
#define CONFIG_TEXT_SIZE_DEFAULT 20
diff --git a/include/swappy.h b/include/swappy.h
index bbb9864..a244da6 100644
--- a/include/swappy.h
+++ b/include/swappy.h
@@ -19,8 +19,8 @@
#define SWAPPY_LINE_SIZE_MIN 1
#define SWAPPY_LINE_SIZE_MAX 50
-#define SWAPPY_BLUR_RADIUS_MIN 1
-#define SWAPPY_BLUR_RADIUS_MAX 50
+#define SWAPPY_BLUR_LEVEL_MIN 1
+#define SWAPPY_BLUR_LEVEL_MAX 500
#define SWAPPY_TEXT_SIZE_MIN 10
#define SWAPPY_TEXT_SIZE_MAX 50
@@ -79,13 +79,15 @@ struct swappy_paint_brush {
};
struct swappy_paint_blur {
- double radius;
- GList *points;
+ double bluriness;
+ struct swappy_point from;
+ struct swappy_point to;
};
struct swappy_paint {
enum swappy_paint_type type;
bool can_draw;
+ bool is_committed;
union {
struct swappy_paint_brush brush;
struct swappy_paint_shape shape;
@@ -108,7 +110,7 @@ struct swappy_state_settings {
double a;
double w;
double t;
- guint32 blur_radius;
+ guint32 blur_level;
};
struct swappy_state_ui {
@@ -134,7 +136,7 @@ struct swappy_state_ui {
GtkRadioButton *custom;
GtkColorButton *color;
- GtkButton *blur_radius;
+ GtkButton *blur_level;
GtkButton *line_size;
GtkButton *text_size;
};
@@ -186,7 +188,7 @@ struct swappy_config {
char *save_dir;
guint32 line_size;
guint32 text_size;
- guint32 blur_radius;
+ guint32 blur_level;
char *text_font;
};
diff --git a/res/swappy.ui b/res/swappy.ui
index 3f4580d..b115723 100644
--- a/res/swappy.ui
+++ b/res/swappy.ui
@@ -701,7 +701,7 @@
False
@@ -716,7 +716,7 @@
True
zoom-out2
True
-
+
False
@@ -730,7 +730,7 @@
False
True
True
-
+
False
@@ -745,7 +745,7 @@
True
zoom-in2
True
-
+
False
diff --git a/src/application.c b/src/application.c
index c8c058a..51e442c 100644
--- a/src/application.c
+++ b/src/application.c
@@ -23,10 +23,10 @@ static void update_ui_undo_redo(struct swappy_state *state) {
gtk_widget_set_sensitive(redo, redo_sensitive);
}
-static void update_ui_blur_radius_widget(struct swappy_state *state) {
- GtkButton *button = GTK_BUTTON(state->ui->blur_radius);
+static void update_ui_blur_level_widget(struct swappy_state *state) {
+ GtkButton *button = GTK_BUTTON(state->ui->blur_level);
char label[255];
- snprintf(label, 255, "%u", state->settings.blur_radius);
+ snprintf(label, 255, "%u", state->settings.blur_level);
gtk_button_set_label(button, label);
}
@@ -123,31 +123,31 @@ static void switch_mode_to_blur(struct swappy_state *state) {
state->mode = SWAPPY_PAINT_MODE_BLUR;
}
-static void action_blur_radius_decrease(struct swappy_state *state) {
- guint step = state->settings.blur_radius <= 10 ? 1 : 5;
+static void action_blur_level_decrease(struct swappy_state *state) {
+ guint step = state->settings.blur_level <= 50 ? 5 : 10;
- state->settings.blur_radius -= step;
+ state->settings.blur_level -= step;
- if (state->settings.blur_radius < SWAPPY_BLUR_RADIUS_MIN) {
- state->settings.blur_radius = SWAPPY_BLUR_RADIUS_MIN;
+ if (state->settings.blur_level < SWAPPY_BLUR_LEVEL_MIN) {
+ state->settings.blur_level = SWAPPY_BLUR_LEVEL_MIN;
}
- update_ui_blur_radius_widget(state);
+ update_ui_blur_level_widget(state);
}
-static void action_blur_radius_increase(struct swappy_state *state) {
- guint step = state->settings.blur_radius >= 10 ? 5 : 1;
- state->settings.blur_radius += step;
+static void action_blur_level_increase(struct swappy_state *state) {
+ guint step = state->settings.blur_level >= 50 ? 10 : 5;
+ state->settings.blur_level += step;
- if (state->settings.blur_radius > SWAPPY_BLUR_RADIUS_MAX) {
- state->settings.blur_radius = SWAPPY_BLUR_RADIUS_MAX;
+ if (state->settings.blur_level > SWAPPY_BLUR_LEVEL_MAX) {
+ state->settings.blur_level = SWAPPY_BLUR_LEVEL_MAX;
}
- update_ui_blur_radius_widget(state);
+ update_ui_blur_level_widget(state);
}
-static void action_blur_radius_reset(struct swappy_state *state) {
- state->settings.blur_radius = state->config->blur_radius;
+static void action_blur_level_reset(struct swappy_state *state) {
+ state->settings.blur_level = state->config->blur_level;
- update_ui_blur_radius_widget(state);
+ update_ui_blur_level_widget(state);
}
static void action_stroke_size_decrease(struct swappy_state *state) {
@@ -496,17 +496,17 @@ void draw_area_button_release_handler(GtkWidget *widget, GdkEventButton *event,
}
}
-void blur_radius_decrease_handler(GtkWidget *widget,
- struct swappy_state *state) {
- action_blur_radius_decrease(state);
+void blur_level_decrease_handler(GtkWidget *widget,
+ struct swappy_state *state) {
+ action_blur_level_decrease(state);
}
-void blur_radius_increase_handler(GtkWidget *widget,
- struct swappy_state *state) {
- action_blur_radius_increase(state);
+void blur_level_increase_handler(GtkWidget *widget,
+ struct swappy_state *state) {
+ action_blur_level_increase(state);
}
-void blur_radius_reset_handler(GtkWidget *widget, struct swappy_state *state) {
- action_blur_radius_reset(state);
+void blur_level_reset_handler(GtkWidget *widget, struct swappy_state *state) {
+ action_blur_level_reset(state);
}
void color_red_clicked_handler(GtkWidget *widget, struct swappy_state *state) {
@@ -654,7 +654,7 @@ static bool load_layout(struct swappy_state *state) {
state->ui->color =
GTK_COLOR_BUTTON(gtk_builder_get_object(builder, "custom-color-button"));
- state->ui->blur_radius =
+ state->ui->blur_level =
GTK_BUTTON(gtk_builder_get_object(builder, "blur-radius-button"));
state->ui->line_size =
GTK_BUTTON(gtk_builder_get_object(builder, "stroke-size-button"));
@@ -694,7 +694,7 @@ static bool init_gtk_window(struct swappy_state *state) {
return false;
}
- update_ui_blur_radius_widget(state);
+ update_ui_blur_level_widget(state);
update_ui_stroke_size_widget(state);
update_ui_text_size_widget(state);
update_ui_undo_redo(state);
@@ -721,7 +721,7 @@ static void init_settings(struct swappy_state *state) {
state->settings.a = 1;
state->settings.w = state->config->line_size;
state->settings.t = state->config->text_size;
- state->settings.blur_radius = state->config->blur_radius;
+ state->settings.blur_level = state->config->blur_level;
}
static gint command_line_handler(GtkApplication *app,
diff --git a/src/config.c b/src/config.c
index 6f038cb..3fdaea8 100644
--- a/src/config.c
+++ b/src/config.c
@@ -13,7 +13,7 @@ static void print_config(struct swappy_config *config) {
g_info("printing config:");
g_info("config_dir: %s", config->config_file);
g_info("save_dir: %s", config->save_dir);
- g_info("blur_radius: %d", config->blur_radius);
+ g_info("blur_level: %d", config->blur_level);
g_info("line_size: %d", config->line_size);
g_info("text_font: %s", config->text_font);
g_info("text_size: %d", config->text_size);
@@ -69,7 +69,7 @@ static void load_config_from_file(struct swappy_config *config,
const gchar *group = "Default";
gchar *save_dir = NULL;
gchar *save_dir_expanded = NULL;
- guint64 line_size, text_size, blur_radius;
+ guint64 line_size, text_size, blur_level;
gchar *text_font = NULL;
GError *error = NULL;
@@ -140,19 +140,19 @@ static void load_config_from_file(struct swappy_config *config,
error = NULL;
}
- blur_radius = g_key_file_get_uint64(gkf, group, "blur_radius", &error);
+ blur_level = g_key_file_get_uint64(gkf, group, "blur_level", &error);
if (error == NULL) {
- if (blur_radius >= SWAPPY_BLUR_RADIUS_MIN &&
- blur_radius <= SWAPPY_BLUR_RADIUS_MAX) {
- config->blur_radius = blur_radius;
+ if (blur_level >= SWAPPY_BLUR_LEVEL_MIN &&
+ blur_level <= SWAPPY_BLUR_LEVEL_MAX) {
+ config->blur_level = blur_level;
} else {
g_warning(
- "blur_radius is not a valid value: %ld - see man page for details",
- blur_radius);
+ "blur_level is not a valid value: %ld - see man page for details",
+ blur_level);
}
} else {
- g_info("blur_radius is missing in %s (%s)", file, error->message);
+ g_info("blur_level is missing in %s (%s)", file, error->message);
g_error_free(error);
error = NULL;
}
@@ -177,7 +177,7 @@ static void load_default_config(struct swappy_config *config) {
}
config->save_dir = get_default_save_dir();
- config->blur_radius = CONFIG_BLUR_RADIUS_DEFAULT;
+ config->blur_level = CONFIG_BLUR_LEVEL_DEFAULT;
config->line_size = CONFIG_LINE_SIZE_DEFAULT;
config->text_font = g_strdup(CONFIG_TEXT_FONT_DEFAULT);
config->text_size = CONFIG_TEXT_SIZE_DEFAULT;
diff --git a/src/paint.c b/src/paint.c
index e4e047d..1f39323 100644
--- a/src/paint.c
+++ b/src/paint.c
@@ -23,7 +23,6 @@ void paint_free(gpointer data) {
switch (paint->type) {
case SWAPPY_PAINT_MODE_BLUR:
- g_list_free_full(paint->content.blur.points, g_free);
break;
case SWAPPY_PAINT_MODE_BRUSH:
g_list_free_full(paint->content.brush.points, g_free);
@@ -65,6 +64,7 @@ void paint_add_temporary(struct swappy_state *state, double x, double y,
double t = state->settings.t;
paint->type = type;
+ paint->is_committed = false;
if (state->temp_paint) {
if (type == SWAPPY_PAINT_MODE_TEXT) {
@@ -77,14 +77,11 @@ void paint_add_temporary(struct swappy_state *state, double x, double y,
switch (type) {
case SWAPPY_PAINT_MODE_BLUR:
- paint->can_draw = true;
-
- paint->content.blur.radius = state->settings.blur_radius;
- point = g_new(struct swappy_point, 1);
- point->x = x;
- point->y = y;
+ paint->can_draw = false;
- paint->content.blur.points = g_list_prepend(NULL, point);
+ paint->content.blur.bluriness = state->settings.blur_level;
+ paint->content.blur.from.x = x;
+ paint->content.blur.from.y = y;
break;
case SWAPPY_PAINT_MODE_BRUSH:
paint->can_draw = true;
@@ -152,12 +149,9 @@ void paint_update_temporary_shape(struct swappy_state *state, double x,
switch (paint->type) {
case SWAPPY_PAINT_MODE_BLUR:
- points = paint->content.blur.points;
- point = g_new(struct swappy_point, 1);
- point->x = x;
- point->y = y;
-
- paint->content.blur.points = g_list_prepend(points, point);
+ paint->can_draw = true;
+ paint->content.blur.to.x = x;
+ paint->content.blur.to.y = y;
break;
case SWAPPY_PAINT_MODE_BRUSH:
points = paint->content.brush.points;
@@ -267,6 +261,7 @@ void paint_commit_temporary(struct swappy_state *state) {
if (!paint->can_draw) {
paint_free(paint);
} else {
+ paint->is_committed = true;
state->paints = g_list_prepend(state->paints, paint);
}
diff --git a/src/render.c b/src/render.c
index 20a4b92..162bf45 100644
--- a/src/render.c
+++ b/src/render.c
@@ -18,19 +18,11 @@
#define ARRAY_LENGTH(a) (sizeof(a) / sizeof(a)[0])
-static gboolean is_point_within_circle(struct swappy_point *point,
- struct swappy_point *center,
- guint32 radius) {
- return pow(point->x - center->x, 2) + pow(point->y - center->y, 2) <
- pow(radius, 2);
-}
-
/*
* This code was largely taken from Kristian Høgsberg and Chris Wilson from:
* https://www.cairographics.org/cookbook/blur.c/
*/
-static void blur_image_surface_at_point(cairo_t *cr, int radius,
- struct swappy_point *point) {
+static void blur_paint(cairo_t *cr, struct swappy_paint_blur *blur) {
cairo_surface_t *tmp;
int width, height;
int src_stride, dst_stride;
@@ -41,7 +33,9 @@ static void blur_image_surface_at_point(cairo_t *cr, int radius,
uint8_t kernel[17];
const int size = ARRAY_LENGTH(kernel);
const int half = size / 2;
- const int radius_extra = radius * 1.5;
+ double bluriness = blur->bluriness;
+ struct swappy_point from = blur->from;
+ struct swappy_point to = blur->to;
cairo_surface_t *surface = cairo_get_target(cr);
@@ -76,25 +70,28 @@ static void blur_image_surface_at_point(cairo_t *cr, int radius,
src = cairo_image_surface_get_data(surface);
src_stride = cairo_image_surface_get_stride(surface);
+ g_debug("sizeof(src): %lu", sizeof(src));
+ g_debug("width*height*stride: %d", width * height * src_stride);
+
dst = cairo_image_surface_get_data(tmp);
dst_stride = cairo_image_surface_get_stride(tmp);
a = 0;
for (i = 0; i < size; i++) {
double f = i - half;
- a += kernel[i] = exp(-f * f / 30.0) * 160;
+ a += kernel[i] = exp(-f * f / bluriness) * 80;
}
- int start_x = fmax(point->x - radius_extra, 0);
- int start_y = fmax(point->y - radius_extra, 0);
+ int start_x = fmax(fmin(from.x, to.x), 0);
+ int start_y = fmax(fmin(from.y, to.y), 0);
- int max_x = fmin(point->x + radius_extra, width);
- int max_y = fmin(point->y + radius_extra, height);
+ int max_x = fmin(fmax(from.x, to.x), width);
+ int max_y = fmin(fmax(from.y, to.y), height);
- for (i = start_y; i < max_y; i++) {
+ for (i = 0; i < height; i++) {
s = (uint32_t *)(src + i * src_stride);
d = (uint32_t *)(dst + i * dst_stride);
- for (j = start_x; j < max_x; j++) {
+ for (j = 0; j < width; j++) {
d[j] = s[j];
}
}
@@ -115,10 +112,7 @@ static void blur_image_surface_at_point(cairo_t *cr, int radius,
z += ((p >> 8) & 0xff) * kernel[k];
w += ((p >> 0) & 0xff) * kernel[k];
}
- struct swappy_point pixel = {.x = j, .y = i};
- if (is_point_within_circle(&pixel, point, radius)) {
- d[j] = (x / a << 24) | (y / a << 16) | (z / a << 8) | w / a;
- }
+ d[j] = (x / a << 24) | (y / a << 16) | (z / a << 8) | w / a;
}
}
@@ -141,10 +135,7 @@ static void blur_image_surface_at_point(cairo_t *cr, int radius,
z += ((p >> 8) & 0xff) * kernel[k];
w += ((p >> 0) & 0xff) * kernel[k];
}
- struct swappy_point pixel = {.x = j, .y = i};
- if (is_point_within_circle(&pixel, point, radius)) {
- d[j] = (x / a << 24) | (y / a << 16) | (z / a << 8) | w / a;
- }
+ d[j] = (x / a << 24) | (y / a << 16) | (z / a << 8) | w / a;
}
}
@@ -347,15 +338,23 @@ static void render_background(cairo_t *cr) {
cairo_paint(cr);
}
-static void render_blur(cairo_t *cr, struct swappy_paint_blur blur) {
- cairo_set_source_rgba(cr, 0, 0, 0, 1);
- cairo_set_line_width(cr, 1);
-
- for (GList *elem = blur.points; elem; elem = elem->next) {
- struct swappy_point *point = elem->data;
-
- blur_image_surface_at_point(cr, blur.radius, point);
+static void render_blur(cairo_t *cr, struct swappy_paint_blur blur,
+ bool is_committed) {
+ if (!is_committed) {
+ // Blur not committed yet, draw bounding rectangle
+ struct swappy_paint_shape rect = {
+ .r = 0,
+ .g = 0.5,
+ .b = 1,
+ .a = 0.5,
+ .w = 5,
+ .from = blur.from,
+ .to = blur.to,
+ .type = SWAPPY_PAINT_MODE_RECTANGLE,
+ };
+ render_shape_rectangle(cr, rect);
}
+ blur_paint(cr, &blur);
}
static void render_brush(cairo_t *cr, struct swappy_paint_brush brush) {
@@ -382,10 +381,9 @@ static void render_paint(cairo_t *cr, struct swappy_paint *paint) {
if (!paint->can_draw) {
return;
}
-
switch (paint->type) {
case SWAPPY_PAINT_MODE_BLUR:
- render_blur(cr, paint->content.blur);
+ render_blur(cr, paint->content.blur, paint->is_committed);
break;
case SWAPPY_PAINT_MODE_BRUSH:
render_brush(cr, paint->content.brush);
@@ -399,7 +397,7 @@ static void render_paint(cairo_t *cr, struct swappy_paint *paint) {
render_text(cr, paint->content.text);
break;
default:
- g_info("unable to draw paint with type: %d", paint->type);
+ g_info("unable to render paint with type: %d", paint->type);
break;
}
}
diff --git a/swappy.1.scd b/swappy.1.scd
index d92da06..71e5eac 100644
--- a/swappy.1.scd
+++ b/swappy.1.scd
@@ -62,14 +62,14 @@ The following lines can be used as swappy's default:
```
[Default]
save_dir=$HOME/Desktop
- blur_radius=15
+ blur_level=80
line_size=5
text_size=20
text_font=sans-serif
```
- *save_dir* is where swappshots will be saved, can contain env variables and must exist in your filesystem
-- *blur_raidus* is the default blur radius (must be between 1 and 50)
+- *blur_level* is the default blur level (must be between 1 and 500)
- *line_size* is the default line size (must be between 1 and 50)
- *text_size* is the default text size (must be between 10 and 50)
- *text_font* is the font used to render text, its format is pango friendly