#include "image.h" #include "window.h" #include #include static GtkWidget *image; static GdkPixbuf *pixbuf; static GdkPixbuf *curr_pixbuf; static int pixbuf_width, pixbuf_height, curr_pixbuf_width, curr_pixbuf_height; static double aspect_ratio; static double curr_zoom; static enum scale_mode curr_scale_mod; static int loading = 0; static GFile *file; static GFileInputStream *is; static GError *error = NULL; GtkWidget *new_image() { image = gtk_image_new(); return image; } void pixbuf_load_callback(GObject *source_object, GAsyncResult *res, gpointer user_data) { if (pixbuf != NULL) g_object_unref(pixbuf); if (is != NULL) g_object_unref(is); pixbuf = gdk_pixbuf_new_from_stream_finish(res, &error); if (error != NULL) { loading = 0; g_printerr("%s\n", error->message); return; } curr_pixbuf_width = pixbuf_width = gdk_pixbuf_get_width(GDK_PIXBUF(pixbuf)); curr_pixbuf_height = pixbuf_height = gdk_pixbuf_get_height(GDK_PIXBUF(pixbuf)); aspect_ratio = (double)pixbuf_width / (double)pixbuf_height; fit_image(); set_window_title(g_file_get_basename(file), pixbuf_width, pixbuf_height); if (file != NULL) g_object_unref(file); loading = 0; } void file_read_callback(GObject *source_object, GAsyncResult *res, gpointer user_data) { is = g_file_read_finish(file, res, &error); if (error != NULL) { loading = 0; g_printerr("%s\n", error->message); return; } gdk_pixbuf_new_from_stream_async(G_INPUT_STREAM(is), NULL, &pixbuf_load_callback, NULL); } int load_image(char *file_name) { if (loading) return -1; loading = 1; file = g_file_new_for_path(file_name); g_file_read_async(file, G_PRIORITY_DEFAULT, NULL, &file_read_callback, NULL); curr_zoom = 1.0; return 0; } void update_pixbuf() { if (curr_pixbuf != NULL) g_object_unref(curr_pixbuf); if (pixbuf == NULL) return; curr_pixbuf = gdk_pixbuf_scale_simple(GDK_PIXBUF(pixbuf), curr_pixbuf_width, curr_pixbuf_height, GDK_INTERP_BILINEAR); gtk_image_set_from_pixbuf(GTK_IMAGE(image), GDK_PIXBUF(curr_pixbuf)); } void fit_image() { gint win_width, win_height; get_curr_win_size(&win_width, &win_height); curr_scale_mod = fit; if (pixbuf == NULL || win_width < 1 || win_height < 1) return; if (win_width < pixbuf_width && win_height >= pixbuf_height) { curr_pixbuf_width = win_width; curr_pixbuf_height = (double)curr_pixbuf_width / aspect_ratio; } else if (win_width >= pixbuf_width && win_height < pixbuf_height) { curr_pixbuf_height = win_height; curr_pixbuf_width = (double)curr_pixbuf_height * aspect_ratio; } else if (win_width < pixbuf_width && win_height < pixbuf_height) { if (((double)win_width / (double)win_height) > aspect_ratio) { curr_pixbuf_height = win_height; curr_pixbuf_width = ((double)curr_pixbuf_height * aspect_ratio); } else { curr_pixbuf_width = win_width; curr_pixbuf_height = (double)curr_pixbuf_width / aspect_ratio; } } else { curr_pixbuf_width = pixbuf_width; curr_pixbuf_height = pixbuf_height; } curr_zoom = (double)curr_pixbuf_width / (double)pixbuf_width; if (curr_pixbuf_width < 1 || curr_pixbuf_height < 1) return; update_pixbuf(); } void zoom(int type) { curr_scale_mod = zoomed; if (pixbuf == NULL) return; if (type == 0) { if (curr_zoom == 1.0) return; curr_zoom = 1.0; } else if (type < 0) { if (curr_zoom < 0.2) return; curr_zoom -= 0.1; } else if (type > 0) { if (curr_zoom > 2) return; curr_zoom += 0.1; } curr_pixbuf_width = curr_zoom * (double)pixbuf_width; curr_pixbuf_height = curr_zoom * (double)pixbuf_height; update_pixbuf(); } enum scale_mode get_current_scale_mode() { return curr_scale_mod; }