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 | #define TILE |
||
5 | |||
6 | /* |
||
7 | * Parse a tiling brush (visual and image brushes at this time) common |
||
8 | * properties. Use the callback to draw the individual tiles. |
||
9 | */ |
||
10 | |||
11 | enum { TILE_NONE, TILE_TILE, TILE_FLIP_X, TILE_FLIP_Y, TILE_FLIP_X_Y }; |
||
12 | |||
13 | struct closure |
||
14 | { |
||
15 | char *base_uri; |
||
16 | xps_resource *dict; |
||
17 | xml_element *root; |
||
18 | void *user; |
||
19 | void (*func)(xps_context*, fz_matrix, fz_rect, char*, xps_resource*, xml_element*, void*); |
||
20 | }; |
||
21 | |||
22 | static void |
||
23 | xps_paint_tiling_brush_clipped(xps_context *ctx, fz_matrix ctm, fz_rect viewbox, struct closure *c) |
||
24 | { |
||
25 | fz_path *path = fz_new_path(); |
||
26 | fz_moveto(path, viewbox.x0, viewbox.y0); |
||
27 | fz_lineto(path, viewbox.x0, viewbox.y1); |
||
28 | fz_lineto(path, viewbox.x1, viewbox.y1); |
||
29 | fz_lineto(path, viewbox.x1, viewbox.y0); |
||
30 | fz_closepath(path); |
||
31 | fz_clip_path(ctx->dev, path, NULL, 0, ctm); |
||
32 | fz_free_path(path); |
||
33 | c->func(ctx, ctm, viewbox, c->base_uri, c->dict, c->root, c->user); |
||
34 | fz_pop_clip(ctx->dev); |
||
35 | } |
||
36 | |||
37 | static void |
||
38 | xps_paint_tiling_brush(xps_context *ctx, fz_matrix ctm, fz_rect viewbox, int tile_mode, struct closure *c) |
||
39 | { |
||
40 | fz_matrix ttm; |
||
41 | |||
42 | xps_paint_tiling_brush_clipped(ctx, ctm, viewbox, c); |
||
43 | |||
44 | if (tile_mode == TILE_FLIP_X || tile_mode == TILE_FLIP_X_Y) |
||
45 | { |
||
46 | ttm = fz_concat(fz_translate(viewbox.x1 * 2, 0), ctm); |
||
47 | ttm = fz_concat(fz_scale(-1, 1), ttm); |
||
48 | xps_paint_tiling_brush_clipped(ctx, ttm, viewbox, c); |
||
49 | } |
||
50 | |||
51 | if (tile_mode == TILE_FLIP_Y || tile_mode == TILE_FLIP_X_Y) |
||
52 | { |
||
53 | ttm = fz_concat(fz_translate(0, viewbox.y1 * 2), ctm); |
||
54 | ttm = fz_concat(fz_scale(1, -1), ttm); |
||
55 | xps_paint_tiling_brush_clipped(ctx, ttm, viewbox, c); |
||
56 | } |
||
57 | |||
58 | if (tile_mode == TILE_FLIP_X_Y) |
||
59 | { |
||
60 | ttm = fz_concat(fz_translate(viewbox.x1 * 2, viewbox.y1 * 2), ctm); |
||
61 | ttm = fz_concat(fz_scale(-1, -1), ttm); |
||
62 | xps_paint_tiling_brush_clipped(ctx, ttm, viewbox, c); |
||
63 | } |
||
64 | } |
||
65 | |||
66 | void |
||
67 | xps_parse_tiling_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, |
||
68 | char *base_uri, xps_resource *dict, xml_element *root, |
||
69 | void (*func)(xps_context*, fz_matrix, fz_rect, char*, xps_resource*, xml_element*, void*), void *user) |
||
70 | { |
||
71 | xml_element *node; |
||
72 | struct closure c; |
||
73 | |||
74 | char *opacity_att; |
||
75 | char *transform_att; |
||
76 | char *viewbox_att; |
||
77 | char *viewport_att; |
||
78 | char *tile_mode_att; |
||
79 | char *viewbox_units_att; |
||
80 | char *viewport_units_att; |
||
81 | |||
82 | xml_element *transform_tag = NULL; |
||
83 | |||
84 | fz_matrix transform; |
||
85 | fz_rect viewbox; |
||
86 | fz_rect viewport; |
||
87 | float xstep, ystep; |
||
88 | float xscale, yscale; |
||
89 | int tile_mode; |
||
90 | |||
91 | opacity_att = xml_att(root, "Opacity"); |
||
92 | transform_att = xml_att(root, "Transform"); |
||
93 | viewbox_att = xml_att(root, "Viewbox"); |
||
94 | viewport_att = xml_att(root, "Viewport"); |
||
95 | tile_mode_att = xml_att(root, "TileMode"); |
||
96 | viewbox_units_att = xml_att(root, "ViewboxUnits"); |
||
97 | viewport_units_att = xml_att(root, "ViewportUnits"); |
||
98 | |||
99 | c.base_uri = base_uri; |
||
100 | c.dict = dict; |
||
101 | c.root = root; |
||
102 | c.user = user; |
||
103 | c.func = func; |
||
104 | |||
105 | for (node = xml_down(root); node; node = xml_next(node)) |
||
106 | { |
||
107 | if (!strcmp(xml_tag(node), "ImageBrush.Transform")) |
||
108 | transform_tag = xml_down(node); |
||
109 | if (!strcmp(xml_tag(node), "VisualBrush.Transform")) |
||
110 | transform_tag = xml_down(node); |
||
111 | } |
||
112 | |||
113 | xps_resolve_resource_reference(ctx, dict, &transform_att, &transform_tag, NULL); |
||
114 | |||
115 | transform = fz_identity; |
||
116 | if (transform_att) |
||
117 | xps_parse_render_transform(ctx, transform_att, &transform); |
||
118 | if (transform_tag) |
||
119 | xps_parse_matrix_transform(ctx, transform_tag, &transform); |
||
120 | ctm = fz_concat(transform, ctm); |
||
121 | |||
122 | viewbox = fz_unit_rect; |
||
123 | if (viewbox_att) |
||
124 | xps_parse_rectangle(ctx, viewbox_att, &viewbox); |
||
125 | |||
126 | viewport = fz_unit_rect; |
||
127 | if (viewport_att) |
||
128 | xps_parse_rectangle(ctx, viewport_att, &viewport); |
||
129 | |||
130 | /* some sanity checks on the viewport/viewbox size */ |
||
131 | if (fabsf(viewport.x1 - viewport.x0) < 0.01f) return; |
||
132 | if (fabsf(viewport.y1 - viewport.y0) < 0.01f) return; |
||
133 | if (fabsf(viewbox.x1 - viewbox.x0) < 0.01f) return; |
||
134 | if (fabsf(viewbox.y1 - viewbox.y0) < 0.01f) return; |
||
135 | |||
136 | xstep = viewbox.x1 - viewbox.x0; |
||
137 | ystep = viewbox.y1 - viewbox.y0; |
||
138 | |||
139 | xscale = (viewport.x1 - viewport.x0) / xstep; |
||
140 | yscale = (viewport.y1 - viewport.y0) / ystep; |
||
141 | |||
142 | tile_mode = TILE_NONE; |
||
143 | if (tile_mode_att) |
||
144 | { |
||
145 | if (!strcmp(tile_mode_att, "None")) |
||
146 | tile_mode = TILE_NONE; |
||
147 | if (!strcmp(tile_mode_att, "Tile")) |
||
148 | tile_mode = TILE_TILE; |
||
149 | if (!strcmp(tile_mode_att, "FlipX")) |
||
150 | tile_mode = TILE_FLIP_X; |
||
151 | if (!strcmp(tile_mode_att, "FlipY")) |
||
152 | tile_mode = TILE_FLIP_Y; |
||
153 | if (!strcmp(tile_mode_att, "FlipXY")) |
||
154 | tile_mode = TILE_FLIP_X_Y; |
||
155 | } |
||
156 | |||
157 | if (tile_mode == TILE_FLIP_X || tile_mode == TILE_FLIP_X_Y) |
||
158 | xstep *= 2; |
||
159 | if (tile_mode == TILE_FLIP_Y || tile_mode == TILE_FLIP_X_Y) |
||
160 | ystep *= 2; |
||
161 | |||
162 | xps_begin_opacity(ctx, ctm, area, base_uri, dict, opacity_att, NULL); |
||
163 | |||
164 | ctm = fz_concat(fz_translate(viewport.x0, viewport.y0), ctm); |
||
165 | ctm = fz_concat(fz_scale(xscale, yscale), ctm); |
||
166 | ctm = fz_concat(fz_translate(-viewbox.x0, -viewbox.y0), ctm); |
||
167 | |||
168 | if (tile_mode != TILE_NONE) |
||
169 | { |
||
170 | int x0, y0, x1, y1; |
||
171 | fz_matrix invctm = fz_invert_matrix(ctm); |
||
172 | area = fz_transform_rect(invctm, area); |
||
173 | x0 = floorf(area.x0 / xstep); |
||
174 | y0 = floorf(area.y0 / ystep); |
||
175 | x1 = ceilf(area.x1 / xstep); |
||
176 | y1 = ceilf(area.y1 / ystep); |
||
177 | |||
178 | #ifdef TILE |
||
179 | { |
||
180 | int n = (x1 - x0) * (y1 - y0); |
||
181 | fz_rect bigview = viewbox; |
||
182 | bigview.x1 = bigview.x0 + xstep; |
||
183 | bigview.y1 = bigview.y0 + ystep; |
||
184 | if (n > 1) |
||
185 | fz_begin_tile(ctx->dev, area, bigview, xstep, ystep, ctm); |
||
186 | if (n > 0) |
||
187 | xps_paint_tiling_brush(ctx, ctm, viewbox, tile_mode, &c); |
||
188 | if (n > 1) |
||
189 | fz_end_tile(ctx->dev); |
||
190 | } |
||
191 | #else |
||
192 | { |
||
193 | int x, y; |
||
194 | for (y = y0; y < y1; y++) |
||
195 | { |
||
196 | for (x = x0; x < x1; x++) |
||
197 | { |
||
198 | fz_matrix ttm = fz_concat(fz_translate(xstep * x, ystep * y), ctm); |
||
199 | xps_paint_tiling_brush(ctx, ttm, viewbox, tile_mode, &c); |
||
200 | } |
||
201 | } |
||
202 | } |
||
203 | #endif |
||
204 | } |
||
205 | else |
||
206 | { |
||
207 | xps_paint_tiling_brush(ctx, ctm, viewbox, tile_mode, &c); |
||
208 | } |
||
209 | |||
210 | xps_end_opacity(ctx, base_uri, dict, opacity_att, NULL); |
||
211 | } |
||
212 | |||
213 | static void |
||
214 | xps_paint_visual_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, |
||
215 | char *base_uri, xps_resource *dict, xml_element *root, void *visual_tag) |
||
216 | { |
||
217 | xps_parse_element(ctx, ctm, area, base_uri, dict, (xml_element *)visual_tag); |
||
218 | } |
||
219 | |||
220 | void |
||
221 | xps_parse_visual_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, |
||
222 | char *base_uri, xps_resource *dict, xml_element *root) |
||
223 | { |
||
224 | xml_element *node; |
||
225 | |||
226 | char *visual_uri; |
||
227 | char *visual_att; |
||
228 | xml_element *visual_tag = NULL; |
||
229 | |||
230 | visual_att = xml_att(root, "Visual"); |
||
231 | |||
232 | for (node = xml_down(root); node; node = xml_next(node)) |
||
233 | { |
||
234 | if (!strcmp(xml_tag(node), "VisualBrush.Visual")) |
||
235 | visual_tag = xml_down(node); |
||
236 | } |
||
237 | |||
238 | visual_uri = base_uri; |
||
239 | xps_resolve_resource_reference(ctx, dict, &visual_att, &visual_tag, &visual_uri); |
||
240 | |||
241 | if (visual_tag) |
||
242 | { |
||
243 | xps_parse_tiling_brush(ctx, ctm, area, |
||
244 | visual_uri, dict, root, xps_paint_visual_brush, visual_tag); |
||
245 | } |
||
246 | } |
||
247 | |||
248 | void |
||
249 | xps_parse_canvas(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *root) |
||
250 | { |
||
251 | xps_resource *new_dict = NULL; |
||
252 | xml_element *node; |
||
253 | char *opacity_mask_uri; |
||
254 | int code; |
||
255 | |||
256 | char *transform_att; |
||
257 | char *clip_att; |
||
258 | char *opacity_att; |
||
259 | char *opacity_mask_att; |
||
260 | |||
261 | xml_element *transform_tag = NULL; |
||
262 | xml_element *clip_tag = NULL; |
||
263 | xml_element *opacity_mask_tag = NULL; |
||
264 | |||
265 | fz_matrix transform; |
||
266 | |||
267 | transform_att = xml_att(root, "RenderTransform"); |
||
268 | clip_att = xml_att(root, "Clip"); |
||
269 | opacity_att = xml_att(root, "Opacity"); |
||
270 | opacity_mask_att = xml_att(root, "OpacityMask"); |
||
271 | |||
272 | for (node = xml_down(root); node; node = xml_next(node)) |
||
273 | { |
||
274 | if (!strcmp(xml_tag(node), "Canvas.Resources") && xml_down(node)) |
||
275 | { |
||
276 | code = xps_parse_resource_dictionary(ctx, &new_dict, base_uri, xml_down(node)); |
||
277 | if (code) |
||
278 | fz_catch(code, "cannot load Canvas.Resources"); |
||
279 | else |
||
280 | { |
||
281 | new_dict->parent = dict; |
||
282 | dict = new_dict; |
||
283 | } |
||
284 | } |
||
285 | |||
286 | if (!strcmp(xml_tag(node), "Canvas.RenderTransform")) |
||
287 | transform_tag = xml_down(node); |
||
288 | if (!strcmp(xml_tag(node), "Canvas.Clip")) |
||
289 | clip_tag = xml_down(node); |
||
290 | if (!strcmp(xml_tag(node), "Canvas.OpacityMask")) |
||
291 | opacity_mask_tag = xml_down(node); |
||
292 | } |
||
293 | |||
294 | opacity_mask_uri = base_uri; |
||
295 | xps_resolve_resource_reference(ctx, dict, &transform_att, &transform_tag, NULL); |
||
296 | xps_resolve_resource_reference(ctx, dict, &clip_att, &clip_tag, NULL); |
||
297 | xps_resolve_resource_reference(ctx, dict, &opacity_mask_att, &opacity_mask_tag, &opacity_mask_uri); |
||
298 | |||
299 | transform = fz_identity; |
||
300 | if (transform_att) |
||
301 | xps_parse_render_transform(ctx, transform_att, &transform); |
||
302 | if (transform_tag) |
||
303 | xps_parse_matrix_transform(ctx, transform_tag, &transform); |
||
304 | ctm = fz_concat(transform, ctm); |
||
305 | |||
306 | if (clip_att || clip_tag) |
||
307 | xps_clip(ctx, ctm, dict, clip_att, clip_tag); |
||
308 | |||
309 | xps_begin_opacity(ctx, ctm, area, opacity_mask_uri, dict, opacity_att, opacity_mask_tag); |
||
310 | |||
311 | for (node = xml_down(root); node; node = xml_next(node)) |
||
312 | { |
||
313 | xps_parse_element(ctx, ctm, area, base_uri, dict, node); |
||
314 | } |
||
315 | |||
316 | xps_end_opacity(ctx, opacity_mask_uri, dict, opacity_att, opacity_mask_tag); |
||
317 | |||
318 | if (clip_att || clip_tag) |
||
319 | fz_pop_clip(ctx->dev); |
||
320 | |||
321 | if (new_dict) |
||
322 | xps_free_resource_dictionary(ctx, new_dict); |
||
323 | } |
||
324 | |||
325 | void |
||
326 | xps_parse_fixed_page(xps_context *ctx, fz_matrix ctm, xps_page *page) |
||
327 | { |
||
328 | xml_element *node; |
||
329 | xps_resource *dict; |
||
330 | char base_uri[1024]; |
||
331 | fz_rect area; |
||
332 | char *s; |
||
333 | int code; |
||
334 | |||
335 | fz_strlcpy(base_uri, page->name, sizeof base_uri); |
||
336 | s = strrchr(base_uri, '/'); |
||
337 | if (s) |
||
338 | s[1] = 0; |
||
339 | |||
340 | dict = NULL; |
||
341 | |||
342 | ctx->opacity_top = 0; |
||
343 | ctx->opacity[0] = 1; |
||
344 | |||
345 | if (!page->root) |
||
346 | return; |
||
347 | |||
348 | area = fz_transform_rect(fz_scale(page->width, page->height), fz_unit_rect); |
||
349 | |||
350 | for (node = xml_down(page->root); node; node = xml_next(node)) |
||
351 | { |
||
352 | if (!strcmp(xml_tag(node), "FixedPage.Resources") && xml_down(node)) |
||
353 | { |
||
354 | code = xps_parse_resource_dictionary(ctx, &dict, base_uri, xml_down(node)); |
||
355 | if (code) |
||
356 | fz_catch(code, "cannot load FixedPage.Resources"); |
||
357 | } |
||
358 | xps_parse_element(ctx, ctm, area, base_uri, dict, node); |
||
359 | } |
||
360 | |||
361 | if (dict) |
||
362 | { |
||
363 | xps_free_resource_dictionary(ctx, dict); |
||
364 | } |
||
365 | }>>>>>> |