Add scaling to fit, make this the default
This commit is contained in:
parent
b8cc43eb91
commit
7d972e9334
102
fastiv-view.c
102
fastiv-view.c
|
@ -16,6 +16,7 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include "fastiv-io.h"
|
#include "fastiv-io.h"
|
||||||
#include "fastiv-view.h"
|
#include "fastiv-view.h"
|
||||||
|
@ -23,14 +24,14 @@
|
||||||
struct _FastivView {
|
struct _FastivView {
|
||||||
GtkWidget parent_instance;
|
GtkWidget parent_instance;
|
||||||
cairo_surface_t *surface;
|
cairo_surface_t *surface;
|
||||||
// TODO(p): Zoom-to-fit indication.
|
bool scale_to_fit;
|
||||||
double scale;
|
double scale;
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE(FastivView, fastiv_view, GTK_TYPE_WIDGET)
|
G_DEFINE_TYPE(FastivView, fastiv_view, GTK_TYPE_WIDGET)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
get_display_dimensions(FastivView *self, int *width, int *height)
|
get_surface_dimensions(FastivView *self, double *width, double *height)
|
||||||
{
|
{
|
||||||
*width = *height = 0;
|
*width = *height = 0;
|
||||||
if (!self->surface)
|
if (!self->surface)
|
||||||
|
@ -39,18 +40,27 @@ get_display_dimensions(FastivView *self, int *width, int *height)
|
||||||
cairo_rectangle_t extents = {};
|
cairo_rectangle_t extents = {};
|
||||||
switch (cairo_surface_get_type(self->surface)) {
|
switch (cairo_surface_get_type(self->surface)) {
|
||||||
case CAIRO_SURFACE_TYPE_IMAGE:
|
case CAIRO_SURFACE_TYPE_IMAGE:
|
||||||
extents.width = cairo_image_surface_get_width(self->surface);
|
*width = cairo_image_surface_get_width(self->surface);
|
||||||
extents.height = cairo_image_surface_get_height(self->surface);
|
*height = cairo_image_surface_get_height(self->surface);
|
||||||
break;
|
return;
|
||||||
case CAIRO_SURFACE_TYPE_RECORDING:
|
case CAIRO_SURFACE_TYPE_RECORDING:
|
||||||
(void) cairo_recording_surface_get_extents(self->surface, &extents);
|
(void) cairo_recording_surface_get_extents(self->surface, &extents);
|
||||||
break;
|
*width = extents.width;
|
||||||
|
*height = extents.height;
|
||||||
|
return;
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
*width = ceil(extents.width * self->scale);
|
static void
|
||||||
*height = ceil(extents.height * self->scale);
|
get_display_dimensions(FastivView *self, int *width, int *height)
|
||||||
|
{
|
||||||
|
double w, h;
|
||||||
|
get_surface_dimensions(self, &w, &h);
|
||||||
|
|
||||||
|
*width = ceil(w * self->scale);
|
||||||
|
*height = ceil(h * self->scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -66,17 +76,53 @@ static void
|
||||||
fastiv_view_get_preferred_height(
|
fastiv_view_get_preferred_height(
|
||||||
GtkWidget *widget, gint *minimum, gint *natural)
|
GtkWidget *widget, gint *minimum, gint *natural)
|
||||||
{
|
{
|
||||||
int width, height;
|
FastivView *self = FASTIV_VIEW(widget);
|
||||||
get_display_dimensions(FASTIV_VIEW(widget), &width, &height);
|
if (self->scale_to_fit) {
|
||||||
*minimum = *natural = height;
|
double sw, sh;
|
||||||
|
get_surface_dimensions(self, &sw, &sh);
|
||||||
|
*natural = ceil(sh);
|
||||||
|
*minimum = 1;
|
||||||
|
} else {
|
||||||
|
int dw, dh;
|
||||||
|
get_display_dimensions(self, &dw, &dh);
|
||||||
|
*minimum = *natural = dh;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fastiv_view_get_preferred_width(GtkWidget *widget, gint *minimum, gint *natural)
|
fastiv_view_get_preferred_width(GtkWidget *widget, gint *minimum, gint *natural)
|
||||||
{
|
{
|
||||||
int width, height;
|
FastivView *self = FASTIV_VIEW(widget);
|
||||||
get_display_dimensions(FASTIV_VIEW(widget), &width, &height);
|
if (self->scale_to_fit) {
|
||||||
*minimum = *natural = width;
|
double sw, sh;
|
||||||
|
get_surface_dimensions(self, &sw, &sh);
|
||||||
|
*natural = ceil(sw);
|
||||||
|
*minimum = 1;
|
||||||
|
} else {
|
||||||
|
int dw, dh;
|
||||||
|
get_display_dimensions(self, &dw, &dh);
|
||||||
|
*minimum = *natural = dw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fastiv_view_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
|
||||||
|
{
|
||||||
|
GTK_WIDGET_CLASS(fastiv_view_parent_class)
|
||||||
|
->size_allocate(widget, allocation);
|
||||||
|
|
||||||
|
FastivView *self = FASTIV_VIEW(widget);
|
||||||
|
if (!self->surface || !self->scale_to_fit)
|
||||||
|
return;
|
||||||
|
|
||||||
|
double w, h;
|
||||||
|
get_surface_dimensions(self, &w, &h);
|
||||||
|
|
||||||
|
self->scale = 1;
|
||||||
|
if (ceil(w * self->scale) > allocation->width)
|
||||||
|
self->scale = allocation->width / w;
|
||||||
|
if (ceil(h * self->scale) > allocation->height)
|
||||||
|
self->scale = allocation->height / h;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -171,6 +217,14 @@ fastiv_view_draw(GtkWidget *widget, cairo_t *cr)
|
||||||
|
|
||||||
#define SCALE_STEP 1.4
|
#define SCALE_STEP 1.4
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
on_scale_updated(FastivView *self)
|
||||||
|
{
|
||||||
|
self->scale_to_fit = false;
|
||||||
|
gtk_widget_queue_resize(GTK_WIDGET(self));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
fastiv_view_scroll_event(GtkWidget *widget, GdkEventScroll *event)
|
fastiv_view_scroll_event(GtkWidget *widget, GdkEventScroll *event)
|
||||||
{
|
{
|
||||||
|
@ -181,12 +235,10 @@ fastiv_view_scroll_event(GtkWidget *widget, GdkEventScroll *event)
|
||||||
switch (event->direction) {
|
switch (event->direction) {
|
||||||
case GDK_SCROLL_UP:
|
case GDK_SCROLL_UP:
|
||||||
self->scale *= SCALE_STEP;
|
self->scale *= SCALE_STEP;
|
||||||
gtk_widget_queue_resize(widget);
|
return on_scale_updated(self);
|
||||||
return TRUE;
|
|
||||||
case GDK_SCROLL_DOWN:
|
case GDK_SCROLL_DOWN:
|
||||||
self->scale /= SCALE_STEP;
|
self->scale /= SCALE_STEP;
|
||||||
gtk_widget_queue_resize(widget);
|
return on_scale_updated(self);
|
||||||
return TRUE;
|
|
||||||
default:
|
default:
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -202,16 +254,16 @@ fastiv_view_key_press_event(GtkWidget *widget, GdkEventKey *event)
|
||||||
switch (event->keyval) {
|
switch (event->keyval) {
|
||||||
case GDK_KEY_1:
|
case GDK_KEY_1:
|
||||||
self->scale = 1;
|
self->scale = 1;
|
||||||
gtk_widget_queue_resize(widget);
|
return on_scale_updated(self);
|
||||||
return TRUE;
|
|
||||||
case GDK_KEY_plus:
|
case GDK_KEY_plus:
|
||||||
self->scale *= SCALE_STEP;
|
self->scale *= SCALE_STEP;
|
||||||
gtk_widget_queue_resize(widget);
|
return on_scale_updated(self);
|
||||||
return TRUE;
|
|
||||||
case GDK_KEY_minus:
|
case GDK_KEY_minus:
|
||||||
self->scale /= SCALE_STEP;
|
self->scale /= SCALE_STEP;
|
||||||
gtk_widget_queue_resize(widget);
|
return on_scale_updated(self);
|
||||||
return TRUE;
|
case GDK_KEY_f:
|
||||||
|
self->scale_to_fit = !self->scale_to_fit;
|
||||||
|
gtk_widget_queue_resize(GTK_WIDGET(self));
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -225,6 +277,7 @@ fastiv_view_class_init(FastivViewClass *klass)
|
||||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
|
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
|
||||||
widget_class->get_preferred_height = fastiv_view_get_preferred_height;
|
widget_class->get_preferred_height = fastiv_view_get_preferred_height;
|
||||||
widget_class->get_preferred_width = fastiv_view_get_preferred_width;
|
widget_class->get_preferred_width = fastiv_view_get_preferred_width;
|
||||||
|
widget_class->size_allocate = fastiv_view_size_allocate;
|
||||||
widget_class->realize = fastiv_view_realize;
|
widget_class->realize = fastiv_view_realize;
|
||||||
widget_class->draw = fastiv_view_draw;
|
widget_class->draw = fastiv_view_draw;
|
||||||
widget_class->scroll_event = fastiv_view_scroll_event;
|
widget_class->scroll_event = fastiv_view_scroll_event;
|
||||||
|
@ -257,6 +310,7 @@ fastiv_view_open(FastivView *self, const gchar *path, GError **error)
|
||||||
|
|
||||||
self->surface = surface;
|
self->surface = surface;
|
||||||
self->scale = 1.0;
|
self->scale = 1.0;
|
||||||
|
self->scale_to_fit = true;
|
||||||
gtk_widget_queue_resize(GTK_WIDGET(self));
|
gtk_widget_queue_resize(GTK_WIDGET(self));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue