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 | |
9 | static void |
10 | xps_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 | |
13 | static void |
14 | xps_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 | |
21 | static void |
22 | xps_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 | |
56 | static void |
57 | xps_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 | |
105 | static void |
106 | xps_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 | |
141 | static void |
142 | xps_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 | |
158 | static void |
159 | xps_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 | |
187 | fz_link * |
188 | xps_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 | |