3 static inline int unhex(int a)
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';
12 xps_lookup_alternate_content(fz_xml *node)
14 for (node = fz_xml_down(node); node; node = fz_xml_next(node))
16 if (fz_xml_is_tag(node, "Choice") && fz_xml_att(node, "Requires"))
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")));
23 return fz_xml_down(node);
25 else if (fz_xml_is_tag(node, "Fallback"))
26 return fz_xml_down(node);
32 xps_parse_brush(xps_document *doc, const fz_matrix *ctm, const fz_rect *area, char *base_uri, xps_resource *dict, fz_xml *node)
34 if (doc->cookie && doc->cookie->abort)
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);
46 fz_warn(doc->ctx, "unknown brush tag: %s", fz_xml_tag(node));
50 xps_parse_element(xps_document *doc, const fz_matrix *ctm, const fz_rect *area, char *base_uri, xps_resource *dict, fz_xml *node)
52 if (doc->cookie && doc->cookie->abort)
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"))
62 node = xps_lookup_alternate_content(node);
64 xps_parse_element(doc, ctm, area, base_uri, dict, node);
66 /* skip unknown tags (like Foo.Resources and similar) */
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)
76 if (!opacity_att && !opacity_mask_tag)
81 opacity = fz_atof(opacity_att);
83 if (opacity_mask_tag && !strcmp(fz_xml_tag(opacity_mask_tag), "SolidColorBrush"))
85 char *scb_opacity_att = fz_xml_att(opacity_mask_tag, "Opacity");
86 char *scb_color_att = fz_xml_att(opacity_mask_tag, "Color");
88 opacity = opacity * fz_atof(scb_opacity_att);
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];
96 opacity_mask_tag = NULL;
99 if (doc->opacity_top + 1 < nelem(doc->opacity))
101 doc->opacity[doc->opacity_top + 1] = doc->opacity[doc->opacity_top] * opacity;
105 if (opacity_mask_tag)
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);
114 xps_end_opacity(xps_document *doc, char *base_uri, xps_resource *dict,
115 char *opacity_att, fz_xml *opacity_mask_tag)
117 if (!opacity_att && !opacity_mask_tag)
120 if (doc->opacity_top > 0)
123 if (opacity_mask_tag)
125 if (strcmp(fz_xml_tag(opacity_mask_tag), "SolidColorBrush"))
126 fz_pop_clip(doc->dev);
131 xps_parse_render_transform(xps_document *doc, char *transform, fz_matrix *matrix)
137 args[0] = 1; args[1] = 0;
138 args[2] = 0; args[3] = 1;
139 args[4] = 0; args[5] = 0;
141 for (i = 0; i < 6 && *s; i++)
143 args[i] = fz_atof(s);
144 while (*s && *s != ',')
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];
156 xps_parse_matrix_transform(xps_document *doc, fz_xml *root, fz_matrix *matrix)
160 *matrix = fz_identity;
162 if (fz_xml_is_tag(root, "MatrixTransform"))
164 transform = fz_xml_att(root, "Matrix");
166 xps_parse_render_transform(doc, transform, matrix);
171 xps_parse_rectangle(xps_document *doc, char *text, fz_rect *rect)
177 args[0] = 0; args[1] = 0;
178 args[2] = 1; args[3] = 1;
180 for (i = 0; i < 4 && *s; i++)
182 args[i] = fz_atof(s);
183 while (*s && *s != ',')
191 rect->x1 = args[0] + args[2];
192 rect->y1 = args[1] + args[3];
195 static int count_commas(char *s)
208 xps_parse_color(xps_document *doc, char *base_uri, char *string,
209 fz_colorspace **csp, float *samples)
211 fz_context *ctx = doc->ctx;
217 *csp = fz_device_rgb(ctx);
224 if (string[0] == '#')
226 if (strlen(string) == 9)
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]);
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]);
247 else if (string[0] == 's' && string[1] == 'c' && string[2] == '#')
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);
255 else if (strstr(string, "ContextColor ") == string)
257 /* Crack the string for profile name and sample values */
258 fz_strlcpy(buf, string, sizeof buf);
260 profile = strchr(buf, ' ');
263 fz_warn(ctx, "cannot find icc profile uri in '%s'", string);
268 p = strchr(profile, ' ');
271 fz_warn(ctx, "cannot find component values in '%s'", profile);
276 n = count_commas(p) + 1;
277 if (n > FZ_MAX_COLORS)
279 fz_warn(ctx, "ignoring %d color components (max %d allowed)", n - FZ_MAX_COLORS, FZ_MAX_COLORS);
285 samples[i++] = fz_atof(p);
298 /* TODO: load ICC profile */
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;
310 xps_set_color(xps_document *doc, fz_colorspace *colorspace, float *samples)
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];