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