From 3274b64f5aecbb6cd68a606fce439f08ecf14acb Mon Sep 17 00:00:00 2001 From: Přemysl Eric Janouch Date: Fri, 7 Jan 2022 08:50:07 +0100 Subject: Fix SVG thumbnailing They're not loaded as image surfaces. --- fiv-io.c | 47 ++++++++++++++++++++++++++++++++++------------- fiv-io.h | 11 +++++------ fiv-thumbnail.c | 28 ++++++++++++++++------------ fiv-view.c | 39 ++++++++++++++------------------------- 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); } -- cgit v1.2.3-54-g00ecf