fix(blur): blur based on device scaling factor

This commit is contained in:
Jeremy Attali 2020-06-11 23:45:17 -04:00
parent 46fb08dce1
commit 1699474c39
3 changed files with 48 additions and 14 deletions

View File

@ -14,6 +14,13 @@
#include "swappy.h"
#include "wayland.h"
static void on_area_size_allocate(GtkWidget *area, struct swappy_state *state) {
GtkAllocation *alloc = g_new(GtkAllocation, 1);
gtk_widget_get_allocation(area, alloc);
g_info("size of area to render: %ux%u", alloc->width, alloc->height);
g_free(alloc);
}
static void update_ui_undo_redo(struct swappy_state *state) {
GtkWidget *undo = GTK_WIDGET(state->ui->undo);
GtkWidget *redo = GTK_WIDGET(state->ui->redo);
@ -567,7 +574,7 @@ static void compute_window_size(struct swappy_state *state) {
GdkDisplay *display = gdk_display_get_default();
GdkWindow *window = gtk_widget_get_window(GTK_WIDGET(state->ui->window));
GdkMonitor *monitor = gdk_display_get_monitor_at_window(display, window);
gint scaling_factor = gdk_monitor_get_scale_factor(monitor);
gint scaling_factor = gdk_window_get_scale_factor(window);
gdk_monitor_get_workarea(monitor, &workarea);
g_info("scale_factor: %d", scaling_factor);
g_info("size of monitor at window: %ux%u", workarea.width, workarea.height);
@ -680,6 +687,9 @@ static bool load_layout(struct swappy_state *state) {
state->ui->area = area;
state->ui->window = window;
g_signal_connect(area, "size-allocate", G_CALLBACK(on_area_size_allocate),
state);
compute_window_size(state);
gtk_widget_set_size_request(area, state->window->width,

View File

@ -69,6 +69,8 @@ void paint_add_temporary(struct swappy_state *state, double x, double y,
paint->type = type;
paint->is_committed = false;
g_debug("adding temporary paint at: %.2lfx%.2lf", x, y);
if (state->temp_paint) {
if (type == SWAPPY_PAINT_MODE_TEXT) {
paint_commit_temporary(state);

View File

@ -27,13 +27,19 @@ static cairo_surface_t *blur_surface(cairo_surface_t *surface, double x,
int i, j, k;
const int size = (int)blur_level * 2 + 1;
const int half = size / 2;
const double offset_y = 10.0;
// const double offset_y = 10.0;
gdouble scale_x, scale_y;
guint sum;
if (cairo_surface_status(surface)) {
return NULL;
}
cairo_surface_get_device_scale(surface, &scale_x, &scale_y);
g_debug("blurring surface at: %.2lf, %.2lf (%.2lfx%.2lf)", x, y, width,
height);
cairo_format_t src_format = cairo_image_surface_get_format(surface);
switch (src_format) {
case CAIRO_FORMAT_A1:
@ -51,12 +57,17 @@ static cairo_surface_t *blur_surface(cairo_surface_t *surface, double x,
src_width = cairo_image_surface_get_width(surface);
src_height = cairo_image_surface_get_height(surface);
g_debug("src surface (%dx%d)", src_width, src_height);
g_assert(src_height >= height);
g_assert(src_width >= width);
dest_surface = cairo_image_surface_create(src_format, src_width, src_height);
tmp_surface = cairo_image_surface_create(src_format, src_width, src_height);
cairo_surface_set_device_scale(dest_surface, scale_x, scale_y);
cairo_surface_set_device_scale(tmp_surface, scale_x, scale_y);
if (cairo_surface_status(dest_surface) || cairo_surface_status(tmp_surface)) {
return NULL;
}
@ -77,11 +88,16 @@ static cairo_surface_t *blur_surface(cairo_surface_t *surface, double x,
struct gaussian_kernel *gaussian = gaussian_kernel(4, 3.1);
int start_x = CLAMP(x, 0, src_width);
int start_y = CLAMP(y - offset_y, 0, src_height);
int start_x = CLAMP(x * scale_x, 0, src_width);
// int start_y = CLAMP(y - offset_y, 0, src_height;
int start_y = CLAMP(y * scale_y, 0, src_height);
int end_x = CLAMP(x + width, 0, src_width);
int end_y = CLAMP(y + height + offset_y, 0, src_height);
int end_x = CLAMP((x + width) * scale_x, 0, src_width);
// int end_y = CLAMP(y + height + offset_y, 0, src_height);
int end_y = CLAMP((y + height) * scale_y, 0, src_height);
g_debug("blurring happening from: %d, %d to: %d, %d", start_x, start_y, end_x,
end_y);
sum = (guint)gaussian->sum;
@ -138,7 +154,8 @@ static cairo_surface_t *blur_surface(cairo_surface_t *surface, double x,
// Mark destination surface as dirty since it was altered with custom data.
cairo_surface_mark_dirty(dest_surface);
cairo_surface_t *final =
cairo_image_surface_create(src_format, (int)width, (int)height);
cairo_image_surface_create(src_format, (int)(width * scale_x), (int)(height * scale_y));
cairo_surface_set_device_scale(final, scale_x, scale_y);
cr = cairo_create(final);
cairo_set_source_surface(cr, dest_surface, -x, -y);
cairo_paint(cr);
@ -328,6 +345,8 @@ static void render_buffers(cairo_t *cr, struct swappy_state *state) {
double sx = (double)state->window->width / state->geometry->width;
double sy = (double)state->window->height / state->geometry->height;
// g_debug("scaling cairo context: (%.2lf, %.2lf)", sx, sy);
cairo_scale(cr, sx, sy);
for (GList *elem = state->patterns; elem; elem = elem->prev) {
@ -344,12 +363,16 @@ static void render_background(cairo_t *cr, struct swappy_state *state) {
cairo_paint(cr);
}
static void render_blur(cairo_t *cr, struct swappy_paint *paint,
gint scaling_factor) {
static void render_blur(cairo_t *cr, struct swappy_paint *paint) {
struct swappy_paint_blur blur = paint->content.blur;
cairo_surface_t *target = cairo_get_target(cr);
double a, b;
cairo_surface_get_device_scale(target, &a, &b);
g_debug("cairo surface device scale: %.2lf, %.2lf", a, b);
double x = MIN(blur.from.x, blur.to.x);
double y = MIN(blur.from.y, blur.to.y);
double w = ABS(blur.from.x - blur.to.x);
@ -414,14 +437,13 @@ static void render_brush(cairo_t *cr, struct swappy_paint_brush brush) {
}
}
static void render_paint(cairo_t *cr, struct swappy_paint *paint,
gint scaling_factor) {
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, scaling_factor);
render_blur(cr, paint);
break;
case SWAPPY_PAINT_MODE_BRUSH:
render_brush(cr, paint->content.brush);
@ -443,11 +465,11 @@ static void render_paint(cairo_t *cr, struct swappy_paint *paint,
static void render_paints(cairo_t *cr, struct swappy_state *state) {
for (GList *elem = g_list_last(state->paints); elem; elem = elem->prev) {
struct swappy_paint *paint = elem->data;
render_paint(cr, paint, state->scaling_factor);
render_paint(cr, paint);
}
if (state->temp_paint) {
render_paint(cr, state->temp_paint, state->scaling_factor);
render_paint(cr, state->temp_paint);
}
}