From ad29013e44e2f32029893edd977b0b555c8a50cd Mon Sep 17 00:00:00 2001
From: Přemysl Eric Janouch
Date: Tue, 21 Dec 2021 07:43:02 +0100
Subject: Add zooming to fit width/height if larger
Also, mildly refactor get_surface_dimensions().
---
fastiv.c | 14 +++++-----
fiv-view.c | 89 ++++++++++++++++++++++++++++++++++++++------------------------
2 files changed, 62 insertions(+), 41 deletions(-)
diff --git a/fastiv.c b/fastiv.c
index 21e778f..6389504 100644
--- a/fastiv.c
+++ b/fastiv.c
@@ -119,6 +119,8 @@ static struct key_section help_keys[] = {
{"1...9", "Set zoom to N:1"},
{"plus plus", "Zoom in"},
{"minus minus", "Zoom out"},
+ {"w", "Zoom to fit width if larger"},
+ {"h", "Zoom to fit height if larger"},
{}
}},
{"Orientation", (struct key[]) {
@@ -127,6 +129,12 @@ static struct key_section help_keys[] = {
{"greater", "Rotate clockwise"},
{}
}},
+ {"Configuration", (struct key[]) {
+ {"x", "Toggle scale to fit if larger"},
+ {"i", "Toggle smooth scaling"},
+ {"t", "Toggle transparency highlighting"},
+ {}
+ }},
{"Control", (struct key[]) {
{"bracketleft", "Previous page"},
{"bracketright", "Next page"},
@@ -135,12 +143,6 @@ static struct key_section help_keys[] = {
{"space", "Toggle playback"},
{}
}},
- {"Configuration", (struct key[]) {
- {"x", "Toggle scale to fit"},
- {"i", "Toggle smooth scaling"},
- {"t", "Toggle transparency highlighting"},
- {}
- }},
{"Tools", (struct key[]) {
{"p", "Print..."},
{"s", "Save page as..."},
diff --git a/fiv-view.c b/fiv-view.c
index 89c4106..b95ad3d 100644
--- a/fiv-view.c
+++ b/fiv-view.c
@@ -50,6 +50,10 @@ struct _FivView {
G_DEFINE_TYPE(FivView, fiv_view, GTK_TYPE_WIDGET)
+struct size {
+ double width, height;
+};
+
static FivIoOrientation view_left[9] = {
[FivIoOrientationUnknown] = FivIoOrientationUnknown,
[FivIoOrientation0] = FivIoOrientation270,
@@ -174,12 +178,11 @@ fiv_view_set_property(
}
}
-static void
-get_surface_dimensions(FivView *self, double *width, double *height)
+static struct size
+get_surface_dimensions(FivView *self)
{
- *width = *height = 0;
if (!self->image)
- return;
+ return (struct size) {};
cairo_rectangle_t extents = {};
switch (cairo_surface_get_type(self->page)) {
@@ -201,23 +204,18 @@ get_surface_dimensions(FivView *self, double *width, double *height)
case FivIoOrientationMirror90:
case FivIoOrientation270:
case FivIoOrientationMirror270:
- *width = extents.height;
- *height = extents.width;
- return;
+ return (struct size) {extents.height, extents.width};
default:
- *width = extents.width;
- *height = extents.height;
+ return (struct size) {extents.width, extents.height};
}
}
static void
get_display_dimensions(FivView *self, int *width, int *height)
{
- double w, h;
- get_surface_dimensions(self, &w, &h);
-
- *width = ceil(w * self->scale);
- *height = ceil(h * self->scale);
+ struct size surface_dimensions = get_surface_dimensions(self);
+ *width = ceil(surface_dimensions.width * self->scale);
+ *height = ceil(surface_dimensions.height * self->scale);
}
static cairo_matrix_t
@@ -265,9 +263,7 @@ fiv_view_get_preferred_height(GtkWidget *widget, gint *minimum, gint *natural)
{
FivView *self = FIV_VIEW(widget);
if (self->scale_to_fit) {
- double sw, sh;
- get_surface_dimensions(self, &sw, &sh);
- *natural = ceil(sh);
+ *natural = ceil(get_surface_dimensions(self).height);
*minimum = 1;
} else {
int dw, dh;
@@ -281,9 +277,7 @@ fiv_view_get_preferred_width(GtkWidget *widget, gint *minimum, gint *natural)
{
FivView *self = FIV_VIEW(widget);
if (self->scale_to_fit) {
- double sw, sh;
- get_surface_dimensions(self, &sw, &sh);
- *natural = ceil(sw);
+ *natural = ceil(get_surface_dimensions(self).width);
*minimum = 1;
} else {
int dw, dh;
@@ -301,14 +295,13 @@ fiv_view_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
if (!self->image || !self->scale_to_fit)
return;
- double w, h;
- get_surface_dimensions(self, &w, &h);
-
+ struct size surface_dimensions = get_surface_dimensions(self);
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;
+
+ if (ceil(surface_dimensions.width * self->scale) > allocation->width)
+ self->scale = allocation->width / surface_dimensions.width;
+ if (ceil(surface_dimensions.height * self->scale) > allocation->height)
+ self->scale = allocation->height / surface_dimensions.height;
g_object_notify_by_pspec(G_OBJECT(widget), view_properties[PROP_SCALE]);
}
@@ -376,9 +369,7 @@ fiv_view_draw(GtkWidget *widget, cairo_t *cr)
return TRUE;
int w, h;
- double sw, sh;
get_display_dimensions(self, &w, &h);
- get_surface_dimensions(self, &sw, &sh);
double x = 0;
double y = 0;
@@ -387,7 +378,9 @@ fiv_view_draw(GtkWidget *widget, cairo_t *cr)
if (h < allocation.height)
y = round((allocation.height - h) / 2.);
- cairo_matrix_t matrix = get_orientation_matrix(self->orientation, sw, sh);
+ struct size surface_dimensions = get_surface_dimensions(self);
+ cairo_matrix_t matrix = get_orientation_matrix(
+ self->orientation, surface_dimensions.width, surface_dimensions.height);
cairo_translate(cr, x, y);
if (self->checkerboard) {
gtk_style_context_save(style);
@@ -478,6 +471,28 @@ set_scale(FivView *self, double scale)
return set_scale_to_fit(self, false);
}
+static gboolean
+set_scale_to_fit_width(FivView *self)
+{
+ double w = get_surface_dimensions(self).width;
+ int allocated = gtk_widget_get_allocated_width(
+ gtk_widget_get_parent(GTK_WIDGET(self)));
+ if (ceil(w * self->scale) > allocated)
+ return set_scale(self, allocated / w);
+ return TRUE;
+}
+
+static gboolean
+set_scale_to_fit_height(FivView *self)
+{
+ double h = get_surface_dimensions(self).height;
+ int allocated = gtk_widget_get_allocated_height(
+ gtk_widget_get_parent(GTK_WIDGET(self)));
+ if (ceil(h * self->scale) > allocated)
+ return set_scale(self, allocated / h);
+ return TRUE;
+}
+
static gboolean
fiv_view_scroll_event(GtkWidget *widget, GdkEventScroll *event)
{
@@ -649,12 +664,11 @@ static void
on_draw_page(G_GNUC_UNUSED GtkPrintOperation *operation,
GtkPrintContext *context, G_GNUC_UNUSED int page_nr, FivView *self)
{
- double surface_width_px = 0, surface_height_px = 0;
- get_surface_dimensions(self, &surface_width_px, &surface_height_px);
-
// Any DPI will be wrong, unless we import that information from the image.
double scale = 1 / 96.;
- double w = surface_width_px * scale, h = surface_height_px * scale;
+ struct size surface_dimensions = get_surface_dimensions(self);
+ double w = surface_dimensions.width * scale;
+ double h = surface_dimensions.height * scale;
// Scale down to fit the print area, taking care to not divide by zero.
double areaw = gtk_print_context_get_width(context);
@@ -665,7 +679,7 @@ on_draw_page(G_GNUC_UNUSED GtkPrintOperation *operation,
cairo_scale(cr, scale, scale);
cairo_set_source_surface(cr, self->frame, 0, 0);
cairo_matrix_t matrix = get_orientation_matrix(
- self->orientation, surface_width_px, surface_height_px);
+ self->orientation, surface_dimensions.width, surface_dimensions.height);
cairo_pattern_set_matrix(cairo_get_source(cr), &matrix);
cairo_paint(cr);
}
@@ -828,6 +842,11 @@ fiv_view_key_press_event(GtkWidget *widget, GdkEventKey *event)
case GDK_KEY_minus:
return command(self, FIV_VIEW_COMMAND_ZOOM_OUT);
+ case GDK_KEY_w:
+ return set_scale_to_fit_width(self);
+ case GDK_KEY_h:
+ return set_scale_to_fit_height(self);
+
case GDK_KEY_x: // Inspired by gThumb, which has more such modes.
return command(self, FIV_VIEW_COMMAND_TOGGLE_SCALE_TO_FIT);
case GDK_KEY_i:
--
cgit v1.2.3-70-g09d2