summaryrefslogtreecommitdiff
path: root/src/whale-svg.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/whale-svg.c')
-rw-r--r--src/whale-svg.c171
1 files changed, 171 insertions, 0 deletions
diff --git a/src/whale-svg.c b/src/whale-svg.c
new file mode 100644
index 0000000..2c4b655
--- /dev/null
+++ b/src/whale-svg.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2018 Vito Caputo - <vcaputo@pengaru.com>
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as published
+ * by the Free Software Foundation.
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h> /* this is needed by cairo headers of all things */
+#include <cairo.h>
+#ifdef HAVE_SVG_CAIRO
+#include <svg-cairo.h>
+#else
+#include <librsvg/rsvg.h>
+#endif
+
+#include "macros.h"
+
+typedef struct whale_svg_t {
+#ifdef HAVE_SVG_CAIRO
+ svg_cairo_t *cairo_svg;
+ unsigned width, height;
+#else
+ RsvgHandle *rsvg;
+ RsvgDimensionData dimensions;
+#endif
+} whale_svg_t;
+
+
+whale_svg_t * whale_svg_new_file(const char *file)
+{
+ whale_svg_t *svg;
+
+ svg = calloc(1, sizeof(whale_svg_t));
+ fatal_if(!svg, "Unable to create svg");
+
+#ifdef HAVE_SVG_CAIRO
+ fatal_if(svg_cairo_create(&svg->cairo_svg) != 0,
+ "Unable to create svg-cairo context");
+ fatal_if(svg_cairo_parse(svg->cairo_svg, file) != 0,
+ "Unable to parse \"%s\"", file);
+ svg_cairo_get_size(svg->cairo_svg, &svg->width, &svg->height);
+#else
+ //rsvg_init();
+ svg->rsvg = rsvg_handle_new_from_file(file, NULL);
+ fatal_if(!svg->rsvg,
+ "Unable to create rsvg handle from file \"%s\"", file);
+ rsvg_handle_get_dimensions(svg->rsvg, &svg->dimensions);
+#endif
+
+ return svg;
+}
+
+
+whale_svg_t * whale_svg_new_buffer(const char *buf, size_t count)
+{
+ whale_svg_t *svg;
+
+ svg = calloc(1, sizeof(whale_svg_t));
+ fatal_if(!svg, "Unable to create svg");
+
+#ifdef HAVE_SVG_CAIRO
+ fatal_if(svg_cairo_create(&svg->cairo_svg) != 0,
+ "Unable to create svg-cairo context");
+ fatal_if(svg_cairo_parse_buffer(svg->cairo_svg, buf, count) != 0,
+ "Unable to parse svg buffer");
+ svg_cairo_get_size(svg->cairo_svg, &svg->width, &svg->height);
+#else
+ //rsvg_init();
+ svg->rsvg = rsvg_handle_new_from_data(buf, count, NULL);
+ fatal_if(!svg->rsvg,
+ "Unable to create rsvg handle from buffer");
+ rsvg_handle_get_dimensions(svg->rsvg, &svg->dimensions);
+#endif
+
+ return svg;
+}
+
+
+
+SDL_Surface * whale_svg_render(whale_svg_t *svg, int width, int height)
+{
+ cairo_surface_t *cairo_surface;
+ SDL_Surface *sdl_surface;
+ cairo_t *cairo;
+ double xscale, yscale, scale, tx, ty, svg_width, svg_height;
+
+#ifdef HAVE_SVG_CAIRO
+ svg_width = svg->width;
+ svg_height = svg->height;
+#else
+ svg_width = svg->dimensions.width;
+ svg_height = svg->dimensions.height;
+#endif
+
+ /* cached size is different so redo the costly SVG render */
+ sdl_surface = SDL_CreateRGBSurfaceWithFormat(0, width, height, 32, SDL_PIXELFORMAT_ARGB8888);
+ fatal_if(!sdl_surface, "Unable to create sdl surface");
+
+ cairo_surface = cairo_image_surface_create_for_data(sdl_surface->pixels,
+ CAIRO_FORMAT_ARGB32,
+ width,
+ height,
+ sdl_surface->pitch);
+ fatal_if(!cairo_surface, "Unable to create cairo surface");
+
+#if 0
+ /* useful for debugging */
+ SDL_FillRect(sdl_surface, NULL, 0xffff0000);
+#endif
+
+ cairo = cairo_create(cairo_surface);
+ fatal_if(!cairo, "Unable to create cairo target");
+
+ /* XXX: this scaling attempts to preserve the svg's aspect ratio,
+ * while filling the destination surface
+ */
+ xscale = (double)width / svg_width;
+ yscale = (double)height / svg_height;
+ scale = xscale < yscale ? xscale : yscale;
+
+ /* if we have a mismatch between the desired width/height aspect ratio,
+ * and the svg's aspect ratio, we need to translate to center the rendering
+ * in the resulting surface
+ */
+ tx = scale * svg_width;
+ ty = scale * svg_height;
+
+ if ((int)((double)tx + 0.5) < width)
+ tx = ((double)width - tx + 0.5) / 2.0;
+ else
+ tx = 0;
+
+ if ((int)((double)ty + 0.5) < height)
+ ty = ((double)height - ty + 0.5) / 2.0;
+ else
+ ty = 0;
+
+ cairo_translate(cairo, tx, ty);
+ cairo_scale(cairo, scale, scale);
+
+#ifdef HAVE_SVG_CAIRO
+ svg_cairo_render(svg->cairo_svg, cairo);
+#else
+ rsvg_handle_render_cairo(svg->rsvg, cairo);
+#endif
+ cairo_surface_flush(cairo_surface);
+ cairo_surface_destroy(cairo_surface);
+ cairo_destroy(cairo);
+
+ return sdl_surface;
+}
+
+
+void whale_svg_free(whale_svg_t *svg)
+{
+#ifdef HAVE_SVG_CAIRO
+ svg_cairo_destroy(svg->cairo_svg);
+#else
+ rsvg_handle_free(svg->rsvg);
+#endif
+ free(svg);
+}
© All Rights Reserved