aboutsummaryrefslogtreecommitdiff
path: root/fastiv-view.c
diff options
context:
space:
mode:
authorPřemysl Eric Janouch <p@janouch.name>2021-11-09 19:42:43 +0100
committerPřemysl Eric Janouch <p@janouch.name>2021-11-10 00:23:19 +0100
commit1c5cc5093937b9ea68bba8200f2d71eb613e2979 (patch)
treeeeb8740a898ccc16c4784e197fdef3302fc1b845 /fastiv-view.c
parent1e380f695a39db754c79126be632cbf9c5d46941 (diff)
downloadfiv-1c5cc5093937b9ea68bba8200f2d71eb613e2979.tar.gz
fiv-1c5cc5093937b9ea68bba8200f2d71eb613e2979.tar.xz
fiv-1c5cc5093937b9ea68bba8200f2d71eb613e2979.zip
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.
Diffstat (limited to 'fastiv-view.c')
-rw-r--r--fastiv-view.c63
1 files changed, 44 insertions, 19 deletions
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);