Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4680 | right-hear | 1 | #include "fitz.h" |
2 | #include "muxps.h" |
||
3 | |||
4 | static xml_element * |
||
5 | xps_find_resource(xps_context *ctx, xps_resource *dict, char *name, char **urip) |
||
6 | { |
||
7 | xps_resource *head, *node; |
||
8 | for (head = dict; head; head = head->parent) |
||
9 | { |
||
10 | for (node = head; node; node = node->next) |
||
11 | { |
||
12 | if (!strcmp(node->name, name)) |
||
13 | { |
||
14 | if (urip && head->base_uri) |
||
15 | *urip = head->base_uri; |
||
16 | return node->data; |
||
17 | } |
||
18 | } |
||
19 | } |
||
20 | return NULL; |
||
21 | } |
||
22 | |||
23 | static xml_element * |
||
24 | xps_parse_resource_reference(xps_context *ctx, xps_resource *dict, char *att, char **urip) |
||
25 | { |
||
26 | char name[1024]; |
||
27 | char *s; |
||
28 | |||
29 | if (strstr(att, "{StaticResource ") != att) |
||
30 | return NULL; |
||
31 | |||
32 | fz_strlcpy(name, att + 16, sizeof name); |
||
33 | s = strrchr(name, '}'); |
||
34 | if (s) |
||
35 | *s = 0; |
||
36 | |||
37 | return xps_find_resource(ctx, dict, name, urip); |
||
38 | } |
||
39 | |||
40 | void |
||
41 | xps_resolve_resource_reference(xps_context *ctx, xps_resource *dict, |
||
42 | char **attp, xml_element **tagp, char **urip) |
||
43 | { |
||
44 | if (*attp) |
||
45 | { |
||
46 | xml_element *rsrc = xps_parse_resource_reference(ctx, dict, *attp, urip); |
||
47 | if (rsrc) |
||
48 | { |
||
49 | *attp = NULL; |
||
50 | *tagp = rsrc; |
||
51 | } |
||
52 | } |
||
53 | } |
||
54 | |||
55 | static int |
||
56 | xps_parse_remote_resource_dictionary(xps_context *ctx, xps_resource **dictp, char *base_uri, char *source_att) |
||
57 | { |
||
58 | char part_name[1024]; |
||
59 | char part_uri[1024]; |
||
60 | xps_resource *dict; |
||
61 | xps_part *part; |
||
62 | xml_element *xml; |
||
63 | char *s; |
||
64 | int code; |
||
65 | |||
66 | /* External resource dictionaries MUST NOT reference other resource dictionaries */ |
||
67 | xps_absolute_path(part_name, base_uri, source_att, sizeof part_name); |
||
68 | part = xps_read_part(ctx, part_name); |
||
69 | if (!part) |
||
70 | { |
||
71 | return fz_throw("cannot find remote resource part '%s'", part_name); |
||
72 | } |
||
73 | |||
74 | xml = xml_parse_document(part->data, part->size); |
||
75 | if (!xml) |
||
76 | { |
||
77 | xps_free_part(ctx, part); |
||
78 | return fz_rethrow(-1, "cannot parse xml"); |
||
79 | } |
||
80 | |||
81 | if (strcmp(xml_tag(xml), "ResourceDictionary")) |
||
82 | { |
||
83 | xml_free_element(xml); |
||
84 | xps_free_part(ctx, part); |
||
85 | return fz_throw("expected ResourceDictionary element (found %s)", xml_tag(xml)); |
||
86 | } |
||
87 | |||
88 | fz_strlcpy(part_uri, part_name, sizeof part_uri); |
||
89 | s = strrchr(part_uri, '/'); |
||
90 | if (s) |
||
91 | s[1] = 0; |
||
92 | |||
93 | code = xps_parse_resource_dictionary(ctx, &dict, part_uri, xml); |
||
94 | if (code) |
||
95 | { |
||
96 | xml_free_element(xml); |
||
97 | xps_free_part(ctx, part); |
||
98 | return fz_rethrow(code, "cannot parse remote resource dictionary: %s", part_uri); |
||
99 | } |
||
100 | |||
101 | dict->base_xml = xml; /* pass on ownership */ |
||
102 | |||
103 | xps_free_part(ctx, part); |
||
104 | |||
105 | *dictp = dict; |
||
106 | return fz_okay; |
||
107 | } |
||
108 | |||
109 | int |
||
110 | xps_parse_resource_dictionary(xps_context *ctx, xps_resource **dictp, char *base_uri, xml_element *root) |
||
111 | { |
||
112 | xps_resource *head; |
||
113 | xps_resource *entry; |
||
114 | xml_element *node; |
||
115 | char *source; |
||
116 | char *key; |
||
117 | int code; |
||
118 | |||
119 | source = xml_att(root, "Source"); |
||
120 | if (source) |
||
121 | { |
||
122 | code = xps_parse_remote_resource_dictionary(ctx, dictp, base_uri, source); |
||
123 | if (code) |
||
124 | return fz_rethrow(code, "cannot parse remote resource dictionary"); |
||
125 | return fz_okay; |
||
126 | } |
||
127 | |||
128 | head = NULL; |
||
129 | |||
130 | for (node = xml_down(root); node; node = xml_next(node)) |
||
131 | { |
||
132 | key = xml_att(node, "x:Key"); |
||
133 | if (key) |
||
134 | { |
||
135 | entry = fz_malloc(sizeof(xps_resource)); |
||
136 | entry->name = key; |
||
137 | entry->base_uri = NULL; |
||
138 | entry->base_xml = NULL; |
||
139 | entry->data = node; |
||
140 | entry->next = head; |
||
141 | entry->parent = NULL; |
||
142 | head = entry; |
||
143 | } |
||
144 | } |
||
145 | |||
146 | if (head) |
||
147 | head->base_uri = fz_strdup(base_uri); |
||
148 | else |
||
149 | return fz_throw("empty resource dictionary"); |
||
150 | |||
151 | *dictp = head; |
||
152 | return fz_okay; |
||
153 | } |
||
154 | |||
155 | void |
||
156 | xps_free_resource_dictionary(xps_context *ctx, xps_resource *dict) |
||
157 | { |
||
158 | xps_resource *next; |
||
159 | while (dict) |
||
160 | { |
||
161 | next = dict->next; |
||
162 | if (dict->base_xml) |
||
163 | xml_free_element(dict->base_xml); |
||
164 | if (dict->base_uri) |
||
165 | fz_free(dict->base_uri); |
||
166 | fz_free(dict); |
||
167 | dict = next; |
||
168 | } |
||
169 | } |
||
170 | |||
171 | void |
||
172 | xps_debug_resource_dictionary(xps_resource *dict) |
||
173 | { |
||
174 | while (dict) |
||
175 | { |
||
176 | if (dict->base_uri) |
||
177 | printf("URI = '%s'\n", dict->base_uri); |
||
178 | printf("KEY = '%s' VAL = %p\n", dict->name, dict->data); |
||
179 | if (dict->parent) |
||
180 | { |
||
181 | printf("PARENT = {\n"); |
||
182 | xps_debug_resource_dictionary(dict->parent); |
||
183 | printf("}\n"); |
||
184 | } |
||
185 | dict = dict->next; |
||
186 | } |
||
187 | } |