From: Michael Orlitzky Date: Fri, 4 Aug 2023 23:34:53 +0000 (-0400) Subject: io-svg.c: more work towards incremental loading (not functional yet). X-Git-Tag: 0.0.1~35 X-Git-Url: https://gitweb.michael.orlitzky.com/?a=commitdiff_plain;h=c628a155bf17f7e6bcd0bb289e0e225a1482514b;p=libsvgtiny-pixbuf.git io-svg.c: more work towards incremental loading (not functional yet). --- diff --git a/io-svg.c b/io-svg.c index 2d509c6..521ed58 100644 --- a/io-svg.c +++ b/io-svg.c @@ -16,6 +16,8 @@ #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; @@ -26,6 +28,12 @@ typedef struct { 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; @@ -105,33 +113,13 @@ static void render_path(cairo_t* cr, shape_t* path) { * 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"); @@ -258,12 +246,17 @@ static cairo_t* cairo_context_from_diagram(diagram_t* diagram) { 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, @@ -310,21 +303,57 @@ static GdkPixbuf* gdk_pixbuf_from_svg_file_stream(FILE *fp, GError** 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, @@ -332,12 +361,28 @@ 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; } @@ -358,12 +403,29 @@ static void emit_prepared(SvgTinyContext* context, GdkPixbuf* pixbuf) { } } + +/* +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); @@ -413,10 +475,10 @@ void fill_info(GdkPixbufFormat* info) { }; 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"; }