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 | |||
3 | typedef struct fz_display_node_s fz_display_node; |
||
4 | |||
5 | #define STACK_SIZE 96 |
||
6 | |||
7 | typedef enum fz_display_command_e |
||
8 | { |
||
9 | FZ_CMD_FILL_PATH, |
||
10 | FZ_CMD_STROKE_PATH, |
||
11 | FZ_CMD_CLIP_PATH, |
||
12 | FZ_CMD_CLIP_STROKE_PATH, |
||
13 | FZ_CMD_FILL_TEXT, |
||
14 | FZ_CMD_STROKE_TEXT, |
||
15 | FZ_CMD_CLIP_TEXT, |
||
16 | FZ_CMD_CLIP_STROKE_TEXT, |
||
17 | FZ_CMD_IGNORE_TEXT, |
||
18 | FZ_CMD_FILL_SHADE, |
||
19 | FZ_CMD_FILL_IMAGE, |
||
20 | FZ_CMD_FILL_IMAGE_MASK, |
||
21 | FZ_CMD_CLIP_IMAGE_MASK, |
||
22 | FZ_CMD_POP_CLIP, |
||
23 | FZ_CMD_BEGIN_MASK, |
||
24 | FZ_CMD_END_MASK, |
||
25 | FZ_CMD_BEGIN_GROUP, |
||
26 | FZ_CMD_END_GROUP, |
||
27 | FZ_CMD_BEGIN_TILE, |
||
28 | FZ_CMD_END_TILE |
||
29 | } fz_display_command; |
||
30 | |||
31 | struct fz_display_node_s |
||
32 | { |
||
33 | fz_display_command cmd; |
||
34 | fz_display_node *next; |
||
35 | fz_rect rect; |
||
36 | union { |
||
37 | fz_path *path; |
||
38 | fz_text *text; |
||
39 | fz_shade *shade; |
||
40 | fz_pixmap *image; |
||
41 | int blendmode; |
||
42 | } item; |
||
43 | fz_stroke_state *stroke; |
||
44 | int flag; /* even_odd, accumulate, isolated/knockout... */ |
||
45 | fz_matrix ctm; |
||
46 | fz_colorspace *colorspace; |
||
47 | float alpha; |
||
48 | float color[FZ_MAX_COLORS]; |
||
49 | }; |
||
50 | |||
51 | struct fz_display_list_s |
||
52 | { |
||
53 | fz_display_node *first; |
||
54 | fz_display_node *last; |
||
55 | |||
56 | int top; |
||
57 | struct { |
||
58 | fz_rect *update; |
||
59 | fz_rect rect; |
||
60 | } stack[STACK_SIZE]; |
||
61 | int tiled; |
||
62 | }; |
||
63 | |||
64 | enum { ISOLATED = 1, KNOCKOUT = 2 }; |
||
65 | |||
66 | static fz_display_node * |
||
67 | fz_new_display_node(fz_display_command cmd, fz_matrix ctm, |
||
68 | fz_colorspace *colorspace, float *color, float alpha) |
||
69 | { |
||
70 | fz_display_node *node; |
||
71 | int i; |
||
72 | |||
73 | node = fz_malloc(sizeof(fz_display_node)); |
||
74 | node->cmd = cmd; |
||
75 | node->next = NULL; |
||
76 | node->rect = fz_empty_rect; |
||
77 | node->item.path = NULL; |
||
78 | node->stroke = NULL; |
||
79 | node->flag = 0; |
||
80 | node->ctm = ctm; |
||
81 | if (colorspace) |
||
82 | { |
||
83 | node->colorspace = fz_keep_colorspace(colorspace); |
||
84 | if (color) |
||
85 | { |
||
86 | for (i = 0; i < node->colorspace->n; i++) |
||
87 | node->color[i] = color[i]; |
||
88 | } |
||
89 | } |
||
90 | else |
||
91 | { |
||
92 | node->colorspace = NULL; |
||
93 | } |
||
94 | node->alpha = alpha; |
||
95 | |||
96 | return node; |
||
97 | } |
||
98 | |||
99 | static fz_stroke_state * |
||
100 | fz_clone_stroke_state(fz_stroke_state *stroke) |
||
101 | { |
||
102 | fz_stroke_state *newstroke = fz_malloc(sizeof(fz_stroke_state)); |
||
103 | *newstroke = *stroke; |
||
104 | return newstroke; |
||
105 | } |
||
106 | |||
107 | static void |
||
108 | fz_append_display_node(fz_display_list *list, fz_display_node *node) |
||
109 | { |
||
110 | switch (node->cmd) |
||
111 | { |
||
112 | case FZ_CMD_CLIP_PATH: |
||
113 | case FZ_CMD_CLIP_STROKE_PATH: |
||
114 | case FZ_CMD_CLIP_IMAGE_MASK: |
||
115 | if (list->top < STACK_SIZE) |
||
116 | { |
||
117 | list->stack[list->top].update = &node->rect; |
||
118 | list->stack[list->top].rect = fz_empty_rect; |
||
119 | } |
||
120 | list->top++; |
||
121 | break; |
||
122 | case FZ_CMD_END_MASK: |
||
123 | case FZ_CMD_CLIP_TEXT: |
||
124 | case FZ_CMD_CLIP_STROKE_TEXT: |
||
125 | if (list->top < STACK_SIZE) |
||
126 | { |
||
127 | list->stack[list->top].update = NULL; |
||
128 | list->stack[list->top].rect = fz_empty_rect; |
||
129 | } |
||
130 | list->top++; |
||
131 | break; |
||
132 | case FZ_CMD_BEGIN_TILE: |
||
133 | list->tiled++; |
||
134 | if (list->top > 0 && list->top < STACK_SIZE) |
||
135 | { |
||
136 | list->stack[list->top-1].rect = fz_infinite_rect; |
||
137 | } |
||
138 | break; |
||
139 | case FZ_CMD_END_TILE: |
||
140 | list->tiled--; |
||
141 | break; |
||
142 | case FZ_CMD_END_GROUP: |
||
143 | break; |
||
144 | case FZ_CMD_POP_CLIP: |
||
145 | if (list->top > STACK_SIZE) |
||
146 | { |
||
147 | list->top--; |
||
148 | node->rect = fz_infinite_rect; |
||
149 | } |
||
150 | else if (list->top > 0) |
||
151 | { |
||
152 | fz_rect *update; |
||
153 | list->top--; |
||
154 | update = list->stack[list->top].update; |
||
155 | if (list->tiled == 0) |
||
156 | { |
||
157 | if (update != NULL) |
||
158 | { |
||
159 | *update = fz_intersect_rect(*update, list->stack[list->top].rect); |
||
160 | node->rect = *update; |
||
161 | } |
||
162 | else |
||
163 | node->rect = list->stack[list->top].rect; |
||
164 | } |
||
165 | else |
||
166 | node->rect = fz_infinite_rect; |
||
167 | } |
||
168 | /* fallthrough */ |
||
169 | default: |
||
170 | if (list->top > 0 && list->tiled == 0 && list->top <= STACK_SIZE) |
||
171 | list->stack[list->top-1].rect = fz_union_rect(list->stack[list->top-1].rect, node->rect); |
||
172 | break; |
||
173 | } |
||
174 | if (!list->first) |
||
175 | { |
||
176 | list->first = node; |
||
177 | list->last = node; |
||
178 | } |
||
179 | else |
||
180 | { |
||
181 | list->last->next = node; |
||
182 | list->last = node; |
||
183 | } |
||
184 | } |
||
185 | |||
186 | static void |
||
187 | fz_free_display_node(fz_display_node *node) |
||
188 | { |
||
189 | switch (node->cmd) |
||
190 | { |
||
191 | case FZ_CMD_FILL_PATH: |
||
192 | case FZ_CMD_STROKE_PATH: |
||
193 | case FZ_CMD_CLIP_PATH: |
||
194 | case FZ_CMD_CLIP_STROKE_PATH: |
||
195 | fz_free_path(node->item.path); |
||
196 | break; |
||
197 | case FZ_CMD_FILL_TEXT: |
||
198 | case FZ_CMD_STROKE_TEXT: |
||
199 | case FZ_CMD_CLIP_TEXT: |
||
200 | case FZ_CMD_CLIP_STROKE_TEXT: |
||
201 | case FZ_CMD_IGNORE_TEXT: |
||
202 | fz_free_text(node->item.text); |
||
203 | break; |
||
204 | case FZ_CMD_FILL_SHADE: |
||
205 | fz_drop_shade(node->item.shade); |
||
206 | break; |
||
207 | case FZ_CMD_FILL_IMAGE: |
||
208 | case FZ_CMD_FILL_IMAGE_MASK: |
||
209 | case FZ_CMD_CLIP_IMAGE_MASK: |
||
210 | fz_drop_pixmap(node->item.image); |
||
211 | break; |
||
212 | case FZ_CMD_POP_CLIP: |
||
213 | case FZ_CMD_BEGIN_MASK: |
||
214 | case FZ_CMD_END_MASK: |
||
215 | case FZ_CMD_BEGIN_GROUP: |
||
216 | case FZ_CMD_END_GROUP: |
||
217 | case FZ_CMD_BEGIN_TILE: |
||
218 | case FZ_CMD_END_TILE: |
||
219 | break; |
||
220 | } |
||
221 | if (node->stroke) |
||
222 | fz_free(node->stroke); |
||
223 | if (node->colorspace) |
||
224 | fz_drop_colorspace(node->colorspace); |
||
225 | fz_free(node); |
||
226 | } |
||
227 | |||
228 | static void |
||
229 | fz_list_fill_path(void *user, fz_path *path, int even_odd, fz_matrix ctm, |
||
230 | fz_colorspace *colorspace, float *color, float alpha) |
||
231 | { |
||
232 | fz_display_node *node; |
||
233 | node = fz_new_display_node(FZ_CMD_FILL_PATH, ctm, colorspace, color, alpha); |
||
234 | node->rect = fz_bound_path(path, NULL, ctm); |
||
235 | node->item.path = fz_clone_path(path); |
||
236 | node->flag = even_odd; |
||
237 | fz_append_display_node(user, node); |
||
238 | } |
||
239 | |||
240 | static void |
||
241 | fz_list_stroke_path(void *user, fz_path *path, fz_stroke_state *stroke, fz_matrix ctm, |
||
242 | fz_colorspace *colorspace, float *color, float alpha) |
||
243 | { |
||
244 | fz_display_node *node; |
||
245 | node = fz_new_display_node(FZ_CMD_STROKE_PATH, ctm, colorspace, color, alpha); |
||
246 | node->rect = fz_bound_path(path, stroke, ctm); |
||
247 | node->item.path = fz_clone_path(path); |
||
248 | node->stroke = fz_clone_stroke_state(stroke); |
||
249 | fz_append_display_node(user, node); |
||
250 | } |
||
251 | |||
252 | static void |
||
253 | fz_list_clip_path(void *user, fz_path *path, fz_rect *rect, int even_odd, fz_matrix ctm) |
||
254 | { |
||
255 | fz_display_node *node; |
||
256 | node = fz_new_display_node(FZ_CMD_CLIP_PATH, ctm, NULL, NULL, 0); |
||
257 | node->rect = fz_bound_path(path, NULL, ctm); |
||
258 | if (rect != NULL) |
||
259 | node->rect = fz_intersect_rect(node->rect, *rect); |
||
260 | node->item.path = fz_clone_path(path); |
||
261 | node->flag = even_odd; |
||
262 | fz_append_display_node(user, node); |
||
263 | } |
||
264 | |||
265 | static void |
||
266 | fz_list_clip_stroke_path(void *user, fz_path *path, fz_rect *rect, fz_stroke_state *stroke, fz_matrix ctm) |
||
267 | { |
||
268 | fz_display_node *node; |
||
269 | node = fz_new_display_node(FZ_CMD_CLIP_STROKE_PATH, ctm, NULL, NULL, 0); |
||
270 | node->rect = fz_bound_path(path, stroke, ctm); |
||
271 | if (rect != NULL) |
||
272 | node->rect = fz_intersect_rect(node->rect, *rect); |
||
273 | node->item.path = fz_clone_path(path); |
||
274 | node->stroke = fz_clone_stroke_state(stroke); |
||
275 | fz_append_display_node(user, node); |
||
276 | } |
||
277 | |||
278 | static void |
||
279 | fz_list_fill_text(void *user, fz_text *text, fz_matrix ctm, |
||
280 | fz_colorspace *colorspace, float *color, float alpha) |
||
281 | { |
||
282 | fz_display_node *node; |
||
283 | node = fz_new_display_node(FZ_CMD_FILL_TEXT, ctm, colorspace, color, alpha); |
||
284 | node->rect = fz_bound_text(text, ctm); |
||
285 | node->item.text = fz_clone_text(text); |
||
286 | fz_append_display_node(user, node); |
||
287 | } |
||
288 | |||
289 | static void |
||
290 | fz_list_stroke_text(void *user, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm, |
||
291 | fz_colorspace *colorspace, float *color, float alpha) |
||
292 | { |
||
293 | fz_display_node *node; |
||
294 | node = fz_new_display_node(FZ_CMD_STROKE_TEXT, ctm, colorspace, color, alpha); |
||
295 | node->rect = fz_bound_text(text, ctm); |
||
296 | node->item.text = fz_clone_text(text); |
||
297 | node->stroke = fz_clone_stroke_state(stroke); |
||
298 | fz_append_display_node(user, node); |
||
299 | } |
||
300 | |||
301 | static void |
||
302 | fz_list_clip_text(void *user, fz_text *text, fz_matrix ctm, int accumulate) |
||
303 | { |
||
304 | fz_display_node *node; |
||
305 | node = fz_new_display_node(FZ_CMD_CLIP_TEXT, ctm, NULL, NULL, 0); |
||
306 | node->rect = fz_bound_text(text, ctm); |
||
307 | node->item.text = fz_clone_text(text); |
||
308 | node->flag = accumulate; |
||
309 | /* when accumulating, be conservative about culling */ |
||
310 | if (accumulate) |
||
311 | node->rect = fz_infinite_rect; |
||
312 | fz_append_display_node(user, node); |
||
313 | } |
||
314 | |||
315 | static void |
||
316 | fz_list_clip_stroke_text(void *user, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm) |
||
317 | { |
||
318 | fz_display_node *node; |
||
319 | node = fz_new_display_node(FZ_CMD_CLIP_STROKE_TEXT, ctm, NULL, NULL, 0); |
||
320 | node->rect = fz_bound_text(text, ctm); |
||
321 | node->item.text = fz_clone_text(text); |
||
322 | node->stroke = fz_clone_stroke_state(stroke); |
||
323 | fz_append_display_node(user, node); |
||
324 | } |
||
325 | |||
326 | static void |
||
327 | fz_list_ignore_text(void *user, fz_text *text, fz_matrix ctm) |
||
328 | { |
||
329 | fz_display_node *node; |
||
330 | node = fz_new_display_node(FZ_CMD_IGNORE_TEXT, ctm, NULL, NULL, 0); |
||
331 | node->rect = fz_bound_text(text, ctm); |
||
332 | node->item.text = fz_clone_text(text); |
||
333 | fz_append_display_node(user, node); |
||
334 | } |
||
335 | |||
336 | static void |
||
337 | fz_list_pop_clip(void *user) |
||
338 | { |
||
339 | fz_display_node *node; |
||
340 | node = fz_new_display_node(FZ_CMD_POP_CLIP, fz_identity, NULL, NULL, 0); |
||
341 | fz_append_display_node(user, node); |
||
342 | } |
||
343 | |||
344 | static void |
||
345 | fz_list_fill_shade(void *user, fz_shade *shade, fz_matrix ctm, float alpha) |
||
346 | { |
||
347 | fz_display_node *node; |
||
348 | node = fz_new_display_node(FZ_CMD_FILL_SHADE, ctm, NULL, NULL, alpha); |
||
349 | node->rect = fz_bound_shade(shade, ctm); |
||
350 | node->item.shade = fz_keep_shade(shade); |
||
351 | fz_append_display_node(user, node); |
||
352 | } |
||
353 | |||
354 | static void |
||
355 | fz_list_fill_image(void *user, fz_pixmap *image, fz_matrix ctm, float alpha) |
||
356 | { |
||
357 | fz_display_node *node; |
||
358 | node = fz_new_display_node(FZ_CMD_FILL_IMAGE, ctm, NULL, NULL, alpha); |
||
359 | node->rect = fz_transform_rect(ctm, fz_unit_rect); |
||
360 | node->item.image = fz_keep_pixmap(image); |
||
361 | fz_append_display_node(user, node); |
||
362 | } |
||
363 | |||
364 | static void |
||
365 | fz_list_fill_image_mask(void *user, fz_pixmap *image, fz_matrix ctm, |
||
366 | fz_colorspace *colorspace, float *color, float alpha) |
||
367 | { |
||
368 | fz_display_node *node; |
||
369 | node = fz_new_display_node(FZ_CMD_FILL_IMAGE_MASK, ctm, colorspace, color, alpha); |
||
370 | node->rect = fz_transform_rect(ctm, fz_unit_rect); |
||
371 | node->item.image = fz_keep_pixmap(image); |
||
372 | fz_append_display_node(user, node); |
||
373 | } |
||
374 | |||
375 | static void |
||
376 | fz_list_clip_image_mask(void *user, fz_pixmap *image, fz_rect *rect, fz_matrix ctm) |
||
377 | { |
||
378 | fz_display_node *node; |
||
379 | node = fz_new_display_node(FZ_CMD_CLIP_IMAGE_MASK, ctm, NULL, NULL, 0); |
||
380 | node->rect = fz_transform_rect(ctm, fz_unit_rect); |
||
381 | if (rect != NULL) |
||
382 | node->rect = fz_intersect_rect(node->rect, *rect); |
||
383 | node->item.image = fz_keep_pixmap(image); |
||
384 | fz_append_display_node(user, node); |
||
385 | } |
||
386 | |||
387 | static void |
||
388 | fz_list_begin_mask(void *user, fz_rect rect, int luminosity, fz_colorspace *colorspace, float *color) |
||
389 | { |
||
390 | fz_display_node *node; |
||
391 | node = fz_new_display_node(FZ_CMD_BEGIN_MASK, fz_identity, colorspace, color, 0); |
||
392 | node->rect = rect; |
||
393 | node->flag = luminosity; |
||
394 | fz_append_display_node(user, node); |
||
395 | } |
||
396 | |||
397 | static void |
||
398 | fz_list_end_mask(void *user) |
||
399 | { |
||
400 | fz_display_node *node; |
||
401 | node = fz_new_display_node(FZ_CMD_END_MASK, fz_identity, NULL, NULL, 0); |
||
402 | fz_append_display_node(user, node); |
||
403 | } |
||
404 | |||
405 | static void |
||
406 | fz_list_begin_group(void *user, fz_rect rect, int isolated, int knockout, int blendmode, float alpha) |
||
407 | { |
||
408 | fz_display_node *node; |
||
409 | node = fz_new_display_node(FZ_CMD_BEGIN_GROUP, fz_identity, NULL, NULL, alpha); |
||
410 | node->rect = rect; |
||
411 | node->item.blendmode = blendmode; |
||
412 | node->flag |= isolated ? ISOLATED : 0; |
||
413 | node->flag |= knockout ? KNOCKOUT : 0; |
||
414 | fz_append_display_node(user, node); |
||
415 | } |
||
416 | |||
417 | static void |
||
418 | fz_list_end_group(void *user) |
||
419 | { |
||
420 | fz_display_node *node; |
||
421 | node = fz_new_display_node(FZ_CMD_END_GROUP, fz_identity, NULL, NULL, 0); |
||
422 | fz_append_display_node(user, node); |
||
423 | } |
||
424 | |||
425 | static void |
||
426 | fz_list_begin_tile(void *user, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm) |
||
427 | { |
||
428 | fz_display_node *node; |
||
429 | node = fz_new_display_node(FZ_CMD_BEGIN_TILE, ctm, NULL, NULL, 0); |
||
430 | node->rect = area; |
||
431 | node->color[0] = xstep; |
||
432 | node->color[1] = ystep; |
||
433 | node->color[2] = view.x0; |
||
434 | node->color[3] = view.y0; |
||
435 | node->color[4] = view.x1; |
||
436 | node->color[5] = view.y1; |
||
437 | fz_append_display_node(user, node); |
||
438 | } |
||
439 | |||
440 | static void |
||
441 | fz_list_end_tile(void *user) |
||
442 | { |
||
443 | fz_display_node *node; |
||
444 | node = fz_new_display_node(FZ_CMD_END_TILE, fz_identity, NULL, NULL, 0); |
||
445 | fz_append_display_node(user, node); |
||
446 | } |
||
447 | |||
448 | fz_device * |
||
449 | fz_new_list_device(fz_display_list *list) |
||
450 | { |
||
451 | fz_device *dev = fz_new_device(list); |
||
452 | |||
453 | dev->fill_path = fz_list_fill_path; |
||
454 | dev->stroke_path = fz_list_stroke_path; |
||
455 | dev->clip_path = fz_list_clip_path; |
||
456 | dev->clip_stroke_path = fz_list_clip_stroke_path; |
||
457 | |||
458 | dev->fill_text = fz_list_fill_text; |
||
459 | dev->stroke_text = fz_list_stroke_text; |
||
460 | dev->clip_text = fz_list_clip_text; |
||
461 | dev->clip_stroke_text = fz_list_clip_stroke_text; |
||
462 | dev->ignore_text = fz_list_ignore_text; |
||
463 | |||
464 | dev->fill_shade = fz_list_fill_shade; |
||
465 | dev->fill_image = fz_list_fill_image; |
||
466 | dev->fill_image_mask = fz_list_fill_image_mask; |
||
467 | dev->clip_image_mask = fz_list_clip_image_mask; |
||
468 | |||
469 | dev->pop_clip = fz_list_pop_clip; |
||
470 | |||
471 | dev->begin_mask = fz_list_begin_mask; |
||
472 | dev->end_mask = fz_list_end_mask; |
||
473 | dev->begin_group = fz_list_begin_group; |
||
474 | dev->end_group = fz_list_end_group; |
||
475 | |||
476 | dev->begin_tile = fz_list_begin_tile; |
||
477 | dev->end_tile = fz_list_end_tile; |
||
478 | |||
479 | return dev; |
||
480 | } |
||
481 | |||
482 | fz_display_list * |
||
483 | fz_new_display_list(void) |
||
484 | { |
||
485 | fz_display_list *list = fz_malloc(sizeof(fz_display_list)); |
||
486 | list->first = NULL; |
||
487 | list->last = NULL; |
||
488 | list->top = 0; |
||
489 | list->tiled = 0; |
||
490 | return list; |
||
491 | } |
||
492 | |||
493 | void |
||
494 | fz_free_display_list(fz_display_list *list) |
||
495 | { |
||
496 | fz_display_node *node = list->first; |
||
497 | while (node) |
||
498 | { |
||
499 | fz_display_node *next = node->next; |
||
500 | fz_free_display_node(node); |
||
501 | node = next; |
||
502 | } |
||
503 | fz_free(list); |
||
504 | } |
||
505 | |||
506 | void |
||
507 | fz_execute_display_list(fz_display_list *list, fz_device *dev, fz_matrix top_ctm, fz_bbox scissor) |
||
508 | { |
||
509 | fz_display_node *node; |
||
510 | fz_matrix ctm; |
||
511 | fz_rect rect; |
||
512 | fz_bbox bbox; |
||
513 | int clipped = 0; |
||
514 | int tiled = 0; |
||
515 | int empty; |
||
516 | |||
517 | if (!fz_is_infinite_bbox(scissor)) |
||
518 | { |
||
519 | /* add some fuzz at the edges, as especially glyph rects |
||
520 | * are sometimes not actually completely bounding the glyph */ |
||
521 | scissor.x0 -= 20; scissor.y0 -= 20; |
||
522 | scissor.x1 += 20; scissor.y1 += 20; |
||
523 | } |
||
524 | |||
525 | for (node = list->first; node; node = node->next) |
||
526 | { |
||
527 | /* cull objects to draw using a quick visibility test */ |
||
528 | |||
529 | if (tiled || node->cmd == FZ_CMD_BEGIN_TILE || node->cmd == FZ_CMD_END_TILE) |
||
530 | { |
||
531 | empty = 0; |
||
532 | } |
||
533 | else |
||
534 | { |
||
535 | bbox = fz_round_rect(fz_transform_rect(top_ctm, node->rect)); |
||
536 | bbox = fz_intersect_bbox(bbox, scissor); |
||
537 | empty = fz_is_empty_bbox(bbox); |
||
538 | } |
||
539 | |||
540 | if (clipped || empty) |
||
541 | { |
||
542 | switch (node->cmd) |
||
543 | { |
||
544 | case FZ_CMD_CLIP_PATH: |
||
545 | case FZ_CMD_CLIP_STROKE_PATH: |
||
546 | case FZ_CMD_CLIP_TEXT: |
||
547 | case FZ_CMD_CLIP_STROKE_TEXT: |
||
548 | case FZ_CMD_CLIP_IMAGE_MASK: |
||
549 | case FZ_CMD_BEGIN_MASK: |
||
550 | case FZ_CMD_BEGIN_GROUP: |
||
551 | clipped++; |
||
552 | continue; |
||
553 | case FZ_CMD_POP_CLIP: |
||
554 | case FZ_CMD_END_GROUP: |
||
555 | if (!clipped) |
||
556 | goto visible; |
||
557 | clipped--; |
||
558 | continue; |
||
559 | case FZ_CMD_END_MASK: |
||
560 | if (!clipped) |
||
561 | goto visible; |
||
562 | continue; |
||
563 | default: |
||
564 | continue; |
||
565 | } |
||
566 | } |
||
567 | |||
568 | visible: |
||
569 | ctm = fz_concat(node->ctm, top_ctm); |
||
570 | |||
571 | switch (node->cmd) |
||
572 | { |
||
573 | case FZ_CMD_FILL_PATH: |
||
574 | fz_fill_path(dev, node->item.path, node->flag, ctm, |
||
575 | node->colorspace, node->color, node->alpha); |
||
576 | break; |
||
577 | case FZ_CMD_STROKE_PATH: |
||
578 | fz_stroke_path(dev, node->item.path, node->stroke, ctm, |
||
579 | node->colorspace, node->color, node->alpha); |
||
580 | break; |
||
581 | case FZ_CMD_CLIP_PATH: |
||
582 | { |
||
583 | fz_rect trect = fz_transform_rect(top_ctm, node->rect); |
||
584 | fz_clip_path(dev, node->item.path, &trect, node->flag, ctm); |
||
585 | break; |
||
586 | } |
||
587 | case FZ_CMD_CLIP_STROKE_PATH: |
||
588 | { |
||
589 | fz_rect trect = fz_transform_rect(top_ctm, node->rect); |
||
590 | fz_clip_stroke_path(dev, node->item.path, &trect, node->stroke, ctm); |
||
591 | break; |
||
592 | } |
||
593 | case FZ_CMD_FILL_TEXT: |
||
594 | fz_fill_text(dev, node->item.text, ctm, |
||
595 | node->colorspace, node->color, node->alpha); |
||
596 | break; |
||
597 | case FZ_CMD_STROKE_TEXT: |
||
598 | fz_stroke_text(dev, node->item.text, node->stroke, ctm, |
||
599 | node->colorspace, node->color, node->alpha); |
||
600 | break; |
||
601 | case FZ_CMD_CLIP_TEXT: |
||
602 | fz_clip_text(dev, node->item.text, ctm, node->flag); |
||
603 | break; |
||
604 | case FZ_CMD_CLIP_STROKE_TEXT: |
||
605 | fz_clip_stroke_text(dev, node->item.text, node->stroke, ctm); |
||
606 | break; |
||
607 | case FZ_CMD_IGNORE_TEXT: |
||
608 | fz_ignore_text(dev, node->item.text, ctm); |
||
609 | break; |
||
610 | case FZ_CMD_FILL_SHADE: |
||
611 | fz_fill_shade(dev, node->item.shade, ctm, node->alpha); |
||
612 | break; |
||
613 | case FZ_CMD_FILL_IMAGE: |
||
614 | fz_fill_image(dev, node->item.image, ctm, node->alpha); |
||
615 | break; |
||
616 | case FZ_CMD_FILL_IMAGE_MASK: |
||
617 | fz_fill_image_mask(dev, node->item.image, ctm, |
||
618 | node->colorspace, node->color, node->alpha); |
||
619 | break; |
||
620 | case FZ_CMD_CLIP_IMAGE_MASK: |
||
621 | { |
||
622 | fz_rect trect = fz_transform_rect(top_ctm, node->rect); |
||
623 | fz_clip_image_mask(dev, node->item.image, &trect, ctm); |
||
624 | break; |
||
625 | } |
||
626 | case FZ_CMD_POP_CLIP: |
||
627 | fz_pop_clip(dev); |
||
628 | break; |
||
629 | case FZ_CMD_BEGIN_MASK: |
||
630 | rect = fz_transform_rect(top_ctm, node->rect); |
||
631 | fz_begin_mask(dev, rect, node->flag, node->colorspace, node->color); |
||
632 | break; |
||
633 | case FZ_CMD_END_MASK: |
||
634 | fz_end_mask(dev); |
||
635 | break; |
||
636 | case FZ_CMD_BEGIN_GROUP: |
||
637 | rect = fz_transform_rect(top_ctm, node->rect); |
||
638 | fz_begin_group(dev, rect, |
||
639 | (node->flag & ISOLATED) != 0, (node->flag & KNOCKOUT) != 0, |
||
640 | node->item.blendmode, node->alpha); |
||
641 | break; |
||
642 | case FZ_CMD_END_GROUP: |
||
643 | fz_end_group(dev); |
||
644 | break; |
||
645 | case FZ_CMD_BEGIN_TILE: |
||
646 | tiled++; |
||
647 | rect.x0 = node->color[2]; |
||
648 | rect.y0 = node->color[3]; |
||
649 | rect.x1 = node->color[4]; |
||
650 | rect.y1 = node->color[5]; |
||
651 | fz_begin_tile(dev, node->rect, rect, |
||
652 | node->color[0], node->color[1], ctm); |
||
653 | break; |
||
654 | case FZ_CMD_END_TILE: |
||
655 | tiled--; |
||
656 | fz_end_tile(dev); |
||
657 | break; |
||
658 | } |
||
659 | } |
||
660 | }=>>>>> |