#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"
#include "output/spv/spv-legacy-data.h"
#include "output/spv/spv-legacy-decoder.h"
#include "output/spv/spv-light-decoder.h"
+#include "output/spv/spv-table-look.h"
#include "output/spv/structure-xml-parser.h"
#include "gl/c-ctype.h"
struct spv_reader
{
- struct string zip_errs;
struct zip_reader *zip;
struct spv_item *root;
struct page_setup *page_setup;
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**";
}
}
SPV_CLASSES
#undef SPV_CLASS
- return SPV_N_CLASSES;
+ return (enum spv_item_class) SPV_N_CLASSES;
}
enum spv_item_type
case SPV_ITEM_MODEL:
return SPV_CLASS_MODELS;
- case SPV_ITEM_OBJECT:
+ case SPV_ITEM_IMAGE:
return SPV_CLASS_OTHER;
case SPV_ITEM_TREE:
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;
+ char *error = zip_member_open (item->spv->zip, item->png_member, &zm);
+ item->image = cairo_image_surface_create_from_png_stream (
+ read_from_zip_member, zm);
+ zip_member_finish (zm);
+ free (error);
+ }
+
+ return item->image;
+}
+
struct spv_item *
spv_item_next (const struct spv_item *item)
{
free (item->children);
pivot_table_unref (item->table);
- spv_legacy_properties_destroy (item->legacy_properties);
+ 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);
}
else
{
uint8_t r, g, b;
- if (sscanf (color, "rgb (%"SCNu8", %"SCNu8", %"SCNu8" )",
+ if (sscanf (color, "rgb (%"SCNu8", %"SCNu8", %"SCNu8")",
&r, &g, &b) == 3)
{
char color2[8];
Do the same for U+2007 FIGURE SPACE, which also crops out weirdly
sometimes. */
ds_extend (s, ds_length (s) + xmlStrlen (node->content));
- for (const uint8_t *p = node->content; *p; )
+ for (const uint8_t *p = node->content; *p;)
{
int c;
if (p[0] == 0xc2 && p[1] == 0xa0)
{
if (spv_item_is_table (item))
spv_item_get_table (item);
+ else if (spv_item_is_image (item))
+ spv_item_get_image (item);
}
bool
struct spvbin_input input;
spvbin_input_init (&input, data, size);
- struct spvlb_table *table;
+ struct spvlb_table *table = NULL;
error = (!size
? xasprintf ("light table member is empty")
: !spvlb_parse_table (&input, &table)
{
*docp = NULL;
- struct zip_member *zm = zip_member_open (spv->zip, member_name);
- if (!zm)
- return ds_steal_cstr (&spv->zip_errs);
+ struct zip_member *zm;
+ char *error = zip_member_open (spv->zip, member_name, &zm);
+ if (error)
+ return error;
xmlParserCtxt *parser;
xmlKeepBlanksDefault (keep_blanks);
if (retval < 0)
{
- char *error = ds_steal_cstr (&spv->zip_errs);
+ char *error = zip_member_steal_error (zm);
zip_member_finish (zm);
xmlFreeDoc (doc);
return error;
error = spvxml_context_finish (&ctx, &v->node_);
if (!error)
- error = decode_spvdx_table (v, item->subtype, item->legacy_properties,
+ error = decode_spvdx_table (v, item->subtype, item->table_look,
&data, &item->table);
if (error)
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_);
if (ts->path)
{
item->xml_member = ts->path ? xstrdup (ts->path->text) : NULL;
- char *error = decode_spvsx_legacy_properties (
- table->table_properties, &item->legacy_properties);
+ char *error = (table->table_properties
+ ? spv_table_look_decode (table->table_properties,
+ &item->table_look)
+ : xstrdup ("Legacy table lacks tableProperties"));
if (error)
{
spv_item_destroy (item);
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 ();
{
const struct spvxml_node *node = seq[i];
- char *error;
+ char *error = NULL;
if (spvsx_is_container (node))
{
const struct spvsx_container *container
char * WARN_UNUSED_RESULT
spv_detect (const char *filename)
{
- struct string zip_error;
- struct zip_reader *zip = zip_reader_create (filename, &zip_error);
- if (!zip)
- return ds_steal_cstr (&zip_error);
+ struct zip_reader *zip;
+ char *error = zip_reader_create (filename, &zip);
+ if (error)
+ return error;
- char *error;
if (spv_detect__ (zip, &error) <= 0 && !error)
error = xasprintf("%s: not an SPV file", filename);
- zip_reader_destroy (zip);
- ds_destroy (&zip_error);
+ zip_reader_unref (zip);
return error;
}
*spvp = NULL;
struct spv_reader *spv = xzalloc (sizeof *spv);
- ds_init_empty (&spv->zip_errs);
- spv->zip = zip_reader_create (filename, &spv->zip_errs);
- if (!spv->zip)
+ char *error = zip_reader_create (filename, &spv->zip);
+ if (error)
{
- char *error = ds_steal_cstr (&spv->zip_errs);
spv_close (spv);
return error;
}
- char *error;
int detect = spv_detect__ (spv->zip, &error);
if (detect <= 0)
{
{
if (spv)
{
- ds_destroy (&spv->zip_errs);
- zip_reader_destroy (spv->zip);
+ zip_reader_unref (spv->zip);
spv_item_destroy (spv->root);
page_setup_destroy (spv->page_setup);
free (spv);
}
}
+void
+spv_item_set_table_look (struct spv_item *item,
+ const struct pivot_table_look *look)
+{
+ /* If this is a table, install the table look in it.
+
+ (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))
+ {
+ 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);
+}
+
char * WARN_UNUSED_RESULT
spv_decode_fmt_spec (uint32_t u32, struct fmt_spec *out)
{