Coverage Report

Created: 2025-12-31 07:06

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