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.
This commit is contained in:
2021-11-09 19:42:43 +01:00
parent 1e380f695a
commit 1c5cc50939
7 changed files with 150 additions and 22 deletions

View File

@@ -29,22 +29,28 @@ struct _FastivView {
G_DEFINE_TYPE(FastivView, fastiv_view, GTK_TYPE_WIDGET)
static int
get_display_width(FastivView *self)
static void
get_display_dimensions(FastivView *self, int *width, int *height)
{
*width = *height = 0;
if (!self->surface)
return 0;
return;
return ceil(cairo_image_surface_get_width(self->surface) * self->scale);
}
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();
}
static int
get_display_height(FastivView *self)
{
if (!self->surface)
return 0;
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);