summaryrefslogtreecommitdiff
path: root/xps/xpsresource.c
diff options
context:
space:
mode:
Diffstat (limited to 'xps/xpsresource.c')
-rw-r--r--xps/xpsresource.c204
1 files changed, 204 insertions, 0 deletions
diff --git a/xps/xpsresource.c b/xps/xpsresource.c
new file mode 100644
index 00000000..a21d6bed
--- /dev/null
+++ b/xps/xpsresource.c
@@ -0,0 +1,204 @@
+/* Copyright (C) 2006-2010 Artifex Software, Inc.
+ All Rights Reserved.
+
+ This software is provided AS-IS with no warranty, either express or
+ implied.
+
+ This software is distributed under license and may not be copied, modified
+ or distributed except as expressly authorized under the terms of that
+ license. Refer to licensing information at http://www.artifex.com/
+ or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
+ San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
+*/
+
+/* XPS interpreter - resource functions */
+
+#include "ghostxps.h"
+
+static xps_item_t *
+xps_find_resource(xps_context_t *ctx, xps_resource_t *dict, char *name, char **urip)
+{
+ xps_resource_t *head, *node;
+ for (head = dict; head; head = head->parent)
+ {
+ for (node = head; node; node = node->next)
+ {
+ if (!strcmp(node->name, name))
+ {
+ if (urip && head->base_uri)
+ *urip = head->base_uri;
+ return node->data;
+ }
+ }
+ }
+ return NULL;
+}
+
+static xps_item_t *
+xps_parse_resource_reference(xps_context_t *ctx, xps_resource_t *dict, char *att, char **urip)
+{
+ char name[1024];
+ char *s;
+
+ if (strstr(att, "{StaticResource ") != att)
+ return NULL;
+
+ xps_strlcpy(name, att + 16, sizeof name);
+ s = strrchr(name, '}');
+ if (s)
+ *s = 0;
+
+ return xps_find_resource(ctx, dict, name, urip);
+}
+
+void
+xps_resolve_resource_reference(xps_context_t *ctx, xps_resource_t *dict,
+ char **attp, xps_item_t **tagp, char **urip)
+{
+ if (*attp)
+ {
+ xps_item_t *rsrc = xps_parse_resource_reference(ctx, dict, *attp, urip);
+ if (rsrc)
+ {
+ *attp = NULL;
+ *tagp = rsrc;
+ }
+ }
+}
+
+static int
+xps_parse_remote_resource_dictionary(xps_context_t *ctx, xps_resource_t **dictp, char *base_uri, char *source_att)
+{
+ char part_name[1024];
+ char part_uri[1024];
+ xps_resource_t *dict;
+ xps_part_t *part;
+ xps_item_t *xml;
+ char *s;
+ int code;
+
+ /* External resource dictionaries MUST NOT reference other resource dictionaries */
+ xps_absolute_path(part_name, base_uri, source_att, sizeof part_name);
+ part = xps_read_part(ctx, part_name);
+ if (!part)
+ {
+ return gs_throw1(-1, "cannot find remote resource part '%s'", part_name);
+ }
+
+ xml = xps_parse_xml(ctx, part->data, part->size);
+ if (!xml)
+ {
+ xps_free_part(ctx, part);
+ return gs_rethrow(-1, "cannot parse xml");
+ }
+
+ if (strcmp(xps_tag(xml), "ResourceDictionary"))
+ {
+ xps_free_item(ctx, xml);
+ xps_free_part(ctx, part);
+ return gs_throw1(-1, "expected ResourceDictionary element (found %s)", xps_tag(xml));
+ }
+
+ xps_strlcpy(part_uri, part_name, sizeof part_uri);
+ s = strrchr(part_uri, '/');
+ if (s)
+ s[1] = 0;
+
+ code = xps_parse_resource_dictionary(ctx, &dict, part_uri, xml);
+ if (code)
+ {
+ xps_free_item(ctx, xml);
+ xps_free_part(ctx, part);
+ return gs_rethrow1(code, "cannot parse remote resource dictionary: %s", part_uri);
+ }
+
+ dict->base_xml = xml; /* pass on ownership */
+
+ xps_free_part(ctx, part);
+
+ *dictp = dict;
+ return gs_okay;
+}
+
+int
+xps_parse_resource_dictionary(xps_context_t *ctx, xps_resource_t **dictp, char *base_uri, xps_item_t *root)
+{
+ xps_resource_t *head;
+ xps_resource_t *entry;
+ xps_item_t *node;
+ char *source;
+ char *key;
+ int code;
+
+ source = xps_att(root, "Source");
+ if (source)
+ {
+ code = xps_parse_remote_resource_dictionary(ctx, dictp, base_uri, source);
+ if (code)
+ return gs_rethrow(code, "cannot parse remote resource dictionary");
+ return gs_okay;
+ }
+
+ head = NULL;
+
+ for (node = xps_down(root); node; node = xps_next(node))
+ {
+ /* Usually "x:Key"; we have already processed and stripped namespace */
+ key = xps_att(node, "Key");
+ if (key)
+ {
+ entry = xps_alloc(ctx, sizeof(xps_resource_t));
+ if (!entry)
+ return gs_throw(-1, "cannot allocate resource entry");
+ entry->name = key;
+ entry->base_uri = NULL;
+ entry->base_xml = NULL;
+ entry->data = node;
+ entry->next = head;
+ entry->parent = NULL;
+ head = entry;
+ }
+ }
+
+ if (head)
+ {
+ head->base_uri = xps_strdup(ctx, base_uri);
+ }
+
+ *dictp = head;
+ return gs_okay;
+}
+
+void
+xps_free_resource_dictionary(xps_context_t *ctx, xps_resource_t *dict)
+{
+ xps_resource_t *next;
+ while (dict)
+ {
+ next = dict->next;
+ if (dict->base_xml)
+ xps_free_item(ctx, dict->base_xml);
+ if (dict->base_uri)
+ xps_free(ctx, dict->base_uri);
+ xps_free(ctx, dict);
+ dict = next;
+ }
+}
+
+void
+xps_debug_resource_dictionary(xps_resource_t *dict)
+{
+ while (dict)
+ {
+ if (dict->base_uri)
+ dprintf1("URI = '%s'\n", dict->base_uri);
+ dprintf2("KEY = '%s' VAL = %p\n", dict->name, dict->data);
+ if (dict->parent)
+ {
+ dputs("PARENT = {\n");
+ xps_debug_resource_dictionary(dict->parent);
+ dputs("}\n");
+ }
+ dict = dict->next;
+ }
+}