1 | #include "mupdf/fitz.h" |
2 | #include "mupdf/pdf.h" |
3 | |
4 | #include <string.h> |
5 | #include <math.h> |
6 | |
7 | #define TILE |
8 | |
9 | /* |
10 | * Emit graphics calls to device. |
11 | */ |
12 | |
13 | typedef struct pdf_material_s pdf_material; |
14 | typedef struct pdf_run_processor_s pdf_run_processor; |
15 | |
16 | static void pdf_run_xobject(fz_context *ctx, pdf_run_processor *proc, pdf_obj *xobj, pdf_obj *page_resources, fz_matrix transform, int is_smask); |
17 | |
18 | enum |
19 | { |
20 | PDF_FILL, |
21 | PDF_STROKE, |
22 | }; |
23 | |
24 | enum |
25 | { |
26 | PDF_MAT_NONE, |
27 | PDF_MAT_COLOR, |
28 | PDF_MAT_PATTERN, |
29 | PDF_MAT_SHADE, |
30 | }; |
31 | |
32 | struct pdf_material_s |
33 | { |
34 | int kind; |
35 | fz_colorspace *colorspace; |
36 | pdf_pattern *pattern; |
37 | fz_shade *shade; |
38 | int gstate_num; |
39 | fz_color_params color_params; |
40 | float alpha; |
41 | float v[FZ_MAX_COLORS]; |
42 | }; |
43 | |
44 | struct pdf_gstate_s |
45 | { |
46 | fz_matrix ctm; |
47 | int clip_depth; |
48 | |
49 | /* path stroking */ |
50 | fz_stroke_state *stroke_state; |
51 | |
52 | /* materials */ |
53 | pdf_material stroke; |
54 | pdf_material fill; |
55 | |
56 | /* text state */ |
57 | pdf_text_state text; |
58 | |
59 | /* transparency */ |
60 | int blendmode; |
61 | pdf_obj *softmask; |
62 | pdf_obj *softmask_resources; |
63 | fz_matrix softmask_ctm; |
64 | float softmask_bc[FZ_MAX_COLORS]; |
65 | int luminosity; |
66 | }; |
67 | |
68 | struct pdf_run_processor_s |
69 | { |
70 | pdf_processor super; |
71 | fz_device *dev; |
72 | fz_cookie *cookie; |
73 | |
74 | fz_default_colorspaces *default_cs; |
75 | |
76 | /* path object state */ |
77 | fz_path *path; |
78 | int clip; |
79 | int clip_even_odd; |
80 | |
81 | /* text object state */ |
82 | pdf_text_object_state tos; |
83 | |
84 | /* graphics state */ |
85 | pdf_gstate *gstate; |
86 | int gcap; |
87 | int gtop; |
88 | int gbot; |
89 | int gparent; |
90 | }; |
91 | |
92 | typedef struct softmask_save_s softmask_save; |
93 | |
94 | struct softmask_save_s |
95 | { |
96 | pdf_obj *softmask; |
97 | pdf_obj *page_resources; |
98 | fz_matrix ctm; |
99 | }; |
100 | |
101 | static pdf_gstate * |
102 | begin_softmask(fz_context *ctx, pdf_run_processor *pr, softmask_save *save) |
103 | { |
104 | pdf_gstate *gstate = pr->gstate + pr->gtop; |
105 | pdf_obj *softmask = gstate->softmask; |
106 | fz_rect mask_bbox; |
107 | fz_matrix tos_save[2], save_ctm; |
108 | fz_matrix mask_matrix; |
109 | fz_colorspace *mask_colorspace; |
110 | int saved_blendmode; |
111 | |
112 | save->softmask = softmask; |
113 | if (softmask == NULL) |
114 | return gstate; |
115 | save->page_resources = gstate->softmask_resources; |
116 | save->ctm = gstate->softmask_ctm; |
117 | save_ctm = gstate->ctm; |
118 | |
119 | mask_bbox = pdf_xobject_bbox(ctx, softmask); |
120 | mask_matrix = pdf_xobject_matrix(ctx, softmask); |
121 | |
122 | pdf_tos_save(ctx, &pr->tos, tos_save); |
123 | |
124 | if (gstate->luminosity) |
125 | mask_bbox = fz_infinite_rect; |
126 | else |
127 | { |
128 | mask_bbox = fz_transform_rect(mask_bbox, mask_matrix); |
129 | mask_bbox = fz_transform_rect(mask_bbox, gstate->softmask_ctm); |
130 | } |
131 | gstate->softmask = NULL; |
132 | gstate->softmask_resources = NULL; |
133 | gstate->ctm = gstate->softmask_ctm; |
134 | |
135 | saved_blendmode = gstate->blendmode; |
136 | |
137 | mask_colorspace = pdf_xobject_colorspace(ctx, softmask); |
138 | if (gstate->luminosity && !mask_colorspace) |
139 | mask_colorspace = fz_keep_colorspace(ctx, fz_device_gray(ctx)); |
140 | |
141 | fz_try(ctx) |
142 | { |
143 | fz_begin_mask(ctx, pr->dev, mask_bbox, gstate->luminosity, mask_colorspace, gstate->softmask_bc, gstate->fill.color_params); |
144 | gstate->blendmode = 0; |
145 | pdf_run_xobject(ctx, pr, softmask, save->page_resources, fz_identity, 1); |
146 | gstate = pr->gstate + pr->gtop; |
147 | gstate->blendmode = saved_blendmode; |
148 | fz_end_mask(ctx, pr->dev); |
149 | } |
150 | fz_always(ctx) |
151 | fz_drop_colorspace(ctx, mask_colorspace); |
152 | fz_catch(ctx) |
153 | fz_rethrow(ctx); |
154 | |
155 | pdf_tos_restore(ctx, &pr->tos, tos_save); |
156 | |
157 | gstate = pr->gstate + pr->gtop; |
158 | gstate->ctm = save_ctm; |
159 | |
160 | return gstate; |
161 | } |
162 | |
163 | static void |
164 | end_softmask(fz_context *ctx, pdf_run_processor *pr, softmask_save *save) |
165 | { |
166 | pdf_gstate *gstate = pr->gstate + pr->gtop; |
167 | |
168 | if (save->softmask == NULL) |
169 | return; |
170 | |
171 | gstate->softmask = save->softmask; |
172 | gstate->softmask_resources = save->page_resources; |
173 | gstate->softmask_ctm = save->ctm; |
174 | save->softmask = NULL; |
175 | save->page_resources = NULL; |
176 | |
177 | fz_pop_clip(ctx, pr->dev); |
178 | } |
179 | |
180 | static pdf_gstate * |
181 | pdf_begin_group(fz_context *ctx, pdf_run_processor *pr, fz_rect bbox, softmask_save *softmask) |
182 | { |
183 | pdf_gstate *gstate = begin_softmask(ctx, pr, softmask); |
184 | |
185 | if (gstate->blendmode) |
186 | fz_begin_group(ctx, pr->dev, bbox, NULL, 0, 0, gstate->blendmode, 1); |
187 | |
188 | return pr->gstate + pr->gtop; |
189 | } |
190 | |
191 | static void |
192 | pdf_end_group(fz_context *ctx, pdf_run_processor *pr, softmask_save *softmask) |
193 | { |
194 | pdf_gstate *gstate = pr->gstate + pr->gtop; |
195 | |
196 | if (gstate->blendmode) |
197 | fz_end_group(ctx, pr->dev); |
198 | |
199 | end_softmask(ctx, pr, softmask); |
200 | } |
201 | |
202 | static void |
203 | pdf_show_shade(fz_context *ctx, pdf_run_processor *pr, fz_shade *shd) |
204 | { |
205 | pdf_gstate *gstate = pr->gstate + pr->gtop; |
206 | fz_rect bbox; |
207 | softmask_save softmask = { NULL }; |
208 | |
209 | if (pr->super.hidden) |
210 | return; |
211 | |
212 | bbox = fz_bound_shade(ctx, shd, gstate->ctm); |
213 | |
214 | gstate = pdf_begin_group(ctx, pr, bbox, &softmask); |
215 | |
216 | /* FIXME: The gstate->ctm in the next line may be wrong; maybe |
217 | * it should be the parent gstates ctm? */ |
218 | fz_fill_shade(ctx, pr->dev, shd, gstate->ctm, gstate->fill.alpha, gstate->fill.color_params); |
219 | |
220 | pdf_end_group(ctx, pr, &softmask); |
221 | } |
222 | |
223 | static pdf_material * |
224 | pdf_keep_material(fz_context *ctx, pdf_material *mat) |
225 | { |
226 | if (mat->colorspace) |
227 | fz_keep_colorspace(ctx, mat->colorspace); |
228 | if (mat->pattern) |
229 | pdf_keep_pattern(ctx, mat->pattern); |
230 | if (mat->shade) |
231 | fz_keep_shade(ctx, mat->shade); |
232 | return mat; |
233 | } |
234 | |
235 | static pdf_material * |
236 | pdf_drop_material(fz_context *ctx, pdf_material *mat) |
237 | { |
238 | fz_drop_colorspace(ctx, mat->colorspace); |
239 | pdf_drop_pattern(ctx, mat->pattern); |
240 | fz_drop_shade(ctx, mat->shade); |
241 | return mat; |
242 | } |
243 | |
244 | static void |
245 | pdf_copy_pattern_gstate(fz_context *ctx, pdf_gstate *dst, const pdf_gstate *src) |
246 | { |
247 | dst->ctm = src->ctm; |
248 | |
249 | pdf_drop_font(ctx, dst->text.font); |
250 | dst->text.font = pdf_keep_font(ctx, src->text.font); |
251 | |
252 | pdf_drop_obj(ctx, dst->softmask); |
253 | dst->softmask = pdf_keep_obj(ctx, src->softmask); |
254 | |
255 | fz_drop_stroke_state(ctx, dst->stroke_state); |
256 | dst->stroke_state = fz_keep_stroke_state(ctx, src->stroke_state); |
257 | } |
258 | |
259 | static void |
260 | pdf_unset_pattern(fz_context *ctx, pdf_run_processor *pr, int what) |
261 | { |
262 | pdf_gstate *gs = pr->gstate + pr->gtop; |
263 | pdf_material *mat; |
264 | mat = what == PDF_FILL ? &gs->fill : &gs->stroke; |
265 | if (mat->kind == PDF_MAT_PATTERN) |
266 | { |
267 | pdf_drop_pattern(ctx, mat->pattern); |
268 | mat->pattern = NULL; |
269 | mat->kind = PDF_MAT_COLOR; |
270 | } |
271 | } |
272 | |
273 | static void |
274 | pdf_keep_gstate(fz_context *ctx, pdf_gstate *gs) |
275 | { |
276 | pdf_keep_material(ctx, &gs->stroke); |
277 | pdf_keep_material(ctx, &gs->fill); |
278 | if (gs->text.font) |
279 | pdf_keep_font(ctx, gs->text.font); |
280 | if (gs->softmask) |
281 | pdf_keep_obj(ctx, gs->softmask); |
282 | if (gs->softmask_resources) |
283 | pdf_keep_obj(ctx, gs->softmask_resources); |
284 | fz_keep_stroke_state(ctx, gs->stroke_state); |
285 | } |
286 | |
287 | static void |
288 | pdf_drop_gstate(fz_context *ctx, pdf_gstate *gs) |
289 | { |
290 | pdf_drop_material(ctx, &gs->stroke); |
291 | pdf_drop_material(ctx, &gs->fill); |
292 | pdf_drop_font(ctx, gs->text.font); |
293 | pdf_drop_obj(ctx, gs->softmask); |
294 | pdf_drop_obj(ctx, gs->softmask_resources); |
295 | fz_drop_stroke_state(ctx, gs->stroke_state); |
296 | } |
297 | |
298 | static void |
299 | pdf_gsave(fz_context *ctx, pdf_run_processor *pr) |
300 | { |
301 | if (pr->gtop == pr->gcap-1) |
302 | { |
303 | pr->gstate = fz_realloc_array(ctx, pr->gstate, pr->gcap*2, pdf_gstate); |
304 | pr->gcap *= 2; |
305 | } |
306 | |
307 | memcpy(&pr->gstate[pr->gtop + 1], &pr->gstate[pr->gtop], sizeof(pdf_gstate)); |
308 | |
309 | pr->gtop++; |
310 | pdf_keep_gstate(ctx, &pr->gstate[pr->gtop]); |
311 | } |
312 | |
313 | static void |
314 | pdf_grestore(fz_context *ctx, pdf_run_processor *pr) |
315 | { |
316 | pdf_gstate *gs = pr->gstate + pr->gtop; |
317 | int clip_depth = gs->clip_depth; |
318 | |
319 | if (pr->gtop <= pr->gbot) |
320 | { |
321 | fz_warn(ctx, "gstate underflow in content stream" ); |
322 | return; |
323 | } |
324 | |
325 | pdf_drop_gstate(ctx, gs); |
326 | pr->gtop --; |
327 | |
328 | gs = pr->gstate + pr->gtop; |
329 | while (clip_depth > gs->clip_depth) |
330 | { |
331 | fz_try(ctx) |
332 | { |
333 | fz_pop_clip(ctx, pr->dev); |
334 | } |
335 | fz_catch(ctx) |
336 | { |
337 | /* Silently swallow the problem - restores must |
338 | * never throw! */ |
339 | } |
340 | clip_depth--; |
341 | } |
342 | } |
343 | |
344 | static pdf_gstate * |
345 | pdf_show_pattern(fz_context *ctx, pdf_run_processor *pr, pdf_pattern *pat, int pat_gstate_num, fz_rect area, int what) |
346 | { |
347 | pdf_gstate *gstate; |
348 | pdf_gstate *pat_gstate; |
349 | int gparent_save; |
350 | fz_matrix ptm, invptm, gparent_save_ctm; |
351 | int x0, y0, x1, y1; |
352 | float fx0, fy0, fx1, fy1; |
353 | fz_rect local_area; |
354 | int id; |
355 | |
356 | pdf_gsave(ctx, pr); |
357 | gstate = pr->gstate + pr->gtop; |
358 | pat_gstate = pr->gstate + pat_gstate_num; |
359 | |
360 | /* Patterns are run with the gstate of the parent */ |
361 | pdf_copy_pattern_gstate(ctx, gstate, pat_gstate); |
362 | |
363 | if (pat->ismask) |
364 | { |
365 | pdf_unset_pattern(ctx, pr, PDF_FILL); |
366 | pdf_unset_pattern(ctx, pr, PDF_STROKE); |
367 | if (what == PDF_FILL) |
368 | { |
369 | pdf_drop_material(ctx, &gstate->stroke); |
370 | pdf_keep_material(ctx, &gstate->fill); |
371 | gstate->stroke = gstate->fill; |
372 | } |
373 | if (what == PDF_STROKE) |
374 | { |
375 | pdf_drop_material(ctx, &gstate->fill); |
376 | pdf_keep_material(ctx, &gstate->stroke); |
377 | gstate->fill = gstate->stroke; |
378 | } |
379 | id = 0; /* don't cache uncolored patterns, since we colorize them when drawing */ |
380 | } |
381 | else |
382 | { |
383 | // TODO: unset only the current fill/stroke or both? |
384 | pdf_unset_pattern(ctx, pr, what); |
385 | id = pat->id; |
386 | } |
387 | |
388 | /* don't apply soft masks to objects in the pattern as well */ |
389 | if (gstate->softmask) |
390 | { |
391 | pdf_drop_obj(ctx, gstate->softmask); |
392 | gstate->softmask = NULL; |
393 | } |
394 | |
395 | ptm = fz_concat(pat->matrix, pat_gstate->ctm); |
396 | invptm = fz_invert_matrix(ptm); |
397 | |
398 | /* The parent_ctm is amended with our pattern matrix */ |
399 | gparent_save = pr->gparent; |
400 | pr->gparent = pr->gtop-1; |
401 | gparent_save_ctm = pr->gstate[pr->gparent].ctm; |
402 | pr->gstate[pr->gparent].ctm = ptm; |
403 | |
404 | /* patterns are painted using the parent_ctm. area = bbox of |
405 | * shape to be filled in device space. Map it back to pattern |
406 | * space. */ |
407 | local_area = fz_transform_rect(area, invptm); |
408 | |
409 | fx0 = (local_area.x0 - pat->bbox.x0) / pat->xstep; |
410 | fy0 = (local_area.y0 - pat->bbox.y0) / pat->ystep; |
411 | fx1 = (local_area.x1 - pat->bbox.x0) / pat->xstep; |
412 | fy1 = (local_area.y1 - pat->bbox.y0) / pat->ystep; |
413 | if (fx0 > fx1) |
414 | { |
415 | float t = fx0; fx0 = fx1; fx1 = t; |
416 | } |
417 | if (fy0 > fy1) |
418 | { |
419 | float t = fy0; fy0 = fy1; fy1 = t; |
420 | } |
421 | |
422 | #ifdef TILE |
423 | /* We have tried various formulations in the past, but this one is |
424 | * best we've found; only use it as a tile if a whole repeat is |
425 | * required in at least one direction. Note, that this allows for |
426 | * 'sections' of 4 tiles to be show, but all non-overlapping. */ |
427 | if (fx1-fx0 > 1 || fy1-fy0 > 1) |
428 | #else |
429 | if (0) |
430 | #endif |
431 | { |
432 | int cached = fz_begin_tile_id(ctx, pr->dev, local_area, pat->bbox, pat->xstep, pat->ystep, ptm, id); |
433 | if (!cached) |
434 | { |
435 | gstate->ctm = ptm; |
436 | pdf_gsave(ctx, pr); |
437 | pdf_process_contents(ctx, (pdf_processor*)pr, pat->document, pat->resources, pat->contents, NULL); |
438 | pdf_grestore(ctx, pr); |
439 | } |
440 | fz_end_tile(ctx, pr->dev); |
441 | } |
442 | else |
443 | { |
444 | int x, y; |
445 | |
446 | /* When calculating the number of tiles required, we adjust by |
447 | * a small amount to allow for rounding errors. By choosing |
448 | * this amount to be smaller than 1/256, we guarantee we won't |
449 | * cause problems that will be visible even under our most |
450 | * extreme antialiasing. */ |
451 | x0 = floorf(fx0 + 0.001f); |
452 | y0 = floorf(fy0 + 0.001f); |
453 | x1 = ceilf(fx1 - 0.001f); |
454 | y1 = ceilf(fy1 - 0.001f); |
455 | /* The above adjustments cause problems for sufficiently |
456 | * large values for xstep/ystep which may be used if the |
457 | * pattern is expected to be rendered exactly once. */ |
458 | if (fx1 > fx0 && x1 == x0) |
459 | x1 = x0 + 1; |
460 | if (fy1 > fy0 && y1 == y0) |
461 | y1 = y0 + 1; |
462 | |
463 | for (y = y0; y < y1; y++) |
464 | { |
465 | for (x = x0; x < x1; x++) |
466 | { |
467 | gstate->ctm = fz_pre_translate(ptm, x * pat->xstep, y * pat->ystep); |
468 | pdf_gsave(ctx, pr); |
469 | pdf_process_contents(ctx, (pdf_processor*)pr, pat->document, pat->resources, pat->contents, NULL); |
470 | pdf_grestore(ctx, pr); |
471 | } |
472 | } |
473 | } |
474 | |
475 | pr->gstate[pr->gparent].ctm = gparent_save_ctm; |
476 | pr->gparent = gparent_save; |
477 | |
478 | pdf_grestore(ctx, pr); |
479 | |
480 | return pr->gstate + pr->gtop; |
481 | } |
482 | |
483 | static void |
484 | pdf_show_image_imp(fz_context *ctx, pdf_run_processor *pr, fz_image *image, fz_matrix image_ctm, fz_rect bbox) |
485 | { |
486 | pdf_gstate *gstate = pr->gstate + pr->gtop; |
487 | |
488 | if (image->colorspace) |
489 | { |
490 | fz_fill_image(ctx, pr->dev, image, image_ctm, gstate->fill.alpha, gstate->fill.color_params); |
491 | } |
492 | else if (gstate->fill.kind == PDF_MAT_COLOR) |
493 | { |
494 | fz_fill_image_mask(ctx, pr->dev, image, image_ctm, gstate->fill.colorspace, gstate->fill.v, gstate->fill.alpha, gstate->fill.color_params); |
495 | } |
496 | else if (gstate->fill.kind == PDF_MAT_PATTERN && gstate->fill.pattern) |
497 | { |
498 | fz_clip_image_mask(ctx, pr->dev, image, image_ctm, bbox); |
499 | gstate = pdf_show_pattern(ctx, pr, gstate->fill.pattern, gstate->fill.gstate_num, bbox, PDF_FILL); |
500 | fz_pop_clip(ctx, pr->dev); |
501 | } |
502 | else if (gstate->fill.kind == PDF_MAT_SHADE && gstate->fill.shade) |
503 | { |
504 | fz_clip_image_mask(ctx, pr->dev, image, image_ctm, bbox); |
505 | fz_fill_shade(ctx, pr->dev, gstate->fill.shade, pr->gstate[gstate->fill.gstate_num].ctm, gstate->fill.alpha, gstate->fill.color_params); |
506 | fz_pop_clip(ctx, pr->dev); |
507 | } |
508 | } |
509 | |
510 | static void |
511 | pdf_show_image(fz_context *ctx, pdf_run_processor *pr, fz_image *image) |
512 | { |
513 | pdf_gstate *gstate = pr->gstate + pr->gtop; |
514 | fz_matrix image_ctm; |
515 | fz_rect bbox; |
516 | |
517 | if (pr->super.hidden) |
518 | return; |
519 | |
520 | /* PDF has images bottom-up, so flip them right side up here */ |
521 | image_ctm = fz_pre_scale(fz_pre_translate(gstate->ctm, 0, 1), 1, -1); |
522 | |
523 | bbox = fz_transform_rect(fz_unit_rect, image_ctm); |
524 | |
525 | if (image->mask && gstate->blendmode) |
526 | { |
527 | /* apply blend group even though we skip the soft mask */ |
528 | fz_begin_group(ctx, pr->dev, bbox, NULL, 0, 0, gstate->blendmode, 1); |
529 | fz_clip_image_mask(ctx, pr->dev, image->mask, image_ctm, bbox); |
530 | pdf_show_image_imp(ctx, pr, image, image_ctm, bbox); |
531 | fz_pop_clip(ctx, pr->dev); |
532 | fz_end_group(ctx, pr->dev); |
533 | } |
534 | else if (image->mask) |
535 | { |
536 | fz_clip_image_mask(ctx, pr->dev, image->mask, image_ctm, bbox); |
537 | pdf_show_image_imp(ctx, pr, image, image_ctm, bbox); |
538 | fz_pop_clip(ctx, pr->dev); |
539 | } |
540 | else |
541 | { |
542 | softmask_save softmask = { NULL }; |
543 | gstate = pdf_begin_group(ctx, pr, bbox, &softmask); |
544 | pdf_show_image_imp(ctx, pr, image, image_ctm, bbox); |
545 | pdf_end_group(ctx, pr, &softmask); |
546 | } |
547 | } |
548 | |
549 | static void |
550 | pdf_show_path(fz_context *ctx, pdf_run_processor *pr, int doclose, int dofill, int dostroke, int even_odd) |
551 | { |
552 | pdf_gstate *gstate = pr->gstate + pr->gtop; |
553 | fz_path *path; |
554 | fz_rect bbox; |
555 | softmask_save softmask = { NULL }; |
556 | int knockout_group = 0; |
557 | |
558 | if (dostroke) { |
559 | if (pr->dev->flags & (FZ_DEVFLAG_STROKECOLOR_UNDEFINED | FZ_DEVFLAG_LINEJOIN_UNDEFINED | FZ_DEVFLAG_LINEWIDTH_UNDEFINED)) |
560 | pr->dev->flags |= FZ_DEVFLAG_UNCACHEABLE; |
561 | else if (gstate->stroke_state->dash_len != 0 && pr->dev->flags & (FZ_DEVFLAG_STARTCAP_UNDEFINED | FZ_DEVFLAG_DASHCAP_UNDEFINED | FZ_DEVFLAG_ENDCAP_UNDEFINED)) |
562 | pr->dev->flags |= FZ_DEVFLAG_UNCACHEABLE; |
563 | else if (gstate->stroke_state->linejoin == FZ_LINEJOIN_MITER && (pr->dev->flags & FZ_DEVFLAG_MITERLIMIT_UNDEFINED)) |
564 | pr->dev->flags |= FZ_DEVFLAG_UNCACHEABLE; |
565 | } |
566 | if (dofill) { |
567 | if (pr->dev->flags & FZ_DEVFLAG_FILLCOLOR_UNDEFINED) |
568 | pr->dev->flags |= FZ_DEVFLAG_UNCACHEABLE; |
569 | } |
570 | |
571 | path = pr->path; |
572 | pr->path = fz_new_path(ctx); |
573 | |
574 | fz_try(ctx) |
575 | { |
576 | if (doclose) |
577 | fz_closepath(ctx, path); |
578 | |
579 | bbox = fz_bound_path(ctx, path, (dostroke ? gstate->stroke_state : NULL), gstate->ctm); |
580 | |
581 | if (pr->super.hidden) |
582 | dostroke = dofill = 0; |
583 | |
584 | if (dofill || dostroke) |
585 | gstate = pdf_begin_group(ctx, pr, bbox, &softmask); |
586 | |
587 | if (dofill && dostroke) |
588 | { |
589 | /* We may need to push a knockout group */ |
590 | if (gstate->stroke.alpha == 0) |
591 | { |
592 | /* No need for group, as stroke won't do anything */ |
593 | } |
594 | else if (gstate->stroke.alpha == 1.0f && gstate->blendmode == FZ_BLEND_NORMAL) |
595 | { |
596 | /* No need for group, as stroke won't show up */ |
597 | } |
598 | else |
599 | { |
600 | knockout_group = 1; |
601 | fz_begin_group(ctx, pr->dev, bbox, NULL, 0, 1, FZ_BLEND_NORMAL, 1); |
602 | } |
603 | } |
604 | |
605 | if (dofill) |
606 | { |
607 | switch (gstate->fill.kind) |
608 | { |
609 | case PDF_MAT_NONE: |
610 | break; |
611 | case PDF_MAT_COLOR: |
612 | fz_fill_path(ctx, pr->dev, path, even_odd, gstate->ctm, |
613 | gstate->fill.colorspace, gstate->fill.v, gstate->fill.alpha, gstate->fill.color_params); |
614 | break; |
615 | case PDF_MAT_PATTERN: |
616 | if (gstate->fill.pattern) |
617 | { |
618 | fz_clip_path(ctx, pr->dev, path, even_odd, gstate->ctm, bbox); |
619 | gstate = pdf_show_pattern(ctx, pr, gstate->fill.pattern, gstate->fill.gstate_num, bbox, PDF_FILL); |
620 | fz_pop_clip(ctx, pr->dev); |
621 | } |
622 | break; |
623 | case PDF_MAT_SHADE: |
624 | if (gstate->fill.shade) |
625 | { |
626 | fz_clip_path(ctx, pr->dev, path, even_odd, gstate->ctm, bbox); |
627 | /* The cluster and page 2 of patterns.pdf shows that fz_fill_shade should NOT be called with gstate->ctm. */ |
628 | fz_fill_shade(ctx, pr->dev, gstate->fill.shade, pr->gstate[gstate->fill.gstate_num].ctm, gstate->fill.alpha, gstate->fill.color_params); |
629 | fz_pop_clip(ctx, pr->dev); |
630 | } |
631 | break; |
632 | } |
633 | } |
634 | |
635 | if (dostroke) |
636 | { |
637 | switch (gstate->stroke.kind) |
638 | { |
639 | case PDF_MAT_NONE: |
640 | break; |
641 | case PDF_MAT_COLOR: |
642 | fz_stroke_path(ctx, pr->dev, path, gstate->stroke_state, gstate->ctm, |
643 | gstate->stroke.colorspace, gstate->stroke.v, gstate->stroke.alpha, gstate->stroke.color_params); |
644 | break; |
645 | case PDF_MAT_PATTERN: |
646 | if (gstate->stroke.pattern) |
647 | { |
648 | fz_clip_stroke_path(ctx, pr->dev, path, gstate->stroke_state, gstate->ctm, bbox); |
649 | gstate = pdf_show_pattern(ctx, pr, gstate->stroke.pattern, gstate->stroke.gstate_num, bbox, PDF_STROKE); |
650 | fz_pop_clip(ctx, pr->dev); |
651 | } |
652 | break; |
653 | case PDF_MAT_SHADE: |
654 | if (gstate->stroke.shade) |
655 | { |
656 | fz_clip_stroke_path(ctx, pr->dev, path, gstate->stroke_state, gstate->ctm, bbox); |
657 | fz_fill_shade(ctx, pr->dev, gstate->stroke.shade, pr->gstate[gstate->stroke.gstate_num].ctm, gstate->stroke.alpha, gstate->stroke.color_params); |
658 | fz_pop_clip(ctx, pr->dev); |
659 | } |
660 | break; |
661 | } |
662 | } |
663 | |
664 | if (knockout_group) |
665 | fz_end_group(ctx, pr->dev); |
666 | |
667 | if (dofill || dostroke) |
668 | pdf_end_group(ctx, pr, &softmask); |
669 | |
670 | if (pr->clip) |
671 | { |
672 | gstate->clip_depth++; |
673 | fz_clip_path(ctx, pr->dev, path, pr->clip_even_odd, gstate->ctm, bbox); |
674 | pr->clip = 0; |
675 | } |
676 | } |
677 | fz_always(ctx) |
678 | { |
679 | fz_drop_path(ctx, path); |
680 | } |
681 | fz_catch(ctx) |
682 | { |
683 | fz_rethrow(ctx); |
684 | } |
685 | } |
686 | |
687 | /* |
688 | * Assemble and emit text |
689 | */ |
690 | |
691 | static pdf_gstate * |
692 | pdf_flush_text(fz_context *ctx, pdf_run_processor *pr) |
693 | { |
694 | pdf_gstate *gstate = pr->gstate + pr->gtop; |
695 | fz_text *text; |
696 | int dofill; |
697 | int dostroke; |
698 | int doclip; |
699 | int doinvisible; |
700 | softmask_save softmask = { NULL }; |
701 | int knockout_group = 0; |
702 | |
703 | text = pdf_tos_get_text(ctx, &pr->tos); |
704 | if (!text) |
705 | return gstate; |
706 | |
707 | dofill = dostroke = doclip = doinvisible = 0; |
708 | switch (pr->tos.text_mode) |
709 | { |
710 | case 0: dofill = 1; break; |
711 | case 1: dostroke = 1; break; |
712 | case 2: dofill = dostroke = 1; break; |
713 | case 3: doinvisible = 1; break; |
714 | case 4: dofill = doclip = 1; break; |
715 | case 5: dostroke = doclip = 1; break; |
716 | case 6: dofill = dostroke = doclip = 1; break; |
717 | case 7: doclip = 1; break; |
718 | } |
719 | |
720 | if (pr->super.hidden) |
721 | dostroke = dofill = 0; |
722 | |
723 | fz_try(ctx) |
724 | { |
725 | fz_rect tb = fz_transform_rect(pr->tos.text_bbox, gstate->ctm); |
726 | if (dostroke) |
727 | tb = fz_adjust_rect_for_stroke(ctx, tb, gstate->stroke_state, gstate->ctm); |
728 | |
729 | /* Don't bother sending a text group with nothing in it */ |
730 | if (!text->head) |
731 | break; |
732 | |
733 | if (dofill || dostroke) |
734 | gstate = pdf_begin_group(ctx, pr, tb, &softmask); |
735 | |
736 | if (dofill && dostroke) |
737 | { |
738 | /* We may need to push a knockout group */ |
739 | if (gstate->stroke.alpha == 0) |
740 | { |
741 | /* No need for group, as stroke won't do anything */ |
742 | } |
743 | else if (gstate->stroke.alpha == 1.0f && gstate->blendmode == FZ_BLEND_NORMAL) |
744 | { |
745 | /* No need for group, as stroke won't show up */ |
746 | } |
747 | else |
748 | { |
749 | knockout_group = 1; |
750 | fz_begin_group(ctx, pr->dev, tb, NULL, 0, 1, FZ_BLEND_NORMAL, 1); |
751 | } |
752 | } |
753 | |
754 | if (doinvisible) |
755 | fz_ignore_text(ctx, pr->dev, text, gstate->ctm); |
756 | |
757 | if (dofill) |
758 | { |
759 | switch (gstate->fill.kind) |
760 | { |
761 | case PDF_MAT_NONE: |
762 | break; |
763 | case PDF_MAT_COLOR: |
764 | fz_fill_text(ctx, pr->dev, text, gstate->ctm, |
765 | gstate->fill.colorspace, gstate->fill.v, gstate->fill.alpha, gstate->fill.color_params); |
766 | break; |
767 | case PDF_MAT_PATTERN: |
768 | if (gstate->fill.pattern) |
769 | { |
770 | fz_clip_text(ctx, pr->dev, text, gstate->ctm, tb); |
771 | gstate = pdf_show_pattern(ctx, pr, gstate->fill.pattern, gstate->fill.gstate_num, tb, PDF_FILL); |
772 | fz_pop_clip(ctx, pr->dev); |
773 | } |
774 | break; |
775 | case PDF_MAT_SHADE: |
776 | if (gstate->fill.shade) |
777 | { |
778 | fz_clip_text(ctx, pr->dev, text, gstate->ctm, tb); |
779 | /* Page 2 of patterns.pdf shows that fz_fill_shade should NOT be called with gstate->ctm */ |
780 | fz_fill_shade(ctx, pr->dev, gstate->fill.shade, pr->gstate[gstate->fill.gstate_num].ctm, gstate->fill.alpha, gstate->fill.color_params); |
781 | fz_pop_clip(ctx, pr->dev); |
782 | } |
783 | break; |
784 | } |
785 | } |
786 | |
787 | if (dostroke) |
788 | { |
789 | switch (gstate->stroke.kind) |
790 | { |
791 | case PDF_MAT_NONE: |
792 | break; |
793 | case PDF_MAT_COLOR: |
794 | fz_stroke_text(ctx, pr->dev, text, gstate->stroke_state, gstate->ctm, |
795 | gstate->stroke.colorspace, gstate->stroke.v, gstate->stroke.alpha, gstate->stroke.color_params); |
796 | break; |
797 | case PDF_MAT_PATTERN: |
798 | if (gstate->stroke.pattern) |
799 | { |
800 | fz_clip_stroke_text(ctx, pr->dev, text, gstate->stroke_state, gstate->ctm, tb); |
801 | gstate = pdf_show_pattern(ctx, pr, gstate->stroke.pattern, gstate->stroke.gstate_num, tb, PDF_STROKE); |
802 | fz_pop_clip(ctx, pr->dev); |
803 | } |
804 | break; |
805 | case PDF_MAT_SHADE: |
806 | if (gstate->stroke.shade) |
807 | { |
808 | fz_clip_stroke_text(ctx, pr->dev, text, gstate->stroke_state, gstate->ctm, tb); |
809 | fz_fill_shade(ctx, pr->dev, gstate->stroke.shade, pr->gstate[gstate->stroke.gstate_num].ctm, gstate->stroke.alpha, gstate->stroke.color_params); |
810 | fz_pop_clip(ctx, pr->dev); |
811 | } |
812 | break; |
813 | } |
814 | } |
815 | |
816 | if (knockout_group) |
817 | fz_end_group(ctx, pr->dev); |
818 | |
819 | if (dofill || dostroke) |
820 | pdf_end_group(ctx, pr, &softmask); |
821 | |
822 | if (doclip) |
823 | { |
824 | gstate->clip_depth++; |
825 | fz_clip_text(ctx, pr->dev, text, gstate->ctm, tb); |
826 | } |
827 | } |
828 | fz_always(ctx) |
829 | { |
830 | fz_drop_text(ctx, text); |
831 | } |
832 | fz_catch(ctx) |
833 | { |
834 | fz_rethrow(ctx); |
835 | } |
836 | |
837 | return pr->gstate + pr->gtop; |
838 | } |
839 | |
840 | static void |
841 | pdf_show_char(fz_context *ctx, pdf_run_processor *pr, int cid) |
842 | { |
843 | pdf_gstate *gstate = pr->gstate + pr->gtop; |
844 | pdf_font_desc *fontdesc = gstate->text.font; |
845 | fz_matrix trm; |
846 | int gid; |
847 | int ucsbuf[8]; |
848 | int ucslen; |
849 | int i; |
850 | int render_direct; |
851 | |
852 | gid = pdf_tos_make_trm(ctx, &pr->tos, &gstate->text, fontdesc, cid, &trm); |
853 | |
854 | /* If we are uncachable, then render direct. */ |
855 | render_direct = !fz_glyph_cacheable(ctx, fontdesc->font, gid); |
856 | |
857 | /* flush buffered text if rendermode has changed */ |
858 | if (!pr->tos.text || gstate->text.render != pr->tos.text_mode || render_direct) |
859 | { |
860 | gstate = pdf_flush_text(ctx, pr); |
861 | pdf_tos_reset(ctx, &pr->tos, gstate->text.render); |
862 | } |
863 | |
864 | if (render_direct) |
865 | { |
866 | /* Render the glyph stream direct here (only happens for |
867 | * type3 glyphs that seem to inherit current graphics |
868 | * attributes, or type 3 glyphs within type3 glyphs). */ |
869 | fz_matrix composed = fz_concat(trm, gstate->ctm); |
870 | fz_render_t3_glyph_direct(ctx, pr->dev, fontdesc->font, gid, composed, gstate, pr->default_cs); |
871 | /* Render text invisibly so that it can still be extracted. */ |
872 | pr->tos.text_mode = 3; |
873 | } |
874 | |
875 | ucslen = 0; |
876 | if (fontdesc->to_unicode) |
877 | ucslen = pdf_lookup_cmap_full(fontdesc->to_unicode, cid, ucsbuf); |
878 | if (ucslen == 0 && (size_t)cid < fontdesc->cid_to_ucs_len) |
879 | { |
880 | ucsbuf[0] = fontdesc->cid_to_ucs[cid]; |
881 | ucslen = 1; |
882 | } |
883 | if (ucslen == 0 || (ucslen == 1 && ucsbuf[0] == 0)) |
884 | { |
885 | ucsbuf[0] = FZ_REPLACEMENT_CHARACTER; |
886 | ucslen = 1; |
887 | } |
888 | |
889 | /* add glyph to textobject */ |
890 | fz_show_glyph(ctx, pr->tos.text, fontdesc->font, trm, gid, ucsbuf[0], fontdesc->wmode, 0, FZ_BIDI_NEUTRAL, FZ_LANG_UNSET); |
891 | |
892 | /* add filler glyphs for one-to-many unicode mapping */ |
893 | for (i = 1; i < ucslen; i++) |
894 | fz_show_glyph(ctx, pr->tos.text, fontdesc->font, trm, -1, ucsbuf[i], fontdesc->wmode, 0, FZ_BIDI_NEUTRAL, FZ_LANG_UNSET); |
895 | |
896 | pdf_tos_move_after_char(ctx, &pr->tos); |
897 | } |
898 | |
899 | static void |
900 | pdf_show_space(fz_context *ctx, pdf_run_processor *pr, float tadj) |
901 | { |
902 | pdf_gstate *gstate = pr->gstate + pr->gtop; |
903 | pdf_font_desc *fontdesc = gstate->text.font; |
904 | |
905 | if (fontdesc->wmode == 0) |
906 | pr->tos.tm = fz_pre_translate(pr->tos.tm, tadj * gstate->text.scale, 0); |
907 | else |
908 | pr->tos.tm = fz_pre_translate(pr->tos.tm, 0, tadj); |
909 | } |
910 | |
911 | static void |
912 | show_string(fz_context *ctx, pdf_run_processor *pr, unsigned char *buf, int len) |
913 | { |
914 | pdf_gstate *gstate = pr->gstate + pr->gtop; |
915 | pdf_font_desc *fontdesc = gstate->text.font; |
916 | unsigned char *end = buf + len; |
917 | unsigned int cpt; |
918 | int cid; |
919 | |
920 | while (buf < end) |
921 | { |
922 | int w = pdf_decode_cmap(fontdesc->encoding, buf, end, &cpt); |
923 | buf += w; |
924 | |
925 | cid = pdf_lookup_cmap(fontdesc->encoding, cpt); |
926 | if (cid >= 0) |
927 | pdf_show_char(ctx, pr, cid); |
928 | else |
929 | fz_warn(ctx, "cannot encode character" ); |
930 | if (cpt == 32 && w == 1) |
931 | pdf_show_space(ctx, pr, gstate->text.word_space); |
932 | } |
933 | } |
934 | |
935 | static void |
936 | pdf_show_string(fz_context *ctx, pdf_run_processor *pr, unsigned char *buf, int len) |
937 | { |
938 | pdf_gstate *gstate = pr->gstate + pr->gtop; |
939 | pdf_font_desc *fontdesc = gstate->text.font; |
940 | |
941 | if (!fontdesc) |
942 | { |
943 | fz_warn(ctx, "cannot draw text since font and size not set" ); |
944 | return; |
945 | } |
946 | |
947 | show_string(ctx, pr, buf, len); |
948 | } |
949 | |
950 | static void |
951 | pdf_show_text(fz_context *ctx, pdf_run_processor *pr, pdf_obj *text) |
952 | { |
953 | pdf_gstate *gstate = pr->gstate + pr->gtop; |
954 | pdf_font_desc *fontdesc = gstate->text.font; |
955 | int i; |
956 | |
957 | if (!fontdesc) |
958 | { |
959 | fz_warn(ctx, "cannot draw text since font and size not set" ); |
960 | return; |
961 | } |
962 | |
963 | if (pdf_is_array(ctx, text)) |
964 | { |
965 | int n = pdf_array_len(ctx, text); |
966 | for (i = 0; i < n; i++) |
967 | { |
968 | pdf_obj *item = pdf_array_get(ctx, text, i); |
969 | if (pdf_is_string(ctx, item)) |
970 | show_string(ctx, pr, (unsigned char *)pdf_to_str_buf(ctx, item), pdf_to_str_len(ctx, item)); |
971 | else |
972 | pdf_show_space(ctx, pr, - pdf_to_real(ctx, item) * gstate->text.size * 0.001f); |
973 | } |
974 | } |
975 | else if (pdf_is_string(ctx, text)) |
976 | { |
977 | pdf_show_string(ctx, pr, (unsigned char *)pdf_to_str_buf(ctx, text), pdf_to_str_len(ctx, text)); |
978 | } |
979 | } |
980 | |
981 | /* |
982 | * Interpreter and graphics state stack. |
983 | */ |
984 | |
985 | static void |
986 | pdf_init_gstate(fz_context *ctx, pdf_gstate *gs, fz_matrix ctm) |
987 | { |
988 | gs->ctm = ctm; |
989 | gs->clip_depth = 0; |
990 | |
991 | gs->stroke_state = fz_new_stroke_state(ctx); |
992 | |
993 | gs->stroke.kind = PDF_MAT_COLOR; |
994 | gs->stroke.colorspace = fz_keep_colorspace(ctx, fz_device_gray(ctx)); |
995 | gs->stroke.v[0] = 0; |
996 | gs->stroke.pattern = NULL; |
997 | gs->stroke.shade = NULL; |
998 | gs->stroke.alpha = 1; |
999 | gs->stroke.gstate_num = -1; |
1000 | |
1001 | gs->fill.kind = PDF_MAT_COLOR; |
1002 | gs->fill.colorspace = fz_keep_colorspace(ctx, fz_device_gray(ctx)); |
1003 | gs->fill.v[0] = 0; |
1004 | gs->fill.pattern = NULL; |
1005 | gs->fill.shade = NULL; |
1006 | gs->fill.alpha = 1; |
1007 | gs->fill.gstate_num = -1; |
1008 | |
1009 | gs->text.char_space = 0; |
1010 | gs->text.word_space = 0; |
1011 | gs->text.scale = 1; |
1012 | gs->text.leading = 0; |
1013 | gs->text.font = NULL; |
1014 | gs->text.size = -1; |
1015 | gs->text.render = 0; |
1016 | gs->text.rise = 0; |
1017 | |
1018 | gs->blendmode = 0; |
1019 | gs->softmask = NULL; |
1020 | gs->softmask_resources = NULL; |
1021 | gs->softmask_ctm = fz_identity; |
1022 | gs->luminosity = 0; |
1023 | |
1024 | gs->fill.color_params = fz_default_color_params; |
1025 | gs->stroke.color_params = fz_default_color_params; |
1026 | } |
1027 | |
1028 | static void |
1029 | pdf_copy_gstate(fz_context *ctx, pdf_gstate *dst, pdf_gstate *src) |
1030 | { |
1031 | pdf_drop_gstate(ctx, dst); |
1032 | *dst = *src; |
1033 | pdf_keep_gstate(ctx, dst); |
1034 | } |
1035 | |
1036 | /* |
1037 | * Material state |
1038 | */ |
1039 | |
1040 | static void |
1041 | pdf_set_colorspace(fz_context *ctx, pdf_run_processor *pr, int what, fz_colorspace *colorspace) |
1042 | { |
1043 | pdf_gstate *gstate = pr->gstate + pr->gtop; |
1044 | pdf_material *mat; |
1045 | int n = fz_colorspace_n(ctx, colorspace); |
1046 | |
1047 | gstate = pdf_flush_text(ctx, pr); |
1048 | |
1049 | mat = what == PDF_FILL ? &gstate->fill : &gstate->stroke; |
1050 | |
1051 | fz_drop_colorspace(ctx, mat->colorspace); |
1052 | |
1053 | mat->kind = PDF_MAT_COLOR; |
1054 | mat->colorspace = fz_keep_colorspace(ctx, colorspace); |
1055 | |
1056 | mat->v[0] = 0; |
1057 | mat->v[1] = 0; |
1058 | mat->v[2] = 0; |
1059 | mat->v[3] = 1; |
1060 | |
1061 | if (pdf_is_tint_colorspace(ctx, colorspace)) |
1062 | { |
1063 | int i; |
1064 | for (i = 0; i < n; i++) |
1065 | mat->v[i] = 1.0f; |
1066 | } |
1067 | } |
1068 | |
1069 | static void |
1070 | pdf_set_color(fz_context *ctx, pdf_run_processor *pr, int what, float *v) |
1071 | { |
1072 | pdf_gstate *gstate = pr->gstate + pr->gtop; |
1073 | pdf_material *mat; |
1074 | |
1075 | gstate = pdf_flush_text(ctx, pr); |
1076 | |
1077 | mat = what == PDF_FILL ? &gstate->fill : &gstate->stroke; |
1078 | |
1079 | switch (mat->kind) |
1080 | { |
1081 | case PDF_MAT_PATTERN: |
1082 | case PDF_MAT_COLOR: |
1083 | fz_clamp_color(ctx, mat->colorspace, v, mat->v); |
1084 | break; |
1085 | default: |
1086 | fz_warn(ctx, "color incompatible with material" ); |
1087 | } |
1088 | |
1089 | mat->gstate_num = pr->gparent; |
1090 | } |
1091 | |
1092 | static void |
1093 | pdf_set_shade(fz_context *ctx, pdf_run_processor *pr, int what, fz_shade *shade) |
1094 | { |
1095 | pdf_gstate *gs; |
1096 | pdf_material *mat; |
1097 | |
1098 | gs = pdf_flush_text(ctx, pr); |
1099 | |
1100 | mat = what == PDF_FILL ? &gs->fill : &gs->stroke; |
1101 | |
1102 | fz_drop_shade(ctx, mat->shade); |
1103 | |
1104 | mat->kind = PDF_MAT_SHADE; |
1105 | mat->shade = fz_keep_shade(ctx, shade); |
1106 | |
1107 | mat->gstate_num = pr->gparent; |
1108 | } |
1109 | |
1110 | static void |
1111 | pdf_set_pattern(fz_context *ctx, pdf_run_processor *pr, int what, pdf_pattern *pat, float *v) |
1112 | { |
1113 | pdf_gstate *gs; |
1114 | pdf_material *mat; |
1115 | |
1116 | gs = pdf_flush_text(ctx, pr); |
1117 | |
1118 | mat = what == PDF_FILL ? &gs->fill : &gs->stroke; |
1119 | |
1120 | pdf_drop_pattern(ctx, mat->pattern); |
1121 | mat->pattern = NULL; |
1122 | |
1123 | mat->kind = PDF_MAT_PATTERN; |
1124 | if (pat) |
1125 | mat->pattern = pdf_keep_pattern(ctx, pat); |
1126 | |
1127 | if (v) |
1128 | pdf_set_color(ctx, pr, what, v); |
1129 | |
1130 | mat->gstate_num = pr->gparent; |
1131 | } |
1132 | |
1133 | static void |
1134 | pdf_run_xobject(fz_context *ctx, pdf_run_processor *proc, pdf_obj *xobj, pdf_obj *page_resources, fz_matrix transform, int is_smask) |
1135 | { |
1136 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1137 | pdf_gstate *gstate = NULL; |
1138 | int oldtop = 0; |
1139 | int oldbot = -1; |
1140 | softmask_save softmask = { NULL }; |
1141 | int gparent_save; |
1142 | fz_matrix gparent_save_ctm; |
1143 | pdf_obj *resources; |
1144 | fz_rect xobj_bbox; |
1145 | fz_matrix xobj_matrix; |
1146 | int transparency = 0; |
1147 | pdf_document *doc; |
1148 | fz_colorspace *cs = NULL; |
1149 | fz_default_colorspaces *save_default_cs = NULL; |
1150 | fz_default_colorspaces *xobj_default_cs = NULL; |
1151 | |
1152 | /* Avoid infinite recursion */ |
1153 | if (xobj == NULL || pdf_mark_obj(ctx, xobj)) |
1154 | return; |
1155 | |
1156 | fz_var(cs); |
1157 | fz_var(xobj_default_cs); |
1158 | |
1159 | gparent_save = pr->gparent; |
1160 | pr->gparent = pr->gtop; |
1161 | oldtop = pr->gtop; |
1162 | |
1163 | save_default_cs = pr->default_cs; |
1164 | |
1165 | fz_try(ctx) |
1166 | { |
1167 | pdf_gsave(ctx, pr); |
1168 | |
1169 | gstate = pr->gstate + pr->gtop; |
1170 | |
1171 | xobj_bbox = pdf_xobject_bbox(ctx, xobj); |
1172 | xobj_matrix = pdf_xobject_matrix(ctx, xobj); |
1173 | transparency = pdf_xobject_transparency(ctx, xobj); |
1174 | |
1175 | /* apply xobject's transform matrix */ |
1176 | transform = fz_concat(xobj_matrix, transform); |
1177 | gstate->ctm = fz_concat(transform, gstate->ctm); |
1178 | |
1179 | /* The gparent is updated with the modified ctm */ |
1180 | gparent_save_ctm = pr->gstate[pr->gparent].ctm; |
1181 | pr->gstate[pr->gparent].ctm = gstate->ctm; |
1182 | |
1183 | /* apply soft mask, create transparency group and reset state */ |
1184 | if (transparency) |
1185 | { |
1186 | int isolated = pdf_xobject_isolated(ctx, xobj); |
1187 | |
1188 | fz_rect bbox = fz_transform_rect(xobj_bbox, gstate->ctm); |
1189 | |
1190 | gstate = begin_softmask(ctx, pr, &softmask); |
1191 | |
1192 | if (isolated) |
1193 | cs = pdf_xobject_colorspace(ctx, xobj); |
1194 | fz_begin_group(ctx, pr->dev, bbox, |
1195 | cs, |
1196 | (is_smask ? 1 : isolated), |
1197 | pdf_xobject_knockout(ctx, xobj), |
1198 | gstate->blendmode, gstate->fill.alpha); |
1199 | |
1200 | gstate->blendmode = 0; |
1201 | gstate->stroke.alpha = 1; |
1202 | gstate->fill.alpha = 1; |
1203 | } |
1204 | |
1205 | pdf_gsave(ctx, pr); /* Save here so the clippath doesn't persist */ |
1206 | |
1207 | /* clip to the bounds */ |
1208 | fz_moveto(ctx, pr->path, xobj_bbox.x0, xobj_bbox.y0); |
1209 | fz_lineto(ctx, pr->path, xobj_bbox.x1, xobj_bbox.y0); |
1210 | fz_lineto(ctx, pr->path, xobj_bbox.x1, xobj_bbox.y1); |
1211 | fz_lineto(ctx, pr->path, xobj_bbox.x0, xobj_bbox.y1); |
1212 | fz_closepath(ctx, pr->path); |
1213 | pr->clip = 1; |
1214 | pdf_show_path(ctx, pr, 0, 0, 0, 0); |
1215 | |
1216 | /* run contents */ |
1217 | |
1218 | resources = pdf_xobject_resources(ctx, xobj); |
1219 | if (!resources) |
1220 | resources = page_resources; |
1221 | |
1222 | fz_try(ctx) |
1223 | xobj_default_cs = pdf_update_default_colorspaces(ctx, pr->default_cs, resources); |
1224 | fz_catch(ctx) |
1225 | { |
1226 | if (fz_caught(ctx) != FZ_ERROR_TRYLATER) |
1227 | fz_rethrow(ctx); |
1228 | if (pr->cookie) |
1229 | pr->cookie->incomplete = 1; |
1230 | } |
1231 | if (xobj_default_cs != save_default_cs) |
1232 | { |
1233 | fz_set_default_colorspaces(ctx, pr->dev, xobj_default_cs); |
1234 | pr->default_cs = xobj_default_cs; |
1235 | } |
1236 | |
1237 | doc = pdf_get_bound_document(ctx, xobj); |
1238 | |
1239 | oldbot = pr->gbot; |
1240 | pr->gbot = pr->gtop; |
1241 | |
1242 | pdf_process_contents(ctx, (pdf_processor*)pr, doc, resources, xobj, pr->cookie); |
1243 | |
1244 | /* Undo any gstate mismatches due to the pdf_process_contents call */ |
1245 | if (oldbot != -1) |
1246 | { |
1247 | while (pr->gtop > pr->gbot) |
1248 | { |
1249 | pdf_grestore(ctx, pr); |
1250 | } |
1251 | pr->gbot = oldbot; |
1252 | } |
1253 | |
1254 | pdf_grestore(ctx, pr); /* Remove the state we pushed for the clippath */ |
1255 | |
1256 | /* wrap up transparency stacks */ |
1257 | if (transparency) |
1258 | { |
1259 | fz_end_group(ctx, pr->dev); |
1260 | end_softmask(ctx, pr, &softmask); |
1261 | } |
1262 | |
1263 | pr->gstate[pr->gparent].ctm = gparent_save_ctm; |
1264 | pr->gparent = gparent_save; |
1265 | |
1266 | while (oldtop < pr->gtop) |
1267 | pdf_grestore(ctx, pr); |
1268 | |
1269 | if (xobj_default_cs != save_default_cs) |
1270 | { |
1271 | fz_set_default_colorspaces(ctx, pr->dev, save_default_cs); |
1272 | } |
1273 | } |
1274 | fz_always(ctx) |
1275 | { |
1276 | pr->default_cs = save_default_cs; |
1277 | fz_drop_default_colorspaces(ctx, xobj_default_cs); |
1278 | fz_drop_colorspace(ctx, cs); |
1279 | pdf_unmark_obj(ctx, xobj); |
1280 | } |
1281 | fz_catch(ctx) |
1282 | { |
1283 | pdf_drop_obj(ctx, softmask.softmask); |
1284 | pdf_drop_obj(ctx, softmask.page_resources); |
1285 | /* Note: Any SYNTAX errors should have been swallowed |
1286 | * by pdf_process_contents, but in case any escape from other |
1287 | * functions, recast the error type here to be safe. */ |
1288 | if (fz_caught(ctx) == FZ_ERROR_SYNTAX) |
1289 | fz_throw(ctx, FZ_ERROR_GENERIC, "syntax error in xobject" ); |
1290 | fz_rethrow(ctx); |
1291 | } |
1292 | } |
1293 | |
1294 | /* general graphics state */ |
1295 | |
1296 | static void pdf_run_w(fz_context *ctx, pdf_processor *proc, float linewidth) |
1297 | { |
1298 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1299 | pdf_gstate *gstate = pdf_flush_text(ctx, pr); |
1300 | |
1301 | pr->dev->flags &= ~FZ_DEVFLAG_LINEWIDTH_UNDEFINED; |
1302 | gstate->stroke_state = fz_unshare_stroke_state(ctx, gstate->stroke_state); |
1303 | gstate->stroke_state->linewidth = linewidth; |
1304 | } |
1305 | |
1306 | static void pdf_run_j(fz_context *ctx, pdf_processor *proc, int linejoin) |
1307 | { |
1308 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1309 | pdf_gstate *gstate = pdf_flush_text(ctx, pr); |
1310 | |
1311 | pr->dev->flags &= ~FZ_DEVFLAG_LINEJOIN_UNDEFINED; |
1312 | gstate->stroke_state = fz_unshare_stroke_state(ctx, gstate->stroke_state); |
1313 | gstate->stroke_state->linejoin = linejoin; |
1314 | } |
1315 | |
1316 | static void pdf_run_J(fz_context *ctx, pdf_processor *proc, int linecap) |
1317 | { |
1318 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1319 | pdf_gstate *gstate = pdf_flush_text(ctx, pr); |
1320 | |
1321 | pr->dev->flags &= ~(FZ_DEVFLAG_STARTCAP_UNDEFINED | FZ_DEVFLAG_DASHCAP_UNDEFINED | FZ_DEVFLAG_ENDCAP_UNDEFINED); |
1322 | gstate->stroke_state = fz_unshare_stroke_state(ctx, gstate->stroke_state); |
1323 | gstate->stroke_state->start_cap = linecap; |
1324 | gstate->stroke_state->dash_cap = linecap; |
1325 | gstate->stroke_state->end_cap = linecap; |
1326 | } |
1327 | |
1328 | static void pdf_run_M(fz_context *ctx, pdf_processor *proc, float miterlimit) |
1329 | { |
1330 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1331 | pdf_gstate *gstate = pdf_flush_text(ctx, pr); |
1332 | |
1333 | pr->dev->flags &= ~FZ_DEVFLAG_MITERLIMIT_UNDEFINED; |
1334 | gstate->stroke_state = fz_unshare_stroke_state(ctx, gstate->stroke_state); |
1335 | gstate->stroke_state->miterlimit = miterlimit; |
1336 | } |
1337 | |
1338 | static void pdf_run_d(fz_context *ctx, pdf_processor *proc, pdf_obj *array, float phase) |
1339 | { |
1340 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1341 | pdf_gstate *gstate = pdf_flush_text(ctx, pr); |
1342 | int len, i; |
1343 | |
1344 | len = pdf_array_len(ctx, array); |
1345 | gstate->stroke_state = fz_unshare_stroke_state_with_dash_len(ctx, gstate->stroke_state, len); |
1346 | gstate->stroke_state->dash_len = len; |
1347 | for (i = 0; i < len; i++) |
1348 | gstate->stroke_state->dash_list[i] = pdf_array_get_real(ctx, array, i); |
1349 | gstate->stroke_state->dash_phase = phase; |
1350 | } |
1351 | |
1352 | static void pdf_run_ri(fz_context *ctx, pdf_processor *proc, const char *intent) |
1353 | { |
1354 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1355 | pdf_gstate *gstate = pdf_flush_text(ctx, pr); |
1356 | gstate->fill.color_params.ri = fz_lookup_rendering_intent(intent); |
1357 | gstate->stroke.color_params.ri = gstate->fill.color_params.ri; |
1358 | } |
1359 | |
1360 | static void pdf_run_gs_OP(fz_context *ctx, pdf_processor *proc, int b) |
1361 | { |
1362 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1363 | pdf_gstate *gstate = pdf_flush_text(ctx, pr); |
1364 | gstate->stroke.color_params.op = b; |
1365 | gstate->fill.color_params.op = b; |
1366 | } |
1367 | |
1368 | static void pdf_run_gs_op(fz_context *ctx, pdf_processor *proc, int b) |
1369 | { |
1370 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1371 | pdf_gstate *gstate = pdf_flush_text(ctx, pr); |
1372 | gstate->fill.color_params.op = b; |
1373 | } |
1374 | |
1375 | static void pdf_run_gs_OPM(fz_context *ctx, pdf_processor *proc, int i) |
1376 | { |
1377 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1378 | pdf_gstate *gstate = pdf_flush_text(ctx, pr); |
1379 | gstate->stroke.color_params.opm = i; |
1380 | gstate->fill.color_params.opm = i; |
1381 | } |
1382 | |
1383 | static void pdf_run_gs_UseBlackPtComp(fz_context *ctx, pdf_processor *proc, pdf_obj *obj) |
1384 | { |
1385 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1386 | pdf_gstate *gstate = pdf_flush_text(ctx, pr); |
1387 | int on = pdf_name_eq(ctx, obj, PDF_NAME(ON)); |
1388 | /* The spec says that "ON" means on, "OFF" means "Off", and |
1389 | * "Default" or anything else means "Meh, do what you want." */ |
1390 | gstate->stroke.color_params.bp = on; |
1391 | gstate->fill.color_params.bp = on; |
1392 | } |
1393 | |
1394 | static void pdf_run_i(fz_context *ctx, pdf_processor *proc, float flatness) |
1395 | { |
1396 | } |
1397 | |
1398 | static void pdf_run_gs_begin(fz_context *ctx, pdf_processor *proc, const char *name, pdf_obj *extgstate) |
1399 | { |
1400 | } |
1401 | |
1402 | static void pdf_run_gs_end(fz_context *ctx, pdf_processor *proc) |
1403 | { |
1404 | } |
1405 | |
1406 | /* transparency graphics state */ |
1407 | |
1408 | static void pdf_run_gs_BM(fz_context *ctx, pdf_processor *proc, const char *blendmode) |
1409 | { |
1410 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1411 | pdf_gstate *gstate = pdf_flush_text(ctx, pr); |
1412 | gstate->blendmode = fz_lookup_blendmode(blendmode); |
1413 | } |
1414 | |
1415 | static void pdf_run_gs_CA(fz_context *ctx, pdf_processor *proc, float alpha) |
1416 | { |
1417 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1418 | pdf_gstate *gstate = pdf_flush_text(ctx, pr); |
1419 | gstate->stroke.alpha = fz_clamp(alpha, 0, 1); |
1420 | } |
1421 | |
1422 | static void pdf_run_gs_ca(fz_context *ctx, pdf_processor *proc, float alpha) |
1423 | { |
1424 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1425 | pdf_gstate *gstate = pdf_flush_text(ctx, pr); |
1426 | gstate->fill.alpha = fz_clamp(alpha, 0, 1); |
1427 | } |
1428 | |
1429 | static void pdf_run_gs_SMask(fz_context *ctx, pdf_processor *proc, pdf_obj *smask, pdf_obj *page_resources, float *bc, int luminosity) |
1430 | { |
1431 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1432 | pdf_gstate *gstate = pdf_flush_text(ctx, pr); |
1433 | int i; |
1434 | |
1435 | if (gstate->softmask) |
1436 | { |
1437 | pdf_drop_obj(ctx, gstate->softmask); |
1438 | gstate->softmask = NULL; |
1439 | pdf_drop_obj(ctx, gstate->softmask_resources); |
1440 | gstate->softmask_resources = NULL; |
1441 | } |
1442 | |
1443 | if (smask) |
1444 | { |
1445 | fz_colorspace *cs = pdf_xobject_colorspace(ctx, smask); |
1446 | int cs_n = 1; |
1447 | if (cs) |
1448 | cs_n = fz_colorspace_n(ctx, cs); |
1449 | gstate->softmask_ctm = gstate->ctm; |
1450 | gstate->softmask = pdf_keep_obj(ctx, smask); |
1451 | gstate->softmask_resources = pdf_keep_obj(ctx, page_resources); |
1452 | for (i = 0; i < cs_n; ++i) |
1453 | gstate->softmask_bc[i] = bc[i]; |
1454 | gstate->luminosity = luminosity; |
1455 | fz_drop_colorspace(ctx, cs); |
1456 | } |
1457 | } |
1458 | |
1459 | /* special graphics state */ |
1460 | |
1461 | static void pdf_run_q(fz_context *ctx, pdf_processor *proc) |
1462 | { |
1463 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1464 | pdf_gsave(ctx, pr); |
1465 | } |
1466 | |
1467 | static void pdf_run_Q(fz_context *ctx, pdf_processor *proc) |
1468 | { |
1469 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1470 | pdf_grestore(ctx, pr); |
1471 | } |
1472 | |
1473 | static void pdf_run_cm(fz_context *ctx, pdf_processor *proc, float a, float b, float c, float d, float e, float f) |
1474 | { |
1475 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1476 | pdf_gstate *gstate = pdf_flush_text(ctx, pr); |
1477 | fz_matrix m; |
1478 | |
1479 | m.a = a; |
1480 | m.b = b; |
1481 | m.c = c; |
1482 | m.d = d; |
1483 | m.e = e; |
1484 | m.f = f; |
1485 | gstate->ctm = fz_concat(m, gstate->ctm); |
1486 | } |
1487 | |
1488 | /* path construction */ |
1489 | |
1490 | static void pdf_run_m(fz_context *ctx, pdf_processor *proc, float x, float y) |
1491 | { |
1492 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1493 | fz_moveto(ctx, pr->path, x, y); |
1494 | } |
1495 | |
1496 | static void pdf_run_l(fz_context *ctx, pdf_processor *proc, float x, float y) |
1497 | { |
1498 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1499 | fz_lineto(ctx, pr->path, x, y); |
1500 | } |
1501 | static void pdf_run_c(fz_context *ctx, pdf_processor *proc, float x1, float y1, float x2, float y2, float x3, float y3) |
1502 | { |
1503 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1504 | fz_curveto(ctx, pr->path, x1, y1, x2, y2, x3, y3); |
1505 | } |
1506 | |
1507 | static void pdf_run_v(fz_context *ctx, pdf_processor *proc, float x2, float y2, float x3, float y3) |
1508 | { |
1509 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1510 | fz_curvetov(ctx, pr->path, x2, y2, x3, y3); |
1511 | } |
1512 | |
1513 | static void pdf_run_y(fz_context *ctx, pdf_processor *proc, float x1, float y1, float x3, float y3) |
1514 | { |
1515 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1516 | fz_curvetoy(ctx, pr->path, x1, y1, x3, y3); |
1517 | } |
1518 | |
1519 | static void pdf_run_h(fz_context *ctx, pdf_processor *proc) |
1520 | { |
1521 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1522 | fz_closepath(ctx, pr->path); |
1523 | } |
1524 | |
1525 | static void pdf_run_re(fz_context *ctx, pdf_processor *proc, float x, float y, float w, float h) |
1526 | { |
1527 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1528 | fz_rectto(ctx, pr->path, x, y, x+w, y+h); |
1529 | } |
1530 | |
1531 | /* path painting */ |
1532 | |
1533 | static void pdf_run_S(fz_context *ctx, pdf_processor *proc) |
1534 | { |
1535 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1536 | pdf_show_path(ctx, pr, 0, 0, 1, 0); |
1537 | } |
1538 | |
1539 | static void pdf_run_s(fz_context *ctx, pdf_processor *proc) |
1540 | { |
1541 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1542 | pdf_show_path(ctx, pr, 1, 0, 1, 0); |
1543 | } |
1544 | |
1545 | static void pdf_run_F(fz_context *ctx, pdf_processor *proc) |
1546 | { |
1547 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1548 | pdf_show_path(ctx, pr, 0, 1, 0, 0); |
1549 | } |
1550 | |
1551 | static void pdf_run_f(fz_context *ctx, pdf_processor *proc) |
1552 | { |
1553 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1554 | pdf_show_path(ctx, pr, 0, 1, 0, 0); |
1555 | } |
1556 | |
1557 | static void pdf_run_fstar(fz_context *ctx, pdf_processor *proc) |
1558 | { |
1559 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1560 | pdf_show_path(ctx, pr, 0, 1, 0, 1); |
1561 | } |
1562 | |
1563 | static void pdf_run_B(fz_context *ctx, pdf_processor *proc) |
1564 | { |
1565 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1566 | pdf_show_path(ctx, pr, 0, 1, 1, 0); |
1567 | } |
1568 | |
1569 | static void pdf_run_Bstar(fz_context *ctx, pdf_processor *proc) |
1570 | { |
1571 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1572 | pdf_show_path(ctx, pr, 0, 1, 1, 1); |
1573 | } |
1574 | |
1575 | static void pdf_run_b(fz_context *ctx, pdf_processor *proc) |
1576 | { |
1577 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1578 | pdf_show_path(ctx, pr, 1, 1, 1, 0); |
1579 | } |
1580 | |
1581 | static void pdf_run_bstar(fz_context *ctx, pdf_processor *proc) |
1582 | { |
1583 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1584 | pdf_show_path(ctx, pr, 1, 1, 1, 1); |
1585 | } |
1586 | |
1587 | static void pdf_run_n(fz_context *ctx, pdf_processor *proc) |
1588 | { |
1589 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1590 | pdf_show_path(ctx, pr, 0, 0, 0, 0); |
1591 | } |
1592 | |
1593 | /* clipping paths */ |
1594 | |
1595 | static void pdf_run_W(fz_context *ctx, pdf_processor *proc) |
1596 | { |
1597 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1598 | pr->clip = 1; |
1599 | pr->clip_even_odd = 0; |
1600 | } |
1601 | |
1602 | static void pdf_run_Wstar(fz_context *ctx, pdf_processor *proc) |
1603 | { |
1604 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1605 | pr->clip = 1; |
1606 | pr->clip_even_odd = 1; |
1607 | } |
1608 | |
1609 | /* text objects */ |
1610 | |
1611 | static void pdf_run_BT(fz_context *ctx, pdf_processor *proc) |
1612 | { |
1613 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1614 | pr->tos.tm = fz_identity; |
1615 | pr->tos.tlm = fz_identity; |
1616 | } |
1617 | |
1618 | static void pdf_run_ET(fz_context *ctx, pdf_processor *proc) |
1619 | { |
1620 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1621 | pdf_flush_text(ctx, pr); |
1622 | } |
1623 | |
1624 | /* text state */ |
1625 | |
1626 | static void pdf_run_Tc(fz_context *ctx, pdf_processor *proc, float charspace) |
1627 | { |
1628 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1629 | pdf_gstate *gstate = pr->gstate + pr->gtop; |
1630 | gstate->text.char_space = charspace; |
1631 | } |
1632 | |
1633 | static void pdf_run_Tw(fz_context *ctx, pdf_processor *proc, float wordspace) |
1634 | { |
1635 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1636 | pdf_gstate *gstate = pr->gstate + pr->gtop; |
1637 | gstate->text.word_space = wordspace; |
1638 | } |
1639 | |
1640 | static void pdf_run_Tz(fz_context *ctx, pdf_processor *proc, float scale) |
1641 | { |
1642 | /* scale is as written in the file. It is 100 times smaller in |
1643 | * the gstate. */ |
1644 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1645 | pdf_gstate *gstate = pr->gstate + pr->gtop; |
1646 | gstate->text.scale = scale / 100; |
1647 | } |
1648 | |
1649 | static void pdf_run_TL(fz_context *ctx, pdf_processor *proc, float leading) |
1650 | { |
1651 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1652 | pdf_gstate *gstate = pr->gstate + pr->gtop; |
1653 | gstate->text.leading = leading; |
1654 | } |
1655 | |
1656 | static void pdf_run_Tf(fz_context *ctx, pdf_processor *proc, const char *name, pdf_font_desc *font, float size) |
1657 | { |
1658 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1659 | pdf_gstate *gstate = pr->gstate + pr->gtop; |
1660 | pdf_drop_font(ctx, gstate->text.font); |
1661 | gstate->text.font = pdf_keep_font(ctx, font); |
1662 | gstate->text.size = size; |
1663 | } |
1664 | |
1665 | static void pdf_run_Tr(fz_context *ctx, pdf_processor *proc, int render) |
1666 | { |
1667 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1668 | pdf_gstate *gstate = pr->gstate + pr->gtop; |
1669 | gstate->text.render = render; |
1670 | } |
1671 | |
1672 | static void pdf_run_Ts(fz_context *ctx, pdf_processor *proc, float rise) |
1673 | { |
1674 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1675 | pdf_gstate *gstate = pr->gstate + pr->gtop; |
1676 | gstate->text.rise = rise; |
1677 | } |
1678 | |
1679 | /* text positioning */ |
1680 | |
1681 | static void pdf_run_Td(fz_context *ctx, pdf_processor *proc, float tx, float ty) |
1682 | { |
1683 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1684 | pdf_tos_translate(&pr->tos, tx, ty); |
1685 | } |
1686 | |
1687 | static void pdf_run_TD(fz_context *ctx, pdf_processor *proc, float tx, float ty) |
1688 | { |
1689 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1690 | pdf_gstate *gstate = pr->gstate + pr->gtop; |
1691 | gstate->text.leading = -ty; |
1692 | pdf_tos_translate(&pr->tos, tx, ty); |
1693 | } |
1694 | |
1695 | static void pdf_run_Tm(fz_context *ctx, pdf_processor *proc, float a, float b, float c, float d, float e, float f) |
1696 | { |
1697 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1698 | pdf_tos_set_matrix(&pr->tos, a, b, c, d, e, f); |
1699 | } |
1700 | |
1701 | static void pdf_run_Tstar(fz_context *ctx, pdf_processor *proc) |
1702 | { |
1703 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1704 | pdf_gstate *gstate = pr->gstate + pr->gtop; |
1705 | pdf_tos_newline(&pr->tos, gstate->text.leading); |
1706 | } |
1707 | |
1708 | /* text showing */ |
1709 | |
1710 | static void pdf_run_TJ(fz_context *ctx, pdf_processor *proc, pdf_obj *obj) |
1711 | { |
1712 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1713 | pdf_show_text(ctx, pr, obj); |
1714 | } |
1715 | |
1716 | static void pdf_run_Tj(fz_context *ctx, pdf_processor *proc, char *string, int string_len) |
1717 | { |
1718 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1719 | pdf_show_string(ctx, pr, (unsigned char *)string, string_len); |
1720 | } |
1721 | |
1722 | static void pdf_run_squote(fz_context *ctx, pdf_processor *proc, char *string, int string_len) |
1723 | { |
1724 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1725 | pdf_gstate *gstate = pr->gstate + pr->gtop; |
1726 | pdf_tos_newline(&pr->tos, gstate->text.leading); |
1727 | pdf_show_string(ctx, pr, (unsigned char*)string, string_len); |
1728 | } |
1729 | |
1730 | static void pdf_run_dquote(fz_context *ctx, pdf_processor *proc, float aw, float ac, char *string, int string_len) |
1731 | { |
1732 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1733 | pdf_gstate *gstate = pr->gstate + pr->gtop; |
1734 | gstate->text.word_space = aw; |
1735 | gstate->text.char_space = ac; |
1736 | pdf_tos_newline(&pr->tos, gstate->text.leading); |
1737 | pdf_show_string(ctx, pr, (unsigned char*)string, string_len); |
1738 | } |
1739 | |
1740 | /* type 3 fonts */ |
1741 | |
1742 | static void pdf_run_d0(fz_context *ctx, pdf_processor *proc, float wx, float wy) |
1743 | { |
1744 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1745 | pr->dev->flags |= FZ_DEVFLAG_COLOR; |
1746 | } |
1747 | |
1748 | static void pdf_run_d1(fz_context *ctx, pdf_processor *proc, float wx, float wy, float llx, float lly, float urx, float ury) |
1749 | { |
1750 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1751 | pr->dev->flags |= FZ_DEVFLAG_MASK | FZ_DEVFLAG_BBOX_DEFINED; |
1752 | pr->dev->flags &= ~(FZ_DEVFLAG_FILLCOLOR_UNDEFINED | |
1753 | FZ_DEVFLAG_STROKECOLOR_UNDEFINED | |
1754 | FZ_DEVFLAG_STARTCAP_UNDEFINED | |
1755 | FZ_DEVFLAG_DASHCAP_UNDEFINED | |
1756 | FZ_DEVFLAG_ENDCAP_UNDEFINED | |
1757 | FZ_DEVFLAG_LINEJOIN_UNDEFINED | |
1758 | FZ_DEVFLAG_MITERLIMIT_UNDEFINED | |
1759 | FZ_DEVFLAG_LINEWIDTH_UNDEFINED); |
1760 | pr->dev->d1_rect.x0 = fz_min(llx, urx); |
1761 | pr->dev->d1_rect.y0 = fz_min(lly, ury); |
1762 | pr->dev->d1_rect.x1 = fz_max(llx, urx); |
1763 | pr->dev->d1_rect.y1 = fz_max(lly, ury); |
1764 | } |
1765 | |
1766 | /* color */ |
1767 | |
1768 | static void pdf_run_CS(fz_context *ctx, pdf_processor *proc, const char *name, fz_colorspace *colorspace) |
1769 | { |
1770 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1771 | pr->dev->flags &= ~FZ_DEVFLAG_STROKECOLOR_UNDEFINED; |
1772 | if (!strcmp(name, "Pattern" )) |
1773 | pdf_set_pattern(ctx, pr, PDF_STROKE, NULL, NULL); |
1774 | else |
1775 | pdf_set_colorspace(ctx, pr, PDF_STROKE, colorspace); |
1776 | } |
1777 | |
1778 | static void pdf_run_cs(fz_context *ctx, pdf_processor *proc, const char *name, fz_colorspace *colorspace) |
1779 | { |
1780 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1781 | pr->dev->flags &= ~FZ_DEVFLAG_FILLCOLOR_UNDEFINED; |
1782 | if (!strcmp(name, "Pattern" )) |
1783 | pdf_set_pattern(ctx, pr, PDF_FILL, NULL, NULL); |
1784 | else |
1785 | pdf_set_colorspace(ctx, pr, PDF_FILL, colorspace); |
1786 | } |
1787 | |
1788 | static void pdf_run_SC_color(fz_context *ctx, pdf_processor *proc, int n, float *color) |
1789 | { |
1790 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1791 | pr->dev->flags &= ~FZ_DEVFLAG_STROKECOLOR_UNDEFINED; |
1792 | pdf_set_color(ctx, pr, PDF_STROKE, color); |
1793 | } |
1794 | |
1795 | static void pdf_run_sc_color(fz_context *ctx, pdf_processor *proc, int n, float *color) |
1796 | { |
1797 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1798 | pr->dev->flags &= ~FZ_DEVFLAG_FILLCOLOR_UNDEFINED; |
1799 | pdf_set_color(ctx, pr, PDF_FILL, color); |
1800 | } |
1801 | |
1802 | static void pdf_run_SC_pattern(fz_context *ctx, pdf_processor *proc, const char *name, pdf_pattern *pat, int n, float *color) |
1803 | { |
1804 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1805 | pr->dev->flags &= ~FZ_DEVFLAG_STROKECOLOR_UNDEFINED; |
1806 | pdf_set_pattern(ctx, pr, PDF_STROKE, pat, color); |
1807 | } |
1808 | |
1809 | static void pdf_run_sc_pattern(fz_context *ctx, pdf_processor *proc, const char *name, pdf_pattern *pat, int n, float *color) |
1810 | { |
1811 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1812 | pr->dev->flags &= ~FZ_DEVFLAG_FILLCOLOR_UNDEFINED; |
1813 | pdf_set_pattern(ctx, pr, PDF_FILL, pat, color); |
1814 | } |
1815 | |
1816 | static void pdf_run_SC_shade(fz_context *ctx, pdf_processor *proc, const char *name, fz_shade *shade) |
1817 | { |
1818 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1819 | pr->dev->flags &= ~FZ_DEVFLAG_STROKECOLOR_UNDEFINED; |
1820 | pdf_set_shade(ctx, pr, PDF_STROKE, shade); |
1821 | } |
1822 | |
1823 | static void pdf_run_sc_shade(fz_context *ctx, pdf_processor *proc, const char *name, fz_shade *shade) |
1824 | { |
1825 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1826 | pr->dev->flags &= ~FZ_DEVFLAG_FILLCOLOR_UNDEFINED; |
1827 | pdf_set_shade(ctx, pr, PDF_FILL, shade); |
1828 | } |
1829 | |
1830 | static void pdf_run_G(fz_context *ctx, pdf_processor *proc, float g) |
1831 | { |
1832 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1833 | pr->dev->flags &= ~FZ_DEVFLAG_STROKECOLOR_UNDEFINED; |
1834 | pdf_set_colorspace(ctx, pr, PDF_STROKE, fz_device_gray(ctx)); |
1835 | pdf_set_color(ctx, pr, PDF_STROKE, &g); |
1836 | } |
1837 | |
1838 | static void pdf_run_g(fz_context *ctx, pdf_processor *proc, float g) |
1839 | { |
1840 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1841 | pr->dev->flags &= ~FZ_DEVFLAG_FILLCOLOR_UNDEFINED; |
1842 | pdf_set_colorspace(ctx, pr, PDF_FILL, fz_device_gray(ctx)); |
1843 | pdf_set_color(ctx, pr, PDF_FILL, &g); |
1844 | } |
1845 | |
1846 | static void pdf_run_K(fz_context *ctx, pdf_processor *proc, float c, float m, float y, float k) |
1847 | { |
1848 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1849 | float color[4] = {c, m, y, k}; |
1850 | pr->dev->flags &= ~FZ_DEVFLAG_STROKECOLOR_UNDEFINED; |
1851 | pdf_set_colorspace(ctx, pr, PDF_STROKE, fz_device_cmyk(ctx)); |
1852 | pdf_set_color(ctx, pr, PDF_STROKE, color); |
1853 | } |
1854 | |
1855 | static void pdf_run_k(fz_context *ctx, pdf_processor *proc, float c, float m, float y, float k) |
1856 | { |
1857 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1858 | float color[4] = {c, m, y, k}; |
1859 | pr->dev->flags &= ~FZ_DEVFLAG_FILLCOLOR_UNDEFINED; |
1860 | pdf_set_colorspace(ctx, pr, PDF_FILL, fz_device_cmyk(ctx)); |
1861 | pdf_set_color(ctx, pr, PDF_FILL, color); |
1862 | } |
1863 | |
1864 | static void pdf_run_RG(fz_context *ctx, pdf_processor *proc, float r, float g, float b) |
1865 | { |
1866 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1867 | float color[3] = {r, g, b}; |
1868 | pr->dev->flags &= ~FZ_DEVFLAG_STROKECOLOR_UNDEFINED; |
1869 | pdf_set_colorspace(ctx, pr, PDF_STROKE, fz_device_rgb(ctx)); |
1870 | pdf_set_color(ctx, pr, PDF_STROKE, color); |
1871 | } |
1872 | |
1873 | static void pdf_run_rg(fz_context *ctx, pdf_processor *proc, float r, float g, float b) |
1874 | { |
1875 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1876 | float color[3] = {r, g, b}; |
1877 | pr->dev->flags &= ~FZ_DEVFLAG_FILLCOLOR_UNDEFINED; |
1878 | pdf_set_colorspace(ctx, pr, PDF_FILL, fz_device_rgb(ctx)); |
1879 | pdf_set_color(ctx, pr, PDF_FILL, color); |
1880 | } |
1881 | |
1882 | /* shadings, images, xobjects */ |
1883 | |
1884 | static void pdf_run_BI(fz_context *ctx, pdf_processor *proc, fz_image *image, const char *colorspace) |
1885 | { |
1886 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1887 | pdf_show_image(ctx, pr, image); |
1888 | } |
1889 | |
1890 | static void pdf_run_sh(fz_context *ctx, pdf_processor *proc, const char *name, fz_shade *shade) |
1891 | { |
1892 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1893 | pdf_show_shade(ctx, pr, shade); |
1894 | } |
1895 | |
1896 | static void pdf_run_Do_image(fz_context *ctx, pdf_processor *proc, const char *name, fz_image *image) |
1897 | { |
1898 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1899 | pdf_show_image(ctx, pr, image); |
1900 | } |
1901 | |
1902 | static void pdf_run_Do_form(fz_context *ctx, pdf_processor *proc, const char *name, pdf_obj *xobj, pdf_obj *page_resources) |
1903 | { |
1904 | pdf_run_xobject(ctx, (pdf_run_processor*)proc, xobj, page_resources, fz_identity, 0); |
1905 | } |
1906 | |
1907 | /* marked content */ |
1908 | |
1909 | static void pdf_run_BMC(fz_context *ctx, pdf_processor *proc, const char *tag) |
1910 | { |
1911 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1912 | |
1913 | if (!tag) |
1914 | tag = "Untitled" ; |
1915 | |
1916 | fz_begin_layer(ctx, pr->dev, tag); |
1917 | } |
1918 | |
1919 | static void pdf_run_BDC(fz_context *ctx, pdf_processor *proc, const char *tag, pdf_obj *raw, pdf_obj *cooked) |
1920 | { |
1921 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1922 | const char *str; |
1923 | |
1924 | if (!tag) |
1925 | tag = "Untitled" ; |
1926 | |
1927 | str = pdf_dict_get_text_string(ctx, cooked, PDF_NAME(Name)); |
1928 | if (strlen(str) == 0) |
1929 | str = tag; |
1930 | |
1931 | fz_begin_layer(ctx, pr->dev, str); |
1932 | } |
1933 | |
1934 | static void pdf_run_EMC(fz_context *ctx, pdf_processor *proc) |
1935 | { |
1936 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1937 | |
1938 | fz_end_layer(ctx, pr->dev); |
1939 | } |
1940 | |
1941 | static void pdf_run_MP(fz_context *ctx, pdf_processor *proc, const char *tag) |
1942 | { |
1943 | pdf_run_BMC(ctx, proc, tag); |
1944 | pdf_run_EMC(ctx, proc); |
1945 | } |
1946 | |
1947 | static void pdf_run_DP(fz_context *ctx, pdf_processor *proc, const char *tag, pdf_obj *raw, pdf_obj *cooked) |
1948 | { |
1949 | pdf_run_BDC(ctx, proc, tag, raw, cooked); |
1950 | pdf_run_EMC(ctx, proc); |
1951 | } |
1952 | |
1953 | /* compatibility */ |
1954 | |
1955 | static void pdf_run_BX(fz_context *ctx, pdf_processor *proc) |
1956 | { |
1957 | } |
1958 | |
1959 | static void pdf_run_EX(fz_context *ctx, pdf_processor *proc) |
1960 | { |
1961 | } |
1962 | |
1963 | static void pdf_run_END(fz_context *ctx, pdf_processor *proc) |
1964 | { |
1965 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1966 | pdf_flush_text(ctx, pr); |
1967 | } |
1968 | |
1969 | static void |
1970 | pdf_close_run_processor(fz_context *ctx, pdf_processor *proc) |
1971 | { |
1972 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1973 | |
1974 | while (pr->gtop) |
1975 | pdf_grestore(ctx, pr); |
1976 | |
1977 | while (pr->gstate[0].clip_depth) |
1978 | { |
1979 | fz_pop_clip(ctx, pr->dev); |
1980 | pr->gstate[0].clip_depth--; |
1981 | } |
1982 | } |
1983 | |
1984 | static void |
1985 | pdf_drop_run_processor(fz_context *ctx, pdf_processor *proc) |
1986 | { |
1987 | pdf_run_processor *pr = (pdf_run_processor *)proc; |
1988 | |
1989 | while (pr->gtop >= 0) |
1990 | { |
1991 | pdf_drop_gstate(ctx, &pr->gstate[pr->gtop]); |
1992 | pr->gtop--; |
1993 | } |
1994 | |
1995 | fz_drop_path(ctx, pr->path); |
1996 | fz_drop_text(ctx, pr->tos.text); |
1997 | |
1998 | fz_drop_default_colorspaces(ctx, pr->default_cs); |
1999 | |
2000 | fz_free(ctx, pr->gstate); |
2001 | } |
2002 | |
2003 | /* |
2004 | Create a new "run" processor. This maps |
2005 | from PDF operators to fz_device level calls. |
2006 | |
2007 | dev: The device to which the resulting device calls are to be |
2008 | sent. |
2009 | |
2010 | ctm: The initial transformation matrix to use. |
2011 | |
2012 | usage: A NULL terminated string that describes the 'usage' of |
2013 | this interpretation. Typically 'View', though 'Print' is also |
2014 | defined within the PDF reference manual, and others are possible. |
2015 | |
2016 | gstate: The initial graphics state. |
2017 | */ |
2018 | pdf_processor * |
2019 | pdf_new_run_processor(fz_context *ctx, fz_device *dev, fz_matrix ctm, const char *usage, pdf_gstate *gstate, fz_default_colorspaces *default_cs, fz_cookie *cookie) |
2020 | { |
2021 | pdf_run_processor *proc = pdf_new_processor(ctx, sizeof *proc); |
2022 | { |
2023 | proc->super.usage = usage; |
2024 | |
2025 | proc->super.close_processor = pdf_close_run_processor; |
2026 | proc->super.drop_processor = pdf_drop_run_processor; |
2027 | |
2028 | /* general graphics state */ |
2029 | proc->super.op_w = pdf_run_w; |
2030 | proc->super.op_j = pdf_run_j; |
2031 | proc->super.op_J = pdf_run_J; |
2032 | proc->super.op_M = pdf_run_M; |
2033 | proc->super.op_d = pdf_run_d; |
2034 | proc->super.op_ri = pdf_run_ri; |
2035 | proc->super.op_i = pdf_run_i; |
2036 | proc->super.op_gs_begin = pdf_run_gs_begin; |
2037 | proc->super.op_gs_end = pdf_run_gs_end; |
2038 | |
2039 | /* transparency graphics state */ |
2040 | proc->super.op_gs_BM = pdf_run_gs_BM; |
2041 | proc->super.op_gs_CA = pdf_run_gs_CA; |
2042 | proc->super.op_gs_ca = pdf_run_gs_ca; |
2043 | proc->super.op_gs_SMask = pdf_run_gs_SMask; |
2044 | |
2045 | /* special graphics state */ |
2046 | proc->super.op_q = pdf_run_q; |
2047 | proc->super.op_Q = pdf_run_Q; |
2048 | proc->super.op_cm = pdf_run_cm; |
2049 | |
2050 | /* path construction */ |
2051 | proc->super.op_m = pdf_run_m; |
2052 | proc->super.op_l = pdf_run_l; |
2053 | proc->super.op_c = pdf_run_c; |
2054 | proc->super.op_v = pdf_run_v; |
2055 | proc->super.op_y = pdf_run_y; |
2056 | proc->super.op_h = pdf_run_h; |
2057 | proc->super.op_re = pdf_run_re; |
2058 | |
2059 | /* path painting */ |
2060 | proc->super.op_S = pdf_run_S; |
2061 | proc->super.op_s = pdf_run_s; |
2062 | proc->super.op_F = pdf_run_F; |
2063 | proc->super.op_f = pdf_run_f; |
2064 | proc->super.op_fstar = pdf_run_fstar; |
2065 | proc->super.op_B = pdf_run_B; |
2066 | proc->super.op_Bstar = pdf_run_Bstar; |
2067 | proc->super.op_b = pdf_run_b; |
2068 | proc->super.op_bstar = pdf_run_bstar; |
2069 | proc->super.op_n = pdf_run_n; |
2070 | |
2071 | /* clipping paths */ |
2072 | proc->super.op_W = pdf_run_W; |
2073 | proc->super.op_Wstar = pdf_run_Wstar; |
2074 | |
2075 | /* text objects */ |
2076 | proc->super.op_BT = pdf_run_BT; |
2077 | proc->super.op_ET = pdf_run_ET; |
2078 | |
2079 | /* text state */ |
2080 | proc->super.op_Tc = pdf_run_Tc; |
2081 | proc->super.op_Tw = pdf_run_Tw; |
2082 | proc->super.op_Tz = pdf_run_Tz; |
2083 | proc->super.op_TL = pdf_run_TL; |
2084 | proc->super.op_Tf = pdf_run_Tf; |
2085 | proc->super.op_Tr = pdf_run_Tr; |
2086 | proc->super.op_Ts = pdf_run_Ts; |
2087 | |
2088 | /* text positioning */ |
2089 | proc->super.op_Td = pdf_run_Td; |
2090 | proc->super.op_TD = pdf_run_TD; |
2091 | proc->super.op_Tm = pdf_run_Tm; |
2092 | proc->super.op_Tstar = pdf_run_Tstar; |
2093 | |
2094 | /* text showing */ |
2095 | proc->super.op_TJ = pdf_run_TJ; |
2096 | proc->super.op_Tj = pdf_run_Tj; |
2097 | proc->super.op_squote = pdf_run_squote; |
2098 | proc->super.op_dquote = pdf_run_dquote; |
2099 | |
2100 | /* type 3 fonts */ |
2101 | proc->super.op_d0 = pdf_run_d0; |
2102 | proc->super.op_d1 = pdf_run_d1; |
2103 | |
2104 | /* color */ |
2105 | proc->super.op_CS = pdf_run_CS; |
2106 | proc->super.op_cs = pdf_run_cs; |
2107 | proc->super.op_SC_color = pdf_run_SC_color; |
2108 | proc->super.op_sc_color = pdf_run_sc_color; |
2109 | proc->super.op_SC_pattern = pdf_run_SC_pattern; |
2110 | proc->super.op_sc_pattern = pdf_run_sc_pattern; |
2111 | proc->super.op_SC_shade = pdf_run_SC_shade; |
2112 | proc->super.op_sc_shade = pdf_run_sc_shade; |
2113 | |
2114 | proc->super.op_G = pdf_run_G; |
2115 | proc->super.op_g = pdf_run_g; |
2116 | proc->super.op_RG = pdf_run_RG; |
2117 | proc->super.op_rg = pdf_run_rg; |
2118 | proc->super.op_K = pdf_run_K; |
2119 | proc->super.op_k = pdf_run_k; |
2120 | |
2121 | /* shadings, images, xobjects */ |
2122 | proc->super.op_sh = pdf_run_sh; |
2123 | if (dev->fill_image || dev->fill_image_mask || dev->clip_image_mask) |
2124 | { |
2125 | proc->super.op_BI = pdf_run_BI; |
2126 | proc->super.op_Do_image = pdf_run_Do_image; |
2127 | } |
2128 | proc->super.op_Do_form = pdf_run_Do_form; |
2129 | |
2130 | /* marked content */ |
2131 | proc->super.op_MP = pdf_run_MP; |
2132 | proc->super.op_DP = pdf_run_DP; |
2133 | proc->super.op_BMC = pdf_run_BMC; |
2134 | proc->super.op_BDC = pdf_run_BDC; |
2135 | proc->super.op_EMC = pdf_run_EMC; |
2136 | |
2137 | /* compatibility */ |
2138 | proc->super.op_BX = pdf_run_BX; |
2139 | proc->super.op_EX = pdf_run_EX; |
2140 | |
2141 | /* extgstate */ |
2142 | proc->super.op_gs_OP = pdf_run_gs_OP; |
2143 | proc->super.op_gs_op = pdf_run_gs_op; |
2144 | proc->super.op_gs_OPM = pdf_run_gs_OPM; |
2145 | proc->super.op_gs_UseBlackPtComp = pdf_run_gs_UseBlackPtComp; |
2146 | |
2147 | proc->super.op_END = pdf_run_END; |
2148 | } |
2149 | |
2150 | proc->dev = dev; |
2151 | proc->cookie = cookie; |
2152 | |
2153 | proc->default_cs = fz_keep_default_colorspaces(ctx, default_cs); |
2154 | |
2155 | proc->path = NULL; |
2156 | proc->clip = 0; |
2157 | proc->clip_even_odd = 0; |
2158 | |
2159 | proc->tos.text = NULL; |
2160 | proc->tos.tlm = fz_identity; |
2161 | proc->tos.tm = fz_identity; |
2162 | proc->tos.text_mode = 0; |
2163 | |
2164 | proc->gtop = -1; |
2165 | |
2166 | fz_try(ctx) |
2167 | { |
2168 | proc->path = fz_new_path(ctx); |
2169 | |
2170 | proc->gcap = 64; |
2171 | proc->gstate = fz_calloc(ctx, proc->gcap, sizeof(pdf_gstate)); |
2172 | |
2173 | proc->gtop = 0; |
2174 | pdf_init_gstate(ctx, &proc->gstate[0], ctm); |
2175 | |
2176 | if (gstate) |
2177 | { |
2178 | pdf_copy_gstate(ctx, &proc->gstate[0], gstate); |
2179 | proc->gstate[0].clip_depth = 0; |
2180 | proc->gstate[0].ctm = ctm; |
2181 | } |
2182 | } |
2183 | fz_catch(ctx) |
2184 | { |
2185 | pdf_drop_run_processor(ctx, (pdf_processor *) proc); |
2186 | fz_free(ctx, proc); |
2187 | fz_rethrow(ctx); |
2188 | } |
2189 | |
2190 | /* We need to save an extra level to allow for level 0 to be the parent gstate level. */ |
2191 | pdf_gsave(ctx, proc); |
2192 | |
2193 | return (pdf_processor*)proc; |
2194 | } |
2195 | |