#define VIEWPORT_WIDTH 512
#define VIEWPORT_HEIGHT 512
+#define SVG_BUFFER_INCREMENT (size_t)4194304
+
/* Convenient typedefs for libsvgtiny */
typedef struct svgtiny_diagram diagram_t;
typedef struct svgtiny_shape shape_t;
GdkPixbufModulePreparedFunc prepared_func;
GdkPixbufModuleSizeFunc size_func;
gpointer user_data;
+
+ /* The "file" */
+ char* svg_data;
+ size_t svg_data_size;
+ size_t svg_data_max;
+
} SvgTinyContext;
* returned; if not, @c NULL is returned. You are expected to @c
* svgtiny_free the result if it is valid.
*/
-static diagram_t* svgtiny_diagram_from_file(FILE* fp, int width, int height) {
+static diagram_t* svgtiny_diagram_from_buffer(char* buffer,
+ size_t bytecount,
+ int width,
+ int height) {
diagram_t* diagram;
-
- size_t bytecount;
- char* buffer;
- size_t bytesread;
svgtiny_code code;
- /* Find the size of the file stream */
- fseek(fp, 0L, SEEK_END);
- bytecount = ftell(fp);
- rewind(fp);
-
- buffer = malloc(bytecount);
- if (!buffer) {
- fprintf(stderr, "Unable to allocate %zd bytes\n", bytecount);
- return NULL;
- }
-
- bytesread = fread(buffer, 1, bytecount, fp);
- if (bytesread != bytecount) {
- fprintf(stderr, "Read only %zd of %zd bytes from stream\n",
- bytesread,
- bytecount);
- }
- fclose(fp);
-
diagram = svgtiny_create();
if (!diagram) {
fprintf(stderr, "svgtiny_create() failed\n");
return cr;
}
-static GdkPixbuf* gdk_pixbuf_from_svg_file_stream(FILE *fp, GError** error) {
+static GdkPixbuf* gdk_pixbuf_from_svg_buffer(char* buffer,
+ size_t bytecount,
+ GError** error) {
diagram_t* diagram;
cairo_t* cr = 0;
GdkPixbuf* pb;
- diagram = svgtiny_diagram_from_file(fp, VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
+ diagram = svgtiny_diagram_from_buffer(buffer,
+ bytecount,
+ VIEWPORT_WIDTH,
+ VIEWPORT_HEIGHT);
if (!diagram) {
g_set_error_literal(error,
GDK_PIXBUF_ERROR,
return pb;
}
+static GdkPixbuf* gdk_pixbuf_from_svg_file_stream(FILE *fp, GError** error) {
+ size_t bytecount, bytesread;
+ char* buffer;
+
+ /* Find the size of the file stream */
+ fseek(fp, 0L, SEEK_END);
+ bytecount = ftell(fp);
+ rewind(fp);
+
+ buffer = malloc(bytecount);
+ if (!buffer) {
+ fprintf(stderr, "Unable to allocate %zd bytes\n", bytecount);
+ return NULL;
+ }
+
+ bytesread = fread(buffer, 1, bytecount, fp);
+ if (bytesread != bytecount) {
+ fprintf(stderr, "Read only %zd of %zd bytes from stream\n",
+ bytesread,
+ bytecount);
+ }
+ fclose(fp);
+
+ return gdk_pixbuf_from_svg_buffer(buffer, bytecount, error);
+}
+
static gpointer gdk_pixbuf_begin_load(GdkPixbufModuleSizeFunc size_func,
GdkPixbufModulePreparedFunc prep_func,
GdkPixbufModuleUpdatedFunc updated_func,
gpointer user_data,
- GError **error)
-{
- SvgTinyContext* context = g_new0(SvgTinyContext, 1);
+ GError **error) {
+
+ SvgTinyContext* context = g_new0(SvgTinyContext, 1);
- context->size_func = size_func;
- context->prepared_func = prep_func;
- context->updated_func = updated_func;
- context->user_data = user_data;
+ context->size_func = size_func;
+ context->prepared_func = prep_func;
+ context->updated_func = updated_func;
+ context->user_data = user_data;
+
+ context->svg_data = malloc(SVG_BUFFER_INCREMENT);
+ if (context->svg_data) {
+ context->svg_data_size = 0;
+ context->svg_data_max = SVG_BUFFER_INCREMENT;
+ }
+ else {
+ fprintf(stderr, "Unable to allocate %zd bytes\n", SVG_BUFFER_INCREMENT);
+ return NULL;
+ }
- return context;
+ return context;
}
static gboolean gdk_pixbuf_load_increment(gpointer data,
guint size,
GError** error) {
SvgTinyContext* context = (SvgTinyContext*)data;
- /*
- if (!rsvg_handle_write (context->handle, buf, size, error)) {
- rsvg_propagate_error (error, _("Error writing"), ERROR_WRITING);
- return FALSE;
+
+ if (context->svg_data_size + size > context->svg_data_max) {
+ size_t increment = 0;
+ if (size > SVG_BUFFER_INCREMENT) {
+ increment = size;
+ }
+ else {
+ increment = SVG_BUFFER_INCREMENT;
+ }
+ context->svg_data = realloc(context->svg_data,
+ context->svg_data_max + increment);
+ if (context->svg_data) {
+ context->svg_data_max += increment;
+ }
+ else {
+ fprintf(stderr, "Unable to (re)allocate %zd bytes\n", increment);
+ return FALSE;
+ }
}
- */
+ memcpy(context->svg_data + context->svg_data_size, buf, size);
+ context->svg_data_size += size;
+
return TRUE;
}
}
}
+
+/*
+static void emit_size(SvgTinyContext* context, GdkPixbuf* pixbuf) {
+
+ int w = gdk_pixbuf_get_width(pixbuf);
+ int h = gdk_pixbuf_get_height(pixbuf);
+ if (context->size_func != NULL) {
+ (*context->size_func)(&w, &h, context->user_data);
+ }
+}
+*/
+
static gboolean gdk_pixbuf_stop_load(gpointer data, GError **error) {
SvgTinyContext* context = (SvgTinyContext*)data;
GdkPixbuf* pixbuf = NULL;
gboolean result = TRUE;
+ pixbuf = gdk_pixbuf_from_svg_buffer(context->svg_data,
+ context->svg_data_size,
+ error);
+
if (pixbuf != NULL) {
+ /* emit_size(context, pixbuf); */
emit_prepared(context, pixbuf);
emit_updated(context, pixbuf);
g_object_unref(pixbuf);
};
info->name = "svg";
- info->signature = (GdkPixbufModulePattern*) signature;
+ info->signature = (GdkPixbufModulePattern*)signature;
info->description = "Scalable Vector Graphics";
- info->mime_types = (gchar**) mime_types;
- info->extensions = (gchar**) extensions;
+ info->mime_types = (gchar**)mime_types;
+ info->extensions = (gchar**)extensions;
info->flags = GDK_PIXBUF_FORMAT_SCALABLE;
info->license = "AGPL3";
}