output-item: Collapse the inheritance hierarchy into a single struct.
[pspp] / src / output / spv / spv.c
index 5f537edfc84da8a6e6482ce55be4bc142ad7315f..fdafb5aba7c96c3ef3cb0ff9a815b2360257a96a 100644 (file)
@@ -31,7 +31,7 @@
 #include "libpspp/message.h"
 #include "libpspp/str.h"
 #include "libpspp/zip-reader.h"
-#include "output/page-setup-item.h"
+#include "output/page-setup.h"
 #include "output/pivot-table.h"
 #include "output/spv/detail-xml-parser.h"
 #include "output/spv/light-binary-parser.h"
@@ -77,7 +77,7 @@ spv_item_type_to_string (enum spv_item_type type)
     case SPV_ITEM_TABLE: return "table";
     case SPV_ITEM_GRAPH: return "graph";
     case SPV_ITEM_MODEL: return "model";
-    case SPV_ITEM_OBJECT: return "object";
+    case SPV_ITEM_IMAGE: return "image";
     default: return "**error**";
     }
 }
@@ -140,7 +140,7 @@ spv_item_get_class (const struct spv_item *item)
     case SPV_ITEM_MODEL:
       return SPV_CLASS_MODELS;
 
-    case SPV_ITEM_OBJECT:
+    case SPV_ITEM_IMAGE:
       return SPV_CLASS_OTHER;
 
     case SPV_ITEM_TREE:
@@ -195,6 +195,51 @@ spv_item_get_text (const struct spv_item *item)
   return item->text;
 }
 
+bool
+spv_item_is_image (const struct spv_item *item)
+{
+  return item->type == SPV_ITEM_IMAGE;
+}
+
+static cairo_status_t
+read_from_zip_member (void *zm_, unsigned char *data, unsigned int length)
+{
+  struct zip_member *zm = zm_;
+  if (!zm)
+    return CAIRO_STATUS_READ_ERROR;
+
+  while (length > 0)
+    {
+      int n = zip_member_read (zm, data, length);
+      if (n <= 0)
+        return CAIRO_STATUS_READ_ERROR;
+
+      data += n;
+      length -= n;
+    }
+
+  return CAIRO_STATUS_SUCCESS;
+}
+
+cairo_surface_t *
+spv_item_get_image (const struct spv_item *item_)
+{
+  struct spv_item *item = CONST_CAST (struct spv_item *, item_);
+  assert (spv_item_is_image (item));
+
+  if (!item->image)
+    {
+      struct zip_member *zm = zip_member_open (item->spv->zip,
+                                               item->png_member);
+      item->image = cairo_image_surface_create_from_png_stream (
+        read_from_zip_member, zm);
+      if (zm)
+        zip_member_finish (zm);
+    }
+
+  return item->image;
+}
+
 struct spv_item *
 spv_item_next (const struct spv_item *item)
 {
@@ -260,19 +305,16 @@ spv_item_destroy (struct spv_item *item)
       free (item->children);
 
       pivot_table_unref (item->table);
-      if (item->table_look)
-        {
-          pivot_table_look_uninit (item->table_look);
-          free (item->table_look);
-        }
+      pivot_table_look_unref (item->table_look);
       free (item->bin_member);
       free (item->xml_member);
       free (item->subtype);
 
       pivot_value_destroy (item->text);
 
-      free (item->object_type);
-      free (item->uri);
+      free (item->png_member);
+      if (item->image)
+        cairo_surface_destroy (item->image);
 
       free (item);
     }
@@ -577,6 +619,8 @@ spv_item_load (const struct spv_item *item)
 {
   if (spv_item_is_table (item))
     spv_item_get_table (item);
+  else if (spv_item_is_image (item))
+    spv_item_get_image (item);
 }
 
 bool
@@ -853,7 +897,7 @@ pivot_table_open_legacy (struct spv_item *item)
   return error;
 }
 
-struct pivot_table *
+const struct pivot_table *
 spv_item_get_table (const struct spv_item *item_)
 {
   struct spv_item *item = CONST_CAST (struct spv_item *, item_);
@@ -938,24 +982,17 @@ spv_decode_container (const struct spvsx_container *c,
   else if (spvsx_is_object (content))
     {
       struct spvsx_object *object = spvsx_cast_object (content);
-      item->type = SPV_ITEM_OBJECT;
-      item->object_type = xstrdup (object->type);
-      item->uri = xstrdup (object->uri);
+      item->type = SPV_ITEM_IMAGE;
+      item->png_member = xstrdup (object->uri);
     }
   else if (spvsx_is_image (content))
     {
       struct spvsx_image *image = spvsx_cast_image (content);
-      item->type = SPV_ITEM_OBJECT;
-      item->object_type = xstrdup ("image");
-      item->uri = xstrdup (image->data_path->text);
+      item->type = SPV_ITEM_IMAGE;
+      item->png_member = xstrdup (image->data_path->text);
     }
   else if (spvsx_is_tree (content))
-    {
-      struct spvsx_tree *tree = spvsx_cast_tree (content);
-      item->type = SPV_ITEM_TREE;
-      item->object_type = xstrdup ("tree");
-      item->uri = xstrdup (tree->data_path->text);
-    }
+    item->type = SPV_ITEM_TREE;
   else
     NOT_REACHED ();
 
@@ -1200,7 +1237,10 @@ spv_item_set_table_look (struct spv_item *item,
      (We can't just set item->table_look because light tables ignore it and
      legacy tables sometimes override it.) */
   if (spv_item_is_table (item))
-    pivot_table_set_look (spv_item_get_table (item), look);
+    {
+      spv_item_load (item);
+      pivot_table_set_look (item->table, look);
+    }
 
   for (size_t i = 0; i < item->n_children; i++)
     spv_item_set_table_look (item->children[i], look);