Skip to content

Commit

Permalink
fix(ui): compute window sizes and buffers properly
Browse files Browse the repository at this point in the history
Compute maximum width and height of area container based on monitor size
and fix image ratio based on appropriate values.

Note that this will lower the resolution of the final image.

Closes #56
  • Loading branch information
jtheoof committed Feb 15, 2021
1 parent 4a0eb82 commit b8380bb
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 130 deletions.
7 changes: 0 additions & 7 deletions include/buffer.h

This file was deleted.

3 changes: 3 additions & 0 deletions include/pixbuf.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@

#include "swappy.h"

GdkPixbuf *pixbuf_init_from_file(struct swappy_state *state);
GdkPixbuf *pixbuf_get_from_state(struct swappy_state *state);
void pixbuf_save_state_to_folder(GdkPixbuf *pixbuf, char *folder,
char *filename_format);
void pixbuf_save_to_file(GdkPixbuf *pixbuf, char *file);
void pixbuf_save_to_stdout(GdkPixbuf *pixbuf);
void pixbuf_scale_surface_from_widget(struct swappy_state *state,
GtkWidget *widget);
3 changes: 1 addition & 2 deletions include/swappy.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ struct swappy_state {
struct swappy_state_ui *ui;
struct swappy_config *config;

GdkPixbuf *original_image;
cairo_surface_t *original_image_surface;
cairo_surface_t *scaled_image_surface;
cairo_surface_t *rendered_surface;
Expand All @@ -165,8 +166,6 @@ struct swappy_state {
struct swappy_box *window;
struct swappy_box *geometry;

cairo_rectangle_int_t *drawing_area_rect;

GList *paints;
GList *redo_paints;
struct swappy_paint *temp_paint;
Expand Down
1 change: 0 additions & 1 deletion meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ executable(
'src/main.c',
'src/algebra.c',
'src/application.c',
'src/buffer.c',
'src/box.c',
'src/config.c',
'src/clipboard.c',
Expand Down
60 changes: 34 additions & 26 deletions src/application.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#include <stdio.h>
#include <time.h>

#include "buffer.h"
#include "clipboard.h"
#include "config.h"
#include "file.h"
Expand Down Expand Up @@ -231,8 +230,6 @@ void blur_clicked_handler(GtkWidget *widget, struct swappy_state *state) {

void application_finish(struct swappy_state *state) {
paint_free_all(state);
buffer_free_all(state);
g_free(state->drawing_area_rect);
cairo_surface_destroy(state->rendered_surface);
cairo_surface_destroy(state->original_image_surface);
cairo_surface_destroy(state->scaled_image_surface);
Expand All @@ -247,6 +244,7 @@ void application_finish(struct swappy_state *state) {
g_free(state->geometry);
g_free(state->window);
g_free(state->ui);
g_object_unref(state->original_image);
g_object_unref(state->app);

config_free(state);
Expand Down Expand Up @@ -394,27 +392,21 @@ gboolean draw_area_handler(GtkWidget *widget, cairo_t *cr,
gboolean draw_area_configure_handler(GtkWidget *widget,
GdkEventConfigure *event,
struct swappy_state *state) {
g_debug("received configure_event handler");
g_debug("received configure_event callback");
cairo_surface_destroy(state->rendered_surface);
g_free(state->drawing_area_rect);

cairo_surface_t *surface = gdk_window_create_similar_surface(
gtk_widget_get_window(widget), CAIRO_CONTENT_COLOR_ALPHA,
gtk_widget_get_allocated_width(widget),
gtk_widget_get_allocated_height(widget));

state->rendered_surface = surface;
g_info("size of drawing area surface: %ux%u",
cairo_image_surface_get_width(surface),
cairo_image_surface_get_height(surface));

GtkAllocation *alloc = g_new(GtkAllocation, 1);
gtk_widget_get_allocation(widget, alloc);
state->drawing_area_rect = alloc;
buffer_resize_patterns(state);
state->rendered_surface = surface;

g_info("size of cairo_surface: %ux%u with type: %d",
cairo_image_surface_get_width(surface),
cairo_image_surface_get_height(surface),
cairo_image_surface_get_format(surface));
g_info("size of area to render: %ux%u", alloc->width, alloc->height);
pixbuf_scale_surface_from_widget(state, widget);

render_state(state);

Expand Down Expand Up @@ -562,18 +554,34 @@ static void compute_window_size(struct swappy_state *state) {
state->window->y = workarea.y;

double threshold = 0.75;
double scaling = 1.0;

if (state->geometry->width > workarea.width * threshold) {
scaling = workarea.width * threshold / state->geometry->width;
} else if (state->geometry->height > workarea.height * threshold) {
scaling = workarea.height * threshold / state->geometry->height;
}
int image_width = gdk_pixbuf_get_width(state->original_image);
int image_height = gdk_pixbuf_get_height(state->original_image);

state->window->width = state->geometry->width * scaling;
state->window->height = state->geometry->height * scaling;
int max_width = workarea.width * threshold;
int max_height = workarea.height * threshold;

g_info("size of image: %ux%u", image_width, image_height);
g_info("size of monitor at window: %ux%u", workarea.width, workarea.height);
g_info("maxium size allowed for window: %ux%u", max_width, max_height);

int scaled_width = image_width;
int scaled_height = image_height;

double scaling_factor_width = (double)max_width / image_width;
double scaling_factor_height = (double)max_height / image_height;

if (scaling_factor_height < 1.0 || scaling_factor_width < 1.0) {
double scaling_factor = MIN(scaling_factor_width, scaling_factor_height);
scaled_width = image_width * scaling_factor;
scaled_height = image_height * scaling_factor;
g_info("rendering area will be scaled by a factor of: %.2lf",
scaling_factor);
}

state->window->width = scaled_width;
state->window->height = scaled_height;

g_info("size of window to render: %ux%u", state->window->width,
state->window->height);
}
Expand Down Expand Up @@ -675,8 +683,8 @@ static bool load_layout(struct swappy_state *state) {
}

static bool init_gtk_window(struct swappy_state *state) {
if (!state->geometry) {
g_critical("no geometry found, did you use -f option?");
if (!state->original_image) {
g_critical("original image not loaded");
return false;
}

Expand Down Expand Up @@ -725,7 +733,7 @@ static gint command_line_handler(GtkApplication *app,
state->temp_file_str = temp_file_str;
}

if (!buffer_init_from_file(state)) {
if (!pixbuf_init_from_file(state)) {
return EXIT_FAILURE;
}
}
Expand Down
94 changes: 0 additions & 94 deletions src/buffer.c

This file was deleted.

55 changes: 55 additions & 0 deletions src/pixbuf.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,65 @@ void pixbuf_save_to_stdout(GdkPixbuf *pixbuf) {
g_object_unref(out);
}

GdkPixbuf *pixbuf_init_from_file(struct swappy_state *state) {
GError *error = NULL;
char *file =
state->temp_file_str != NULL ? state->temp_file_str : state->file_str;
GdkPixbuf *image = gdk_pixbuf_new_from_file(file, &error);

if (error != NULL) {
g_error("unable to load file: %s - reason: %s", file, error->message);
return NULL;
}

state->original_image = image;
return image;
}

void pixbuf_save_to_file(GdkPixbuf *pixbuf, char *file) {
if (g_strcmp0(file, "-") == 0) {
pixbuf_save_to_stdout(pixbuf);
} else {
write_file(pixbuf, file);
}
}

void pixbuf_scale_surface_from_widget(struct swappy_state *state,
GtkWidget *widget) {
GtkAllocation *alloc = g_new(GtkAllocation, 1);
GdkPixbuf *image = state->original_image;
gtk_widget_get_allocation(widget, alloc);

gboolean has_alpha = gdk_pixbuf_get_has_alpha(image);
cairo_format_t format = has_alpha ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24;
gint image_width = gdk_pixbuf_get_width(image);
gint image_height = gdk_pixbuf_get_height(image);
cairo_surface_t *surface =
cairo_image_surface_create(format, image_width, image_height);

if (!surface) {
g_error("unable to create cairo surface from pixbuf");
goto cleanup;
} else {
cairo_t *cr;
cr = cairo_create(surface);
double scale_x = (double)alloc->width / image_width;
double scale_y = (double)alloc->height / image_height;
g_info("image scaled on x,y: %.2lf,%.2lf", scale_x, scale_y);
cairo_scale(cr, scale_x, scale_y);
gdk_cairo_set_source_pixbuf(cr, image, 0, 0);
cairo_paint(cr);
cairo_destroy(cr);
}

g_info("size of area to render: %ux%u", alloc->width, alloc->height);

if (state->scaled_image_surface) {
cairo_surface_destroy(state->scaled_image_surface);
state->scaled_image_surface = NULL;
}
state->scaled_image_surface = surface;

cleanup:
g_free(alloc);
}

0 comments on commit b8380bb

Please sign in to comment.