]> rtime.felk.cvut.cz Git - hornmich/skoda-qr-demo.git/blob - QRScanner/mobile/jni/xps/xps-common.c
Add MuPDF native source codes
[hornmich/skoda-qr-demo.git] / QRScanner / mobile / jni / xps / xps-common.c
1 #include "mupdf/xps.h"
2
3 static inline int unhex(int a)
4 {
5         if (a >= 'A' && a <= 'F') return a - 'A' + 0xA;
6         if (a >= 'a' && a <= 'f') return a - 'a' + 0xA;
7         if (a >= '0' && a <= '9') return a - '0';
8         return 0;
9 }
10
11 fz_xml *
12 xps_lookup_alternate_content(fz_xml *node)
13 {
14         for (node = fz_xml_down(node); node; node = fz_xml_next(node))
15         {
16                 if (fz_xml_is_tag(node, "Choice") && fz_xml_att(node, "Requires"))
17                 {
18                         char list[64];
19                         char *next = list, *item;
20                         fz_strlcpy(list, fz_xml_att(node, "Requires"), sizeof(list));
21                         while ((item = fz_strsep(&next, " \t\r\n")) != NULL && (!*item || !strcmp(item, "xps")));
22                         if (!item)
23                                 return fz_xml_down(node);
24                 }
25                 else if (fz_xml_is_tag(node, "Fallback"))
26                         return fz_xml_down(node);
27         }
28         return NULL;
29 }
30
31 void
32 xps_parse_brush(xps_document *doc, const fz_matrix *ctm, const fz_rect *area, char *base_uri, xps_resource *dict, fz_xml *node)
33 {
34         if (doc->cookie && doc->cookie->abort)
35                 return;
36         /* SolidColorBrushes are handled in a special case and will never show up here */
37         if (fz_xml_is_tag(node, "ImageBrush"))
38                 xps_parse_image_brush(doc, ctm, area, base_uri, dict, node);
39         else if (fz_xml_is_tag(node, "VisualBrush"))
40                 xps_parse_visual_brush(doc, ctm, area, base_uri, dict, node);
41         else if (fz_xml_is_tag(node, "LinearGradientBrush"))
42                 xps_parse_linear_gradient_brush(doc, ctm, area, base_uri, dict, node);
43         else if (fz_xml_is_tag(node, "RadialGradientBrush"))
44                 xps_parse_radial_gradient_brush(doc, ctm, area, base_uri, dict, node);
45         else
46                 fz_warn(doc->ctx, "unknown brush tag: %s", fz_xml_tag(node));
47 }
48
49 void
50 xps_parse_element(xps_document *doc, const fz_matrix *ctm, const fz_rect *area, char *base_uri, xps_resource *dict, fz_xml *node)
51 {
52         if (doc->cookie && doc->cookie->abort)
53                 return;
54         if (fz_xml_is_tag(node, "Path"))
55                 xps_parse_path(doc, ctm, base_uri, dict, node);
56         if (fz_xml_is_tag(node, "Glyphs"))
57                 xps_parse_glyphs(doc, ctm, base_uri, dict, node);
58         if (fz_xml_is_tag(node, "Canvas"))
59                 xps_parse_canvas(doc, ctm, area, base_uri, dict, node);
60         if (fz_xml_is_tag(node, "AlternateContent"))
61         {
62                 node = xps_lookup_alternate_content(node);
63                 if (node)
64                         xps_parse_element(doc, ctm, area, base_uri, dict, node);
65         }
66         /* skip unknown tags (like Foo.Resources and similar) */
67 }
68
69 void
70 xps_begin_opacity(xps_document *doc, const fz_matrix *ctm, const fz_rect *area,
71         char *base_uri, xps_resource *dict,
72         char *opacity_att, fz_xml *opacity_mask_tag)
73 {
74         float opacity;
75
76         if (!opacity_att && !opacity_mask_tag)
77                 return;
78
79         opacity = 1;
80         if (opacity_att)
81                 opacity = fz_atof(opacity_att);
82
83         if (opacity_mask_tag && !strcmp(fz_xml_tag(opacity_mask_tag), "SolidColorBrush"))
84         {
85                 char *scb_opacity_att = fz_xml_att(opacity_mask_tag, "Opacity");
86                 char *scb_color_att = fz_xml_att(opacity_mask_tag, "Color");
87                 if (scb_opacity_att)
88                         opacity = opacity * fz_atof(scb_opacity_att);
89                 if (scb_color_att)
90                 {
91                         fz_colorspace *colorspace;
92                         float samples[FZ_MAX_COLORS];
93                         xps_parse_color(doc, base_uri, scb_color_att, &colorspace, samples);
94                         opacity = opacity * samples[0];
95                 }
96                 opacity_mask_tag = NULL;
97         }
98
99         if (doc->opacity_top + 1 < nelem(doc->opacity))
100         {
101                 doc->opacity[doc->opacity_top + 1] = doc->opacity[doc->opacity_top] * opacity;
102                 doc->opacity_top++;
103         }
104
105         if (opacity_mask_tag)
106         {
107                 fz_begin_mask(doc->dev, area, 0, NULL, NULL);
108                 xps_parse_brush(doc, ctm, area, base_uri, dict, opacity_mask_tag);
109                 fz_end_mask(doc->dev);
110         }
111 }
112
113 void
114 xps_end_opacity(xps_document *doc, char *base_uri, xps_resource *dict,
115         char *opacity_att, fz_xml *opacity_mask_tag)
116 {
117         if (!opacity_att && !opacity_mask_tag)
118                 return;
119
120         if (doc->opacity_top > 0)
121                 doc->opacity_top--;
122
123         if (opacity_mask_tag)
124         {
125                 if (strcmp(fz_xml_tag(opacity_mask_tag), "SolidColorBrush"))
126                         fz_pop_clip(doc->dev);
127         }
128 }
129
130 void
131 xps_parse_render_transform(xps_document *doc, char *transform, fz_matrix *matrix)
132 {
133         float args[6];
134         char *s = transform;
135         int i;
136
137         args[0] = 1; args[1] = 0;
138         args[2] = 0; args[3] = 1;
139         args[4] = 0; args[5] = 0;
140
141         for (i = 0; i < 6 && *s; i++)
142         {
143                 args[i] = fz_atof(s);
144                 while (*s && *s != ',')
145                         s++;
146                 if (*s == ',')
147                         s++;
148         }
149
150         matrix->a = args[0]; matrix->b = args[1];
151         matrix->c = args[2]; matrix->d = args[3];
152         matrix->e = args[4]; matrix->f = args[5];
153 }
154
155 void
156 xps_parse_matrix_transform(xps_document *doc, fz_xml *root, fz_matrix *matrix)
157 {
158         char *transform;
159
160         *matrix = fz_identity;
161
162         if (fz_xml_is_tag(root, "MatrixTransform"))
163         {
164                 transform = fz_xml_att(root, "Matrix");
165                 if (transform)
166                         xps_parse_render_transform(doc, transform, matrix);
167         }
168 }
169
170 void
171 xps_parse_rectangle(xps_document *doc, char *text, fz_rect *rect)
172 {
173         float args[4];
174         char *s = text;
175         int i;
176
177         args[0] = 0; args[1] = 0;
178         args[2] = 1; args[3] = 1;
179
180         for (i = 0; i < 4 && *s; i++)
181         {
182                 args[i] = fz_atof(s);
183                 while (*s && *s != ',')
184                         s++;
185                 if (*s == ',')
186                         s++;
187         }
188
189         rect->x0 = args[0];
190         rect->y0 = args[1];
191         rect->x1 = args[0] + args[2];
192         rect->y1 = args[1] + args[3];
193 }
194
195 static int count_commas(char *s)
196 {
197         int n = 0;
198         while (*s)
199         {
200                 if (*s == ',')
201                         n ++;
202                 s ++;
203         }
204         return n;
205 }
206
207 void
208 xps_parse_color(xps_document *doc, char *base_uri, char *string,
209                 fz_colorspace **csp, float *samples)
210 {
211         fz_context *ctx = doc->ctx;
212         char *p;
213         int i, n;
214         char buf[1024];
215         char *profile;
216
217         *csp = fz_device_rgb(ctx);
218
219         samples[0] = 1;
220         samples[1] = 0;
221         samples[2] = 0;
222         samples[3] = 0;
223
224         if (string[0] == '#')
225         {
226                 if (strlen(string) == 9)
227                 {
228                         samples[0] = unhex(string[1]) * 16 + unhex(string[2]);
229                         samples[1] = unhex(string[3]) * 16 + unhex(string[4]);
230                         samples[2] = unhex(string[5]) * 16 + unhex(string[6]);
231                         samples[3] = unhex(string[7]) * 16 + unhex(string[8]);
232                 }
233                 else
234                 {
235                         samples[0] = 255;
236                         samples[1] = unhex(string[1]) * 16 + unhex(string[2]);
237                         samples[2] = unhex(string[3]) * 16 + unhex(string[4]);
238                         samples[3] = unhex(string[5]) * 16 + unhex(string[6]);
239                 }
240
241                 samples[0] /= 255;
242                 samples[1] /= 255;
243                 samples[2] /= 255;
244                 samples[3] /= 255;
245         }
246
247         else if (string[0] == 's' && string[1] == 'c' && string[2] == '#')
248         {
249                 if (count_commas(string) == 2)
250                         sscanf(string, "sc#%g,%g,%g", samples + 1, samples + 2, samples + 3);
251                 if (count_commas(string) == 3)
252                         sscanf(string, "sc#%g,%g,%g,%g", samples, samples + 1, samples + 2, samples + 3);
253         }
254
255         else if (strstr(string, "ContextColor ") == string)
256         {
257                 /* Crack the string for profile name and sample values */
258                 fz_strlcpy(buf, string, sizeof buf);
259
260                 profile = strchr(buf, ' ');
261                 if (!profile)
262                 {
263                         fz_warn(ctx, "cannot find icc profile uri in '%s'", string);
264                         return;
265                 }
266
267                 *profile++ = 0;
268                 p = strchr(profile, ' ');
269                 if (!p)
270                 {
271                         fz_warn(ctx, "cannot find component values in '%s'", profile);
272                         return;
273                 }
274
275                 *p++ = 0;
276                 n = count_commas(p) + 1;
277                 if (n > FZ_MAX_COLORS)
278                 {
279                         fz_warn(ctx, "ignoring %d color components (max %d allowed)", n - FZ_MAX_COLORS, FZ_MAX_COLORS);
280                         n = FZ_MAX_COLORS;
281                 }
282                 i = 0;
283                 while (i < n)
284                 {
285                         samples[i++] = fz_atof(p);
286                         p = strchr(p, ',');
287                         if (!p)
288                                 break;
289                         p ++;
290                         if (*p == ' ')
291                                 p ++;
292                 }
293                 while (i < n)
294                 {
295                         samples[i++] = 0;
296                 }
297
298                 /* TODO: load ICC profile */
299                 switch (n)
300                 {
301                 case 2: *csp = fz_device_gray(ctx); break;
302                 case 4: *csp = fz_device_rgb(ctx); break;
303                 case 5: *csp = fz_device_cmyk(ctx); break;
304                 default: *csp = fz_device_gray(ctx); break;
305                 }
306         }
307 }
308
309 void
310 xps_set_color(xps_document *doc, fz_colorspace *colorspace, float *samples)
311 {
312         int i;
313         doc->colorspace = colorspace;
314         for (i = 0; i < colorspace->n; i++)
315                 doc->color[i] = samples[i + 1];
316         doc->alpha = samples[0] * doc->opacity[doc->opacity_top];
317 }