comparison mupdf-source/source/pdf/pdf-op-run.c @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
1 // Copyright (C) 2004-2025 Artifex Software, Inc.
2 //
3 // This file is part of MuPDF.
4 //
5 // MuPDF is free software: you can redistribute it and/or modify it under the
6 // terms of the GNU Affero General Public License as published by the Free
7 // Software Foundation, either version 3 of the License, or (at your option)
8 // any later version.
9 //
10 // MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
11 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
13 // details.
14 //
15 // You should have received a copy of the GNU Affero General Public License
16 // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
17 //
18 // Alternative licensing terms are available from the licensor.
19 // For commercial licensing, see <https://www.artifex.com/> or contact
20 // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
21 // CA 94129, USA, for further information.
22
23 #include "mupdf/fitz.h"
24 #include "mupdf/pdf.h"
25
26 #include <string.h>
27 #include <math.h>
28
29 #include "mupdf/ucdn.h"
30
31 #define TILE
32
33 /* Enable this to watch changes in the structure stack. */
34 #undef DEBUG_STRUCTURE
35
36 /*
37 * Emit graphics calls to device.
38 */
39
40 typedef struct pdf_run_processor pdf_run_processor;
41
42 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);
43
44 enum
45 {
46 PDF_FILL,
47 PDF_STROKE,
48 };
49
50 enum
51 {
52 PDF_MAT_NONE,
53 PDF_MAT_COLOR,
54 PDF_MAT_PATTERN,
55 PDF_MAT_SHADE,
56 };
57
58 typedef struct
59 {
60 int kind;
61 fz_colorspace *colorspace;
62 pdf_pattern *pattern;
63 fz_shade *shade;
64 int gstate_num;
65 fz_color_params color_params;
66 float alpha;
67 float v[FZ_MAX_COLORS];
68 } pdf_material;
69
70 struct pdf_gstate
71 {
72 fz_matrix ctm;
73 int clip_depth;
74
75 /* path stroking */
76 fz_stroke_state *stroke_state;
77
78 /* materials */
79 pdf_material stroke;
80 pdf_material fill;
81
82 /* pattern paint type 2 */
83 int ismask;
84
85 /* text state */
86 pdf_text_state text;
87
88 /* transparency */
89 int blendmode;
90 pdf_obj *softmask;
91 pdf_obj *softmask_resources;
92 pdf_obj *softmask_tr;
93 fz_matrix softmask_ctm;
94 fz_colorspace *softmask_cs;
95 float softmask_bc[FZ_MAX_COLORS];
96 int luminosity;
97 };
98
99 typedef struct resources_stack
100 {
101 struct resources_stack *next;
102 pdf_obj *resources;
103 } resources_stack;
104
105 typedef struct marked_content_stack
106 {
107 struct marked_content_stack *next;
108 pdf_obj *tag;
109 pdf_obj *val;
110 int structure_pushed;
111 } marked_content_stack;
112
113 typedef struct begin_layer_stack
114 {
115 struct begin_layer_stack *next;
116 char *layer;
117 } begin_layer_stack;
118
119 struct pdf_run_processor
120 {
121 pdf_processor super;
122 pdf_document *doc;
123 fz_device *dev;
124 fz_cookie *cookie;
125
126 fz_default_colorspaces *default_cs;
127
128 resources_stack *rstack;
129
130 /* path object state */
131 fz_path *path;
132 int clip;
133 int clip_even_odd;
134
135 /* text object state */
136 pdf_text_object_state tos;
137 int bidi;
138
139 /* graphics state */
140 pdf_gstate *gstate;
141 int gcap;
142 int gtop;
143 int gbot;
144 int gparent;
145
146 /* xobject cycle detector */
147 pdf_cycle_list *cycle;
148
149 pdf_obj *role_map;
150
151 marked_content_stack *marked_content;
152 pdf_obj *mcid_sent;
153 pdf_obj *pending_mcid_pop;
154
155 int struct_parent;
156 int broken_struct_tree;
157
158 /* Pending begin layers */
159 begin_layer_stack *begin_layer;
160 begin_layer_stack **next_begin_layer;
161
162 int mc_depth;
163 /* The nest_mark array holds a record of the way in which clips and
164 * marked content are nested to ensure we pop stuff in the same order
165 * that we push it - i.e. to keep calls nested nicely. An entry x,
166 * where x >= 0 represents that a push has happened for mc_depth == x.
167 * An entry x, where x < 0 means that -x clips have happened at this
168 * position. */
169 int nest_depth;
170 int nest_mark[1024];
171 };
172
173 /* Forward definition */
174 static void
175 pop_any_pending_mcid_changes(fz_context *ctx, pdf_run_processor *pr);
176
177 static void
178 push_begin_layer(fz_context *ctx, pdf_run_processor *proc, const char *str)
179 {
180 begin_layer_stack *s = fz_malloc_struct(ctx, begin_layer_stack);
181
182 fz_try(ctx)
183 s->layer = fz_strdup(ctx, str);
184 fz_catch(ctx)
185 {
186 fz_free(ctx, s);
187 fz_rethrow(ctx);
188 }
189
190 s->next = NULL;
191 *proc->next_begin_layer = s;
192 proc->next_begin_layer = &s->next;
193 }
194
195 static void
196 flush_begin_layer(fz_context *ctx, pdf_run_processor *proc)
197 {
198 begin_layer_stack *s;
199
200 while (proc->begin_layer)
201 {
202 s = proc->begin_layer;
203
204 if (proc->nest_depth == nelem(proc->nest_mark))
205 fz_throw(ctx, FZ_ERROR_LIMIT, "layer/clip nesting too deep");
206
207 proc->nest_mark[proc->nest_depth++] = ++proc->mc_depth;
208
209 fz_begin_layer(ctx, proc->dev, s->layer);
210 proc->begin_layer = s->next;
211 fz_free(ctx, s->layer);
212 fz_free(ctx, s);
213 }
214 proc->next_begin_layer = &proc->begin_layer;
215 }
216
217 static void nest_layer_clip(fz_context *ctx, pdf_run_processor *proc)
218 {
219 if (proc->nest_depth == nelem(proc->nest_mark))
220 fz_throw(ctx, FZ_ERROR_LIMIT, "layer/clip nesting too deep");
221 if (proc->nest_depth > 0 && proc->nest_mark[proc->nest_depth-1] < 0)
222 {
223 /* The last mark was a clip. Just increase that count. */
224 proc->nest_mark[proc->nest_depth-1]--;
225 }
226 else
227 {
228 /* Create a new entry for a single clip. */
229 proc->nest_mark[proc->nest_depth++] = -1;
230 }
231 }
232
233 static void
234 do_end_layer(fz_context *ctx, pdf_run_processor *proc)
235 {
236 if (proc->nest_depth > 0 && proc->nest_mark[proc->nest_depth-1] == proc->mc_depth)
237 {
238 fz_end_layer(ctx, proc->dev);
239 proc->nest_depth--;
240 }
241 else
242 {
243 /* If EMC is unbalanced with q/Q, we will emit the end layer
244 * device call before or after the Q operator instead of its true location
245 */
246 fz_warn(ctx, "invalid marked content and clip nesting");
247 }
248
249 if (proc->mc_depth > 0)
250 proc->mc_depth--;
251 }
252
253 typedef struct
254 {
255 pdf_obj *softmask;
256 fz_colorspace *softmask_cs;
257 pdf_obj *page_resources;
258 fz_matrix ctm;
259 } softmask_save;
260
261 static fz_function *
262 load_transfer_function(fz_context *ctx, pdf_obj *obj)
263 {
264 if (obj == NULL || pdf_name_eq(ctx, obj, PDF_NAME(Identity)))
265 return NULL;
266
267 return (fz_function *)pdf_load_function(ctx, obj, 1, 1);
268 }
269
270 static pdf_gstate *
271 begin_softmask(fz_context *ctx, pdf_run_processor *pr, softmask_save *save, fz_rect bbox)
272 {
273 pdf_gstate *gstate = pr->gstate + pr->gtop;
274 pdf_obj *softmask = gstate->softmask;
275 fz_colorspace *softmask_cs = gstate->softmask_cs;
276 fz_rect mask_bbox;
277 fz_matrix tos_save[2], save_ctm;
278 fz_matrix mask_matrix;
279 fz_colorspace *mask_colorspace;
280 int saved_blendmode;
281 fz_function *tr = NULL;
282
283 fz_var(tr);
284
285 save->softmask = softmask;
286 if (softmask == NULL)
287 return gstate;
288 save->softmask_cs = softmask_cs;
289 save->page_resources = gstate->softmask_resources;
290 save->ctm = gstate->softmask_ctm;
291 save_ctm = gstate->ctm;
292
293 mask_bbox = pdf_xobject_bbox(ctx, softmask);
294 mask_matrix = pdf_xobject_matrix(ctx, softmask);
295
296 pdf_tos_save(ctx, &pr->tos, tos_save);
297
298 mask_colorspace = gstate->softmask_cs;
299 if (gstate->luminosity && !mask_colorspace)
300 mask_colorspace = fz_device_gray(ctx);
301
302 if (gstate->luminosity)
303 mask_bbox = fz_infinite_rect;
304 else
305 {
306 mask_bbox = fz_transform_rect(mask_bbox, mask_matrix);
307 mask_bbox = fz_transform_rect(mask_bbox, gstate->softmask_ctm);
308 }
309 mask_bbox = fz_intersect_rect(mask_bbox, bbox);
310 gstate->softmask = NULL;
311 gstate->softmask_cs = NULL;
312 gstate->softmask_resources = NULL;
313 gstate->ctm = gstate->softmask_ctm;
314
315 saved_blendmode = gstate->blendmode;
316
317 fz_try(ctx)
318 {
319 if (gstate->softmask_tr)
320 {
321 tr = load_transfer_function(ctx, gstate->softmask_tr);
322 pdf_drop_obj(ctx, gstate->softmask_tr);
323 gstate->softmask_tr = NULL;
324 }
325
326 fz_begin_mask(ctx, pr->dev, mask_bbox, gstate->luminosity, mask_colorspace, gstate->softmask_bc, gstate->fill.color_params);
327 gstate->blendmode = 0;
328 pdf_run_xobject(ctx, pr, softmask, save->page_resources, fz_identity, 1);
329 gstate = pr->gstate + pr->gtop;
330 gstate->blendmode = saved_blendmode;
331 fz_end_mask_tr(ctx, pr->dev, tr);
332 }
333 fz_always(ctx)
334 {
335 fz_drop_function(ctx, tr);
336 }
337 fz_catch(ctx)
338 fz_rethrow(ctx);
339
340 pdf_tos_restore(ctx, &pr->tos, tos_save);
341
342 gstate = pr->gstate + pr->gtop;
343 gstate->ctm = save_ctm;
344
345 return gstate;
346 }
347
348 static void
349 end_softmask(fz_context *ctx, pdf_run_processor *pr, softmask_save *save)
350 {
351 pdf_gstate *gstate = pr->gstate + pr->gtop;
352
353 if (save->softmask == NULL)
354 return;
355
356 gstate->softmask = save->softmask;
357 gstate->softmask_cs = save->softmask_cs;
358 gstate->softmask_resources = save->page_resources;
359 gstate->softmask_ctm = save->ctm;
360 save->softmask = NULL;
361 save->page_resources = NULL;
362
363 fz_pop_clip(ctx, pr->dev);
364 }
365
366 static pdf_gstate *
367 pdf_begin_group(fz_context *ctx, pdf_run_processor *pr, fz_rect bbox, softmask_save *softmask)
368 {
369 pdf_gstate *gstate = begin_softmask(ctx, pr, softmask, bbox);
370
371 if (gstate->blendmode)
372 fz_begin_group(ctx, pr->dev, bbox, NULL, 0, 0, gstate->blendmode, 1);
373
374 return pr->gstate + pr->gtop;
375 }
376
377 static void
378 pdf_end_group(fz_context *ctx, pdf_run_processor *pr, softmask_save *softmask)
379 {
380 pdf_gstate *gstate = pr->gstate + pr->gtop;
381
382 if (gstate->blendmode)
383 fz_end_group(ctx, pr->dev);
384
385 end_softmask(ctx, pr, softmask);
386 }
387
388 static void
389 pdf_show_shade(fz_context *ctx, pdf_run_processor *pr, fz_shade *shd)
390 {
391 pdf_gstate *gstate = pr->gstate + pr->gtop;
392 fz_rect bbox;
393 softmask_save softmask = { NULL };
394
395 if (pr->super.hidden)
396 return;
397
398 bbox = fz_bound_shade(ctx, shd, gstate->ctm);
399
400 fz_try(ctx)
401 {
402 gstate = pdf_begin_group(ctx, pr, bbox, &softmask);
403
404 /* FIXME: The gstate->ctm in the next line may be wrong; maybe
405 * it should be the parent gstates ctm? */
406 fz_fill_shade(ctx, pr->dev, shd, gstate->ctm, gstate->fill.alpha, gstate->fill.color_params);
407
408 pdf_end_group(ctx, pr, &softmask);
409 }
410 fz_catch(ctx)
411 {
412 pdf_drop_obj(ctx, softmask.softmask);
413 fz_drop_colorspace(ctx, softmask.softmask_cs);
414 pdf_drop_obj(ctx, softmask.page_resources);
415 fz_rethrow(ctx);
416 }
417 }
418
419 static pdf_material *
420 pdf_keep_material(fz_context *ctx, pdf_material *mat)
421 {
422 if (mat->colorspace)
423 fz_keep_colorspace(ctx, mat->colorspace);
424 if (mat->pattern)
425 pdf_keep_pattern(ctx, mat->pattern);
426 if (mat->shade)
427 fz_keep_shade(ctx, mat->shade);
428 return mat;
429 }
430
431 static pdf_material *
432 pdf_drop_material(fz_context *ctx, pdf_material *mat)
433 {
434 fz_drop_colorspace(ctx, mat->colorspace);
435 pdf_drop_pattern(ctx, mat->pattern);
436 fz_drop_shade(ctx, mat->shade);
437 return mat;
438 }
439
440 static void
441 pdf_copy_pattern_gstate(fz_context *ctx, pdf_gstate *dst, const pdf_gstate *src)
442 {
443 pdf_font_desc *old_font = dst->text.font;
444
445 dst->ctm = src->ctm;
446
447 dst->text = src->text;
448 pdf_keep_font(ctx, src->text.font);
449 pdf_drop_font(ctx, old_font);
450
451 pdf_drop_obj(ctx, dst->softmask);
452 dst->softmask = pdf_keep_obj(ctx, src->softmask);
453
454 pdf_drop_obj(ctx, dst->softmask_resources);
455 dst->softmask_resources = pdf_keep_obj(ctx, src->softmask_resources);
456
457 fz_drop_colorspace(ctx, dst->softmask_cs);
458 dst->softmask_cs = fz_keep_colorspace(ctx, src->softmask_cs);
459
460 fz_drop_stroke_state(ctx, dst->stroke_state);
461 dst->stroke_state = fz_keep_stroke_state(ctx, src->stroke_state);
462 }
463
464 static void
465 pdf_unset_pattern(fz_context *ctx, pdf_run_processor *pr, int what)
466 {
467 pdf_gstate *gs = pr->gstate + pr->gtop;
468 pdf_material *mat;
469 mat = what == PDF_FILL ? &gs->fill : &gs->stroke;
470 if (mat->kind == PDF_MAT_PATTERN)
471 {
472 pdf_drop_pattern(ctx, mat->pattern);
473 mat->pattern = NULL;
474 mat->kind = PDF_MAT_COLOR;
475 }
476 }
477
478 static void
479 pdf_keep_gstate(fz_context *ctx, pdf_gstate *gs)
480 {
481 pdf_keep_material(ctx, &gs->stroke);
482 pdf_keep_material(ctx, &gs->fill);
483 if (gs->text.font)
484 pdf_keep_font(ctx, gs->text.font);
485 if (gs->softmask)
486 pdf_keep_obj(ctx, gs->softmask);
487 if (gs->softmask_cs)
488 fz_keep_colorspace(ctx, gs->softmask_cs);
489 if (gs->softmask_resources)
490 pdf_keep_obj(ctx, gs->softmask_resources);
491 fz_keep_stroke_state(ctx, gs->stroke_state);
492 pdf_keep_obj(ctx, gs->softmask_tr);
493 }
494
495 static void
496 pdf_drop_gstate(fz_context *ctx, pdf_gstate *gs)
497 {
498 pdf_drop_material(ctx, &gs->stroke);
499 pdf_drop_material(ctx, &gs->fill);
500 pdf_drop_font(ctx, gs->text.font);
501 pdf_drop_obj(ctx, gs->softmask);
502 fz_drop_colorspace(ctx, gs->softmask_cs);
503 pdf_drop_obj(ctx, gs->softmask_resources);
504 fz_drop_stroke_state(ctx, gs->stroke_state);
505 pdf_drop_obj(ctx, gs->softmask_tr);
506 }
507
508 static void
509 pdf_gsave(fz_context *ctx, pdf_run_processor *pr)
510 {
511 if (pr->gtop == pr->gcap-1)
512 {
513 if (pr->gcap * 2 >= 4096)
514 fz_throw(ctx, FZ_ERROR_LIMIT, "too many nested graphics states");
515
516 pr->gstate = fz_realloc_array(ctx, pr->gstate, pr->gcap*2, pdf_gstate);
517 pr->gcap *= 2;
518 }
519
520 memcpy(&pr->gstate[pr->gtop + 1], &pr->gstate[pr->gtop], sizeof(pdf_gstate));
521
522 pr->gtop++;
523 pdf_keep_gstate(ctx, &pr->gstate[pr->gtop]);
524 }
525
526 static void
527 pdf_grestore(fz_context *ctx, pdf_run_processor *pr)
528 {
529 pdf_gstate *gs = pr->gstate + pr->gtop;
530 int clip_depth = gs->clip_depth;
531
532 if (pr->gtop <= pr->gbot)
533 {
534 fz_warn(ctx, "gstate underflow in content stream");
535 return;
536 }
537
538 pdf_drop_gstate(ctx, gs);
539 pr->gtop --;
540
541 gs = pr->gstate + pr->gtop;
542 while (clip_depth > gs->clip_depth)
543 {
544 fz_try(ctx)
545 {
546 // End layer early (before Q) if unbalanced Q appears between BMC and EMC.
547 while (pr->nest_depth > 0 && pr->nest_mark[pr->nest_depth-1] >= 0)
548 {
549 fz_end_layer(ctx, pr->dev);
550 pr->nest_depth--;
551 }
552
553 if (pr->nest_depth > 0)
554 {
555 /* So this one must be a clip record. */
556 fz_pop_clip(ctx, pr->dev);
557 /* Pop a single clip record off. */
558 pr->nest_mark[pr->nest_depth-1]++;
559 if (pr->nest_mark[pr->nest_depth-1] == 0)
560 pr->nest_depth--;
561 }
562
563 // End layer late (after Q) if unbalanced EMC appears between q and Q.
564 while (pr->nest_depth > 0 && pr->nest_mark[pr->nest_depth-1] > pr->mc_depth)
565 {
566 fz_end_layer(ctx, pr->dev);
567 pr->nest_depth--;
568 }
569 }
570 fz_catch(ctx)
571 {
572 /* Silently swallow the problem - restores must
573 * never throw! */
574 fz_rethrow_if(ctx, FZ_ERROR_SYSTEM); // FIXME - unsure if we can throw here?
575 fz_report_error(ctx);
576 }
577 clip_depth--;
578 }
579 }
580
581 static pdf_gstate *
582 pdf_show_pattern(fz_context *ctx, pdf_run_processor *pr, pdf_pattern *pat, int pat_gstate_num, fz_rect area, int what)
583 {
584 pdf_gstate *gstate;
585 pdf_gstate *pat_gstate;
586 int gparent_save;
587 fz_matrix ptm, invptm, gparent_save_ctm;
588 int x0, y0, x1, y1;
589 float fx0, fy0, fx1, fy1;
590 fz_rect local_area;
591 int oldbot;
592 int id;
593
594 pdf_gsave(ctx, pr);
595 gstate = pr->gstate + pr->gtop;
596 pat_gstate = pr->gstate + pat_gstate_num;
597
598 /* Patterns are run with the gstate of the parent */
599 pdf_copy_pattern_gstate(ctx, gstate, pat_gstate);
600
601 if (pat->ismask)
602 {
603 /* Inhibit any changes to the color since we're drawing an uncolored pattern. */
604 gstate->ismask = 1;
605 pdf_unset_pattern(ctx, pr, PDF_FILL);
606 pdf_unset_pattern(ctx, pr, PDF_STROKE);
607 if (what == PDF_FILL)
608 {
609 pdf_drop_material(ctx, &gstate->stroke);
610 pdf_keep_material(ctx, &gstate->fill);
611 gstate->stroke = gstate->fill;
612 }
613 if (what == PDF_STROKE)
614 {
615 pdf_drop_material(ctx, &gstate->fill);
616 pdf_keep_material(ctx, &gstate->stroke);
617 gstate->fill = gstate->stroke;
618 }
619 id = 0; /* don't cache uncolored patterns, since we colorize them when drawing */
620 }
621 else
622 {
623 // TODO: unset only the current fill/stroke or both?
624 pdf_unset_pattern(ctx, pr, what);
625 id = pat->id;
626 }
627
628 /* don't apply soft masks to objects in the pattern as well */
629 if (gstate->softmask)
630 {
631 pdf_drop_obj(ctx, gstate->softmask);
632 gstate->softmask = NULL;
633 }
634
635 ptm = fz_concat(pat->matrix, pat_gstate->ctm);
636 invptm = fz_invert_matrix(ptm);
637
638 /* The parent_ctm is amended with our pattern matrix */
639 gparent_save = pr->gparent;
640 pr->gparent = pr->gtop-1;
641 gparent_save_ctm = pr->gstate[pr->gparent].ctm;
642 pr->gstate[pr->gparent].ctm = ptm;
643
644 /* patterns are painted using the parent_ctm. area = bbox of
645 * shape to be filled in device space. Map it back to pattern
646 * space. */
647 local_area = fz_transform_rect(area, invptm);
648
649 fx0 = (local_area.x0 - pat->bbox.x0) / pat->xstep;
650 fy0 = (local_area.y0 - pat->bbox.y0) / pat->ystep;
651 fx1 = (local_area.x1 - pat->bbox.x0) / pat->xstep;
652 fy1 = (local_area.y1 - pat->bbox.y0) / pat->ystep;
653 if (fx0 > fx1)
654 {
655 float t = fx0; fx0 = fx1; fx1 = t;
656 }
657 if (fy0 > fy1)
658 {
659 float t = fy0; fy0 = fy1; fy1 = t;
660 }
661
662 #ifdef TILE
663 /* We have tried various formulations in the past, but this one is
664 * best we've found; only use it as a tile if a whole repeat is
665 * required in at least one direction. Note, that this allows for
666 * 'sections' of 4 tiles to be show, but all non-overlapping. */
667 if (fx1-fx0 > 1 || fy1-fy0 > 1)
668 #else
669 if (0)
670 #endif
671 {
672 int cached = fz_begin_tile_tid(ctx, pr->dev, local_area, pat->bbox, pat->xstep, pat->ystep, ptm, id, pat->document->super.id);
673 if (!cached)
674 {
675 gstate->ctm = ptm;
676
677 oldbot = pr->gbot;
678 pr->gbot = pr->gtop;
679
680 pdf_gsave(ctx, pr);
681 pdf_process_contents(ctx, (pdf_processor*)pr, pat->document, pat->resources, pat->contents, NULL, NULL);
682 pdf_grestore(ctx, pr);
683
684 while (pr->gtop > pr->gbot)
685 pdf_grestore(ctx, pr);
686 pr->gbot = oldbot;
687 }
688 fz_end_tile(ctx, pr->dev);
689 }
690 else
691 {
692 int x, y;
693
694 /* When calculating the number of tiles required, we adjust by
695 * a small amount to allow for rounding errors. By choosing
696 * this amount to be smaller than 1/256, we guarantee we won't
697 * cause problems that will be visible even under our most
698 * extreme antialiasing. */
699 x0 = floorf(fx0 + 0.001f);
700 y0 = floorf(fy0 + 0.001f);
701 x1 = ceilf(fx1 - 0.001f);
702 y1 = ceilf(fy1 - 0.001f);
703 /* The above adjustments cause problems for sufficiently
704 * large values for xstep/ystep which may be used if the
705 * pattern is expected to be rendered exactly once. */
706 if (fx1 > fx0 && x1 == x0)
707 x1 = x0 + 1;
708 if (fy1 > fy0 && y1 == y0)
709 y1 = y0 + 1;
710
711 for (y = y0; y < y1; y++)
712 {
713 for (x = x0; x < x1; x++)
714 {
715 /* Calls to pdf_process_contents may cause the
716 * gstate array to be realloced to be larger.
717 * That can invalidate gstate. Hence reload
718 * it each time round the loop. */
719 gstate = pr->gstate + pr->gtop;
720 gstate->ctm = fz_pre_translate(ptm, x * pat->xstep, y * pat->ystep);
721
722 oldbot = pr->gbot;
723 pr->gbot = pr->gtop;
724
725 pdf_gsave(ctx, pr);
726 pdf_process_contents(ctx, (pdf_processor*)pr, pat->document, pat->resources, pat->contents, NULL, NULL);
727 pdf_grestore(ctx, pr);
728
729 while (pr->gtop > pr->gbot)
730 pdf_grestore(ctx, pr);
731 pr->gbot = oldbot;
732 }
733 }
734 }
735
736 pr->gstate[pr->gparent].ctm = gparent_save_ctm;
737 pr->gparent = gparent_save;
738
739 pdf_grestore(ctx, pr);
740
741 return pr->gstate + pr->gtop;
742 }
743
744 static void
745 pdf_show_image_imp(fz_context *ctx, pdf_run_processor *pr, fz_image *image, fz_matrix image_ctm, fz_rect bbox)
746 {
747 pdf_gstate *gstate = pr->gstate + pr->gtop;
748 fz_color_params cp = gstate->fill.color_params;
749
750 if (image->has_intent)
751 cp.ri = image->intent;
752
753 if (image->colorspace)
754 {
755 fz_fill_image(ctx, pr->dev, image, image_ctm, gstate->fill.alpha, cp);
756 }
757 else if (gstate->fill.kind == PDF_MAT_COLOR)
758 {
759 fz_fill_image_mask(ctx, pr->dev, image, image_ctm, gstate->fill.colorspace, gstate->fill.v, gstate->fill.alpha, cp);
760 }
761 else if (gstate->fill.kind == PDF_MAT_PATTERN && gstate->fill.pattern)
762 {
763 fz_clip_image_mask(ctx, pr->dev, image, image_ctm, bbox);
764 gstate = pdf_show_pattern(ctx, pr, gstate->fill.pattern, gstate->fill.gstate_num, bbox, PDF_FILL);
765 fz_pop_clip(ctx, pr->dev);
766 }
767 else if (gstate->fill.kind == PDF_MAT_SHADE && gstate->fill.shade)
768 {
769 fz_clip_image_mask(ctx, pr->dev, image, image_ctm, bbox);
770 fz_fill_shade(ctx, pr->dev, gstate->fill.shade, pr->gstate[gstate->fill.gstate_num].ctm, gstate->fill.alpha, cp);
771 fz_pop_clip(ctx, pr->dev);
772 }
773 }
774
775 static void
776 pdf_show_image(fz_context *ctx, pdf_run_processor *pr, fz_image *image)
777 {
778 pdf_gstate *gstate = pr->gstate + pr->gtop;
779 fz_matrix image_ctm;
780 fz_rect bbox;
781
782 if (pr->super.hidden)
783 return;
784
785 /* image can be NULL here if we are, for example, running to an
786 * stext device. */
787 if (image == NULL)
788 return;
789
790 pop_any_pending_mcid_changes(ctx, pr);
791 flush_begin_layer(ctx, pr);
792
793 /* PDF has images bottom-up, so flip them right side up here */
794 image_ctm = fz_pre_scale(fz_pre_translate(gstate->ctm, 0, 1), 1, -1);
795
796 bbox = fz_transform_rect(fz_unit_rect, image_ctm);
797
798 if (image->mask && gstate->blendmode)
799 {
800 /* apply blend group even though we skip the soft mask */
801 fz_begin_group(ctx, pr->dev, bbox, NULL, 0, 0, gstate->blendmode, 1);
802 fz_clip_image_mask(ctx, pr->dev, image->mask, image_ctm, bbox);
803 pdf_show_image_imp(ctx, pr, image, image_ctm, bbox);
804 fz_pop_clip(ctx, pr->dev);
805 fz_end_group(ctx, pr->dev);
806 }
807 else if (image->mask)
808 {
809 fz_clip_image_mask(ctx, pr->dev, image->mask, image_ctm, bbox);
810 pdf_show_image_imp(ctx, pr, image, image_ctm, bbox);
811 fz_pop_clip(ctx, pr->dev);
812 }
813 else
814 {
815 softmask_save softmask = { NULL };
816 fz_try(ctx)
817 {
818 gstate = pdf_begin_group(ctx, pr, bbox, &softmask);
819 pdf_show_image_imp(ctx, pr, image, image_ctm, bbox);
820 pdf_end_group(ctx, pr, &softmask);
821 }
822 fz_catch(ctx)
823 {
824 pdf_drop_obj(ctx, softmask.softmask);
825 fz_drop_colorspace(ctx, softmask.softmask_cs);
826 pdf_drop_obj(ctx, softmask.page_resources);
827 fz_rethrow(ctx);
828 }
829 }
830 }
831
832 static void
833 pdf_show_path(fz_context *ctx, pdf_run_processor *pr, int doclose, int dofill, int dostroke, int even_odd)
834 {
835 pdf_gstate *gstate = pr->gstate + pr->gtop;
836 fz_path *path;
837 fz_rect bbox;
838 softmask_save softmask = { NULL };
839 int knockout_group = 0;
840
841 pop_any_pending_mcid_changes(ctx, pr);
842 flush_begin_layer(ctx, pr);
843
844 if (dostroke) {
845 if (pr->dev->flags & (FZ_DEVFLAG_STROKECOLOR_UNDEFINED | FZ_DEVFLAG_LINEJOIN_UNDEFINED | FZ_DEVFLAG_LINEWIDTH_UNDEFINED | FZ_DEVFLAG_DASH_PATTERN_UNDEFINED))
846 pr->dev->flags |= FZ_DEVFLAG_UNCACHEABLE;
847 else if (gstate->stroke_state->dash_len != 0 && pr->dev->flags & (FZ_DEVFLAG_STARTCAP_UNDEFINED | FZ_DEVFLAG_DASHCAP_UNDEFINED | FZ_DEVFLAG_ENDCAP_UNDEFINED))
848 pr->dev->flags |= FZ_DEVFLAG_UNCACHEABLE;
849 else if (gstate->stroke_state->linejoin == FZ_LINEJOIN_MITER && (pr->dev->flags & FZ_DEVFLAG_MITERLIMIT_UNDEFINED))
850 pr->dev->flags |= FZ_DEVFLAG_UNCACHEABLE;
851 }
852 if (dofill) {
853 if (pr->dev->flags & FZ_DEVFLAG_FILLCOLOR_UNDEFINED)
854 pr->dev->flags |= FZ_DEVFLAG_UNCACHEABLE;
855 }
856
857 path = pr->path;
858 pr->path = fz_new_path(ctx);
859
860 fz_try(ctx)
861 {
862 if (doclose)
863 fz_closepath(ctx, path);
864
865 bbox = fz_bound_path(ctx, path, (dostroke ? gstate->stroke_state : NULL), gstate->ctm);
866
867 if (pr->super.hidden)
868 dostroke = dofill = 0;
869
870 if (dofill || dostroke)
871 gstate = pdf_begin_group(ctx, pr, bbox, &softmask);
872
873 if (dofill && dostroke)
874 {
875 /* We may need to push a knockout group */
876 if (gstate->stroke.alpha == 0)
877 {
878 /* No need for group, as stroke won't do anything */
879 }
880 else if (gstate->stroke.alpha == 1.0f && gstate->blendmode == FZ_BLEND_NORMAL)
881 {
882 /* No need for group, as stroke won't show up */
883 }
884 else
885 {
886 knockout_group = 1;
887 fz_begin_group(ctx, pr->dev, bbox, NULL, 0, 1, FZ_BLEND_NORMAL, 1);
888 }
889 }
890
891 if (dofill)
892 {
893 switch (gstate->fill.kind)
894 {
895 case PDF_MAT_NONE:
896 break;
897 case PDF_MAT_COLOR:
898 fz_fill_path(ctx, pr->dev, path, even_odd, gstate->ctm,
899 gstate->fill.colorspace, gstate->fill.v, gstate->fill.alpha, gstate->fill.color_params);
900 break;
901 case PDF_MAT_PATTERN:
902 if (gstate->fill.pattern)
903 {
904 fz_clip_path(ctx, pr->dev, path, even_odd, gstate->ctm, bbox);
905 gstate = pdf_show_pattern(ctx, pr, gstate->fill.pattern, gstate->fill.gstate_num, bbox, PDF_FILL);
906 fz_pop_clip(ctx, pr->dev);
907 }
908 break;
909 case PDF_MAT_SHADE:
910 if (gstate->fill.shade)
911 {
912 fz_clip_path(ctx, pr->dev, path, even_odd, gstate->ctm, bbox);
913 /* The cluster and page 2 of patterns.pdf shows that fz_fill_shade should NOT be called with gstate->ctm. */
914 fz_fill_shade(ctx, pr->dev, gstate->fill.shade, pr->gstate[gstate->fill.gstate_num].ctm, gstate->fill.alpha, gstate->fill.color_params);
915 fz_pop_clip(ctx, pr->dev);
916 }
917 break;
918 }
919 }
920
921 if (dostroke)
922 {
923 switch (gstate->stroke.kind)
924 {
925 case PDF_MAT_NONE:
926 break;
927 case PDF_MAT_COLOR:
928 fz_stroke_path(ctx, pr->dev, path, gstate->stroke_state, gstate->ctm,
929 gstate->stroke.colorspace, gstate->stroke.v, gstate->stroke.alpha, gstate->stroke.color_params);
930 break;
931 case PDF_MAT_PATTERN:
932 if (gstate->stroke.pattern)
933 {
934 fz_clip_stroke_path(ctx, pr->dev, path, gstate->stroke_state, gstate->ctm, bbox);
935 gstate = pdf_show_pattern(ctx, pr, gstate->stroke.pattern, gstate->stroke.gstate_num, bbox, PDF_STROKE);
936 fz_pop_clip(ctx, pr->dev);
937 }
938 break;
939 case PDF_MAT_SHADE:
940 if (gstate->stroke.shade)
941 {
942 fz_clip_stroke_path(ctx, pr->dev, path, gstate->stroke_state, gstate->ctm, bbox);
943 fz_fill_shade(ctx, pr->dev, gstate->stroke.shade, pr->gstate[gstate->stroke.gstate_num].ctm, gstate->stroke.alpha, gstate->stroke.color_params);
944 fz_pop_clip(ctx, pr->dev);
945 }
946 break;
947 }
948 }
949
950 if (knockout_group)
951 fz_end_group(ctx, pr->dev);
952
953 if (dofill || dostroke)
954 pdf_end_group(ctx, pr, &softmask);
955
956 if (pr->clip)
957 {
958 nest_layer_clip(ctx, pr);
959 gstate->clip_depth++;
960 fz_clip_path(ctx, pr->dev, path, pr->clip_even_odd, gstate->ctm, bbox);
961 pr->clip = 0;
962 }
963 }
964 fz_always(ctx)
965 {
966 fz_drop_path(ctx, path);
967 }
968 fz_catch(ctx)
969 {
970 pdf_drop_obj(ctx, softmask.softmask);
971 fz_drop_colorspace(ctx, softmask.softmask_cs);
972 pdf_drop_obj(ctx, softmask.page_resources);
973 fz_rethrow(ctx);
974 }
975 }
976
977 /*
978 * Assemble and emit text
979 */
980
981 static pdf_gstate *
982 pdf_flush_text(fz_context *ctx, pdf_run_processor *pr)
983 {
984 pdf_gstate *gstate = pr->gstate + pr->gtop;
985 fz_text *text;
986 int dofill;
987 int dostroke;
988 int doclip;
989 int doinvisible;
990 softmask_save softmask = { NULL };
991 int knockout_group = 0;
992
993 text = pdf_tos_get_text(ctx, &pr->tos);
994 if (!text)
995 return gstate;
996
997 pop_any_pending_mcid_changes(ctx, pr);
998 /* If we are going to output text, we need to have flushed any begin layers first. */
999 flush_begin_layer(ctx, pr);
1000
1001 dofill = dostroke = doclip = doinvisible = 0;
1002 switch (pr->tos.text_mode)
1003 {
1004 case 0: dofill = 1; break;
1005 case 1: dostroke = 1; break;
1006 case 2: dofill = dostroke = 1; break;
1007 case 3: doinvisible = 1; break;
1008 case 4: dofill = doclip = 1; break;
1009 case 5: dostroke = doclip = 1; break;
1010 case 6: dofill = dostroke = doclip = 1; break;
1011 case 7: doclip = 1; break;
1012 }
1013
1014 if (pr->super.hidden)
1015 dostroke = dofill = 0;
1016
1017 fz_try(ctx)
1018 {
1019 fz_rect tb = fz_transform_rect(pr->tos.text_bbox, gstate->ctm);
1020 if (dostroke)
1021 tb = fz_adjust_rect_for_stroke(ctx, tb, gstate->stroke_state, gstate->ctm);
1022
1023 /* Don't bother sending a text group with nothing in it */
1024 if (!text->head)
1025 break;
1026
1027 if (dofill || dostroke)
1028 gstate = pdf_begin_group(ctx, pr, tb, &softmask);
1029
1030 if (dofill && dostroke)
1031 {
1032 /* We may need to push a knockout group */
1033 if (gstate->stroke.alpha == 0)
1034 {
1035 /* No need for group, as stroke won't do anything */
1036 }
1037 else if (gstate->stroke.alpha == 1.0f && gstate->blendmode == FZ_BLEND_NORMAL)
1038 {
1039 /* No need for group, as stroke won't show up */
1040 }
1041 else
1042 {
1043 knockout_group = 1;
1044 fz_begin_group(ctx, pr->dev, tb, NULL, 0, 1, FZ_BLEND_NORMAL, 1);
1045 }
1046 }
1047
1048 if (doinvisible)
1049 fz_ignore_text(ctx, pr->dev, text, gstate->ctm);
1050
1051 if (dofill)
1052 {
1053 switch (gstate->fill.kind)
1054 {
1055 case PDF_MAT_NONE:
1056 break;
1057 case PDF_MAT_COLOR:
1058 fz_fill_text(ctx, pr->dev, text, gstate->ctm,
1059 gstate->fill.colorspace, gstate->fill.v, gstate->fill.alpha, gstate->fill.color_params);
1060 break;
1061 case PDF_MAT_PATTERN:
1062 if (gstate->fill.pattern)
1063 {
1064 fz_clip_text(ctx, pr->dev, text, gstate->ctm, tb);
1065 gstate = pdf_show_pattern(ctx, pr, gstate->fill.pattern, gstate->fill.gstate_num, tb, PDF_FILL);
1066 fz_pop_clip(ctx, pr->dev);
1067 }
1068 break;
1069 case PDF_MAT_SHADE:
1070 if (gstate->fill.shade)
1071 {
1072 fz_clip_text(ctx, pr->dev, text, gstate->ctm, tb);
1073 /* Page 2 of patterns.pdf shows that fz_fill_shade should NOT be called with gstate->ctm */
1074 fz_fill_shade(ctx, pr->dev, gstate->fill.shade, pr->gstate[gstate->fill.gstate_num].ctm, gstate->fill.alpha, gstate->fill.color_params);
1075 fz_pop_clip(ctx, pr->dev);
1076 }
1077 break;
1078 }
1079 }
1080
1081 if (dostroke)
1082 {
1083 switch (gstate->stroke.kind)
1084 {
1085 case PDF_MAT_NONE:
1086 break;
1087 case PDF_MAT_COLOR:
1088 fz_stroke_text(ctx, pr->dev, text, gstate->stroke_state, gstate->ctm,
1089 gstate->stroke.colorspace, gstate->stroke.v, gstate->stroke.alpha, gstate->stroke.color_params);
1090 break;
1091 case PDF_MAT_PATTERN:
1092 if (gstate->stroke.pattern)
1093 {
1094 fz_clip_stroke_text(ctx, pr->dev, text, gstate->stroke_state, gstate->ctm, tb);
1095 gstate = pdf_show_pattern(ctx, pr, gstate->stroke.pattern, gstate->stroke.gstate_num, tb, PDF_STROKE);
1096 fz_pop_clip(ctx, pr->dev);
1097 }
1098 break;
1099 case PDF_MAT_SHADE:
1100 if (gstate->stroke.shade)
1101 {
1102 fz_clip_stroke_text(ctx, pr->dev, text, gstate->stroke_state, gstate->ctm, tb);
1103 fz_fill_shade(ctx, pr->dev, gstate->stroke.shade, pr->gstate[gstate->stroke.gstate_num].ctm, gstate->stroke.alpha, gstate->stroke.color_params);
1104 fz_pop_clip(ctx, pr->dev);
1105 }
1106 break;
1107 }
1108 }
1109
1110 if (knockout_group)
1111 fz_end_group(ctx, pr->dev);
1112
1113 if (dofill || dostroke)
1114 pdf_end_group(ctx, pr, &softmask);
1115
1116 if (doclip)
1117 {
1118 nest_layer_clip(ctx, pr);
1119 gstate->clip_depth++;
1120 fz_clip_text(ctx, pr->dev, text, gstate->ctm, tb);
1121 }
1122 }
1123 fz_always(ctx)
1124 {
1125 fz_drop_text(ctx, text);
1126 }
1127 fz_catch(ctx)
1128 {
1129 pdf_drop_obj(ctx, softmask.softmask);
1130 fz_drop_colorspace(ctx, softmask.softmask_cs);
1131 pdf_drop_obj(ctx, softmask.page_resources);
1132 fz_rethrow(ctx);
1133 }
1134
1135 return pr->gstate + pr->gtop;
1136 }
1137
1138 static int
1139 guess_bidi_level(int bidiclass, int cur_bidi)
1140 {
1141 switch (bidiclass)
1142 {
1143 /* strong */
1144 case UCDN_BIDI_CLASS_L: return 0;
1145 case UCDN_BIDI_CLASS_R: return 1;
1146 case UCDN_BIDI_CLASS_AL: return 1;
1147
1148 /* weak */
1149 case UCDN_BIDI_CLASS_EN:
1150 case UCDN_BIDI_CLASS_ES:
1151 case UCDN_BIDI_CLASS_ET:
1152 return 0;
1153 case UCDN_BIDI_CLASS_AN:
1154 return 1;
1155 case UCDN_BIDI_CLASS_CS:
1156 case UCDN_BIDI_CLASS_NSM:
1157 case UCDN_BIDI_CLASS_BN:
1158 return cur_bidi;
1159
1160 /* neutral */
1161 case UCDN_BIDI_CLASS_B:
1162 case UCDN_BIDI_CLASS_S:
1163 case UCDN_BIDI_CLASS_WS:
1164 case UCDN_BIDI_CLASS_ON:
1165 return cur_bidi;
1166
1167 /* embedding, override, pop ... we don't support them */
1168 default:
1169 return 0;
1170 }
1171 }
1172
1173 static void
1174 pdf_show_char(fz_context *ctx, pdf_run_processor *pr, int cid, fz_text_language lang)
1175 {
1176 pdf_gstate *gstate = pr->gstate + pr->gtop;
1177 pdf_font_desc *fontdesc = gstate->text.font;
1178 fz_matrix trm;
1179 float adv;
1180 int gid;
1181 int ucsbuf[PDF_MRANGE_CAP];
1182 int ucslen;
1183 int i;
1184 int render_direct;
1185 int type3_hitr;
1186
1187 gid = pdf_tos_make_trm(ctx, &pr->tos, &gstate->text, fontdesc, cid, &trm, &adv);
1188
1189 /* If we are uncachable, then render direct. */
1190 render_direct = !fz_glyph_cacheable(ctx, fontdesc->font, gid);
1191
1192 /* PDF spec: ISO 32000-2 latest version at the time of writing:
1193 * Section 9.3.6:
1194 * Where text is drawn using a Type 3 font:
1195 * + if text rendering mode is set to a value of 3 or 7, the text shall not be rendered.
1196 * + if text rendering mode is set to a value other than 3 or 7, the text shall be rendered using the glyph descriptions in the Type 3 font.
1197 * + If text rendering mode is set to a value of 4, 5, 6 or 7, nothing shall be added to the clipping path.
1198 */
1199 type3_hitr = (fontdesc->font->t3procs && pr->tos.text_mode >= 4);
1200
1201 /* flush buffered text if rendermode has changed */
1202 if (!pr->tos.text || gstate->text.render != pr->tos.text_mode || render_direct || type3_hitr)
1203 {
1204 gstate = pdf_flush_text(ctx, pr);
1205 pdf_tos_reset(ctx, &pr->tos, gstate->text.render);
1206 }
1207
1208 /* If Type3 and tr >= 4, then ignore the clipping path part. */
1209 if (type3_hitr)
1210 pr->tos.text_mode -= 4;
1211
1212 if (render_direct && pr->tos.text_mode != 3 /* or 7, by type3_hitr */)
1213 {
1214 /* Render the glyph stream direct here (only happens for
1215 * type3 glyphs that seem to inherit current graphics
1216 * attributes, or type 3 glyphs within type3 glyphs). */
1217 fz_matrix composed = fz_concat(trm, gstate->ctm);
1218 /* Whatever problems the underlying char has is no concern of
1219 * ours. Store the flags, restore them afterwards. */
1220 int old_flags = pr->dev->flags;
1221 pdf_gstate *fill_gstate = NULL;
1222 pdf_gstate *stroke_gstate = NULL;
1223 pdf_gsave(ctx, pr);
1224 gstate = pr->gstate + pr->gtop;
1225 if (gstate->fill.kind == PDF_MAT_PATTERN && gstate->fill.gstate_num >= 0)
1226 fill_gstate = pr->gstate + gstate->fill.gstate_num;
1227 if (gstate->stroke.kind == PDF_MAT_PATTERN && gstate->stroke.gstate_num >= 0)
1228 stroke_gstate = pr->gstate + gstate->stroke.gstate_num;
1229 pdf_drop_font(ctx, gstate->text.font);
1230 gstate->text.font = NULL; /* don't inherit the current font... */
1231 fz_render_t3_glyph_direct(ctx, pr->dev, fontdesc->font, gid, composed, gstate, pr->default_cs, fill_gstate, stroke_gstate);
1232 pr->dev->flags = old_flags;
1233 pdf_grestore(ctx, pr);
1234 /* Render text invisibly so that it can still be extracted. */
1235 pr->tos.text_mode = 3;
1236 }
1237
1238 ucslen = 0;
1239 if (fontdesc->to_unicode)
1240 ucslen = pdf_lookup_cmap_full(fontdesc->to_unicode, cid, ucsbuf);
1241
1242 /* convert ascii whitespace control characters to spaces */
1243 if (ucslen == 1 && (ucsbuf[0] >= 8 && ucsbuf[0] <= 13))
1244 ucsbuf[0] = ' ';
1245
1246 /* ignore obviously bad values in ToUnicode, fall back to the cid_to_ucs table */
1247 if (ucslen == 1 && (ucsbuf[0] < 32 || (ucsbuf[0] >= 127 && ucsbuf[0] < 160)))
1248 ucslen = 0;
1249
1250 if (ucslen == 0 && (size_t)cid < fontdesc->cid_to_ucs_len)
1251 {
1252 ucsbuf[0] = fontdesc->cid_to_ucs[cid];
1253 ucslen = 1;
1254 }
1255 if (ucslen == 0 || (ucslen == 1 && ucsbuf[0] == 0))
1256 {
1257 ucsbuf[0] = FZ_REPLACEMENT_CHARACTER;
1258 ucslen = 1;
1259 }
1260
1261 /* guess bidi level from unicode value */
1262 pr->bidi = guess_bidi_level(ucdn_get_bidi_class(ucsbuf[0]), pr->bidi);
1263
1264 /* add glyph to textobject */
1265 fz_show_glyph_aux(ctx, pr->tos.text, fontdesc->font, trm, adv, gid, ucsbuf[0], cid, fontdesc->wmode, pr->bidi, FZ_BIDI_NEUTRAL, lang);
1266
1267 /* add filler glyphs for one-to-many unicode mapping */
1268 for (i = 1; i < ucslen; i++)
1269 fz_show_glyph_aux(ctx, pr->tos.text, fontdesc->font, trm, 0, -1, ucsbuf[i], -1, fontdesc->wmode, pr->bidi, FZ_BIDI_NEUTRAL, lang);
1270
1271 pdf_tos_move_after_char(ctx, &pr->tos);
1272 }
1273
1274 static void
1275 pdf_show_space(fz_context *ctx, pdf_run_processor *pr, float tadj)
1276 {
1277 pdf_gstate *gstate = pr->gstate + pr->gtop;
1278 pdf_font_desc *fontdesc = gstate->text.font;
1279
1280 if (fontdesc->wmode == 0)
1281 pr->tos.tm = fz_pre_translate(pr->tos.tm, tadj * gstate->text.scale, 0);
1282 else
1283 pr->tos.tm = fz_pre_translate(pr->tos.tm, 0, tadj);
1284 }
1285
1286 static int
1287 int_in_singleton_or_array(fz_context *ctx, pdf_obj *k, int id)
1288 {
1289 /* In the most common case the /K value will be id. */
1290 if (pdf_is_int(ctx, k) && pdf_to_int(ctx, k) == id)
1291 return 1;
1292
1293 /* In the next most common case, there will be an array of
1294 * items, one of which is k. */
1295 if (pdf_is_array(ctx, k))
1296 {
1297 int i, n = pdf_array_len(ctx, k);
1298
1299 for (i = 0; i < n; i++)
1300 {
1301 pdf_obj *o = pdf_array_get(ctx, k, i);
1302 if (pdf_is_int(ctx, o) && pdf_to_int(ctx, o) == id)
1303 return 1;
1304 }
1305 }
1306
1307 return 0;
1308 }
1309
1310 pdf_obj *
1311 pdf_lookup_mcid_in_mcids(fz_context *ctx, int id, pdf_obj *mcids)
1312 {
1313 pdf_obj *mcid = pdf_array_get(ctx, mcids, id);
1314 pdf_obj *k = pdf_dict_get(ctx, mcid, PDF_NAME(K));
1315 int i, n;
1316
1317 if (int_in_singleton_or_array(ctx, k, id))
1318 return mcid;
1319
1320 /* At this point, something has gone wrong. One common case that
1321 * appears to fail is where the MCIDs array has the right things
1322 * in, but at the wrong indexes. So do some searching. */
1323 n = pdf_array_len(ctx, mcids);
1324 for (i = 0; i < n; i++)
1325 {
1326 pdf_obj *o = pdf_array_get(ctx, mcids, i);
1327 if (int_in_singleton_or_array(ctx, pdf_dict_get(ctx, o, PDF_NAME(K)), id))
1328 return o;
1329 }
1330
1331 return NULL;
1332 }
1333
1334 static pdf_obj *
1335 lookup_mcid(fz_context *ctx, pdf_run_processor *proc, pdf_obj *val)
1336 {
1337 pdf_obj *mcid;
1338 int id;
1339 pdf_obj *mcids;
1340
1341 if (proc->struct_parent == -1)
1342 return NULL;
1343
1344 mcid = pdf_dict_get(ctx, val, PDF_NAME(MCID));
1345 if (!mcid)
1346 return NULL;
1347
1348 if (!pdf_is_number(ctx, mcid))
1349 return NULL;
1350
1351 id = pdf_to_int(ctx, mcid);
1352 mcids = pdf_lookup_number(ctx, pdf_dict_getl(ctx, pdf_trailer(ctx, proc->doc), PDF_NAME(Root), PDF_NAME(StructTreeRoot), PDF_NAME(ParentTree), NULL), proc->struct_parent);
1353 return pdf_lookup_mcid_in_mcids(ctx, id, mcids);
1354 }
1355
1356 static fz_text_language
1357 find_lang_from_mc(fz_context *ctx, pdf_run_processor *pr)
1358 {
1359 marked_content_stack *mc;
1360
1361 for (mc = pr->marked_content; mc != NULL; mc = mc->next)
1362 {
1363 size_t len;
1364 const char *lang;
1365
1366 lang = pdf_dict_get_string(ctx, mc->val, PDF_NAME(Lang), &len);
1367 if (!lang)
1368 lang = pdf_dict_get_string(ctx, lookup_mcid(ctx, pr, mc->val), PDF_NAME(Lang), &len);
1369 if (lang)
1370 {
1371 char text[8];
1372 memcpy(text, lang, len < 8 ? len : 7);
1373 text[len < 8 ? len : 7] = 0;
1374 return fz_text_language_from_string(text);
1375 }
1376 }
1377
1378 return FZ_LANG_UNSET;
1379 }
1380
1381 static void
1382 show_string(fz_context *ctx, pdf_run_processor *pr, unsigned char *buf, size_t len)
1383 {
1384 pdf_gstate *gstate = pr->gstate + pr->gtop;
1385 pdf_font_desc *fontdesc = gstate->text.font;
1386 unsigned char *end = buf + len;
1387 unsigned int cpt;
1388 int cid;
1389 fz_text_language lang = find_lang_from_mc(ctx, pr);
1390
1391 pop_any_pending_mcid_changes(ctx, pr);
1392 flush_begin_layer(ctx, pr);
1393
1394 while (buf < end)
1395 {
1396 int w = pdf_decode_cmap(fontdesc->encoding, buf, end, &cpt);
1397 buf += w;
1398
1399 cid = pdf_lookup_cmap(fontdesc->encoding, cpt);
1400 if (cid >= 0)
1401 pdf_show_char(ctx, pr, cid, lang);
1402 else
1403 fz_warn(ctx, "cannot encode character");
1404 if (cpt == 32 && w == 1)
1405 {
1406 /* Bug 703151: pdf_show_char can realloc gstate. */
1407 gstate = pr->gstate + pr->gtop;
1408 pdf_show_space(ctx, pr, gstate->text.word_space);
1409 }
1410 }
1411 }
1412
1413 static void
1414 pdf_show_string(fz_context *ctx, pdf_run_processor *pr, unsigned char *buf, size_t len)
1415 {
1416 pdf_gstate *gstate = pr->gstate + pr->gtop;
1417 pdf_font_desc *fontdesc = gstate->text.font;
1418
1419 if (!fontdesc)
1420 {
1421 fz_warn(ctx, "cannot draw text since font and size not set");
1422 return;
1423 }
1424
1425 show_string(ctx, pr, buf, len);
1426 }
1427
1428 static void
1429 pdf_show_text(fz_context *ctx, pdf_run_processor *pr, pdf_obj *text)
1430 {
1431 pdf_gstate *gstate = pr->gstate + pr->gtop;
1432 pdf_font_desc *fontdesc = gstate->text.font;
1433 int i;
1434
1435 if (!fontdesc)
1436 {
1437 fz_warn(ctx, "cannot draw text since font and size not set");
1438 return;
1439 }
1440
1441 if (pdf_is_array(ctx, text))
1442 {
1443 int n = pdf_array_len(ctx, text);
1444 for (i = 0; i < n; i++)
1445 {
1446 pdf_obj *item = pdf_array_get(ctx, text, i);
1447 if (pdf_is_string(ctx, item))
1448 show_string(ctx, pr, (unsigned char *)pdf_to_str_buf(ctx, item), pdf_to_str_len(ctx, item));
1449 else
1450 pdf_show_space(ctx, pr, - pdf_to_real(ctx, item) * gstate->text.size * 0.001f);
1451 }
1452 }
1453 else if (pdf_is_string(ctx, text))
1454 {
1455 pdf_show_string(ctx, pr, (unsigned char *)pdf_to_str_buf(ctx, text), pdf_to_str_len(ctx, text));
1456 }
1457 }
1458
1459 /*
1460 * Interpreter and graphics state stack.
1461 */
1462
1463 static void
1464 pdf_init_gstate(fz_context *ctx, pdf_gstate *gs, fz_matrix ctm)
1465 {
1466 gs->ctm = ctm;
1467 gs->clip_depth = 0;
1468
1469 gs->stroke_state = fz_new_stroke_state(ctx);
1470
1471 gs->stroke.kind = PDF_MAT_COLOR;
1472 gs->stroke.colorspace = fz_keep_colorspace(ctx, fz_device_gray(ctx));
1473 gs->stroke.v[0] = 0;
1474 gs->stroke.pattern = NULL;
1475 gs->stroke.shade = NULL;
1476 gs->stroke.alpha = 1;
1477 gs->stroke.gstate_num = -1;
1478
1479 gs->fill.kind = PDF_MAT_COLOR;
1480 gs->fill.colorspace = fz_keep_colorspace(ctx, fz_device_gray(ctx));
1481 gs->fill.v[0] = 0;
1482 gs->fill.pattern = NULL;
1483 gs->fill.shade = NULL;
1484 gs->fill.alpha = 1;
1485 gs->fill.gstate_num = -1;
1486
1487 gs->text.char_space = 0;
1488 gs->text.word_space = 0;
1489 gs->text.scale = 1;
1490 gs->text.leading = 0;
1491 gs->text.font = NULL;
1492 gs->text.size = -1;
1493 gs->text.render = 0;
1494 gs->text.rise = 0;
1495
1496 gs->blendmode = 0;
1497 gs->softmask = NULL;
1498 gs->softmask_cs = NULL;
1499 gs->softmask_resources = NULL;
1500 gs->softmask_ctm = fz_identity;
1501 gs->luminosity = 0;
1502
1503 gs->fill.color_params = fz_default_color_params;
1504 gs->stroke.color_params = fz_default_color_params;
1505
1506 gs->ismask = 0;
1507 }
1508
1509 static void
1510 pdf_copy_gstate(fz_context *ctx, pdf_gstate *dst, pdf_gstate *src)
1511 {
1512 pdf_drop_gstate(ctx, dst);
1513 *dst = *src;
1514 pdf_keep_gstate(ctx, dst);
1515 }
1516
1517 /*
1518 * Material state
1519 */
1520
1521 static void
1522 pdf_set_colorspace(fz_context *ctx, pdf_run_processor *pr, int what, fz_colorspace *colorspace)
1523 {
1524 pdf_gstate *gstate = pr->gstate + pr->gtop;
1525 pdf_material *mat;
1526 int n = fz_colorspace_n(ctx, colorspace);
1527
1528 gstate = pdf_flush_text(ctx, pr);
1529
1530 /* Don't change color if we're drawing an uncolored pattern tile! */
1531 if (gstate->ismask)
1532 return;
1533
1534 mat = what == PDF_FILL ? &gstate->fill : &gstate->stroke;
1535
1536 fz_drop_colorspace(ctx, mat->colorspace);
1537
1538 mat->kind = PDF_MAT_COLOR;
1539 mat->colorspace = fz_keep_colorspace(ctx, colorspace);
1540
1541 mat->v[0] = 0;
1542 mat->v[1] = 0;
1543 mat->v[2] = 0;
1544 mat->v[3] = 1;
1545
1546 if (pdf_is_tint_colorspace(ctx, colorspace))
1547 {
1548 int i;
1549 for (i = 0; i < n; i++)
1550 mat->v[i] = 1.0f;
1551 }
1552 }
1553
1554 static void
1555 pdf_set_color(fz_context *ctx, pdf_run_processor *pr, int what, float *v)
1556 {
1557 pdf_gstate *gstate = pr->gstate + pr->gtop;
1558 pdf_material *mat;
1559
1560 gstate = pdf_flush_text(ctx, pr);
1561
1562 /* Don't change color if we're drawing an uncolored pattern tile! */
1563 if (gstate->ismask)
1564 return;
1565
1566 mat = what == PDF_FILL ? &gstate->fill : &gstate->stroke;
1567
1568 switch (mat->kind)
1569 {
1570 case PDF_MAT_PATTERN:
1571 case PDF_MAT_COLOR:
1572 fz_clamp_color(ctx, mat->colorspace, v, mat->v);
1573 break;
1574 default:
1575 fz_warn(ctx, "color incompatible with material");
1576 }
1577
1578 mat->gstate_num = pr->gparent;
1579 }
1580
1581 static void
1582 pdf_set_shade(fz_context *ctx, pdf_run_processor *pr, int what, fz_shade *shade)
1583 {
1584 pdf_gstate *gs;
1585 pdf_material *mat;
1586
1587 gs = pdf_flush_text(ctx, pr);
1588
1589 mat = what == PDF_FILL ? &gs->fill : &gs->stroke;
1590
1591 fz_drop_shade(ctx, mat->shade);
1592
1593 mat->kind = PDF_MAT_SHADE;
1594 mat->shade = fz_keep_shade(ctx, shade);
1595
1596 mat->gstate_num = pr->gparent;
1597 }
1598
1599 static void
1600 pdf_set_pattern(fz_context *ctx, pdf_run_processor *pr, int what, pdf_pattern *pat, float *v)
1601 {
1602 pdf_gstate *gs;
1603 pdf_material *mat;
1604
1605 gs = pdf_flush_text(ctx, pr);
1606
1607 mat = what == PDF_FILL ? &gs->fill : &gs->stroke;
1608
1609 pdf_drop_pattern(ctx, mat->pattern);
1610 mat->pattern = NULL;
1611
1612 mat->kind = PDF_MAT_PATTERN;
1613 if (pat)
1614 mat->pattern = pdf_keep_pattern(ctx, pat);
1615
1616 if (v)
1617 pdf_set_color(ctx, pr, what, v);
1618
1619 mat->gstate_num = pr->gparent;
1620 }
1621
1622 static void
1623 begin_metatext(fz_context *ctx, pdf_run_processor *proc, pdf_obj *val, pdf_obj *mcid, fz_metatext meta, pdf_obj *name)
1624 {
1625 pdf_obj *text = pdf_dict_get(ctx, val, name);
1626
1627 if (!text)
1628 text = pdf_dict_get(ctx, mcid, name);
1629 if (!text)
1630 return;
1631
1632 pdf_flush_text(ctx, proc);
1633
1634 fz_begin_metatext(ctx, proc->dev, meta, pdf_to_text_string(ctx, text));
1635 }
1636
1637 static void
1638 end_metatext(fz_context *ctx, pdf_run_processor *proc, pdf_obj *val, pdf_obj *mcid, pdf_obj *name)
1639 {
1640 pdf_obj *text = pdf_dict_get(ctx, val, name);
1641
1642 if (!text)
1643 text = pdf_dict_get(ctx, mcid, name);
1644 if (!text)
1645 return;
1646
1647 pdf_flush_text(ctx, proc);
1648
1649 fz_end_metatext(ctx, proc->dev);
1650 }
1651
1652 static void
1653 begin_oc(fz_context *ctx, pdf_run_processor *proc, pdf_obj *val, pdf_cycle_list *cycle_up)
1654 {
1655 /* val has been resolved to a dict for us by the originally specified name
1656 * having been looked up in Properties already for us. Either there will
1657 * be a Name entry, or there will be an OCGs and it'll be a group one. */
1658 pdf_cycle_list cycle;
1659 pdf_obj *obj;
1660 int i, n;
1661
1662 if (pdf_cycle(ctx, &cycle, cycle_up, val))
1663 return;
1664
1665 obj = pdf_dict_get(ctx, val, PDF_NAME(Name));
1666 if (obj)
1667 {
1668 const char *name = "";
1669 pdf_flush_text(ctx, proc);
1670 if (pdf_is_name(ctx, obj))
1671 name = pdf_to_name(ctx, obj);
1672 else if (pdf_is_string(ctx, obj))
1673 name = pdf_to_text_string(ctx, obj);
1674
1675 push_begin_layer(ctx, proc, name);
1676 return;
1677 }
1678
1679 obj = pdf_dict_get(ctx, val, PDF_NAME(OCGs));
1680 n = pdf_array_len(ctx, obj);
1681 for (i = 0; i < n; i++)
1682 {
1683 begin_oc(ctx, proc, pdf_array_get(ctx, obj, i), &cycle);
1684 }
1685 }
1686
1687 static void
1688 end_oc(fz_context *ctx, pdf_run_processor *proc, pdf_obj *val, pdf_cycle_list *cycle_up)
1689 {
1690 /* val has been resolved to a dict for us by the originally specified name
1691 * having been looked up in Properties already for us. Either there will
1692 * be a Name entry, or there will be an OCGs and it'll be a group one. */
1693 pdf_cycle_list cycle;
1694 pdf_obj *obj;
1695 int i, n;
1696
1697 if (pdf_cycle(ctx, &cycle, cycle_up, val))
1698 return;
1699
1700 obj = pdf_dict_get(ctx, val, PDF_NAME(Name));
1701 if (obj)
1702 {
1703 flush_begin_layer(ctx, proc);
1704 do_end_layer(ctx, proc);
1705 return;
1706 }
1707
1708 obj = pdf_dict_get(ctx, val, PDF_NAME(OCGs));
1709 n = pdf_array_len(ctx, obj);
1710 for (i = n-1; i >= 0; i--)
1711 {
1712 end_oc(ctx, proc, pdf_array_get(ctx, obj, i), &cycle);
1713 }
1714 }
1715
1716 static void
1717 begin_layer(fz_context *ctx, pdf_run_processor *proc, pdf_obj *val)
1718 {
1719 /* val has been resolved to a dict for us by the originally specified name
1720 * having been looked up in Properties already for us. Go with the 'Title'
1721 * entry. */
1722 pdf_obj *obj = pdf_dict_get(ctx, val, PDF_NAME(Title));
1723 if (obj)
1724 {
1725 pdf_flush_text(ctx, proc);
1726 push_begin_layer(ctx, proc, pdf_to_text_string(ctx, obj));
1727 }
1728 }
1729
1730 static void
1731 end_layer(fz_context *ctx, pdf_run_processor *proc, pdf_obj *val)
1732 {
1733 /* val has been resolved to a dict for us by the originally specified name
1734 * having been looked up in Properties already for us. Go with the 'Title'
1735 * entry. */
1736 pdf_obj *obj = pdf_dict_get(ctx, val, PDF_NAME(Title));
1737 if (obj)
1738 {
1739 do_end_layer(ctx, proc);
1740 }
1741 }
1742
1743 #ifdef DEBUG_STRUCTURE
1744 static void
1745 structure_dump(fz_context *ctx, const char *str, pdf_obj *obj)
1746 {
1747 fprintf(stderr, "%s STACK=", str);
1748
1749 if (obj == NULL)
1750 {
1751 fprintf(stderr, "empty\n");
1752 return;
1753 }
1754
1755 do
1756 {
1757 pdf_obj *s = pdf_dict_get(ctx, obj, PDF_NAME(S));
1758 int n = pdf_to_num(ctx, obj);
1759 fprintf(stderr, " %d", n);
1760 if (s)
1761 fprintf(stderr, "[%s]", pdf_to_name(ctx, s));
1762 obj = pdf_dict_get(ctx, obj, PDF_NAME(P));
1763 }
1764 while (obj);
1765 fprintf(stderr, "\n");
1766 }
1767 #endif
1768
1769 static void
1770 pop_structure_to(fz_context *ctx, pdf_run_processor *proc, pdf_obj *common)
1771 {
1772 pdf_obj *struct_tree_root = pdf_dict_getl(ctx, pdf_trailer(ctx, proc->doc), PDF_NAME(Root), PDF_NAME(StructTreeRoot), NULL);
1773
1774 #ifdef DEBUG_STRUCTURE
1775 structure_dump(ctx, "pop_structure_to (before)", proc->mcid_sent);
1776
1777 {
1778 int n = pdf_to_num(ctx, common);
1779 fprintf(stderr, "Popping until %d\n", n);
1780 }
1781 #endif
1782
1783 while (proc->mcid_sent != NULL && pdf_objcmp(ctx, proc->mcid_sent, common))
1784 {
1785 pdf_obj *p = pdf_dict_get(ctx, proc->mcid_sent, PDF_NAME(P));
1786 pdf_obj *tag = pdf_dict_get(ctx, proc->mcid_sent, PDF_NAME(S));
1787 fz_structure standard = pdf_structure_type(ctx, proc->role_map, tag);
1788 #ifdef DEBUG_STRUCTURE
1789 fprintf(stderr, "sending pop [tag=%s][std=%d]\n", pdf_to_name(ctx, tag) ? pdf_to_name(ctx, tag) : "null", standard);
1790 #endif
1791 if (standard != FZ_STRUCTURE_INVALID)
1792 fz_end_structure(ctx, proc->dev);
1793 pdf_drop_obj(ctx, proc->mcid_sent);
1794 proc->mcid_sent = pdf_keep_obj(ctx, p);
1795 if (!pdf_objcmp(ctx, p, struct_tree_root))
1796 {
1797 pdf_drop_obj(ctx, proc->mcid_sent);
1798 proc->mcid_sent = NULL;
1799 break;
1800 }
1801 }
1802 #ifdef DEBUG_STRUCTURE
1803 structure_dump(ctx, "pop_structure_to (after)", proc->mcid_sent);
1804 #endif
1805 }
1806
1807 static void
1808 pop_any_pending_mcid_changes(fz_context *ctx, pdf_run_processor *pr)
1809 {
1810 if (pr->pending_mcid_pop == NULL)
1811 return;
1812
1813 pop_structure_to(ctx, pr, pr->pending_mcid_pop);
1814 pr->pending_mcid_pop = NULL;
1815 }
1816
1817 struct line
1818 {
1819 pdf_obj *obj;
1820 struct line *child;
1821 };
1822
1823 static pdf_obj *
1824 find_most_recent_common_ancestor_imp(fz_context *ctx, pdf_obj *a, struct line *line_a, pdf_obj *b, struct line *line_b, pdf_cycle_list *cycle_up_a, pdf_cycle_list *cycle_up_b)
1825 {
1826 struct line line;
1827 pdf_obj *common = NULL;
1828 pdf_cycle_list cycle;
1829 pdf_obj *parent;
1830
1831 /* First ascend one lineage. */
1832 if (pdf_is_dict(ctx, a))
1833 {
1834 if (pdf_cycle(ctx, &cycle, cycle_up_a, a))
1835 fz_throw(ctx, FZ_ERROR_FORMAT, "cycle in structure tree");
1836 line.obj = a;
1837 line.child = line_a;
1838 parent = pdf_dict_get(ctx, a, PDF_NAME(P));
1839 return find_most_recent_common_ancestor_imp(ctx, parent, &line, b, NULL, &cycle, NULL);
1840 }
1841 /* Then ascend the other lineage. */
1842 else if (pdf_is_dict(ctx, b))
1843 {
1844 if (pdf_cycle(ctx, &cycle, cycle_up_b, b))
1845 fz_throw(ctx, FZ_ERROR_FORMAT, "cycle in structure tree");
1846 line.obj = b;
1847 line.child = line_b;
1848 parent = pdf_dict_get(ctx, b, PDF_NAME(P));
1849 return find_most_recent_common_ancestor_imp(ctx, a, line_a, parent, &line, cycle_up_a, &cycle);
1850 }
1851
1852 /* Once both lineages are know, traverse top-down to find most recent common ancestor. */
1853 while (line_a && line_b && !pdf_objcmp(ctx, line_a->obj, line_b->obj))
1854 {
1855 common = line_a->obj;
1856 line_a = line_a->child;
1857 line_b = line_b->child;
1858 }
1859 return common;
1860 }
1861
1862 static pdf_obj *
1863 find_most_recent_common_ancestor(fz_context *ctx, pdf_obj *a, pdf_obj *b)
1864 {
1865 if (!pdf_is_dict(ctx, a) || !pdf_is_dict(ctx, b))
1866 return NULL;
1867 return find_most_recent_common_ancestor_imp(ctx, a, NULL, b, NULL, NULL, NULL);
1868 }
1869
1870 static int
1871 get_struct_index(fz_context *ctx, pdf_obj *send)
1872 {
1873 pdf_obj *p = pdf_dict_get(ctx, send, PDF_NAME(P));
1874 pdf_obj *k;
1875 int i, n;
1876
1877 if (p == NULL)
1878 return 0; /* Presumably the StructTreeRoot */
1879
1880 /* So, get the kids array. */
1881 k = pdf_dict_get(ctx, p, PDF_NAME(K));
1882 n = pdf_array_len(ctx, k);
1883 if (n == 0)
1884 {
1885 /* Not an array, presumably a singleton. */
1886 if (pdf_objcmp(ctx, k, send) == 0)
1887 return 0;
1888 return -1;
1889 }
1890 for (i = 0; i < n; i++)
1891 {
1892 if (pdf_objcmp(ctx, pdf_array_get(ctx, k, i), send) == 0)
1893 return i;
1894 }
1895 return -1;
1896 }
1897
1898 static int
1899 send_begin_structure(fz_context *ctx, pdf_run_processor *proc, pdf_obj *mc_dict)
1900 {
1901 pdf_obj *common = NULL;
1902
1903 #ifdef DEBUG_STRUCTURE
1904 fprintf(stderr, "send_begin_structure %d\n", pdf_to_num(ctx, mc_dict));
1905 structure_dump(ctx, "on entry", proc->mcid_sent);
1906 #endif
1907
1908 /* We are currently nested in A,B,C,...E,F,mcid_sent. We want to update to
1909 * being in A,B,C,...G,H,mc_dict. So we need to find the lowest common point. */
1910 common = find_most_recent_common_ancestor(ctx, proc->mcid_sent, mc_dict);
1911
1912 /* So, we need to pop everything up to common (i.e. everything below common will be closed). */
1913 pop_structure_to(ctx, proc, common);
1914
1915 #ifdef DEBUG_STRUCTURE
1916 structure_dump(ctx, "after popping", proc->mcid_sent);
1917 #endif
1918 /* Now we need to send everything between common (proc->mcid_sent) and mc_dict.
1919 * Again, n^2 will do... */
1920 while (pdf_objcmp(ctx, proc->mcid_sent, mc_dict))
1921 {
1922 pdf_obj *send = mc_dict;
1923 fz_structure standard;
1924 pdf_obj *tag;
1925 int idx;
1926 pdf_obj *slowptr = send;
1927 int slow = 0;
1928
1929 /* Run up the ancestor stack, looking for the first child of mcid_sent.
1930 * That's the one we need to send next. */
1931 while (1) {
1932 pdf_obj *p = pdf_dict_get(ctx, send, PDF_NAME(P));
1933
1934 /* If we ever fail to find a dict, then do not step down lest
1935 * we can't get back later! */
1936 if (!pdf_is_dict(ctx, send))
1937 {
1938 fz_warn(ctx, "Bad parent link in structure tree. Ignoring structure.");
1939 proc->broken_struct_tree = 1;
1940 return 0;
1941 }
1942 /* If p is the one we last sent, then we want to send 'send'
1943 * next. Exit the loop. */
1944 if (!pdf_objcmp(ctx, p, proc->mcid_sent))
1945 break;
1946
1947 /* We need to go at least one step further up the stack. */
1948 send = p;
1949
1950 /* Check for a loop in the parent tree. */
1951 slow ^= 1;
1952 if (slow == 0)
1953 slowptr = pdf_dict_get(ctx, slowptr, PDF_NAME(P));
1954 if (!pdf_objcmp(ctx, send, slowptr))
1955 {
1956 fz_warn(ctx, "Loop found in structure tree. Ignoring structure.");
1957 proc->broken_struct_tree = 1;
1958 return 0;
1959 }
1960 }
1961
1962 idx = get_struct_index(ctx, send);
1963 tag = pdf_dict_get(ctx, send, PDF_NAME(S));
1964 standard = pdf_structure_type(ctx, proc->role_map, tag);
1965 #ifdef DEBUG_STRUCTURE
1966 fprintf(stderr, "sending %d[idx=%d][tag=%s][std=%d]\n", pdf_to_num(ctx, send), idx, pdf_to_name(ctx, tag) ? pdf_to_name(ctx, tag) : "null", standard);
1967 #endif
1968 if (standard != FZ_STRUCTURE_INVALID)
1969 fz_begin_structure(ctx, proc->dev, standard, pdf_to_name(ctx, tag), idx);
1970
1971 pdf_drop_obj(ctx, proc->mcid_sent);
1972 proc->mcid_sent = pdf_keep_obj(ctx, send);
1973 }
1974 #ifdef DEBUG_STRUCTURE
1975 structure_dump(ctx, "on exit", proc->mcid_sent);
1976 #endif
1977
1978 return 1;
1979 }
1980
1981 static void
1982 push_marked_content(fz_context *ctx, pdf_run_processor *proc, const char *tagstr, pdf_obj *val)
1983 {
1984 pdf_obj *tag;
1985 marked_content_stack *mc = NULL;
1986 int drop_tag = 1;
1987 pdf_obj *mc_dict = NULL;
1988
1989 /* Ignore any pending pops. */
1990 proc->pending_mcid_pop = NULL;
1991
1992 /* Flush any pending text so it's not in the wrong layer. */
1993 pdf_flush_text(ctx, proc);
1994
1995 if (!tagstr)
1996 tagstr = "Untitled";
1997 tag = pdf_new_name(ctx, tagstr);
1998
1999 fz_var(drop_tag);
2000
2001 fz_try(ctx)
2002 {
2003 /* First, push it on the stack. */
2004 mc = fz_malloc_struct(ctx, marked_content_stack);
2005 mc->next = proc->marked_content;
2006 mc->tag = tag;
2007 mc->val = pdf_keep_obj(ctx, val);
2008 mc->structure_pushed = 0;
2009 proc->marked_content = mc;
2010 drop_tag = 0;
2011
2012 /* Check to see if val contains an MCID. */
2013 mc_dict = lookup_mcid(ctx, proc, val);
2014
2015 /* Start any optional content layers. */
2016 if (pdf_name_eq(ctx, tag, PDF_NAME(OC)))
2017 begin_oc(ctx, proc, val, NULL);
2018
2019 /* Special handling for common non-spec extension. */
2020 if (pdf_name_eq(ctx, tag, PDF_NAME(Layer)))
2021 begin_layer(ctx, proc, val);
2022
2023 /* Structure */
2024 if (mc_dict && !proc->broken_struct_tree)
2025 {
2026 fz_try(ctx)
2027 mc->structure_pushed = send_begin_structure(ctx, proc, mc_dict);
2028 fz_catch(ctx)
2029 {
2030 fz_report_error(ctx);
2031 fz_warn(ctx, "structure tree broken, assume tree is missing");
2032 proc->broken_struct_tree = 1;
2033 }
2034 }
2035
2036 /* Previously, I'd tried to send stuff like:
2037 * /Artifact <</Type/Pagination>>BDC
2038 * as a structure entry, lured by the fact that 'Artifact' is a
2039 * structure tag. I now believe this is wrong. Only stuff with
2040 * an MCID pointer should be sent using the structure mechanism.
2041 */
2042
2043 /* ActualText */
2044 begin_metatext(ctx, proc, val, mc_dict, FZ_METATEXT_ACTUALTEXT, PDF_NAME(ActualText));
2045
2046 /* Alt */
2047 begin_metatext(ctx, proc, val, mc_dict, FZ_METATEXT_ALT, PDF_NAME(Alt));
2048
2049 /* Abbreviation */
2050 begin_metatext(ctx, proc, val, mc_dict, FZ_METATEXT_ABBREVIATION, PDF_NAME(E));
2051
2052 /* Title */
2053 begin_metatext(ctx, proc, val, mc_dict, FZ_METATEXT_TITLE, PDF_NAME(T));
2054 }
2055 fz_catch(ctx)
2056 {
2057 if (drop_tag)
2058 pdf_drop_obj(ctx, tag);
2059 fz_rethrow(ctx);
2060 }
2061 }
2062
2063 static void
2064 pop_marked_content(fz_context *ctx, pdf_run_processor *proc, int neat)
2065 {
2066 marked_content_stack *mc = proc->marked_content;
2067 pdf_obj *val, *tag;
2068 pdf_obj *mc_dict = NULL;
2069 int pushed;
2070
2071 if (mc == NULL)
2072 return;
2073
2074 proc->marked_content = mc->next;
2075 tag = mc->tag;
2076 val = mc->val;
2077 pushed = mc->structure_pushed;
2078 fz_free(ctx, mc);
2079
2080 /* If we're not interested in neatly closing any open layers etc
2081 * in the processor, (maybe we've had errors already), then just
2082 * exit here. */
2083 if (!neat)
2084 {
2085 pdf_drop_obj(ctx, tag);
2086 pdf_drop_obj(ctx, val);
2087 return;
2088 }
2089
2090 /* Close structure/layers here, in reverse order to how we opened them. */
2091 fz_try(ctx)
2092 {
2093 /* Make sure that any pending text is written into the correct layer. */
2094 pdf_flush_text(ctx, proc);
2095
2096 /* Check to see if val contains an MCID. */
2097 mc_dict = lookup_mcid(ctx, proc, val);
2098
2099 /* Title */
2100 end_metatext(ctx, proc, val, mc_dict, PDF_NAME(T));
2101
2102 /* Abbreviation */
2103 end_metatext(ctx, proc, val, mc_dict, PDF_NAME(E));
2104
2105 /* Alt */
2106 end_metatext(ctx, proc, val, mc_dict, PDF_NAME(Alt));
2107
2108 /* ActualText */
2109 end_metatext(ctx, proc, val, mc_dict, PDF_NAME(ActualText));
2110
2111 /* Structure */
2112 if (mc_dict && !proc->broken_struct_tree && pushed)
2113 {
2114 /* Is there a nested mc_dict? If so we want to pop back to that.
2115 * If not, we want to pop back to the top.
2116 * proc->marked_content = the previous one, but maybe not the
2117 * previous one with an mc_dict. So we may need to search further.
2118 */
2119 pdf_obj *previous_mcid = NULL;
2120 marked_content_stack *mc_with_mcid = proc->marked_content;
2121 while (mc_with_mcid)
2122 {
2123 previous_mcid = lookup_mcid(ctx, proc, mc_with_mcid->val);
2124 if (previous_mcid != NULL)
2125 break;
2126 mc_with_mcid = mc_with_mcid->next;
2127 }
2128
2129 proc->pending_mcid_pop = previous_mcid;
2130 }
2131
2132 /* Finally, close any layers. */
2133 if (pdf_name_eq(ctx, tag, PDF_NAME(Layer)))
2134 end_layer(ctx, proc, val);
2135
2136 if (pdf_name_eq(ctx, tag, PDF_NAME(OC)))
2137 end_oc(ctx, proc, val, NULL);
2138 }
2139 fz_always(ctx)
2140 {
2141 pdf_drop_obj(ctx, tag);
2142 pdf_drop_obj(ctx, val);
2143 }
2144 fz_catch(ctx)
2145 fz_rethrow(ctx);
2146 }
2147
2148 static void
2149 clear_marked_content(fz_context *ctx, pdf_run_processor *pr)
2150 {
2151 if (pr->marked_content == NULL)
2152 return;
2153
2154 fz_try(ctx)
2155 while (pr->marked_content)
2156 pop_marked_content(ctx, pr, 1);
2157 fz_always(ctx)
2158 while (pr->marked_content)
2159 pop_marked_content(ctx, pr, 0);
2160 fz_catch(ctx)
2161 fz_rethrow(ctx);
2162 }
2163
2164 static void
2165 pdf_run_xobject(fz_context *ctx, pdf_run_processor *pr, pdf_obj *xobj, pdf_obj *page_resources, fz_matrix transform, int is_smask)
2166 {
2167 pdf_cycle_list cycle_here;
2168 pdf_gstate *gstate = NULL;
2169 int oldtop = 0;
2170 int oldbot = -1;
2171 softmask_save softmask = { NULL };
2172 int gparent_save;
2173 fz_matrix gparent_save_ctm;
2174 pdf_obj *resources;
2175 fz_rect xobj_bbox;
2176 fz_matrix xobj_matrix;
2177 int transparency = 0;
2178 pdf_document *doc;
2179 fz_colorspace *cs = NULL;
2180 fz_default_colorspaces *save_default_cs = NULL;
2181 fz_default_colorspaces *xobj_default_cs = NULL;
2182 marked_content_stack *save_marked_content = NULL;
2183 int save_struct_parent;
2184 pdf_obj *oc;
2185
2186 /* Avoid infinite recursion */
2187 pdf_cycle_list *cycle_up = pr->cycle;
2188 if (xobj == NULL || pdf_cycle(ctx, &cycle_here, cycle_up, xobj))
2189 return;
2190 pr->cycle = &cycle_here;
2191
2192 pop_any_pending_mcid_changes(ctx, pr);
2193 flush_begin_layer(ctx, pr);
2194
2195 fz_var(cs);
2196 fz_var(xobj_default_cs);
2197
2198 gparent_save = pr->gparent;
2199 pr->gparent = pr->gtop;
2200 oldtop = pr->gtop;
2201
2202 save_default_cs = pr->default_cs;
2203 save_marked_content = pr->marked_content;
2204 pr->marked_content = NULL;
2205 save_struct_parent = pr->struct_parent;
2206
2207 fz_try(ctx)
2208 {
2209 pr->struct_parent = pdf_dict_get_int_default(ctx, xobj, PDF_NAME(StructParent), -1);
2210
2211 oc = pdf_dict_get(ctx, xobj, PDF_NAME(OC));
2212 if (oc)
2213 begin_oc(ctx, pr, oc, NULL);
2214
2215 pdf_gsave(ctx, pr);
2216
2217 gstate = pr->gstate + pr->gtop;
2218
2219 xobj_bbox = pdf_xobject_bbox(ctx, xobj);
2220 xobj_matrix = pdf_xobject_matrix(ctx, xobj);
2221 transparency = pdf_xobject_transparency(ctx, xobj);
2222
2223 /* apply xobject's transform matrix */
2224 transform = fz_concat(xobj_matrix, transform);
2225 gstate->ctm = fz_concat(transform, gstate->ctm);
2226
2227 /* The gparent is updated with the modified ctm */
2228 gparent_save_ctm = pr->gstate[pr->gparent].ctm;
2229 pr->gstate[pr->gparent].ctm = gstate->ctm;
2230
2231 /* apply soft mask, create transparency group and reset state */
2232 if (transparency)
2233 {
2234 int isolated = pdf_xobject_isolated(ctx, xobj);
2235
2236 fz_rect bbox = fz_transform_rect(xobj_bbox, gstate->ctm);
2237
2238 gstate = begin_softmask(ctx, pr, &softmask, bbox);
2239
2240 if (isolated)
2241 cs = pdf_xobject_colorspace(ctx, xobj);
2242 fz_begin_group(ctx, pr->dev, bbox,
2243 cs,
2244 (is_smask ? 1 : isolated),
2245 pdf_xobject_knockout(ctx, xobj),
2246 gstate->blendmode, gstate->fill.alpha);
2247
2248 gstate->blendmode = 0;
2249 gstate->stroke.alpha = 1;
2250 gstate->fill.alpha = 1;
2251 }
2252
2253 pdf_gsave(ctx, pr); /* Save here so the clippath doesn't persist */
2254
2255 /* clip to the bounds */
2256 fz_moveto(ctx, pr->path, xobj_bbox.x0, xobj_bbox.y0);
2257 fz_lineto(ctx, pr->path, xobj_bbox.x1, xobj_bbox.y0);
2258 fz_lineto(ctx, pr->path, xobj_bbox.x1, xobj_bbox.y1);
2259 fz_lineto(ctx, pr->path, xobj_bbox.x0, xobj_bbox.y1);
2260 fz_closepath(ctx, pr->path);
2261 pr->clip = 1;
2262 pdf_show_path(ctx, pr, 0, 0, 0, 0);
2263
2264 /* run contents */
2265
2266 resources = pdf_xobject_resources(ctx, xobj);
2267 if (!resources)
2268 resources = page_resources;
2269
2270 fz_try(ctx)
2271 xobj_default_cs = pdf_update_default_colorspaces(ctx, pr->default_cs, resources);
2272 fz_catch(ctx)
2273 {
2274 fz_rethrow_unless(ctx, FZ_ERROR_TRYLATER);
2275 fz_ignore_error(ctx);
2276 if (pr->cookie)
2277 pr->cookie->incomplete = 1;
2278 }
2279 if (xobj_default_cs != save_default_cs)
2280 {
2281 fz_set_default_colorspaces(ctx, pr->dev, xobj_default_cs);
2282 pr->default_cs = xobj_default_cs;
2283 }
2284
2285 doc = pdf_get_bound_document(ctx, xobj);
2286
2287 oldbot = pr->gbot;
2288 pr->gbot = pr->gtop;
2289
2290 pdf_process_contents(ctx, (pdf_processor*)pr, doc, resources, xobj, pr->cookie, NULL);
2291
2292 /* Undo any gstate mismatches due to the pdf_process_contents call */
2293 if (oldbot != -1)
2294 {
2295 while (pr->gtop > pr->gbot)
2296 {
2297 pdf_grestore(ctx, pr);
2298 }
2299 pr->gbot = oldbot;
2300 }
2301
2302 pdf_grestore(ctx, pr); /* Remove the state we pushed for the clippath */
2303
2304 /* wrap up transparency stacks */
2305 if (transparency)
2306 {
2307 fz_end_group(ctx, pr->dev);
2308 end_softmask(ctx, pr, &softmask);
2309 }
2310
2311 pr->gstate[pr->gparent].ctm = gparent_save_ctm;
2312 pr->gparent = gparent_save;
2313
2314 while (oldtop < pr->gtop)
2315 pdf_grestore(ctx, pr);
2316
2317 if (oc)
2318 end_oc(ctx, pr, oc, NULL);
2319
2320 if (xobj_default_cs != save_default_cs)
2321 {
2322 fz_set_default_colorspaces(ctx, pr->dev, save_default_cs);
2323 }
2324 }
2325 fz_always(ctx)
2326 {
2327 clear_marked_content(ctx, pr);
2328 pr->marked_content = save_marked_content;
2329 pr->default_cs = save_default_cs;
2330 fz_drop_default_colorspaces(ctx, xobj_default_cs);
2331 fz_drop_colorspace(ctx, cs);
2332 pr->cycle = cycle_up;
2333 pr->struct_parent = save_struct_parent;
2334 }
2335 fz_catch(ctx)
2336 {
2337 pdf_drop_obj(ctx, softmask.softmask);
2338 fz_drop_colorspace(ctx, softmask.softmask_cs);
2339 pdf_drop_obj(ctx, softmask.page_resources);
2340 /* Note: Any SYNTAX errors should have been swallowed
2341 * by pdf_process_contents, but in case any escape from other
2342 * functions, recast the error type here to be safe. */
2343 fz_morph_error(ctx, FZ_ERROR_SYNTAX, FZ_ERROR_FORMAT);
2344 fz_rethrow(ctx);
2345 }
2346 }
2347
2348 /* general graphics state */
2349
2350 static void pdf_run_w(fz_context *ctx, pdf_processor *proc, float linewidth)
2351 {
2352 pdf_run_processor *pr = (pdf_run_processor *)proc;
2353 pdf_gstate *gstate = pdf_flush_text(ctx, pr);
2354
2355 pop_any_pending_mcid_changes(ctx, pr);
2356 flush_begin_layer(ctx, pr);
2357
2358 pr->dev->flags &= ~FZ_DEVFLAG_LINEWIDTH_UNDEFINED;
2359 gstate->stroke_state = fz_unshare_stroke_state(ctx, gstate->stroke_state);
2360 gstate->stroke_state->linewidth = linewidth;
2361 }
2362
2363 static void pdf_run_j(fz_context *ctx, pdf_processor *proc, int linejoin)
2364 {
2365 pdf_run_processor *pr = (pdf_run_processor *)proc;
2366 pdf_gstate *gstate = pdf_flush_text(ctx, pr);
2367
2368 pr->dev->flags &= ~FZ_DEVFLAG_LINEJOIN_UNDEFINED;
2369 gstate->stroke_state = fz_unshare_stroke_state(ctx, gstate->stroke_state);
2370 gstate->stroke_state->linejoin = linejoin;
2371 }
2372
2373 static void pdf_run_J(fz_context *ctx, pdf_processor *proc, int linecap)
2374 {
2375 pdf_run_processor *pr = (pdf_run_processor *)proc;
2376 pdf_gstate *gstate = pdf_flush_text(ctx, pr);
2377
2378 pr->dev->flags &= ~(FZ_DEVFLAG_STARTCAP_UNDEFINED | FZ_DEVFLAG_DASHCAP_UNDEFINED | FZ_DEVFLAG_ENDCAP_UNDEFINED);
2379 gstate->stroke_state = fz_unshare_stroke_state(ctx, gstate->stroke_state);
2380 gstate->stroke_state->start_cap = linecap;
2381 gstate->stroke_state->dash_cap = linecap;
2382 gstate->stroke_state->end_cap = linecap;
2383 }
2384
2385 static void pdf_run_M(fz_context *ctx, pdf_processor *proc, float miterlimit)
2386 {
2387 pdf_run_processor *pr = (pdf_run_processor *)proc;
2388 pdf_gstate *gstate = pdf_flush_text(ctx, pr);
2389
2390 pr->dev->flags &= ~FZ_DEVFLAG_MITERLIMIT_UNDEFINED;
2391 gstate->stroke_state = fz_unshare_stroke_state(ctx, gstate->stroke_state);
2392 gstate->stroke_state->miterlimit = miterlimit;
2393 }
2394
2395 static void pdf_run_d(fz_context *ctx, pdf_processor *proc, pdf_obj *array, float phase)
2396 {
2397 pdf_run_processor *pr = (pdf_run_processor *)proc;
2398 pdf_gstate *gstate = pdf_flush_text(ctx, pr);
2399 int len, i;
2400
2401 pr->dev->flags &= ~FZ_DEVFLAG_DASH_PATTERN_UNDEFINED;
2402 len = pdf_array_len(ctx, array);
2403 gstate->stroke_state = fz_unshare_stroke_state_with_dash_len(ctx, gstate->stroke_state, len);
2404 for (i = 0; i < len; i++)
2405 gstate->stroke_state->dash_list[i] = pdf_array_get_real(ctx, array, i);
2406 gstate->stroke_state->dash_phase = phase;
2407 }
2408
2409 static void pdf_run_ri(fz_context *ctx, pdf_processor *proc, const char *intent)
2410 {
2411 pdf_run_processor *pr = (pdf_run_processor *)proc;
2412 pdf_gstate *gstate = pdf_flush_text(ctx, pr);
2413 gstate->fill.color_params.ri = fz_lookup_rendering_intent(intent);
2414 gstate->stroke.color_params.ri = gstate->fill.color_params.ri;
2415 }
2416
2417 static void pdf_run_gs_OP(fz_context *ctx, pdf_processor *proc, int b)
2418 {
2419 pdf_run_processor *pr = (pdf_run_processor *)proc;
2420 pdf_gstate *gstate = pdf_flush_text(ctx, pr);
2421 gstate->stroke.color_params.op = b;
2422 gstate->fill.color_params.op = b;
2423 }
2424
2425 static void pdf_run_gs_op(fz_context *ctx, pdf_processor *proc, int b)
2426 {
2427 pdf_run_processor *pr = (pdf_run_processor *)proc;
2428 pdf_gstate *gstate = pdf_flush_text(ctx, pr);
2429 gstate->fill.color_params.op = b;
2430 }
2431
2432 static void pdf_run_gs_OPM(fz_context *ctx, pdf_processor *proc, int i)
2433 {
2434 pdf_run_processor *pr = (pdf_run_processor *)proc;
2435 pdf_gstate *gstate = pdf_flush_text(ctx, pr);
2436 gstate->stroke.color_params.opm = i;
2437 gstate->fill.color_params.opm = i;
2438 }
2439
2440 static void pdf_run_gs_UseBlackPtComp(fz_context *ctx, pdf_processor *proc, pdf_obj *obj)
2441 {
2442 pdf_run_processor *pr = (pdf_run_processor *)proc;
2443 pdf_gstate *gstate = pdf_flush_text(ctx, pr);
2444 int on = pdf_name_eq(ctx, obj, PDF_NAME(ON));
2445 /* The spec says that "ON" means on, "OFF" means "Off", and
2446 * "Default" or anything else means "Meh, do what you want." */
2447 gstate->stroke.color_params.bp = on;
2448 gstate->fill.color_params.bp = on;
2449 }
2450
2451 static void pdf_run_i(fz_context *ctx, pdf_processor *proc, float flatness)
2452 {
2453 }
2454
2455 static void pdf_run_gs_begin(fz_context *ctx, pdf_processor *proc, const char *name, pdf_obj *extgstate)
2456 {
2457 }
2458
2459 static void pdf_run_gs_end(fz_context *ctx, pdf_processor *proc)
2460 {
2461 }
2462
2463 /* transparency graphics state */
2464
2465 static void pdf_run_gs_BM(fz_context *ctx, pdf_processor *proc, const char *blendmode)
2466 {
2467 pdf_run_processor *pr = (pdf_run_processor *)proc;
2468 pdf_gstate *gstate = pdf_flush_text(ctx, pr);
2469 gstate->blendmode = fz_lookup_blendmode(blendmode);
2470 }
2471
2472 static void pdf_run_gs_CA(fz_context *ctx, pdf_processor *proc, float alpha)
2473 {
2474 pdf_run_processor *pr = (pdf_run_processor *)proc;
2475 pdf_gstate *gstate = pdf_flush_text(ctx, pr);
2476 gstate->stroke.alpha = fz_clamp(alpha, 0, 1);
2477 }
2478
2479 static void pdf_run_gs_ca(fz_context *ctx, pdf_processor *proc, float alpha)
2480 {
2481 pdf_run_processor *pr = (pdf_run_processor *)proc;
2482 pdf_gstate *gstate = pdf_flush_text(ctx, pr);
2483 gstate->fill.alpha = fz_clamp(alpha, 0, 1);
2484 }
2485
2486 static void pdf_run_gs_SMask(fz_context *ctx, pdf_processor *proc, pdf_obj *smask, fz_colorspace *smask_cs, float *bc, int luminosity, pdf_obj *tr)
2487 {
2488 pdf_run_processor *pr = (pdf_run_processor *)proc;
2489 pdf_gstate *gstate = pdf_flush_text(ctx, pr);
2490 int i;
2491
2492 if (gstate->softmask)
2493 {
2494 pdf_drop_obj(ctx, gstate->softmask);
2495 gstate->softmask = NULL;
2496 fz_drop_colorspace(ctx, gstate->softmask_cs);
2497 gstate->softmask_cs = NULL;
2498 pdf_drop_obj(ctx, gstate->softmask_resources);
2499 gstate->softmask_resources = NULL;
2500 }
2501
2502 if (smask)
2503 {
2504 int cs_n = fz_colorspace_n(ctx, smask_cs);
2505 gstate->softmask_ctm = gstate->ctm;
2506 gstate->softmask = pdf_keep_obj(ctx, smask);
2507 gstate->softmask_cs = fz_keep_colorspace(ctx, smask_cs);
2508 gstate->softmask_resources = pdf_keep_obj(ctx, pr->rstack->resources);
2509 pdf_drop_obj(ctx, gstate->softmask_tr);
2510 gstate->softmask_tr = NULL;
2511 if (tr)
2512 gstate->softmask_tr = pdf_keep_obj(ctx, tr);
2513 for (i = 0; i < cs_n; ++i)
2514 gstate->softmask_bc[i] = bc[i];
2515 gstate->luminosity = luminosity;
2516 }
2517 }
2518
2519 /* special graphics state */
2520
2521 static void pdf_run_q(fz_context *ctx, pdf_processor *proc)
2522 {
2523 pdf_run_processor *pr = (pdf_run_processor *)proc;
2524 flush_begin_layer(ctx, pr);
2525 pdf_gsave(ctx, pr);
2526 }
2527
2528 static void pdf_run_Q(fz_context *ctx, pdf_processor *proc)
2529 {
2530 pdf_run_processor *pr = (pdf_run_processor *)proc;
2531 pdf_flush_text(ctx, pr);
2532 pdf_grestore(ctx, pr);
2533 }
2534
2535 static void pdf_run_cm(fz_context *ctx, pdf_processor *proc, float a, float b, float c, float d, float e, float f)
2536 {
2537 pdf_run_processor *pr = (pdf_run_processor *)proc;
2538 pdf_gstate *gstate = pdf_flush_text(ctx, pr);
2539 fz_matrix m;
2540
2541 m.a = a;
2542 m.b = b;
2543 m.c = c;
2544 m.d = d;
2545 m.e = e;
2546 m.f = f;
2547 gstate->ctm = fz_concat(m, gstate->ctm);
2548 }
2549
2550 /* path construction */
2551
2552 static void pdf_run_m(fz_context *ctx, pdf_processor *proc, float x, float y)
2553 {
2554 pdf_run_processor *pr = (pdf_run_processor *)proc;
2555 fz_moveto(ctx, pr->path, x, y);
2556 }
2557
2558 static void pdf_run_l(fz_context *ctx, pdf_processor *proc, float x, float y)
2559 {
2560 pdf_run_processor *pr = (pdf_run_processor *)proc;
2561 fz_lineto(ctx, pr->path, x, y);
2562 }
2563 static void pdf_run_c(fz_context *ctx, pdf_processor *proc, float x1, float y1, float x2, float y2, float x3, float y3)
2564 {
2565 pdf_run_processor *pr = (pdf_run_processor *)proc;
2566 fz_curveto(ctx, pr->path, x1, y1, x2, y2, x3, y3);
2567 }
2568
2569 static void pdf_run_v(fz_context *ctx, pdf_processor *proc, float x2, float y2, float x3, float y3)
2570 {
2571 pdf_run_processor *pr = (pdf_run_processor *)proc;
2572 fz_curvetov(ctx, pr->path, x2, y2, x3, y3);
2573 }
2574
2575 static void pdf_run_y(fz_context *ctx, pdf_processor *proc, float x1, float y1, float x3, float y3)
2576 {
2577 pdf_run_processor *pr = (pdf_run_processor *)proc;
2578 fz_curvetoy(ctx, pr->path, x1, y1, x3, y3);
2579 }
2580
2581 static void pdf_run_h(fz_context *ctx, pdf_processor *proc)
2582 {
2583 pdf_run_processor *pr = (pdf_run_processor *)proc;
2584 fz_closepath(ctx, pr->path);
2585 }
2586
2587 static void pdf_run_re(fz_context *ctx, pdf_processor *proc, float x, float y, float w, float h)
2588 {
2589 pdf_run_processor *pr = (pdf_run_processor *)proc;
2590 fz_rectto(ctx, pr->path, x, y, x+w, y+h);
2591 }
2592
2593 /* path painting */
2594
2595 static void pdf_run_S(fz_context *ctx, pdf_processor *proc)
2596 {
2597 pdf_run_processor *pr = (pdf_run_processor *)proc;
2598 pdf_show_path(ctx, pr, 0, 0, 1, 0);
2599 }
2600
2601 static void pdf_run_s(fz_context *ctx, pdf_processor *proc)
2602 {
2603 pdf_run_processor *pr = (pdf_run_processor *)proc;
2604 pdf_show_path(ctx, pr, 1, 0, 1, 0);
2605 }
2606
2607 static void pdf_run_F(fz_context *ctx, pdf_processor *proc)
2608 {
2609 pdf_run_processor *pr = (pdf_run_processor *)proc;
2610 pdf_show_path(ctx, pr, 0, 1, 0, 0);
2611 }
2612
2613 static void pdf_run_f(fz_context *ctx, pdf_processor *proc)
2614 {
2615 pdf_run_processor *pr = (pdf_run_processor *)proc;
2616 pdf_show_path(ctx, pr, 0, 1, 0, 0);
2617 }
2618
2619 static void pdf_run_fstar(fz_context *ctx, pdf_processor *proc)
2620 {
2621 pdf_run_processor *pr = (pdf_run_processor *)proc;
2622 pdf_show_path(ctx, pr, 0, 1, 0, 1);
2623 }
2624
2625 static void pdf_run_B(fz_context *ctx, pdf_processor *proc)
2626 {
2627 pdf_run_processor *pr = (pdf_run_processor *)proc;
2628 pdf_show_path(ctx, pr, 0, 1, 1, 0);
2629 }
2630
2631 static void pdf_run_Bstar(fz_context *ctx, pdf_processor *proc)
2632 {
2633 pdf_run_processor *pr = (pdf_run_processor *)proc;
2634 pdf_show_path(ctx, pr, 0, 1, 1, 1);
2635 }
2636
2637 static void pdf_run_b(fz_context *ctx, pdf_processor *proc)
2638 {
2639 pdf_run_processor *pr = (pdf_run_processor *)proc;
2640 pdf_show_path(ctx, pr, 1, 1, 1, 0);
2641 }
2642
2643 static void pdf_run_bstar(fz_context *ctx, pdf_processor *proc)
2644 {
2645 pdf_run_processor *pr = (pdf_run_processor *)proc;
2646 pdf_show_path(ctx, pr, 1, 1, 1, 1);
2647 }
2648
2649 static void pdf_run_n(fz_context *ctx, pdf_processor *proc)
2650 {
2651 pdf_run_processor *pr = (pdf_run_processor *)proc;
2652 pdf_show_path(ctx, pr, 0, 0, 0, 0);
2653 }
2654
2655 /* clipping paths */
2656
2657 static void pdf_run_W(fz_context *ctx, pdf_processor *proc)
2658 {
2659 pdf_run_processor *pr = (pdf_run_processor *)proc;
2660 pdf_flush_text(ctx, pr);
2661 pr->clip = 1;
2662 pr->clip_even_odd = 0;
2663 }
2664
2665 static void pdf_run_Wstar(fz_context *ctx, pdf_processor *proc)
2666 {
2667 pdf_run_processor *pr = (pdf_run_processor *)proc;
2668 pdf_flush_text(ctx, pr);
2669 pr->clip = 1;
2670 pr->clip_even_odd = 1;
2671 }
2672
2673 /* text objects */
2674
2675 static void pdf_run_BT(fz_context *ctx, pdf_processor *proc)
2676 {
2677 pdf_run_processor *pr = (pdf_run_processor *)proc;
2678 pr->tos.tm = fz_identity;
2679 pr->tos.tlm = fz_identity;
2680 pr->bidi = 0;
2681 }
2682
2683 static void pdf_run_ET(fz_context *ctx, pdf_processor *proc)
2684 {
2685 pdf_run_processor *pr = (pdf_run_processor *)proc;
2686 pdf_flush_text(ctx, pr);
2687 }
2688
2689 /* text state */
2690
2691 static void pdf_run_Tc(fz_context *ctx, pdf_processor *proc, float charspace)
2692 {
2693 pdf_run_processor *pr = (pdf_run_processor *)proc;
2694 pdf_gstate *gstate = pr->gstate + pr->gtop;
2695 gstate->text.char_space = charspace;
2696 }
2697
2698 static void pdf_run_Tw(fz_context *ctx, pdf_processor *proc, float wordspace)
2699 {
2700 pdf_run_processor *pr = (pdf_run_processor *)proc;
2701 pdf_gstate *gstate = pr->gstate + pr->gtop;
2702 gstate->text.word_space = wordspace;
2703 }
2704
2705 static void pdf_run_Tz(fz_context *ctx, pdf_processor *proc, float scale)
2706 {
2707 /* scale is as written in the file. It is 100 times smaller in
2708 * the gstate. */
2709 pdf_run_processor *pr = (pdf_run_processor *)proc;
2710 pdf_gstate *gstate = pr->gstate + pr->gtop;
2711 gstate->text.scale = scale / 100;
2712 }
2713
2714 static void pdf_run_TL(fz_context *ctx, pdf_processor *proc, float leading)
2715 {
2716 pdf_run_processor *pr = (pdf_run_processor *)proc;
2717 pdf_gstate *gstate = pr->gstate + pr->gtop;
2718 gstate->text.leading = leading;
2719 }
2720
2721 static void pdf_run_Tf(fz_context *ctx, pdf_processor *proc, const char *name, pdf_font_desc *font, float size)
2722 {
2723 pdf_run_processor *pr = (pdf_run_processor *)proc;
2724 pdf_gstate *gstate = pr->gstate + pr->gtop;
2725 pdf_drop_font(ctx, gstate->text.font);
2726 gstate->text.font = pdf_keep_font(ctx, font);
2727 gstate->text.size = size;
2728 }
2729
2730 static void pdf_run_Tr(fz_context *ctx, pdf_processor *proc, int render)
2731 {
2732 pdf_run_processor *pr = (pdf_run_processor *)proc;
2733 pdf_gstate *gstate = pr->gstate + pr->gtop;
2734 gstate->text.render = render;
2735 }
2736
2737 static void pdf_run_Ts(fz_context *ctx, pdf_processor *proc, float rise)
2738 {
2739 pdf_run_processor *pr = (pdf_run_processor *)proc;
2740 pdf_gstate *gstate = pr->gstate + pr->gtop;
2741 gstate->text.rise = rise;
2742 }
2743
2744 /* text positioning */
2745
2746 static void pdf_run_Td(fz_context *ctx, pdf_processor *proc, float tx, float ty)
2747 {
2748 pdf_run_processor *pr = (pdf_run_processor *)proc;
2749 pdf_tos_translate(&pr->tos, tx, ty);
2750 }
2751
2752 static void pdf_run_TD(fz_context *ctx, pdf_processor *proc, float tx, float ty)
2753 {
2754 pdf_run_processor *pr = (pdf_run_processor *)proc;
2755 pdf_gstate *gstate = pr->gstate + pr->gtop;
2756 gstate->text.leading = -ty;
2757 pdf_tos_translate(&pr->tos, tx, ty);
2758 }
2759
2760 static void pdf_run_Tm(fz_context *ctx, pdf_processor *proc, float a, float b, float c, float d, float e, float f)
2761 {
2762 pdf_run_processor *pr = (pdf_run_processor *)proc;
2763 pdf_tos_set_matrix(&pr->tos, a, b, c, d, e, f);
2764 }
2765
2766 static void pdf_run_Tstar(fz_context *ctx, pdf_processor *proc)
2767 {
2768 pdf_run_processor *pr = (pdf_run_processor *)proc;
2769 pdf_gstate *gstate = pr->gstate + pr->gtop;
2770 pdf_tos_newline(&pr->tos, gstate->text.leading);
2771 }
2772
2773 /* text showing */
2774
2775 static void pdf_run_TJ(fz_context *ctx, pdf_processor *proc, pdf_obj *obj)
2776 {
2777 pdf_run_processor *pr = (pdf_run_processor *)proc;
2778 pdf_show_text(ctx, pr, obj);
2779 }
2780
2781 static void pdf_run_Tj(fz_context *ctx, pdf_processor *proc, char *string, size_t string_len)
2782 {
2783 pdf_run_processor *pr = (pdf_run_processor *)proc;
2784 pdf_show_string(ctx, pr, (unsigned char *)string, string_len);
2785 }
2786
2787 static void pdf_run_squote(fz_context *ctx, pdf_processor *proc, char *string, size_t string_len)
2788 {
2789 pdf_run_processor *pr = (pdf_run_processor *)proc;
2790 pdf_gstate *gstate = pr->gstate + pr->gtop;
2791 pdf_tos_newline(&pr->tos, gstate->text.leading);
2792 pdf_show_string(ctx, pr, (unsigned char*)string, string_len);
2793 }
2794
2795 static void pdf_run_dquote(fz_context *ctx, pdf_processor *proc, float aw, float ac, char *string, size_t string_len)
2796 {
2797 pdf_run_processor *pr = (pdf_run_processor *)proc;
2798 pdf_gstate *gstate = pr->gstate + pr->gtop;
2799 gstate->text.word_space = aw;
2800 gstate->text.char_space = ac;
2801 pdf_tos_newline(&pr->tos, gstate->text.leading);
2802 pdf_show_string(ctx, pr, (unsigned char*)string, string_len);
2803 }
2804
2805 /* type 3 fonts */
2806
2807 static void pdf_run_d0(fz_context *ctx, pdf_processor *proc, float wx, float wy)
2808 {
2809 pdf_run_processor *pr = (pdf_run_processor *)proc;
2810 pr->dev->flags |= FZ_DEVFLAG_COLOR;
2811 }
2812
2813 static void pdf_run_d1(fz_context *ctx, pdf_processor *proc, float wx, float wy, float llx, float lly, float urx, float ury)
2814 {
2815 pdf_run_processor *pr = (pdf_run_processor *)proc;
2816 pr->dev->flags |= FZ_DEVFLAG_MASK | FZ_DEVFLAG_BBOX_DEFINED;
2817 pr->dev->d1_rect.x0 = fz_min(llx, urx);
2818 pr->dev->d1_rect.y0 = fz_min(lly, ury);
2819 pr->dev->d1_rect.x1 = fz_max(llx, urx);
2820 pr->dev->d1_rect.y1 = fz_max(lly, ury);
2821 }
2822
2823 /* color */
2824
2825 static void pdf_run_CS(fz_context *ctx, pdf_processor *proc, const char *name, fz_colorspace *colorspace)
2826 {
2827 pdf_run_processor *pr = (pdf_run_processor *)proc;
2828 pr->dev->flags &= ~FZ_DEVFLAG_STROKECOLOR_UNDEFINED;
2829 if (pr->dev->flags & FZ_DEVFLAG_MASK)
2830 return;
2831 if (!strcmp(name, "Pattern"))
2832 pdf_set_pattern(ctx, pr, PDF_STROKE, NULL, NULL);
2833 else
2834 pdf_set_colorspace(ctx, pr, PDF_STROKE, colorspace);
2835 }
2836
2837 static void pdf_run_cs(fz_context *ctx, pdf_processor *proc, const char *name, fz_colorspace *colorspace)
2838 {
2839 pdf_run_processor *pr = (pdf_run_processor *)proc;
2840 pr->dev->flags &= ~FZ_DEVFLAG_FILLCOLOR_UNDEFINED;
2841 if (pr->dev->flags & FZ_DEVFLAG_MASK)
2842 return;
2843 if (!strcmp(name, "Pattern"))
2844 pdf_set_pattern(ctx, pr, PDF_FILL, NULL, NULL);
2845 else
2846 pdf_set_colorspace(ctx, pr, PDF_FILL, colorspace);
2847 }
2848
2849 static void pdf_run_SC_color(fz_context *ctx, pdf_processor *proc, int n, float *color)
2850 {
2851 pdf_run_processor *pr = (pdf_run_processor *)proc;
2852 pr->dev->flags &= ~FZ_DEVFLAG_STROKECOLOR_UNDEFINED;
2853 if (pr->dev->flags & FZ_DEVFLAG_MASK)
2854 return;
2855 pdf_set_color(ctx, pr, PDF_STROKE, color);
2856 }
2857
2858 static void pdf_run_sc_color(fz_context *ctx, pdf_processor *proc, int n, float *color)
2859 {
2860 pdf_run_processor *pr = (pdf_run_processor *)proc;
2861 pr->dev->flags &= ~FZ_DEVFLAG_FILLCOLOR_UNDEFINED;
2862 if (pr->dev->flags & FZ_DEVFLAG_MASK)
2863 return;
2864 pdf_set_color(ctx, pr, PDF_FILL, color);
2865 }
2866
2867 static void pdf_run_SC_pattern(fz_context *ctx, pdf_processor *proc, const char *name, pdf_pattern *pat, int n, float *color)
2868 {
2869 pdf_run_processor *pr = (pdf_run_processor *)proc;
2870 pr->dev->flags &= ~FZ_DEVFLAG_STROKECOLOR_UNDEFINED;
2871 if (pr->dev->flags & FZ_DEVFLAG_MASK)
2872 return;
2873 pdf_set_pattern(ctx, pr, PDF_STROKE, pat, color);
2874 }
2875
2876 static void pdf_run_sc_pattern(fz_context *ctx, pdf_processor *proc, const char *name, pdf_pattern *pat, int n, float *color)
2877 {
2878 pdf_run_processor *pr = (pdf_run_processor *)proc;
2879 pr->dev->flags &= ~FZ_DEVFLAG_FILLCOLOR_UNDEFINED;
2880 if (pr->dev->flags & FZ_DEVFLAG_MASK)
2881 return;
2882 pdf_set_pattern(ctx, pr, PDF_FILL, pat, color);
2883 }
2884
2885 static void pdf_run_SC_shade(fz_context *ctx, pdf_processor *proc, const char *name, fz_shade *shade)
2886 {
2887 pdf_run_processor *pr = (pdf_run_processor *)proc;
2888 pr->dev->flags &= ~FZ_DEVFLAG_STROKECOLOR_UNDEFINED;
2889 if (pr->dev->flags & FZ_DEVFLAG_MASK)
2890 return;
2891 pdf_set_shade(ctx, pr, PDF_STROKE, shade);
2892 }
2893
2894 static void pdf_run_sc_shade(fz_context *ctx, pdf_processor *proc, const char *name, fz_shade *shade)
2895 {
2896 pdf_run_processor *pr = (pdf_run_processor *)proc;
2897 pr->dev->flags &= ~FZ_DEVFLAG_FILLCOLOR_UNDEFINED;
2898 if (pr->dev->flags & FZ_DEVFLAG_MASK)
2899 return;
2900 pdf_set_shade(ctx, pr, PDF_FILL, shade);
2901 }
2902
2903 static void pdf_run_G(fz_context *ctx, pdf_processor *proc, float g)
2904 {
2905 pdf_run_processor *pr = (pdf_run_processor *)proc;
2906 pr->dev->flags &= ~FZ_DEVFLAG_STROKECOLOR_UNDEFINED;
2907 if (pr->dev->flags & FZ_DEVFLAG_MASK)
2908 return;
2909 pdf_set_colorspace(ctx, pr, PDF_STROKE, fz_device_gray(ctx));
2910 pdf_set_color(ctx, pr, PDF_STROKE, &g);
2911 }
2912
2913 static void pdf_run_g(fz_context *ctx, pdf_processor *proc, float g)
2914 {
2915 pdf_run_processor *pr = (pdf_run_processor *)proc;
2916 pr->dev->flags &= ~FZ_DEVFLAG_FILLCOLOR_UNDEFINED;
2917 if (pr->dev->flags & FZ_DEVFLAG_MASK)
2918 return;
2919 pdf_set_colorspace(ctx, pr, PDF_FILL, fz_device_gray(ctx));
2920 pdf_set_color(ctx, pr, PDF_FILL, &g);
2921 }
2922
2923 static void pdf_run_K(fz_context *ctx, pdf_processor *proc, float c, float m, float y, float k)
2924 {
2925 pdf_run_processor *pr = (pdf_run_processor *)proc;
2926 float color[4] = {c, m, y, k};
2927 pr->dev->flags &= ~FZ_DEVFLAG_STROKECOLOR_UNDEFINED;
2928 if (pr->dev->flags & FZ_DEVFLAG_MASK)
2929 return;
2930 pdf_set_colorspace(ctx, pr, PDF_STROKE, fz_device_cmyk(ctx));
2931 pdf_set_color(ctx, pr, PDF_STROKE, color);
2932 }
2933
2934 static void pdf_run_k(fz_context *ctx, pdf_processor *proc, float c, float m, float y, float k)
2935 {
2936 pdf_run_processor *pr = (pdf_run_processor *)proc;
2937 float color[4] = {c, m, y, k};
2938 pr->dev->flags &= ~FZ_DEVFLAG_FILLCOLOR_UNDEFINED;
2939 if (pr->dev->flags & FZ_DEVFLAG_MASK)
2940 return;
2941 pdf_set_colorspace(ctx, pr, PDF_FILL, fz_device_cmyk(ctx));
2942 pdf_set_color(ctx, pr, PDF_FILL, color);
2943 }
2944
2945 static void pdf_run_RG(fz_context *ctx, pdf_processor *proc, float r, float g, float b)
2946 {
2947 pdf_run_processor *pr = (pdf_run_processor *)proc;
2948 float color[3] = {r, g, b};
2949 pr->dev->flags &= ~FZ_DEVFLAG_STROKECOLOR_UNDEFINED;
2950 if (pr->dev->flags & FZ_DEVFLAG_MASK)
2951 return;
2952 pdf_set_colorspace(ctx, pr, PDF_STROKE, fz_device_rgb(ctx));
2953 pdf_set_color(ctx, pr, PDF_STROKE, color);
2954 }
2955
2956 static void pdf_run_rg(fz_context *ctx, pdf_processor *proc, float r, float g, float b)
2957 {
2958 pdf_run_processor *pr = (pdf_run_processor *)proc;
2959 float color[3] = {r, g, b};
2960 pr->dev->flags &= ~FZ_DEVFLAG_FILLCOLOR_UNDEFINED;
2961 if (pr->dev->flags & FZ_DEVFLAG_MASK)
2962 return;
2963 pdf_set_colorspace(ctx, pr, PDF_FILL, fz_device_rgb(ctx));
2964 pdf_set_color(ctx, pr, PDF_FILL, color);
2965 }
2966
2967 /* shadings, images, xobjects */
2968
2969 static void pdf_run_BI(fz_context *ctx, pdf_processor *proc, fz_image *image, const char *colorspace)
2970 {
2971 pdf_run_processor *pr = (pdf_run_processor *)proc;
2972 pdf_show_image(ctx, pr, image);
2973 }
2974
2975 static void pdf_run_sh(fz_context *ctx, pdf_processor *proc, const char *name, fz_shade *shade)
2976 {
2977 pdf_run_processor *pr = (pdf_run_processor *)proc;
2978
2979 pop_any_pending_mcid_changes(ctx, pr);
2980 flush_begin_layer(ctx, pr);
2981 pdf_show_shade(ctx, pr, shade);
2982 }
2983
2984 static void pdf_run_Do_image(fz_context *ctx, pdf_processor *proc, const char *name, fz_image *image)
2985 {
2986 pdf_run_processor *pr = (pdf_run_processor *)proc;
2987 pdf_show_image(ctx, pr, image);
2988 }
2989
2990 static void pdf_run_Do_form(fz_context *ctx, pdf_processor *proc, const char *name, pdf_obj *xobj)
2991 {
2992 pdf_run_processor *pr = (pdf_run_processor *)proc;
2993 pdf_run_xobject(ctx, (pdf_run_processor*)proc, xobj, pr->rstack->resources, fz_identity, 0);
2994 }
2995
2996 /* marked content */
2997
2998 static void pdf_run_BMC(fz_context *ctx, pdf_processor *proc, const char *tag)
2999 {
3000 pdf_run_processor *pr = (pdf_run_processor *)proc;
3001 push_marked_content(ctx, pr, tag, NULL);
3002 }
3003
3004 static void pdf_run_BDC(fz_context *ctx, pdf_processor *proc, const char *tag, pdf_obj *raw, pdf_obj *cooked)
3005 {
3006 pdf_run_processor *pr = (pdf_run_processor *)proc;
3007 push_marked_content(ctx, pr, tag, cooked);
3008 }
3009
3010 static void pdf_run_EMC(fz_context *ctx, pdf_processor *proc)
3011 {
3012 pdf_run_processor *pr = (pdf_run_processor *)proc;
3013
3014 pop_marked_content(ctx, pr, 1);
3015 }
3016
3017 static void pdf_run_MP(fz_context *ctx, pdf_processor *proc, const char *tag)
3018 {
3019 pdf_run_BMC(ctx, proc, tag);
3020 pdf_run_EMC(ctx, proc);
3021 }
3022
3023 static void pdf_run_DP(fz_context *ctx, pdf_processor *proc, const char *tag, pdf_obj *raw, pdf_obj *cooked)
3024 {
3025 pdf_run_BDC(ctx, proc, tag, raw, cooked);
3026 pdf_run_EMC(ctx, proc);
3027 }
3028
3029 /* compatibility */
3030
3031 static void pdf_run_BX(fz_context *ctx, pdf_processor *proc)
3032 {
3033 }
3034
3035 static void pdf_run_EX(fz_context *ctx, pdf_processor *proc)
3036 {
3037 }
3038
3039 static void pdf_run_END(fz_context *ctx, pdf_processor *proc)
3040 {
3041 pdf_run_processor *pr = (pdf_run_processor *)proc;
3042 pdf_flush_text(ctx, pr);
3043 }
3044
3045 static void
3046 pdf_close_run_processor(fz_context *ctx, pdf_processor *proc)
3047 {
3048 pdf_run_processor *pr = (pdf_run_processor *)proc;
3049
3050 while (pr->gtop)
3051 pdf_grestore(ctx, pr);
3052
3053 while (pr->nest_depth > 0)
3054 {
3055 if (pr->nest_mark[pr->nest_depth-1] < 0)
3056 {
3057 /* It's a clip. */
3058 fz_pop_clip(ctx, pr->dev);
3059 pr->nest_mark[pr->nest_depth-1]++;
3060 if (pr->nest_mark[pr->nest_depth-1] == 0)
3061 pr->nest_depth--;
3062 }
3063 else
3064 {
3065 /* It's a layer. */
3066 fz_end_layer(ctx, pr->dev);
3067 pr->nest_depth--;
3068 }
3069 }
3070
3071 pop_structure_to(ctx, pr, NULL);
3072
3073 clear_marked_content(ctx, pr);
3074 }
3075
3076 static void
3077 pdf_drop_run_processor(fz_context *ctx, pdf_processor *proc)
3078 {
3079 pdf_run_processor *pr = (pdf_run_processor *)proc;
3080
3081 while (pr->gtop >= 0)
3082 {
3083 pdf_drop_gstate(ctx, &pr->gstate[pr->gtop]);
3084 pr->gtop--;
3085 }
3086
3087 fz_drop_path(ctx, pr->path);
3088 fz_drop_text(ctx, pr->tos.text);
3089
3090 fz_drop_default_colorspaces(ctx, pr->default_cs);
3091
3092 fz_free(ctx, pr->gstate);
3093
3094 while (pr->rstack)
3095 {
3096 resources_stack *stk = pr->rstack;
3097 pr->rstack = stk->next;
3098 pdf_drop_obj(ctx, stk->resources);
3099 fz_free(ctx, stk);
3100 }
3101
3102 while (pr->begin_layer)
3103 {
3104 begin_layer_stack *stk = pr->begin_layer;
3105 pr->begin_layer = stk->next;
3106 fz_free(ctx, stk->layer);
3107 fz_free(ctx, stk);
3108 }
3109
3110 while (pr->marked_content)
3111 pop_marked_content(ctx, pr, 0);
3112
3113 pdf_drop_obj(ctx, pr->mcid_sent);
3114
3115 pdf_drop_document(ctx, pr->doc);
3116 pdf_drop_obj(ctx, pr->role_map);
3117 }
3118
3119 static void
3120 pdf_run_push_resources(fz_context *ctx, pdf_processor *proc, pdf_obj *resources)
3121 {
3122 pdf_run_processor *pr = (pdf_run_processor *)proc;
3123 resources_stack *stk = fz_malloc_struct(ctx, resources_stack);
3124
3125 stk->next = pr->rstack;
3126 pr->rstack = stk;
3127 stk->resources = pdf_keep_obj(ctx, resources);
3128 }
3129
3130 static pdf_obj *
3131 pdf_run_pop_resources(fz_context *ctx, pdf_processor *proc)
3132 {
3133 pdf_run_processor *pr = (pdf_run_processor *)proc;
3134 resources_stack *stk = pr->rstack;
3135
3136 if (stk)
3137 {
3138 pr->rstack = stk->next;
3139 pdf_drop_obj(ctx, stk->resources);
3140 fz_free(ctx, stk);
3141 }
3142
3143 return NULL;
3144 }
3145
3146 /*
3147 Create a new "run" processor. This maps
3148 from PDF operators to fz_device level calls.
3149
3150 dev: The device to which the resulting device calls are to be
3151 sent.
3152
3153 ctm: The initial transformation matrix to use.
3154
3155 usage: A NULL terminated string that describes the 'usage' of
3156 this interpretation. Typically 'View', though 'Print' is also
3157 defined within the PDF reference manual, and others are possible.
3158
3159 gstate: The initial graphics state.
3160 */
3161 pdf_processor *
3162 pdf_new_run_processor(fz_context *ctx, pdf_document *doc, fz_device *dev, fz_matrix ctm, int struct_parent, const char *usage, pdf_gstate *gstate, fz_default_colorspaces *default_cs, fz_cookie *cookie, pdf_gstate *fill_gstate, pdf_gstate *stroke_gstate)
3163 {
3164 pdf_run_processor *proc = pdf_new_processor(ctx, sizeof *proc);
3165 {
3166 proc->super.usage = usage;
3167
3168 proc->super.close_processor = pdf_close_run_processor;
3169 proc->super.drop_processor = pdf_drop_run_processor;
3170
3171 proc->super.push_resources = pdf_run_push_resources;
3172 proc->super.pop_resources = pdf_run_pop_resources;
3173
3174 /* general graphics state */
3175 proc->super.op_w = pdf_run_w;
3176 proc->super.op_j = pdf_run_j;
3177 proc->super.op_J = pdf_run_J;
3178 proc->super.op_M = pdf_run_M;
3179 proc->super.op_d = pdf_run_d;
3180 proc->super.op_ri = pdf_run_ri;
3181 proc->super.op_i = pdf_run_i;
3182 proc->super.op_gs_begin = pdf_run_gs_begin;
3183 proc->super.op_gs_end = pdf_run_gs_end;
3184
3185 /* transparency graphics state */
3186 proc->super.op_gs_BM = pdf_run_gs_BM;
3187 proc->super.op_gs_CA = pdf_run_gs_CA;
3188 proc->super.op_gs_ca = pdf_run_gs_ca;
3189 proc->super.op_gs_SMask = pdf_run_gs_SMask;
3190
3191 /* special graphics state */
3192 proc->super.op_q = pdf_run_q;
3193 proc->super.op_Q = pdf_run_Q;
3194 proc->super.op_cm = pdf_run_cm;
3195
3196 /* path construction */
3197 proc->super.op_m = pdf_run_m;
3198 proc->super.op_l = pdf_run_l;
3199 proc->super.op_c = pdf_run_c;
3200 proc->super.op_v = pdf_run_v;
3201 proc->super.op_y = pdf_run_y;
3202 proc->super.op_h = pdf_run_h;
3203 proc->super.op_re = pdf_run_re;
3204
3205 /* path painting */
3206 proc->super.op_S = pdf_run_S;
3207 proc->super.op_s = pdf_run_s;
3208 proc->super.op_F = pdf_run_F;
3209 proc->super.op_f = pdf_run_f;
3210 proc->super.op_fstar = pdf_run_fstar;
3211 proc->super.op_B = pdf_run_B;
3212 proc->super.op_Bstar = pdf_run_Bstar;
3213 proc->super.op_b = pdf_run_b;
3214 proc->super.op_bstar = pdf_run_bstar;
3215 proc->super.op_n = pdf_run_n;
3216
3217 /* clipping paths */
3218 proc->super.op_W = pdf_run_W;
3219 proc->super.op_Wstar = pdf_run_Wstar;
3220
3221 /* text objects */
3222 proc->super.op_BT = pdf_run_BT;
3223 proc->super.op_ET = pdf_run_ET;
3224
3225 /* text state */
3226 proc->super.op_Tc = pdf_run_Tc;
3227 proc->super.op_Tw = pdf_run_Tw;
3228 proc->super.op_Tz = pdf_run_Tz;
3229 proc->super.op_TL = pdf_run_TL;
3230 proc->super.op_Tf = pdf_run_Tf;
3231 proc->super.op_Tr = pdf_run_Tr;
3232 proc->super.op_Ts = pdf_run_Ts;
3233
3234 /* text positioning */
3235 proc->super.op_Td = pdf_run_Td;
3236 proc->super.op_TD = pdf_run_TD;
3237 proc->super.op_Tm = pdf_run_Tm;
3238 proc->super.op_Tstar = pdf_run_Tstar;
3239
3240 /* text showing */
3241 proc->super.op_TJ = pdf_run_TJ;
3242 proc->super.op_Tj = pdf_run_Tj;
3243 proc->super.op_squote = pdf_run_squote;
3244 proc->super.op_dquote = pdf_run_dquote;
3245
3246 /* type 3 fonts */
3247 proc->super.op_d0 = pdf_run_d0;
3248 proc->super.op_d1 = pdf_run_d1;
3249
3250 /* color */
3251 proc->super.op_CS = pdf_run_CS;
3252 proc->super.op_cs = pdf_run_cs;
3253 proc->super.op_SC_color = pdf_run_SC_color;
3254 proc->super.op_sc_color = pdf_run_sc_color;
3255 proc->super.op_SC_pattern = pdf_run_SC_pattern;
3256 proc->super.op_sc_pattern = pdf_run_sc_pattern;
3257 proc->super.op_SC_shade = pdf_run_SC_shade;
3258 proc->super.op_sc_shade = pdf_run_sc_shade;
3259
3260 proc->super.op_G = pdf_run_G;
3261 proc->super.op_g = pdf_run_g;
3262 proc->super.op_RG = pdf_run_RG;
3263 proc->super.op_rg = pdf_run_rg;
3264 proc->super.op_K = pdf_run_K;
3265 proc->super.op_k = pdf_run_k;
3266
3267 /* shadings, images, xobjects */
3268 proc->super.op_sh = pdf_run_sh;
3269 if (dev->fill_image || dev->fill_image_mask || dev->clip_image_mask)
3270 {
3271 proc->super.op_BI = pdf_run_BI;
3272 proc->super.op_Do_image = pdf_run_Do_image;
3273 }
3274 proc->super.op_Do_form = pdf_run_Do_form;
3275
3276 /* marked content */
3277 proc->super.op_MP = pdf_run_MP;
3278 proc->super.op_DP = pdf_run_DP;
3279 proc->super.op_BMC = pdf_run_BMC;
3280 proc->super.op_BDC = pdf_run_BDC;
3281 proc->super.op_EMC = pdf_run_EMC;
3282
3283 /* compatibility */
3284 proc->super.op_BX = pdf_run_BX;
3285 proc->super.op_EX = pdf_run_EX;
3286
3287 /* extgstate */
3288 proc->super.op_gs_OP = pdf_run_gs_OP;
3289 proc->super.op_gs_op = pdf_run_gs_op;
3290 proc->super.op_gs_OPM = pdf_run_gs_OPM;
3291 proc->super.op_gs_UseBlackPtComp = pdf_run_gs_UseBlackPtComp;
3292
3293 proc->super.op_END = pdf_run_END;
3294 }
3295
3296 proc->super.requirements = 0;
3297 if ((dev->hints & FZ_DONT_DECODE_IMAGES) == 0)
3298 proc->super.requirements |= PDF_PROCESSOR_REQUIRES_DECODED_IMAGES;
3299
3300 proc->doc = pdf_keep_document(ctx, doc);
3301 proc->dev = dev;
3302 proc->cookie = cookie;
3303
3304 proc->default_cs = fz_keep_default_colorspaces(ctx, default_cs);
3305
3306 proc->path = NULL;
3307 proc->clip = 0;
3308 proc->clip_even_odd = 0;
3309
3310 proc->tos.text = NULL;
3311 proc->tos.tlm = fz_identity;
3312 proc->tos.tm = fz_identity;
3313 proc->tos.text_mode = 0;
3314
3315 proc->gtop = -1;
3316
3317 proc->marked_content = NULL;
3318
3319 proc->next_begin_layer = &proc->begin_layer;
3320
3321 fz_try(ctx)
3322 {
3323 proc->path = fz_new_path(ctx);
3324
3325 proc->gcap = 64;
3326 proc->gstate = fz_malloc_struct_array(ctx, proc->gcap, pdf_gstate);
3327
3328 proc->gtop = 0;
3329 pdf_init_gstate(ctx, &proc->gstate[0], ctm);
3330
3331 if (fill_gstate)
3332 {
3333 pdf_copy_gstate(ctx, &proc->gstate[0], fill_gstate);
3334 proc->gstate[0].clip_depth = 0;
3335 proc->gtop++;
3336 }
3337 if (stroke_gstate)
3338 {
3339 pdf_copy_gstate(ctx, &proc->gstate[proc->gtop], stroke_gstate);
3340 proc->gstate[proc->gtop].clip_depth = 0;
3341 proc->gtop++;
3342 }
3343 if (gstate)
3344 {
3345 pdf_copy_gstate(ctx, &proc->gstate[proc->gtop], gstate);
3346 proc->gstate[proc->gtop].clip_depth = 0;
3347 proc->gstate[proc->gtop].ctm = ctm;
3348 }
3349 proc->gparent = proc->gtop;
3350 if (fill_gstate)
3351 proc->gstate[proc->gtop].fill.gstate_num = 0;
3352 if (stroke_gstate)
3353 proc->gstate[proc->gtop].fill.gstate_num = (fill_gstate != NULL);
3354
3355 /* We need to save an extra level to allow for the parent gstate level. */
3356 pdf_gsave(ctx, proc);
3357
3358 /* Structure details */
3359 {
3360 pdf_obj *struct_tree_root = pdf_dict_getl(ctx, pdf_trailer(ctx, doc), PDF_NAME(Root), PDF_NAME(StructTreeRoot), NULL);
3361 proc->struct_parent = struct_parent;
3362 proc->role_map = pdf_keep_obj(ctx, pdf_dict_get(ctx, struct_tree_root, PDF_NAME(RoleMap)));
3363
3364 /* Annotations and XObjects can be their own content items. We spot this by
3365 * the struct_parent looking up to be a singular object. */
3366 if (struct_parent != -1 && struct_tree_root)
3367 {
3368 pdf_obj *struct_obj = pdf_lookup_number(ctx, pdf_dict_get(ctx, struct_tree_root, PDF_NAME(ParentTree)), struct_parent);
3369 if (pdf_is_dict(ctx, struct_obj))
3370 send_begin_structure(ctx, proc, struct_obj);
3371 /* We always end structure as required on closedown, so this is safe. */
3372 }
3373 }
3374 }
3375 fz_catch(ctx)
3376 {
3377 pdf_drop_run_processor(ctx, (pdf_processor *) proc);
3378 fz_free(ctx, proc);
3379 fz_rethrow(ctx);
3380 }
3381
3382 return (pdf_processor*)proc;
3383 }