X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Foutput%2Fspv%2Fspv.c;h=fc058281eccd633f1e1824cd78c12a728de8fb51;hb=bd5e8f74de87b9061ff62615f48fb378e844e87d;hp=f186e638e70c9f8944a31a826081bc36f3f5e296;hpb=50f6ea7d66d03895020891215fb4f55bbf061003;p=pspp diff --git a/src/output/spv/spv.c b/src/output/spv/spv.c index f186e638e7..fc058281ec 100644 --- a/src/output/spv/spv.c +++ b/src/output/spv/spv.c @@ -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" @@ -39,6 +39,7 @@ #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" @@ -54,7 +55,6 @@ struct spv_reader { - struct string zip_errs; struct zip_reader *zip; struct spv_item *root; struct page_setup *page_setup; @@ -76,7 +76,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**"; } } @@ -101,7 +101,7 @@ spv_item_class_from_string (const char *name) SPV_CLASSES #undef SPV_CLASS - return SPV_N_CLASSES; + return (enum spv_item_class) SPV_N_CLASSES; } enum spv_item_type @@ -139,7 +139,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: @@ -194,6 +194,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; + 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) { @@ -259,15 +304,16 @@ spv_item_destroy (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); } @@ -374,7 +420,7 @@ extract_html_text (const xmlNode *node, int base_font_size, struct string *s) 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]; @@ -420,7 +466,7 @@ extract_html_text (const xmlNode *node, int base_font_size, struct string *s) 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) @@ -572,6 +618,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 @@ -605,7 +653,7 @@ spv_item_get_light_table (const struct spv_item *item, 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) @@ -680,9 +728,10 @@ spv_read_xml_member (struct spv_reader *spv, const char *member_name, { *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); @@ -705,7 +754,7 @@ spv_read_xml_member (struct spv_reader *spv, const char *member_name, 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; @@ -827,7 +876,7 @@ pivot_table_open_legacy (struct spv_item *item) 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) @@ -848,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_); @@ -905,8 +954,10 @@ spv_decode_container (const struct spvsx_container *c, 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); @@ -931,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 (); @@ -965,7 +1009,7 @@ spv_decode_children (struct spv_reader *spv, const char *structure_member, { const struct spvxml_node *node = seq[i]; - char *error; + char *error = NULL; if (spvsx_is_container (node)) { const struct spvsx_container *container @@ -1109,16 +1153,14 @@ spv_detect__ (struct zip_reader *zip, char **errorp) 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; } @@ -1128,16 +1170,13 @@ spv_open (const char *filename, struct spv_reader **spvp) *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) { @@ -1176,14 +1215,31 @@ spv_close (struct spv_reader *spv) { 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) {