X-Git-Url: https://gitweb.michael.orlitzky.com/?a=blobdiff_plain;f=io-svg.c;h=8ef9ff90e3c1bfb73dcbd7e3bb919475d9495f4c;hb=HEAD;hp=68f8b4dc4e7aa9e454256e1a6589c4628d530dc5;hpb=8bdd57bdeb61e2af87a6bd5d05352d03902b646a;p=libsvgtiny-pixbuf.git diff --git a/io-svg.c b/io-svg.c index 68f8b4d..8ef9ff9 100644 --- a/io-svg.c +++ b/io-svg.c @@ -1,20 +1,29 @@ #include /* memcpy, memset */ #include -#include #include /* includes glib.h */ #include #include #include #include -/* - * The width and height of the viewport that we'll render the SVG +/* This "header" includes extra code that we've copy/pasted from GDK */ +#include "gdk_pixbuf_get_from_surface.h" + +/* Declare the two functions that we export. Their names aren't + * mentioned in gdk-pixbuf-io.h, but they are required by the + * implementation, as you can confirm from the API docs or in + * gdk-pixbuf-io.c. The G_MODULE_EXPORT macro is defined in + * glib's gmodule.h */ +G_MODULE_EXPORT void fill_vtable(GdkPixbufModule* module); +G_MODULE_EXPORT void fill_info(GdkPixbufFormat *info); + + +/* The width and height of the viewport that we'll render the SVG * into. The final "picture" may not actually be this size; based on * the height, width, viewBox, and preserveAspectRatio attributes in * the SVG itself, libsvgtiny may scale, stretch, offset, etc. the - * paths to make them fit nicely into the viewport. - */ + * paths to make them fit nicely into the viewport. */ #define VIEWPORT_WIDTH 512 #define VIEWPORT_HEIGHT 512 @@ -23,10 +32,14 @@ typedef struct svgtiny_diagram diagram_t; typedef struct svgtiny_shape shape_t; +/* Our main data structure. One of these is created when we start + * loading an SVG, and it persists while the SVG is being read. It + * contains a few boilerplate members, and the svg_data/svg_data_size + * fields that we use to keep track of the buffer where the SVG file + * lives. */ typedef struct { GdkPixbufModuleUpdatedFunc updated_func; GdkPixbufModulePreparedFunc prepared_func; - GdkPixbufModuleSizeFunc size_func; gpointer user_data; /* The SVG "file" that we're building in memory. */ @@ -43,6 +56,9 @@ typedef struct { /** * @brief Render an svgtiny path using cairo. * + * This was lovingly borrowed from @c examples/svgtiny_display_x11.c + * in libsvgtiny itself, and modified to use a transparent background. + * * @param cr * A pointer to a valid cairo context. * @@ -134,11 +150,23 @@ static diagram_t* svgtiny_diagram_from_buffer(const gchar* buffer, g_assert((int)width >= 0); g_assert((int)height >= 0); + + /* There's a thread-safety issue in libwapcaplet that can cause + * svgtiny_parse() to crash if you load lots of SVGs at once: + * + * https://bugs.netsurf-browser.org/mantis/view.php?id=2857 + * + * Putting a lock around svgtiny_parse() is a pretty simple solution + * and looks like it does the trick. + */ + static GMutex mutex; + g_mutex_lock(&mutex); code = svgtiny_parse(diagram, - buffer, - bytecount, "", - (int)width, - (int)height); + buffer, + bytecount, "", + (int)width, + (int)height); + g_mutex_unlock (&mutex); switch(code) { case svgtiny_OK: @@ -335,6 +363,10 @@ static GdkPixbuf* gdk_pixbuf_from_svg_buffer(const gchar* buffer, } +/** + * @brief Our implementation of GdkPixbufModuleBeginLoadFunc, as + * defined in gdk-pixbuf-io.h. + */ static gpointer gdk_pixbuf_begin_load(GdkPixbufModuleSizeFunc size_func, GdkPixbufModulePreparedFunc prep_func, GdkPixbufModuleUpdatedFunc updated_func, @@ -343,7 +375,6 @@ static gpointer gdk_pixbuf_begin_load(GdkPixbufModuleSizeFunc size_func, SvgTinyContext* context = g_new(SvgTinyContext, 1); - context->size_func = size_func; context->prepared_func = prep_func; context->updated_func = updated_func; context->user_data = user_data; @@ -354,6 +385,11 @@ static gpointer gdk_pixbuf_begin_load(GdkPixbufModuleSizeFunc size_func, return context; } + +/** + * @brief Our implementation of GdkPixbufModuleIncrementLoadFunc, as + * defined in gdk-pixbuf-io.h. + */ static gboolean gdk_pixbuf_load_increment(gpointer data, const guchar* buf, guint buf_size, @@ -372,6 +408,10 @@ static gboolean gdk_pixbuf_load_increment(gpointer data, return TRUE; } +/** + * @brief Convenience function to execute the "updated" callback + * stored in our @c context. + */ static void emit_updated(SvgTinyContext* context, GdkPixbuf* pixbuf) { if (context->updated_func != NULL) { (*context->updated_func)(pixbuf, @@ -383,6 +423,10 @@ static void emit_updated(SvgTinyContext* context, GdkPixbuf* pixbuf) { } } +/** + * @brief Convenience function to execute the "prepared" callback + * stored in our @c context. + */ static void emit_prepared(SvgTinyContext* context, GdkPixbuf* pixbuf) { if (context->prepared_func != NULL) { (*context->prepared_func)(pixbuf, NULL, context->user_data); @@ -602,6 +646,10 @@ static gchar* process_gtk_symbolic_svg_xinclude(const gchar* buffer, } +/** + * @brief Our implementation of GdkPixbufModuleStopLoadFunc, as + * defined in gdk-pixbuf-io.h. + */ static gboolean gdk_pixbuf_stop_load(gpointer data, GError **error) { SvgTinyContext* context = (SvgTinyContext*)data; GdkPixbuf* pixbuf = NULL; @@ -648,14 +696,20 @@ static gboolean gdk_pixbuf_stop_load(gpointer data, GError **error) { } -G_MODULE_EXPORT void fill_vtable(GdkPixbufModule* module); +/** + * @brief Our implementation of GdkPixbufModuleFillVtableFunc, as + * defined in gdk-pixbuf-io.h. + */ void fill_vtable(GdkPixbufModule* module) { module->begin_load = gdk_pixbuf_begin_load; module->load_increment = gdk_pixbuf_load_increment; module->stop_load = gdk_pixbuf_stop_load; } -G_MODULE_EXPORT void fill_info(GdkPixbufFormat *info); +/** + * @brief Our implementation of GdkPixbufModuleFillInfoFunc, as + * defined in gdk-pixbuf-io.h. + */ void fill_info(GdkPixbufFormat* info) { /* Borrowed from librsvg-2.40.21 */ static const GdkPixbufModulePattern signature[] = {