1#include "mupdf/fitz.h"
2#include "xps-imp.h"
3
4#include <string.h>
5#include <stdlib.h>
6
7/* Quick parsing of document to find links. */
8
9static void
10xps_load_links_in_element(fz_context *ctx, xps_document *doc, fz_matrix ctm,
11 char *base_uri, xps_resource *dict, fz_xml *node, fz_link **link);
12
13static void
14xps_add_link(fz_context *ctx, xps_document *doc, fz_rect area, char *base_uri, char *target_uri, fz_link **head)
15{
16 fz_link *link = fz_new_link(ctx, area, doc, target_uri);
17 link->next = *head;
18 *head = link;
19}
20
21static void
22xps_load_links_in_path(fz_context *ctx, xps_document *doc, fz_matrix ctm,
23 char *base_uri, xps_resource *dict, fz_xml *root, fz_link **link)
24{
25 char *navigate_uri_att = fz_xml_att(root, "FixedPage.NavigateUri");
26 if (navigate_uri_att)
27 {
28 char *transform_att = fz_xml_att(root, "RenderTransform");
29 fz_xml *transform_tag = fz_xml_down(fz_xml_find_down(root, "Path.RenderTransform"));
30
31 char *data_att = fz_xml_att(root, "Data");
32 fz_xml *data_tag = fz_xml_down(fz_xml_find_down(root, "Path.Data"));
33
34 fz_path *path = NULL;
35 int fill_rule;
36 fz_rect area;
37
38 xps_resolve_resource_reference(ctx, doc, dict, &data_att, &data_tag, NULL);
39 xps_resolve_resource_reference(ctx, doc, dict, &transform_att, &transform_tag, NULL);
40
41 ctm = xps_parse_transform(ctx, doc, transform_att, transform_tag, ctm);
42
43 if (data_att)
44 path = xps_parse_abbreviated_geometry(ctx, doc, data_att, &fill_rule);
45 else if (data_tag)
46 path = xps_parse_path_geometry(ctx, doc, dict, data_tag, 0, &fill_rule);
47 if (path)
48 {
49 area = fz_bound_path(ctx, path, NULL, ctm);
50 fz_drop_path(ctx, path);
51 xps_add_link(ctx, doc, area, base_uri, navigate_uri_att, link);
52 }
53 }
54}
55
56static void
57xps_load_links_in_glyphs(fz_context *ctx, xps_document *doc, fz_matrix ctm,
58 char *base_uri, xps_resource *dict, fz_xml *root, fz_link **link)
59{
60 char *navigate_uri_att = fz_xml_att(root, "FixedPage.NavigateUri");
61 if (navigate_uri_att)
62 {
63 char *transform_att = fz_xml_att(root, "RenderTransform");
64 fz_xml *transform_tag = fz_xml_down(fz_xml_find_down(root, "Path.RenderTransform"));
65
66 char *bidi_level_att = fz_xml_att(root, "BidiLevel");
67 char *font_size_att = fz_xml_att(root, "FontRenderingEmSize");
68 char *font_uri_att = fz_xml_att(root, "FontUri");
69 char *origin_x_att = fz_xml_att(root, "OriginX");
70 char *origin_y_att = fz_xml_att(root, "OriginY");
71 char *is_sideways_att = fz_xml_att(root, "IsSideways");
72 char *indices_att = fz_xml_att(root, "Indices");
73 char *unicode_att = fz_xml_att(root, "UnicodeString");
74 char *style_att = fz_xml_att(root, "StyleSimulations");
75
76 int is_sideways = 0;
77 int bidi_level = 0;
78 fz_font *font;
79 fz_text *text;
80 fz_rect area;
81
82 xps_resolve_resource_reference(ctx, doc, dict, &transform_att, &transform_tag, NULL);
83
84 ctm = xps_parse_transform(ctx, doc, transform_att, transform_tag, ctm);
85
86 if (is_sideways_att)
87 is_sideways = !strcmp(is_sideways_att, "true");
88 if (bidi_level_att)
89 bidi_level = atoi(bidi_level_att);
90
91 font = xps_lookup_font(ctx, doc, base_uri, font_uri_att, style_att);
92 if (!font)
93 return;
94 text = xps_parse_glyphs_imp(ctx, doc, ctm, font, fz_atof(font_size_att),
95 fz_atof(origin_x_att), fz_atof(origin_y_att),
96 is_sideways, bidi_level, indices_att, unicode_att);
97 area = fz_bound_text(ctx, text, NULL, ctm);
98 fz_drop_text(ctx, text);
99 fz_drop_font(ctx, font);
100
101 xps_add_link(ctx, doc, area, base_uri, navigate_uri_att, link);
102 }
103}
104
105static void
106xps_load_links_in_canvas(fz_context *ctx, xps_document *doc, fz_matrix ctm,
107 char *base_uri, xps_resource *dict, fz_xml *root, fz_link **link)
108{
109 xps_resource *new_dict = NULL;
110 fz_xml *node;
111
112 char *navigate_uri_att = fz_xml_att(root, "FixedPage.NavigateUri");
113 char *transform_att = fz_xml_att(root, "RenderTransform");
114 fz_xml *transform_tag = fz_xml_down(fz_xml_find_down(root, "Canvas.RenderTransform"));
115 fz_xml *resource_tag = fz_xml_down(fz_xml_find_down(root, "Canvas.Resources"));
116
117 if (resource_tag)
118 {
119 new_dict = xps_parse_resource_dictionary(ctx, doc, base_uri, resource_tag);
120 if (new_dict)
121 {
122 new_dict->parent = dict;
123 dict = new_dict;
124 }
125 }
126
127 xps_resolve_resource_reference(ctx, doc, dict, &transform_att, &transform_tag, NULL);
128
129 ctm = xps_parse_transform(ctx, doc, transform_att, transform_tag, ctm);
130
131 if (navigate_uri_att)
132 fz_warn(ctx, "FixedPage.NavigateUri attribute on Canvas element");
133
134 for (node = fz_xml_down(root); node; node = fz_xml_next(node))
135 xps_load_links_in_element(ctx, doc, ctm, base_uri, dict, node, link);
136
137 if (new_dict)
138 xps_drop_resource_dictionary(ctx, doc, new_dict);
139}
140
141static void
142xps_load_links_in_element(fz_context *ctx, xps_document *doc, fz_matrix ctm, char *base_uri, xps_resource *dict, fz_xml *node, fz_link **link)
143{
144 if (fz_xml_is_tag(node, "Path"))
145 xps_load_links_in_path(ctx, doc, ctm, base_uri, dict, node, link);
146 else if (fz_xml_is_tag(node, "Glyphs"))
147 xps_load_links_in_glyphs(ctx, doc, ctm, base_uri, dict, node, link);
148 else if (fz_xml_is_tag(node, "Canvas"))
149 xps_load_links_in_canvas(ctx, doc, ctm, base_uri, dict, node, link);
150 else if (fz_xml_is_tag(node, "AlternateContent"))
151 {
152 node = xps_lookup_alternate_content(ctx, doc, node);
153 if (node)
154 xps_load_links_in_element(ctx, doc, ctm, base_uri, dict, node, link);
155 }
156}
157
158static void
159xps_load_links_in_fixed_page(fz_context *ctx, xps_document *doc, fz_matrix ctm, xps_page *page, fz_link **link)
160{
161 fz_xml *root, *node, *resource_tag;
162 xps_resource *dict = NULL;
163 char base_uri[1024];
164 char *s;
165
166 root = fz_xml_root(page->xml);
167
168 if (!root)
169 return;
170
171 fz_strlcpy(base_uri, page->fix->name, sizeof base_uri);
172 s = strrchr(base_uri, '/');
173 if (s)
174 s[1] = 0;
175
176 resource_tag = fz_xml_down(fz_xml_find_down(root, "FixedPage.Resources"));
177 if (resource_tag)
178 dict = xps_parse_resource_dictionary(ctx, doc, base_uri, resource_tag);
179
180 for (node = fz_xml_down(root); node; node = fz_xml_next(node))
181 xps_load_links_in_element(ctx, doc, ctm, base_uri, dict, node, link);
182
183 if (dict)
184 xps_drop_resource_dictionary(ctx, doc, dict);
185}
186
187fz_link *
188xps_load_links(fz_context *ctx, fz_page *page_)
189{
190 xps_page *page = (xps_page*)page_;
191 fz_matrix ctm;
192 fz_link *link = NULL;
193 ctm = fz_scale(72.0f / 96.0f, 72.0f / 96.0f);
194 xps_load_links_in_fixed_page(ctx, page->doc, ctm, page, &link);
195 return link;
196}
197