aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPřemysl Eric Janouch <p@janouch.name>2022-01-07 08:50:07 +0100
committerPřemysl Eric Janouch <p@janouch.name>2022-01-07 09:43:28 +0100
commit3274b64f5aecbb6cd68a606fce439f08ecf14acb (patch)
tree18756372760665343d777fe87f45a848d485b038
parentfeda4fd70f592d845fce374b0e9bb38f05f26656 (diff)
downloadfiv-3274b64f5aecbb6cd68a606fce439f08ecf14acb.tar.gz
fiv-3274b64f5aecbb6cd68a606fce439f08ecf14acb.tar.xz
fiv-3274b64f5aecbb6cd68a606fce439f08ecf14acb.zip
Fix SVG thumbnailing
They're not loaded as image surfaces.
-rw-r--r--fiv-io.c47
-rw-r--r--fiv-io.h11
-rw-r--r--fiv-thumbnail.c28
-rw-r--r--fiv-view.c39
4 files changed, 69 insertions, 56 deletions
diff --git a/fiv-io.c b/fiv-io.c
index 266e139..d539f1a 100644
--- a/fiv-io.c
+++ b/fiv-io.c
@@ -2969,51 +2969,72 @@ fiv_io_save(cairo_surface_t *page, cairo_surface_t *frame, FivIoProfile target,
// --- Metadata ----------------------------------------------------------------
-gboolean
-fiv_io_orientation_is_sideways(FivIoOrientation orientation)
-{
+void
+fiv_io_orientation_dimensions(cairo_surface_t *surface,
+ FivIoOrientation orientation, double *w, double *h)
+{
+ cairo_rectangle_t extents = {};
+ switch (cairo_surface_get_type(surface)) {
+ case CAIRO_SURFACE_TYPE_IMAGE:
+ extents.width = cairo_image_surface_get_width(surface);
+ extents.height = cairo_image_surface_get_height(surface);
+ break;
+ case CAIRO_SURFACE_TYPE_RECORDING:
+ if (!cairo_recording_surface_get_extents(surface, &extents))
+ cairo_recording_surface_ink_extents(surface,
+ &extents.x, &extents.y, &extents.width, &extents.height);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
switch (orientation) {
case FivIoOrientation90:
case FivIoOrientationMirror90:
case FivIoOrientation270:
case FivIoOrientationMirror270:
- return TRUE;
+ *w = extents.height;
+ *h = extents.width;
+ break;
default:
- return FALSE;
+ *w = extents.width;
+ *h = extents.height;
}
}
cairo_matrix_t
-fiv_io_orientation_matrix(
- FivIoOrientation orientation, double width, double height)
+fiv_io_orientation_apply(cairo_surface_t *surface,
+ FivIoOrientation orientation, double *width, double *height)
{
+ fiv_io_orientation_dimensions(surface, orientation, width, height);
+
cairo_matrix_t matrix = {};
cairo_matrix_init_identity(&matrix);
switch (orientation) {
case FivIoOrientation90:
cairo_matrix_rotate(&matrix, -M_PI_2);
- cairo_matrix_translate(&matrix, -width, 0);
+ cairo_matrix_translate(&matrix, -*width, 0);
break;
case FivIoOrientation180:
cairo_matrix_scale(&matrix, -1, -1);
- cairo_matrix_translate(&matrix, -width, -height);
+ cairo_matrix_translate(&matrix, -*width, -*height);
break;
case FivIoOrientation270:
cairo_matrix_rotate(&matrix, +M_PI_2);
- cairo_matrix_translate(&matrix, 0, -height);
+ cairo_matrix_translate(&matrix, 0, -*height);
break;
case FivIoOrientationMirror0:
cairo_matrix_scale(&matrix, -1, +1);
- cairo_matrix_translate(&matrix, -width, 0);
+ cairo_matrix_translate(&matrix, -*width, 0);
break;
case FivIoOrientationMirror90:
cairo_matrix_rotate(&matrix, +M_PI_2);
cairo_matrix_scale(&matrix, -1, +1);
- cairo_matrix_translate(&matrix, -width, -height);
+ cairo_matrix_translate(&matrix, -*width, -*height);
break;
case FivIoOrientationMirror180:
cairo_matrix_scale(&matrix, +1, -1);
- cairo_matrix_translate(&matrix, 0, -height);
+ cairo_matrix_translate(&matrix, 0, -*height);
break;
case FivIoOrientationMirror270:
cairo_matrix_rotate(&matrix, -M_PI_2);
diff --git a/fiv-io.h b/fiv-io.h
index f8f3118..066770c 100644
--- a/fiv-io.h
+++ b/fiv-io.h
@@ -130,12 +130,11 @@ typedef enum _FivIoOrientation {
FivIoOrientation270 = 8
} FivIoOrientation;
-/// Returns whether dimensions need to be swapped for rendering.
-gboolean fiv_io_orientation_is_sideways(FivIoOrientation orientation);
-
-/// Returns a rendering matrix for a surface. Dimensions need to be pre-swapped.
-cairo_matrix_t fiv_io_orientation_matrix(
- FivIoOrientation orientation, double width, double height);
+/// Returns a rendering matrix for a surface, and its target dimensions.
+cairo_matrix_t fiv_io_orientation_apply(cairo_surface_t *surface,
+ FivIoOrientation orientation, double *width, double *height);
+void fiv_io_orientation_dimensions(cairo_surface_t *surface,
+ FivIoOrientation orientation, double *width, double *height);
/// Extracts the orientation field from Exif, if there's any.
FivIoOrientation fiv_io_exif_orientation(const guint8 *exif, gsize len);
diff --git a/fiv-thumbnail.c b/fiv-thumbnail.c
index bd7e6e9..ca45dc1 100644
--- a/fiv-thumbnail.c
+++ b/fiv-thumbnail.c
@@ -108,16 +108,13 @@ fiv_thumbnail_get_root(void)
static cairo_surface_t *
adjust_thumbnail(cairo_surface_t *thumbnail, double row_height)
{
- cairo_format_t format = cairo_image_surface_get_format(thumbnail);
- int w = 0, width = cairo_image_surface_get_width(thumbnail);
- int h = 0, height = cairo_image_surface_get_height(thumbnail);
-
// Hardcode orientation.
FivIoOrientation orientation = (uintptr_t) cairo_surface_get_user_data(
thumbnail, &fiv_io_key_orientation);
- cairo_matrix_t matrix = fiv_io_orientation_is_sideways(orientation)
- ? fiv_io_orientation_matrix(orientation, (w = height), (h = width))
- : fiv_io_orientation_matrix(orientation, (w = width), (h = height));
+
+ double w = 0, h = 0;
+ cairo_matrix_t matrix =
+ fiv_io_orientation_apply(thumbnail, orientation, &w, &h);
double scale_x = 1;
double scale_y = 1;
@@ -128,7 +125,11 @@ adjust_thumbnail(cairo_surface_t *thumbnail, double row_height)
scale_y = row_height / h;
scale_x = round(scale_y * w) / w;
}
- if (orientation <= FivIoOrientation0 && scale_x == 1 && scale_y == 1)
+
+ // This will be CAIRO_FORMAT_INVALID with non-image surfaces, which is fine.
+ cairo_format_t format = cairo_image_surface_get_format(thumbnail);
+ if (format != CAIRO_FORMAT_INVALID &&
+ orientation <= FivIoOrientation0 && scale_x == 1 && scale_y == 1)
return cairo_surface_reference(thumbnail);
int projected_width = round(scale_x * w);
@@ -265,10 +266,13 @@ fiv_thumbnail_produce(GFile *target, FivThumbnailSize max_size, GError **error)
thum, "%s%c%ld%c", THUMB_MTIME, 0, (long) st.st_mtim.tv_sec, 0);
g_string_append_printf(
thum, "%s%c%ld%c", THUMB_SIZE, 0, (long) filesize, 0);
- g_string_append_printf(thum, "%s%c%d%c", THUMB_IMAGE_WIDTH, 0,
- cairo_image_surface_get_width(surface), 0);
- g_string_append_printf(thum, "%s%c%d%c", THUMB_IMAGE_HEIGHT, 0,
- cairo_image_surface_get_height(surface), 0);
+
+ if (cairo_surface_get_type(surface) == CAIRO_SURFACE_TYPE_IMAGE) {
+ g_string_append_printf(thum, "%s%c%d%c", THUMB_IMAGE_WIDTH, 0,
+ cairo_image_surface_get_width(surface), 0);
+ g_string_append_printf(thum, "%s%c%d%c", THUMB_IMAGE_HEIGHT, 0,
+ cairo_image_surface_get_height(surface), 0);
+ }
// Without a CMM, no conversion is attempted.
if (sRGB) {
diff --git a/fiv-view.c b/fiv-view.c
index fbac427..8626e51 100644
--- a/fiv-view.c
+++ b/fiv-view.c
@@ -207,25 +207,10 @@ get_surface_dimensions(FivView *self)
if (!self->image)
return (Dimensions) {};
- cairo_rectangle_t extents = {};
- switch (cairo_surface_get_type(self->page)) {
- case CAIRO_SURFACE_TYPE_IMAGE:
- extents.width = cairo_image_surface_get_width(self->page);
- extents.height = cairo_image_surface_get_height(self->page);
- break;
- case CAIRO_SURFACE_TYPE_RECORDING:
- if (!cairo_recording_surface_get_extents(self->page, &extents))
- cairo_recording_surface_ink_extents(self->page,
- &extents.x, &extents.y, &extents.width, &extents.height);
- break;
- default:
- g_assert_not_reached();
- }
-
- if (fiv_io_orientation_is_sideways(self->orientation))
- return (Dimensions) {extents.height, extents.width};
-
- return (Dimensions) {extents.width, extents.height};
+ Dimensions dimensions = {};
+ fiv_io_orientation_dimensions(
+ self->page, self->orientation, &dimensions.width, &dimensions.height);
+ return dimensions;
}
static void
@@ -398,9 +383,11 @@ fiv_view_draw(GtkWidget *widget, cairo_t *cr)
if (h < allocation.height)
y = round((allocation.height - h) / 2.);
- Dimensions surface_dimensions = get_surface_dimensions(self);
- cairo_matrix_t matrix = fiv_io_orientation_matrix(
- self->orientation, surface_dimensions.width, surface_dimensions.height);
+ Dimensions surface_dimensions = {};
+ cairo_matrix_t matrix =
+ fiv_io_orientation_apply(self->page, self->orientation,
+ &surface_dimensions.width, &surface_dimensions.height);
+
cairo_translate(cr, x, y);
if (self->checkerboard) {
gtk_style_context_save(style);
@@ -686,7 +673,11 @@ on_draw_page(G_GNUC_UNUSED GtkPrintOperation *operation,
{
// Any DPI will be wrong, unless we import that information from the image.
double scale = 1 / 96.;
- Dimensions surface_dimensions = get_surface_dimensions(self);
+ Dimensions surface_dimensions = {};
+ cairo_matrix_t matrix =
+ fiv_io_orientation_apply(self->page, self->orientation,
+ &surface_dimensions.width, &surface_dimensions.height);
+
double w = surface_dimensions.width * scale;
double h = surface_dimensions.height * scale;
@@ -698,8 +689,6 @@ on_draw_page(G_GNUC_UNUSED GtkPrintOperation *operation,
cairo_t *cr = gtk_print_context_get_cairo_context(context);
cairo_scale(cr, scale, scale);
cairo_set_source_surface(cr, self->frame, 0, 0);
- cairo_matrix_t matrix = fiv_io_orientation_matrix(
- self->orientation, surface_dimensions.width, surface_dimensions.height);
cairo_pattern_set_matrix(cairo_get_source(cr), &matrix);
cairo_paint(cr);
}