]> gitweb.michael.orlitzky.com - libsvgtiny-pixbuf.git/commitdiff
io-svg.c: more work towards incremental loading (not functional yet).
authorMichael Orlitzky <michael@orlitzky.com>
Fri, 4 Aug 2023 23:34:53 +0000 (19:34 -0400)
committerMichael Orlitzky <michael@orlitzky.com>
Fri, 4 Aug 2023 23:34:53 +0000 (19:34 -0400)
io-svg.c

index 2d509c62b5b38319ea42399c26c86d9b440e2591..521ed5818944e4fcd4b9b85aa7bb43f1839b5700 100644 (file)
--- 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";
 }