/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * Pix * * Copyright (C) 2011 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include "cairo-image-surface-svg.h" /* GthImageSvg (private class) */ #define GTH_IMAGE_SVG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), gth_image_svg_get_type(), GthImageSvg)) typedef struct { GthImage __parent; RsvgHandle *rsvg; int original_width; int original_height; double last_zoom; } GthImageSvg; typedef GthImageClass GthImageSvgClass; static gpointer gth_image_svg_parent_class; GType gth_image_svg_get_type (void); G_DEFINE_TYPE (GthImageSvg, gth_image_svg, GTH_TYPE_IMAGE) static void gth_image_svg_finalize (GObject *object) { GthImageSvg *self; self = GTH_IMAGE_SVG (object); _g_object_unref (self->rsvg); G_OBJECT_CLASS (gth_image_svg_parent_class)->finalize (object); } static void gth_image_svg_init (GthImageSvg *self) { self->rsvg = NULL; self->original_width = 0; self->original_height = 0; self->last_zoom = 0.0; } static gboolean gth_image_svg_get_is_zoomable (GthImage *base) { return (((GthImageSvg *) base)->rsvg != NULL); } static gboolean gth_image_svg_set_zoom (GthImage *base, double zoom, int *original_width, int *original_height) { GthImageSvg *self; cairo_surface_t *surface; cairo_t *cr; gboolean changed = FALSE; self = GTH_IMAGE_SVG (base); if (self->rsvg == NULL) return FALSE; if (zoom != self->last_zoom) { self->last_zoom = zoom; surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, zoom * self->original_width, zoom * self->original_height); cr = cairo_create (surface); cairo_scale (cr, zoom, zoom); rsvg_handle_render_cairo (self->rsvg, cr); gth_image_set_cairo_surface (base, surface); changed = TRUE; cairo_destroy (cr); cairo_surface_destroy (surface); } if (original_width != NULL) *original_width = self->original_width; if (original_height != NULL) *original_height = self->original_height; return changed; } static void gth_image_svg_class_init (GthImageSvgClass *klass) { GObjectClass *object_class; GthImageClass *image_class; object_class = G_OBJECT_CLASS (klass); object_class->finalize = gth_image_svg_finalize; image_class = GTH_IMAGE_CLASS (klass); image_class->get_is_zoomable = gth_image_svg_get_is_zoomable; image_class->set_zoom = gth_image_svg_set_zoom; } static GthImage * gth_image_svg_new (void) { return g_object_new (gth_image_svg_get_type (), NULL); } static gboolean gth_image_svg_set_handle (GthImageSvg *self, RsvgHandle *rsvg) { RsvgDimensionData dimension_data; if (self->rsvg == rsvg) return TRUE; rsvg_handle_get_dimensions (rsvg, &dimension_data); if ((dimension_data.width == 0) || (dimension_data.height == 0)) return FALSE; self->rsvg = g_object_ref (rsvg); self->original_width = dimension_data.width; self->original_height = dimension_data.height; gth_image_svg_set_zoom (GTH_IMAGE (self), 1.0, NULL, NULL); return TRUE; } /* -- _cairo_image_surface_create_from_svg -- */ GthImage * _cairo_image_surface_create_from_svg (GInputStream *istream, GthFileData *file_data, int requested_size, int *original_width, int *original_height, gboolean *loaded_original, gpointer user_data, GCancellable *cancellable, GError **error) { GthImage *image; RsvgHandle *rsvg; image = gth_image_svg_new (); rsvg = rsvg_handle_new_from_stream_sync (istream, (file_data != NULL ? file_data->file : NULL), RSVG_HANDLE_FLAGS_NONE, cancellable, error); if (rsvg != NULL) { if (! gth_image_svg_set_handle (GTH_IMAGE_SVG (image), rsvg)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, "Error"); g_object_unref (image); image = NULL; } g_object_unref (rsvg); } return image; }