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