From 1c5cc5093937b9ea68bba8200f2d71eb613e2979 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C5=99emysl=20Eric=20Janouch?= Date: Tue, 9 Nov 2021 19:42:43 +0100 Subject: Add very basic SVG support We need to refactor, so that SVGs are pre-rendered on each change of scaling by librsvg directly, because some elements may be rasterized. It would be best to also support building against resvg. --- fastiv-view.c | 63 +++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 19 deletions(-) (limited to 'fastiv-view.c') diff --git a/fastiv-view.c b/fastiv-view.c index da4aa12..948db9e 100644 --- a/fastiv-view.c +++ b/fastiv-view.c @@ -29,22 +29,28 @@ struct _FastivView { G_DEFINE_TYPE(FastivView, fastiv_view, GTK_TYPE_WIDGET) -static int -get_display_width(FastivView *self) -{ - if (!self->surface) - return 0; - - return ceil(cairo_image_surface_get_width(self->surface) * self->scale); -} - -static int -get_display_height(FastivView *self) +static void +get_display_dimensions(FastivView *self, int *width, int *height) { + *width = *height = 0; if (!self->surface) - return 0; + return; + + cairo_rectangle_t extents = {}; + switch (cairo_surface_get_type(self->surface)) { + case CAIRO_SURFACE_TYPE_IMAGE: + extents.width = cairo_image_surface_get_width(self->surface); + extents.height = cairo_image_surface_get_height(self->surface); + break; + case CAIRO_SURFACE_TYPE_RECORDING: + (void) cairo_recording_surface_get_extents(self->surface, &extents); + break; + default: + g_assert_not_reached(); + } - return ceil(cairo_image_surface_get_height(self->surface) * self->scale); + *width = ceil(extents.width * self->scale); + *height = ceil(extents.height * self->scale); } static void @@ -60,15 +66,17 @@ static void fastiv_view_get_preferred_height( GtkWidget *widget, gint *minimum, gint *natural) { - FastivView *self = FASTIV_VIEW(widget); - *minimum = *natural = get_display_height(self); + int width, height; + get_display_dimensions(FASTIV_VIEW(widget), &width, &height); + *minimum = *natural = height; } static void fastiv_view_get_preferred_width(GtkWidget *widget, gint *minimum, gint *natural) { - FastivView *self = FASTIV_VIEW(widget); - *minimum = *natural = get_display_width(self); + int width, height; + get_display_dimensions(FASTIV_VIEW(widget), &width, &height); + *minimum = *natural = width; } static void @@ -115,8 +123,8 @@ fastiv_view_draw(GtkWidget *widget, cairo_t *cr) gtk_render_background(gtk_widget_get_style_context(widget), cr, 0, 0, allocation.width, allocation.height); - int w = get_display_width(self); - int h = get_display_height(self); + int w, h; + get_display_dimensions(self, &w, &h); double x = 0; double y = 0; @@ -125,6 +133,23 @@ fastiv_view_draw(GtkWidget *widget, cairo_t *cr) if (h < allocation.height) y = round((allocation.height - h) / 2.); + // FIXME: Recording surfaces do not work well with CAIRO_SURFACE_TYPE_XLIB, + // we always get a shitty pixmap, where transparency contains junk. + if (cairo_surface_get_type(self->surface) == CAIRO_SURFACE_TYPE_RECORDING) { + cairo_surface_t *image = + cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w, h); + cairo_t *tcr = cairo_create(image); + cairo_scale(tcr, self->scale, self->scale); + cairo_set_source_surface(tcr, self->surface, 0, 0); + cairo_paint(tcr); + cairo_destroy(tcr); + + cairo_set_source_surface(cr, image, x, y); + cairo_paint(cr); + cairo_surface_destroy(image); + return TRUE; + } + // XXX: The rounding together with padding may result in up to // a pixel's worth of made-up picture data. cairo_rectangle(cr, x, y, w, h); -- cgit v1.2.3