Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
7639 views
1
#include "mupdf/pdf.h"
2
3
typedef struct filter_gstate_s filter_gstate;
4
5
typedef enum
6
{
7
FLUSH_CTM = 1,
8
FLUSH_COLOR_F = 2,
9
FLUSH_COLOR_S = 4,
10
11
FLUSH_ALL = 7,
12
FLUSH_STROKE = 1+4,
13
FLUSH_FILL = 1+2
14
} gstate_flush_flags;
15
16
struct filter_gstate_s
17
{
18
filter_gstate *next;
19
int pushed;
20
fz_matrix ctm;
21
fz_matrix current_ctm;
22
struct
23
{
24
char name[256];
25
fz_colorspace *cs;
26
} cs, CS, current_cs, current_CS;
27
struct
28
{
29
char name[256];
30
pdf_pattern *pat;
31
fz_shade *shd;
32
int n;
33
float c[FZ_MAX_COLORS];
34
} sc, SC, current_sc, current_SC;
35
struct
36
{
37
fz_linecap linecap;
38
fz_linejoin linejoin;
39
float linewidth;
40
float miterlimit;
41
} stroke, current_stroke;
42
};
43
44
typedef struct pdf_filter_processor_s
45
{
46
pdf_processor super;
47
pdf_processor *chain;
48
filter_gstate *gstate;
49
pdf_document *doc;
50
pdf_obj *old_rdb, *new_rdb;
51
} pdf_filter_processor;
52
53
static void
54
copy_resource(fz_context *ctx, pdf_filter_processor *p, pdf_obj *key, const char *name)
55
{
56
pdf_obj *res, *obj;
57
58
if (!name || name[0] == 0)
59
return;
60
61
res = pdf_dict_get(ctx, p->old_rdb, key);
62
obj = pdf_dict_gets(ctx, res, name);
63
if (obj)
64
{
65
res = pdf_dict_get(ctx, p->new_rdb, key);
66
if (!res)
67
{
68
res = pdf_new_dict(ctx, p->doc, 1);
69
pdf_dict_put_drop(ctx, p->new_rdb, key, res);
70
}
71
pdf_dict_putp(ctx, res, name, obj);
72
}
73
}
74
75
static void
76
filter_push(fz_context *ctx, pdf_filter_processor *p)
77
{
78
filter_gstate *gstate = p->gstate;
79
filter_gstate *new_gstate = fz_malloc_struct(ctx, filter_gstate);
80
*new_gstate = *gstate;
81
new_gstate->pushed = 0;
82
new_gstate->next = gstate;
83
p->gstate = new_gstate;
84
}
85
86
static int
87
filter_pop(fz_context *ctx, pdf_filter_processor *p)
88
{
89
filter_gstate *gstate = p->gstate;
90
filter_gstate *old = gstate->next;
91
92
/* We are at the top, so nothing to pop! */
93
if (old == NULL)
94
return 1;
95
96
if (gstate->pushed)
97
if (p->chain->op_Q)
98
p->chain->op_Q(ctx, p->chain);
99
100
fz_free(ctx, gstate);
101
p->gstate = old;
102
return 0;
103
}
104
105
/* We never allow the topmost gstate to be changed. This allows us
106
* to pop back to the zeroth level and be sure that our gstate is
107
* sane. This is important for being able to add new operators at
108
* the end of pages in a sane way. */
109
static filter_gstate *
110
gstate_to_update(fz_context *ctx, pdf_filter_processor *p)
111
{
112
filter_gstate *gstate = p->gstate;
113
114
/* If we're not the top, that's fine */
115
if (gstate->next != NULL)
116
return gstate;
117
118
/* We are the top. Push a group, so we're not */
119
filter_push(ctx, p);
120
gstate = p->gstate;
121
gstate->pushed = 1;
122
if (p->chain->op_q)
123
p->chain->op_q(ctx, p->chain);
124
125
return p->gstate;
126
}
127
128
static void filter_flush(fz_context *ctx, pdf_filter_processor *p, int flush)
129
{
130
filter_gstate *gstate = gstate_to_update(ctx, p);
131
int i;
132
133
if (gstate->pushed == 0)
134
{
135
gstate->pushed = 1;
136
if (p->chain->op_q)
137
p->chain->op_q(ctx, p->chain);
138
}
139
140
if (flush & FLUSH_CTM)
141
{
142
if (gstate->ctm.a != 1 || gstate->ctm.b != 0 ||
143
gstate->ctm.c != 0 || gstate->ctm.d != 1 ||
144
gstate->ctm.e != 0 || gstate->ctm.f != 0)
145
{
146
fz_matrix current = gstate->current_ctm;
147
148
if (p->chain->op_cm)
149
p->chain->op_cm(ctx, p->chain,
150
gstate->ctm.a,
151
gstate->ctm.b,
152
gstate->ctm.c,
153
gstate->ctm.d,
154
gstate->ctm.e,
155
gstate->ctm.f);
156
157
fz_concat(&gstate->current_ctm, &current, &gstate->ctm);
158
gstate->ctm.a = 1;
159
gstate->ctm.b = 0;
160
gstate->ctm.c = 0;
161
gstate->ctm.d = 1;
162
gstate->ctm.e = 0;
163
gstate->ctm.f = 0;
164
}
165
}
166
167
if (flush & FLUSH_COLOR_F)
168
{
169
if (gstate->cs.cs == fz_device_gray(ctx) && !gstate->sc.pat && !gstate->sc.shd && gstate->sc.n == 1)
170
{
171
if (p->chain->op_g)
172
p->chain->op_g(ctx, p->chain, gstate->sc.c[0]);
173
goto done_sc;
174
}
175
if (gstate->cs.cs == fz_device_rgb(ctx) && !gstate->sc.pat && !gstate->sc.shd && gstate->sc.n == 3)
176
{
177
if (p->chain->op_rg)
178
p->chain->op_rg(ctx, p->chain, gstate->sc.c[0], gstate->sc.c[1], gstate->sc.c[2]);
179
goto done_sc;
180
}
181
if (gstate->cs.cs == fz_device_cmyk(ctx) && !gstate->sc.pat && !gstate->sc.shd && gstate->sc.n == 4)
182
{
183
if (p->chain->op_k)
184
p->chain->op_k(ctx, p->chain, gstate->sc.c[0], gstate->sc.c[1], gstate->sc.c[2], gstate->sc.c[3]);
185
goto done_sc;
186
}
187
188
if (strcmp(gstate->cs.name, gstate->current_cs.name))
189
{
190
if (p->chain->op_cs)
191
p->chain->op_cs(ctx, p->chain, gstate->cs.name, gstate->cs.cs);
192
}
193
194
/* pattern or shading */
195
if (gstate->sc.name[0])
196
{
197
int emit = 0;
198
if (strcmp(gstate->sc.name, gstate->current_sc.name))
199
emit = 1;
200
if (gstate->sc.n != gstate->current_sc.n)
201
emit = 1;
202
else
203
for (i = 0; i < gstate->sc.n; ++i)
204
if (gstate->sc.c[i] != gstate->current_sc.c[i])
205
emit = 1;
206
if (emit)
207
{
208
if (gstate->sc.pat)
209
if (p->chain->op_sc_pattern)
210
p->chain->op_sc_pattern(ctx, p->chain, gstate->sc.name, gstate->sc.pat, gstate->sc.n, gstate->sc.c);
211
if (gstate->sc.shd)
212
if (p->chain->op_sc_shade)
213
p->chain->op_sc_shade(ctx, p->chain, gstate->sc.name, gstate->sc.shd);
214
}
215
}
216
217
/* plain color */
218
else
219
{
220
int emit = 0;
221
if (gstate->sc.n != gstate->current_sc.n)
222
emit = 1;
223
else
224
for (i = 0; i < gstate->sc.n; ++i)
225
if (gstate->sc.c[i] != gstate->current_sc.c[i])
226
emit = 1;
227
if (emit)
228
{
229
if (p->chain->op_sc_color)
230
p->chain->op_sc_color(ctx, p->chain, gstate->sc.n, gstate->sc.c);
231
}
232
}
233
234
done_sc:
235
gstate->current_cs = gstate->cs;
236
gstate->current_sc = gstate->sc;
237
}
238
239
if (flush & FLUSH_COLOR_S)
240
{
241
if (gstate->CS.cs == fz_device_gray(ctx) && !gstate->SC.pat && !gstate->SC.shd && gstate->SC.n == 1)
242
{
243
if (p->chain->op_G)
244
p->chain->op_G(ctx, p->chain, gstate->SC.c[0]);
245
goto done_SC;
246
}
247
if (gstate->CS.cs == fz_device_rgb(ctx) && !gstate->SC.pat && !gstate->SC.shd && gstate->SC.n == 3)
248
{
249
if (p->chain->op_RG)
250
p->chain->op_RG(ctx, p->chain, gstate->SC.c[0], gstate->SC.c[1], gstate->SC.c[2]);
251
goto done_SC;
252
}
253
if (gstate->CS.cs == fz_device_cmyk(ctx) && !gstate->SC.pat && !gstate->SC.shd && gstate->SC.n == 4)
254
{
255
if (p->chain->op_K)
256
p->chain->op_K(ctx, p->chain, gstate->SC.c[0], gstate->SC.c[1], gstate->SC.c[2], gstate->SC.c[3]);
257
goto done_SC;
258
}
259
260
if (strcmp(gstate->CS.name, gstate->current_CS.name))
261
{
262
if (p->chain->op_CS)
263
p->chain->op_CS(ctx, p->chain, gstate->CS.name, gstate->CS.cs);
264
}
265
266
/* pattern or shading */
267
if (gstate->SC.name[0])
268
{
269
int emit = 0;
270
if (strcmp(gstate->SC.name, gstate->current_SC.name))
271
emit = 1;
272
if (gstate->SC.n != gstate->current_SC.n)
273
emit = 1;
274
else
275
for (i = 0; i < gstate->SC.n; ++i)
276
if (gstate->SC.c[i] != gstate->current_SC.c[i])
277
emit = 1;
278
if (emit)
279
{
280
if (gstate->SC.pat)
281
if (p->chain->op_SC_pattern)
282
p->chain->op_SC_pattern(ctx, p->chain, gstate->SC.name, gstate->SC.pat, gstate->SC.n, gstate->SC.c);
283
if (gstate->SC.shd)
284
if (p->chain->op_SC_shade)
285
p->chain->op_SC_shade(ctx, p->chain, gstate->SC.name, gstate->SC.shd);
286
}
287
}
288
289
/* plain color */
290
else
291
{
292
int emit = 0;
293
if (gstate->SC.n != gstate->current_SC.n)
294
emit = 1;
295
else
296
for (i = 0; i < gstate->SC.n; ++i)
297
if (gstate->SC.c[i] != gstate->current_SC.c[i])
298
emit = 1;
299
if (emit)
300
{
301
if (p->chain->op_SC_color)
302
p->chain->op_SC_color(ctx, p->chain, gstate->SC.n, gstate->SC.c);
303
}
304
}
305
306
done_SC:
307
gstate->current_CS = gstate->CS;
308
gstate->current_SC = gstate->SC;
309
}
310
311
if (flush & FLUSH_STROKE)
312
{
313
if (gstate->stroke.linecap != gstate->current_stroke.linecap)
314
{
315
if (p->chain->op_J)
316
p->chain->op_J(ctx, p->chain, gstate->stroke.linecap);
317
}
318
if (gstate->stroke.linejoin != gstate->current_stroke.linejoin)
319
{
320
if (p->chain->op_j)
321
p->chain->op_j(ctx, p->chain, gstate->stroke.linejoin);
322
}
323
if (gstate->stroke.linewidth != gstate->current_stroke.linewidth)
324
{
325
if (p->chain->op_w)
326
p->chain->op_w(ctx, p->chain, gstate->stroke.linewidth);
327
}
328
if (gstate->stroke.miterlimit != gstate->current_stroke.miterlimit)
329
{
330
if (p->chain->op_M)
331
p->chain->op_M(ctx, p->chain, gstate->stroke.linewidth);
332
}
333
gstate->current_stroke = gstate->stroke;
334
}
335
}
336
337
/* general graphics state */
338
339
static void
340
pdf_filter_w(fz_context *ctx, pdf_processor *proc, float linewidth)
341
{
342
pdf_filter_processor *p = (pdf_filter_processor*)proc;
343
filter_gstate *gstate = gstate_to_update(ctx, p);
344
gstate->stroke.linewidth = linewidth;
345
}
346
347
static void
348
pdf_filter_j(fz_context *ctx, pdf_processor *proc, int linejoin)
349
{
350
pdf_filter_processor *p = (pdf_filter_processor*)proc;
351
filter_gstate *gstate = gstate_to_update(ctx, p);
352
gstate->stroke.linejoin = linejoin;
353
}
354
355
static void
356
pdf_filter_J(fz_context *ctx, pdf_processor *proc, int linecap)
357
{
358
pdf_filter_processor *p = (pdf_filter_processor*)proc;
359
filter_gstate *gstate = gstate_to_update(ctx, p);
360
gstate->stroke.linecap = linecap;
361
}
362
363
static void
364
pdf_filter_M(fz_context *ctx, pdf_processor *proc, float miterlimit)
365
{
366
pdf_filter_processor *p = (pdf_filter_processor*)proc;
367
filter_gstate *gstate = gstate_to_update(ctx, p);
368
gstate->stroke.miterlimit = miterlimit;
369
}
370
371
static void
372
pdf_filter_d(fz_context *ctx, pdf_processor *proc, pdf_obj *array, float phase)
373
{
374
pdf_filter_processor *p = (pdf_filter_processor*)proc;
375
filter_flush(ctx, p, 0);
376
if (p->chain->op_d)
377
p->chain->op_d(ctx, p->chain, array, phase);
378
}
379
380
static void
381
pdf_filter_ri(fz_context *ctx, pdf_processor *proc, const char *intent)
382
{
383
pdf_filter_processor *p = (pdf_filter_processor*)proc;
384
filter_flush(ctx, p, 0);
385
if (p->chain->op_ri)
386
p->chain->op_ri(ctx, p->chain, intent);
387
}
388
389
static void
390
pdf_filter_i(fz_context *ctx, pdf_processor *proc, float flatness)
391
{
392
pdf_filter_processor *p = (pdf_filter_processor*)proc;
393
filter_flush(ctx, p, 0);
394
if (p->chain->op_i)
395
p->chain->op_i(ctx, p->chain, flatness);
396
}
397
398
static void
399
pdf_filter_gs_begin(fz_context *ctx, pdf_processor *proc, const char *name, pdf_obj *extgstate)
400
{
401
pdf_filter_processor *p = (pdf_filter_processor*)proc;
402
filter_flush(ctx, p, FLUSH_ALL);
403
if (p->chain->op_gs_begin)
404
p->chain->op_gs_begin(ctx, p->chain, name, extgstate);
405
copy_resource(ctx, p, PDF_NAME_ExtGState, name);
406
}
407
408
static void
409
pdf_filter_gs_BM(fz_context *ctx, pdf_processor *proc, const char *blendmode)
410
{
411
pdf_filter_processor *p = (pdf_filter_processor*)proc;
412
if (p->chain->op_gs_BM)
413
p->chain->op_gs_BM(ctx, p->chain, blendmode);
414
}
415
416
static void
417
pdf_filter_gs_CA(fz_context *ctx, pdf_processor *proc, float alpha)
418
{
419
pdf_filter_processor *p = (pdf_filter_processor*)proc;
420
if (p->chain->op_gs_CA)
421
p->chain->op_gs_CA(ctx, p->chain, alpha);
422
}
423
424
static void
425
pdf_filter_gs_ca(fz_context *ctx, pdf_processor *proc, float alpha)
426
{
427
pdf_filter_processor *p = (pdf_filter_processor*)proc;
428
if (p->chain->op_gs_ca)
429
p->chain->op_gs_ca(ctx, p->chain, alpha);
430
}
431
432
static void
433
pdf_filter_gs_SMask(fz_context *ctx, pdf_processor *proc, pdf_xobject *smask, pdf_obj *page_resources, float *bc, int luminosity)
434
{
435
pdf_filter_processor *p = (pdf_filter_processor*)proc;
436
if (p->chain->op_gs_SMask)
437
p->chain->op_gs_SMask(ctx, p->chain, smask, page_resources, bc, luminosity);
438
}
439
440
static void
441
pdf_filter_gs_end(fz_context *ctx, pdf_processor *proc)
442
{
443
pdf_filter_processor *p = (pdf_filter_processor*)proc;
444
if (p->chain->op_gs_end)
445
p->chain->op_gs_end(ctx, p->chain);
446
}
447
448
/* special graphics state */
449
450
static void
451
pdf_filter_q(fz_context *ctx, pdf_processor *proc)
452
{
453
pdf_filter_processor *p = (pdf_filter_processor*)proc;
454
filter_push(ctx, p);
455
}
456
457
static void
458
pdf_filter_Q(fz_context *ctx, pdf_processor *proc)
459
{
460
pdf_filter_processor *p = (pdf_filter_processor*)proc;
461
filter_pop(ctx, p);
462
}
463
464
static void
465
pdf_filter_cm(fz_context *ctx, pdf_processor *proc, float a, float b, float c, float d, float e, float f)
466
{
467
pdf_filter_processor *p = (pdf_filter_processor*)proc;
468
filter_gstate *gstate = gstate_to_update(ctx, p);
469
fz_matrix old, ctm;
470
471
/* If we're being given an identity matrix, don't bother sending it */
472
if (a == 1 && b == 0 && c == 0 && d == 1 && e == 0 && f == 0)
473
return;
474
475
ctm.a = a;
476
ctm.b = b;
477
ctm.c = c;
478
ctm.d = d;
479
ctm.e = e;
480
ctm.f = f;
481
482
old = gstate->ctm;
483
fz_concat(&gstate->ctm, &ctm, &old);
484
}
485
486
/* path construction */
487
488
static void
489
pdf_filter_m(fz_context *ctx, pdf_processor *proc, float x, float y)
490
{
491
pdf_filter_processor *p = (pdf_filter_processor*)proc;
492
filter_flush(ctx, p, FLUSH_CTM);
493
if (p->chain->op_m)
494
p->chain->op_m(ctx, p->chain, x, y);
495
}
496
497
static void
498
pdf_filter_l(fz_context *ctx, pdf_processor *proc, float x, float y)
499
{
500
pdf_filter_processor *p = (pdf_filter_processor*)proc;
501
filter_flush(ctx, p, FLUSH_CTM);
502
if (p->chain->op_l)
503
p->chain->op_l(ctx, p->chain, x, y);
504
}
505
506
static void
507
pdf_filter_c(fz_context *ctx, pdf_processor *proc, float x1, float y1, float x2, float y2, float x3, float y3)
508
{
509
pdf_filter_processor *p = (pdf_filter_processor*)proc;
510
filter_flush(ctx, p, FLUSH_CTM);
511
if (p->chain->op_c)
512
p->chain->op_c(ctx, p->chain, x1, y1, x2, y2, x3, y3);
513
}
514
515
static void
516
pdf_filter_v(fz_context *ctx, pdf_processor *proc, float x2, float y2, float x3, float y3)
517
{
518
pdf_filter_processor *p = (pdf_filter_processor*)proc;
519
filter_flush(ctx, p, FLUSH_CTM);
520
if (p->chain->op_v)
521
p->chain->op_v(ctx, p->chain, x2, y2, x3, y3);
522
}
523
524
static void
525
pdf_filter_y(fz_context *ctx, pdf_processor *proc, float x1, float y1, float x3, float y3)
526
{
527
pdf_filter_processor *p = (pdf_filter_processor*)proc;
528
filter_flush(ctx, p, FLUSH_CTM);
529
if (p->chain->op_y)
530
p->chain->op_y(ctx, p->chain, x1, y1, x3, y3);
531
}
532
533
static void
534
pdf_filter_h(fz_context *ctx, pdf_processor *proc)
535
{
536
pdf_filter_processor *p = (pdf_filter_processor*)proc;
537
filter_flush(ctx, p, FLUSH_CTM);
538
if (p->chain->op_h)
539
p->chain->op_h(ctx, p->chain);
540
}
541
542
static void
543
pdf_filter_re(fz_context *ctx, pdf_processor *proc, float x, float y, float w, float h)
544
{
545
pdf_filter_processor *p = (pdf_filter_processor*)proc;
546
filter_flush(ctx, p, FLUSH_CTM);
547
if (p->chain->op_re)
548
p->chain->op_re(ctx, p->chain, x, y, w, h);
549
}
550
551
/* path painting */
552
553
static void
554
pdf_filter_S(fz_context *ctx, pdf_processor *proc)
555
{
556
pdf_filter_processor *p = (pdf_filter_processor*)proc;
557
filter_flush(ctx, p, FLUSH_STROKE);
558
if (p->chain->op_S)
559
p->chain->op_S(ctx, p->chain);
560
}
561
562
static void
563
pdf_filter_s(fz_context *ctx, pdf_processor *proc)
564
{
565
pdf_filter_processor *p = (pdf_filter_processor*)proc;
566
filter_flush(ctx, p, FLUSH_STROKE);
567
if (p->chain->op_s)
568
p->chain->op_s(ctx, p->chain);
569
}
570
571
static void
572
pdf_filter_F(fz_context *ctx, pdf_processor *proc)
573
{
574
pdf_filter_processor *p = (pdf_filter_processor*)proc;
575
filter_flush(ctx, p, FLUSH_FILL);
576
if (p->chain->op_F)
577
p->chain->op_F(ctx, p->chain);
578
}
579
580
static void
581
pdf_filter_f(fz_context *ctx, pdf_processor *proc)
582
{
583
pdf_filter_processor *p = (pdf_filter_processor*)proc;
584
filter_flush(ctx, p, FLUSH_FILL);
585
if (p->chain->op_f)
586
p->chain->op_f(ctx, p->chain);
587
}
588
589
static void
590
pdf_filter_fstar(fz_context *ctx, pdf_processor *proc)
591
{
592
pdf_filter_processor *p = (pdf_filter_processor*)proc;
593
filter_flush(ctx, p, FLUSH_FILL);
594
if (p->chain->op_fstar)
595
p->chain->op_fstar(ctx, p->chain);
596
}
597
598
static void
599
pdf_filter_B(fz_context *ctx, pdf_processor *proc)
600
{
601
pdf_filter_processor *p = (pdf_filter_processor*)proc;
602
filter_flush(ctx, p, FLUSH_ALL);
603
if (p->chain->op_B)
604
p->chain->op_B(ctx, p->chain);
605
}
606
607
static void
608
pdf_filter_Bstar(fz_context *ctx, pdf_processor *proc)
609
{
610
pdf_filter_processor *p = (pdf_filter_processor*)proc;
611
filter_flush(ctx, p, FLUSH_ALL);
612
if (p->chain->op_Bstar)
613
p->chain->op_Bstar(ctx, p->chain);
614
}
615
616
static void
617
pdf_filter_b(fz_context *ctx, pdf_processor *proc)
618
{
619
pdf_filter_processor *p = (pdf_filter_processor*)proc;
620
filter_flush(ctx, p, FLUSH_ALL);
621
if (p->chain->op_b)
622
p->chain->op_b(ctx, p->chain);
623
}
624
625
static void
626
pdf_filter_bstar(fz_context *ctx, pdf_processor *proc)
627
{
628
pdf_filter_processor *p = (pdf_filter_processor*)proc;
629
filter_flush(ctx, p, FLUSH_ALL);
630
if (p->chain->op_bstar)
631
p->chain->op_bstar(ctx, p->chain);
632
}
633
634
static void
635
pdf_filter_n(fz_context *ctx, pdf_processor *proc)
636
{
637
pdf_filter_processor *p = (pdf_filter_processor*)proc;
638
filter_flush(ctx, p, FLUSH_CTM);
639
if (p->chain->op_n)
640
p->chain->op_n(ctx, p->chain);
641
}
642
643
/* clipping paths */
644
645
static void
646
pdf_filter_W(fz_context *ctx, pdf_processor *proc)
647
{
648
pdf_filter_processor *p = (pdf_filter_processor*)proc;
649
filter_flush(ctx, p, FLUSH_CTM);
650
if (p->chain->op_W)
651
p->chain->op_W(ctx, p->chain);
652
}
653
654
static void
655
pdf_filter_Wstar(fz_context *ctx, pdf_processor *proc)
656
{
657
pdf_filter_processor *p = (pdf_filter_processor*)proc;
658
filter_flush(ctx, p, FLUSH_CTM);
659
if (p->chain->op_Wstar)
660
p->chain->op_Wstar(ctx, p->chain);
661
}
662
663
/* text objects */
664
665
static void
666
pdf_filter_BT(fz_context *ctx, pdf_processor *proc)
667
{
668
pdf_filter_processor *p = (pdf_filter_processor*)proc;
669
filter_flush(ctx, p, 0);
670
if (p->chain->op_BT)
671
p->chain->op_BT(ctx, p->chain);
672
}
673
674
static void
675
pdf_filter_ET(fz_context *ctx, pdf_processor *proc)
676
{
677
pdf_filter_processor *p = (pdf_filter_processor*)proc;
678
filter_flush(ctx, p, 0);
679
if (p->chain->op_ET)
680
p->chain->op_ET(ctx, p->chain);
681
}
682
683
/* text state */
684
685
static void
686
pdf_filter_Tc(fz_context *ctx, pdf_processor *proc, float charspace)
687
{
688
pdf_filter_processor *p = (pdf_filter_processor*)proc;
689
filter_flush(ctx, p, 0);
690
if (p->chain->op_Tc)
691
p->chain->op_Tc(ctx, p->chain, charspace);
692
}
693
694
static void
695
pdf_filter_Tw(fz_context *ctx, pdf_processor *proc, float wordspace)
696
{
697
pdf_filter_processor *p = (pdf_filter_processor*)proc;
698
filter_flush(ctx, p, 0);
699
if (p->chain->op_Tw)
700
p->chain->op_Tw(ctx, p->chain, wordspace);
701
}
702
703
static void
704
pdf_filter_Tz(fz_context *ctx, pdf_processor *proc, float scale)
705
{
706
pdf_filter_processor *p = (pdf_filter_processor*)proc;
707
filter_flush(ctx, p, 0);
708
if (p->chain->op_Tz)
709
p->chain->op_Tz(ctx, p->chain, scale);
710
}
711
712
static void
713
pdf_filter_TL(fz_context *ctx, pdf_processor *proc, float leading)
714
{
715
pdf_filter_processor *p = (pdf_filter_processor*)proc;
716
filter_flush(ctx, p, 0);
717
if (p->chain->op_TL)
718
p->chain->op_TL(ctx, p->chain, leading);
719
}
720
721
static void
722
pdf_filter_Tf(fz_context *ctx, pdf_processor *proc, const char *name, pdf_font_desc *font, float size)
723
{
724
pdf_filter_processor *p = (pdf_filter_processor*)proc;
725
filter_flush(ctx, p, 0);
726
if (p->chain->op_Tf)
727
p->chain->op_Tf(ctx, p->chain, name, font, size);
728
copy_resource(ctx, p, PDF_NAME_Font, name);
729
}
730
731
static void
732
pdf_filter_Tr(fz_context *ctx, pdf_processor *proc, int render)
733
{
734
pdf_filter_processor *p = (pdf_filter_processor*)proc;
735
filter_flush(ctx, p, 0);
736
if (p->chain->op_Tr)
737
p->chain->op_Tr(ctx, p->chain, render);
738
}
739
740
static void
741
pdf_filter_Ts(fz_context *ctx, pdf_processor *proc, float rise)
742
{
743
pdf_filter_processor *p = (pdf_filter_processor*)proc;
744
filter_flush(ctx, p, 0);
745
if (p->chain->op_Ts)
746
p->chain->op_Ts(ctx, p->chain, rise);
747
}
748
749
/* text positioning */
750
751
static void
752
pdf_filter_Td(fz_context *ctx, pdf_processor *proc, float tx, float ty)
753
{
754
pdf_filter_processor *p = (pdf_filter_processor*)proc;
755
filter_flush(ctx, p, FLUSH_CTM);
756
if (p->chain->op_Td)
757
p->chain->op_Td(ctx, p->chain, tx, ty);
758
}
759
760
static void
761
pdf_filter_TD(fz_context *ctx, pdf_processor *proc, float tx, float ty)
762
{
763
pdf_filter_processor *p = (pdf_filter_processor*)proc;
764
filter_flush(ctx, p, FLUSH_CTM);
765
if (p->chain->op_TD)
766
p->chain->op_TD(ctx, p->chain, tx, ty);
767
}
768
769
static void
770
pdf_filter_Tm(fz_context *ctx, pdf_processor *proc, float a, float b, float c, float d, float e, float f)
771
{
772
pdf_filter_processor *p = (pdf_filter_processor*)proc;
773
filter_flush(ctx, p, FLUSH_CTM);
774
if (p->chain->op_Tm)
775
p->chain->op_Tm(ctx, p->chain, a, b, c, d, e, f);
776
}
777
778
static void
779
pdf_filter_Tstar(fz_context *ctx, pdf_processor *proc)
780
{
781
pdf_filter_processor *p = (pdf_filter_processor*)proc;
782
filter_flush(ctx, p, FLUSH_CTM);
783
if (p->chain->op_Tstar)
784
p->chain->op_Tstar(ctx, p->chain);
785
}
786
787
/* text showing */
788
789
static void
790
pdf_filter_TJ(fz_context *ctx, pdf_processor *proc, pdf_obj *array)
791
{
792
pdf_filter_processor *p = (pdf_filter_processor*)proc;
793
filter_flush(ctx, p, FLUSH_ALL);
794
if (p->chain->op_TJ)
795
p->chain->op_TJ(ctx, p->chain, array);
796
}
797
798
static void
799
pdf_filter_Tj(fz_context *ctx, pdf_processor *proc, char *str, int len)
800
{
801
pdf_filter_processor *p = (pdf_filter_processor*)proc;
802
filter_flush(ctx, p, FLUSH_ALL);
803
if (p->chain->op_Tj)
804
p->chain->op_Tj(ctx, p->chain, str, len);
805
}
806
807
static void
808
pdf_filter_squote(fz_context *ctx, pdf_processor *proc, char *str, int len)
809
{
810
pdf_filter_processor *p = (pdf_filter_processor*)proc;
811
filter_flush(ctx, p, FLUSH_ALL);
812
if (p->chain->op_squote)
813
p->chain->op_squote(ctx, p->chain, str, len);
814
}
815
816
static void
817
pdf_filter_dquote(fz_context *ctx, pdf_processor *proc, float aw, float ac, char *str, int len)
818
{
819
pdf_filter_processor *p = (pdf_filter_processor*)proc;
820
filter_flush(ctx, p, FLUSH_ALL);
821
if (p->chain->op_dquote)
822
p->chain->op_dquote(ctx, p->chain, aw, ac, str, len);
823
}
824
825
/* type 3 fonts */
826
827
static void
828
pdf_filter_d0(fz_context *ctx, pdf_processor *proc, float wx, float wy)
829
{
830
pdf_filter_processor *p = (pdf_filter_processor*)proc;
831
filter_flush(ctx, p, 0);
832
if (p->chain->op_d0)
833
p->chain->op_d0(ctx, p->chain, wx, wy);
834
}
835
836
static void
837
pdf_filter_d1(fz_context *ctx, pdf_processor *proc, float wx, float wy, float llx, float lly, float urx, float ury)
838
{
839
pdf_filter_processor *p = (pdf_filter_processor*)proc;
840
filter_flush(ctx, p, 0);
841
if (p->chain->op_d1)
842
p->chain->op_d1(ctx, p->chain, wx, wy, llx, lly, urx, ury);
843
}
844
845
/* color */
846
847
static void
848
pdf_filter_CS(fz_context *ctx, pdf_processor *proc, const char *name, fz_colorspace *cs)
849
{
850
pdf_filter_processor *p = (pdf_filter_processor*)proc;
851
filter_gstate *gstate = gstate_to_update(ctx, p);
852
fz_strlcpy(gstate->CS.name, name, sizeof gstate->CS.name);
853
gstate->CS.cs = cs;
854
copy_resource(ctx, p, PDF_NAME_ColorSpace, name);
855
}
856
857
static void
858
pdf_filter_cs(fz_context *ctx, pdf_processor *proc, const char *name, fz_colorspace *cs)
859
{
860
pdf_filter_processor *p = (pdf_filter_processor*)proc;
861
filter_gstate *gstate = gstate_to_update(ctx, p);
862
fz_strlcpy(gstate->cs.name, name, sizeof gstate->cs.name);
863
gstate->cs.cs = cs;
864
copy_resource(ctx, p, PDF_NAME_ColorSpace, name);
865
}
866
867
static void
868
pdf_filter_SC_pattern(fz_context *ctx, pdf_processor *proc, const char *name, pdf_pattern *pat, int n, float *color)
869
{
870
pdf_filter_processor *p = (pdf_filter_processor*)proc;
871
filter_gstate *gstate = gstate_to_update(ctx, p);
872
int i;
873
fz_strlcpy(gstate->SC.name, name, sizeof gstate->SC.name);
874
gstate->SC.pat = pat;
875
gstate->SC.shd = NULL;
876
gstate->SC.n = n;
877
for (i = 0; i < n; ++i)
878
gstate->SC.c[i] = color[i];
879
copy_resource(ctx, p, PDF_NAME_Pattern, name);
880
}
881
882
static void
883
pdf_filter_sc_pattern(fz_context *ctx, pdf_processor *proc, const char *name, pdf_pattern *pat, int n, float *color)
884
{
885
pdf_filter_processor *p = (pdf_filter_processor*)proc;
886
filter_gstate *gstate = gstate_to_update(ctx, p);
887
int i;
888
fz_strlcpy(gstate->sc.name, name, sizeof gstate->sc.name);
889
gstate->sc.pat = pat;
890
gstate->sc.shd = NULL;
891
gstate->sc.n = n;
892
for (i = 0; i < n; ++i)
893
gstate->sc.c[i] = color[i];
894
copy_resource(ctx, p, PDF_NAME_Pattern, name);
895
}
896
897
static void
898
pdf_filter_SC_shade(fz_context *ctx, pdf_processor *proc, const char *name, fz_shade *shade)
899
{
900
pdf_filter_processor *p = (pdf_filter_processor*)proc;
901
filter_gstate *gstate = gstate_to_update(ctx, p);
902
fz_strlcpy(gstate->SC.name, name, sizeof gstate->SC.name);
903
gstate->SC.pat = NULL;
904
gstate->SC.shd = shade;
905
gstate->SC.n = 0;
906
copy_resource(ctx, p, PDF_NAME_Pattern, name);
907
}
908
909
static void
910
pdf_filter_sc_shade(fz_context *ctx, pdf_processor *proc, const char *name, fz_shade *shade)
911
{
912
pdf_filter_processor *p = (pdf_filter_processor*)proc;
913
filter_gstate *gstate = gstate_to_update(ctx, p);
914
fz_strlcpy(gstate->sc.name, name, sizeof gstate->sc.name);
915
gstate->sc.pat = NULL;
916
gstate->sc.shd = shade;
917
gstate->sc.n = 0;
918
copy_resource(ctx, p, PDF_NAME_Pattern, name);
919
}
920
921
static void
922
pdf_filter_SC_color(fz_context *ctx, pdf_processor *proc, int n, float *color)
923
{
924
pdf_filter_processor *p = (pdf_filter_processor*)proc;
925
filter_gstate *gstate = gstate_to_update(ctx, p);
926
int i;
927
gstate->SC.name[0] = 0;
928
gstate->SC.pat = NULL;
929
gstate->SC.shd = NULL;
930
gstate->SC.n = n;
931
for (i = 0; i < n; ++i)
932
gstate->SC.c[i] = color[i];
933
}
934
935
static void
936
pdf_filter_sc_color(fz_context *ctx, pdf_processor *proc, int n, float *color)
937
{
938
pdf_filter_processor *p = (pdf_filter_processor*)proc;
939
filter_gstate *gstate = gstate_to_update(ctx, p);
940
int i;
941
gstate->sc.name[0] = 0;
942
gstate->sc.pat = NULL;
943
gstate->sc.shd = NULL;
944
gstate->sc.n = n;
945
for (i = 0; i < n; ++i)
946
gstate->sc.c[i] = color[i];
947
}
948
949
static void
950
pdf_filter_G(fz_context *ctx, pdf_processor *proc, float g)
951
{
952
float color[1] = { g };
953
pdf_filter_CS(ctx, proc, "DeviceGray", fz_device_gray(ctx));
954
pdf_filter_SC_color(ctx, proc, 1, color);
955
}
956
957
static void
958
pdf_filter_g(fz_context *ctx, pdf_processor *proc, float g)
959
{
960
float color[1] = { g };
961
pdf_filter_cs(ctx, proc, "DeviceGray", fz_device_gray(ctx));
962
pdf_filter_sc_color(ctx, proc, 1, color);
963
}
964
965
static void
966
pdf_filter_RG(fz_context *ctx, pdf_processor *proc, float r, float g, float b)
967
{
968
float color[3] = { r, g, b };
969
pdf_filter_CS(ctx, proc, "DeviceRGB", fz_device_rgb(ctx));
970
pdf_filter_SC_color(ctx, proc, 3, color);
971
}
972
973
static void
974
pdf_filter_rg(fz_context *ctx, pdf_processor *proc, float r, float g, float b)
975
{
976
float color[3] = { r, g, b };
977
pdf_filter_cs(ctx, proc, "DeviceRGB", fz_device_rgb(ctx));
978
pdf_filter_sc_color(ctx, proc, 3, color);
979
}
980
981
static void
982
pdf_filter_K(fz_context *ctx, pdf_processor *proc, float c, float m, float y, float k)
983
{
984
float color[4] = { c, m, y, k };
985
pdf_filter_CS(ctx, proc, "DeviceCMYK", fz_device_cmyk(ctx));
986
pdf_filter_SC_color(ctx, proc, 4, color);
987
}
988
989
static void
990
pdf_filter_k(fz_context *ctx, pdf_processor *proc, float c, float m, float y, float k)
991
{
992
float color[4] = { c, m, y, k };
993
pdf_filter_cs(ctx, proc, "DeviceCMYK", fz_device_cmyk(ctx));
994
pdf_filter_sc_color(ctx, proc, 4, color);
995
}
996
997
/* shadings, images, xobjects */
998
999
static void
1000
pdf_filter_BI(fz_context *ctx, pdf_processor *proc, fz_image *img)
1001
{
1002
pdf_filter_processor *p = (pdf_filter_processor*)proc;
1003
filter_flush(ctx, p, FLUSH_ALL);
1004
if (p->chain->op_BI)
1005
p->chain->op_BI(ctx, p->chain, img);
1006
}
1007
1008
static void
1009
pdf_filter_sh(fz_context *ctx, pdf_processor *proc, const char *name, fz_shade *shade)
1010
{
1011
pdf_filter_processor *p = (pdf_filter_processor*)proc;
1012
filter_flush(ctx, p, FLUSH_ALL);
1013
if (p->chain->op_sh)
1014
p->chain->op_sh(ctx, p->chain, name, shade);
1015
copy_resource(ctx, p, PDF_NAME_Shading, name);
1016
}
1017
1018
static void
1019
pdf_filter_Do_image(fz_context *ctx, pdf_processor *proc, const char *name, fz_image *image)
1020
{
1021
pdf_filter_processor *p = (pdf_filter_processor*)proc;
1022
filter_flush(ctx, p, FLUSH_ALL);
1023
if (p->chain->op_Do_image)
1024
p->chain->op_Do_image(ctx, p->chain, name, image);
1025
copy_resource(ctx, p, PDF_NAME_XObject, name);
1026
}
1027
1028
static void
1029
pdf_filter_Do_form(fz_context *ctx, pdf_processor *proc, const char *name, pdf_xobject *xobj, pdf_obj *page_resources)
1030
{
1031
pdf_filter_processor *p = (pdf_filter_processor*)proc;
1032
filter_flush(ctx, p, FLUSH_ALL);
1033
if (p->chain->op_Do_form)
1034
p->chain->op_Do_form(ctx, p->chain, name, xobj, page_resources);
1035
copy_resource(ctx, p, PDF_NAME_XObject, name);
1036
}
1037
1038
/* marked content */
1039
1040
static void
1041
pdf_filter_MP(fz_context *ctx, pdf_processor *proc, const char *tag)
1042
{
1043
pdf_filter_processor *p = (pdf_filter_processor*)proc;
1044
filter_flush(ctx, p, 0);
1045
if (p->chain->op_MP)
1046
p->chain->op_MP(ctx, p->chain, tag);
1047
}
1048
1049
static void
1050
pdf_filter_DP(fz_context *ctx, pdf_processor *proc, const char *tag, pdf_obj *properties)
1051
{
1052
pdf_filter_processor *p = (pdf_filter_processor*)proc;
1053
filter_flush(ctx, p, 0);
1054
if (p->chain->op_DP)
1055
p->chain->op_DP(ctx, p->chain, tag, properties);
1056
}
1057
1058
static void
1059
pdf_filter_BMC(fz_context *ctx, pdf_processor *proc, const char *tag)
1060
{
1061
pdf_filter_processor *p = (pdf_filter_processor*)proc;
1062
filter_flush(ctx, p, 0);
1063
if (p->chain->op_BMC)
1064
p->chain->op_BMC(ctx, p->chain, tag);
1065
}
1066
1067
static void
1068
pdf_filter_BDC(fz_context *ctx, pdf_processor *proc, const char *tag, pdf_obj *properties)
1069
{
1070
pdf_filter_processor *p = (pdf_filter_processor*)proc;
1071
filter_flush(ctx, p, 0);
1072
if (p->chain->op_BDC)
1073
p->chain->op_BDC(ctx, p->chain, tag, properties);
1074
}
1075
1076
static void
1077
pdf_filter_EMC(fz_context *ctx, pdf_processor *proc)
1078
{
1079
pdf_filter_processor *p = (pdf_filter_processor*)proc;
1080
filter_flush(ctx, p, 0);
1081
if (p->chain->op_EMC)
1082
p->chain->op_EMC(ctx, p->chain);
1083
}
1084
1085
/* compatibility */
1086
1087
static void
1088
pdf_filter_BX(fz_context *ctx, pdf_processor *proc)
1089
{
1090
pdf_filter_processor *p = (pdf_filter_processor*)proc;
1091
filter_flush(ctx, p, 0);
1092
if (p->chain->op_BX)
1093
p->chain->op_BX(ctx, p->chain);
1094
}
1095
1096
static void
1097
pdf_filter_EX(fz_context *ctx, pdf_processor *proc)
1098
{
1099
pdf_filter_processor *p = (pdf_filter_processor*)proc;
1100
filter_flush(ctx, p, 0);
1101
if (p->chain->op_EX)
1102
p->chain->op_EX(ctx, p->chain);
1103
}
1104
1105
static void
1106
pdf_filter_END(fz_context *ctx, pdf_processor *proc)
1107
{
1108
pdf_filter_processor *p = (pdf_filter_processor*)proc;
1109
while (!filter_pop(ctx, p))
1110
{
1111
/* Nothing to do in the loop, all work done above */
1112
}
1113
}
1114
1115
static void
1116
pdf_drop_imp_filter_processor(fz_context *ctx, pdf_processor *proc)
1117
{
1118
pdf_filter_processor *p = (pdf_filter_processor*)proc;
1119
fz_free(ctx, p->gstate);
1120
}
1121
1122
pdf_processor *
1123
pdf_new_filter_processor(fz_context *ctx, pdf_processor *chain, pdf_document *doc, pdf_obj *old_rdb, pdf_obj *new_rdb)
1124
{
1125
1126
pdf_filter_processor *proc = pdf_new_processor(ctx, sizeof *proc);
1127
{
1128
proc->super.drop_imp = pdf_drop_imp_filter_processor;
1129
1130
/* general graphics state */
1131
proc->super.op_w = pdf_filter_w;
1132
proc->super.op_j = pdf_filter_j;
1133
proc->super.op_J = pdf_filter_J;
1134
proc->super.op_M = pdf_filter_M;
1135
proc->super.op_d = pdf_filter_d;
1136
proc->super.op_ri = pdf_filter_ri;
1137
proc->super.op_i = pdf_filter_i;
1138
proc->super.op_gs_begin = pdf_filter_gs_begin;
1139
proc->super.op_gs_end = pdf_filter_gs_end;
1140
1141
/* transparency graphics state */
1142
proc->super.op_gs_BM = pdf_filter_gs_BM;
1143
proc->super.op_gs_CA = pdf_filter_gs_CA;
1144
proc->super.op_gs_ca = pdf_filter_gs_ca;
1145
proc->super.op_gs_SMask = pdf_filter_gs_SMask;
1146
1147
/* special graphics state */
1148
proc->super.op_q = pdf_filter_q;
1149
proc->super.op_Q = pdf_filter_Q;
1150
proc->super.op_cm = pdf_filter_cm;
1151
1152
/* path construction */
1153
proc->super.op_m = pdf_filter_m;
1154
proc->super.op_l = pdf_filter_l;
1155
proc->super.op_c = pdf_filter_c;
1156
proc->super.op_v = pdf_filter_v;
1157
proc->super.op_y = pdf_filter_y;
1158
proc->super.op_h = pdf_filter_h;
1159
proc->super.op_re = pdf_filter_re;
1160
1161
/* path painting */
1162
proc->super.op_S = pdf_filter_S;
1163
proc->super.op_s = pdf_filter_s;
1164
proc->super.op_F = pdf_filter_F;
1165
proc->super.op_f = pdf_filter_f;
1166
proc->super.op_fstar = pdf_filter_fstar;
1167
proc->super.op_B = pdf_filter_B;
1168
proc->super.op_Bstar = pdf_filter_Bstar;
1169
proc->super.op_b = pdf_filter_b;
1170
proc->super.op_bstar = pdf_filter_bstar;
1171
proc->super.op_n = pdf_filter_n;
1172
1173
/* clipping paths */
1174
proc->super.op_W = pdf_filter_W;
1175
proc->super.op_Wstar = pdf_filter_Wstar;
1176
1177
/* text objects */
1178
proc->super.op_BT = pdf_filter_BT;
1179
proc->super.op_ET = pdf_filter_ET;
1180
1181
/* text state */
1182
proc->super.op_Tc = pdf_filter_Tc;
1183
proc->super.op_Tw = pdf_filter_Tw;
1184
proc->super.op_Tz = pdf_filter_Tz;
1185
proc->super.op_TL = pdf_filter_TL;
1186
proc->super.op_Tf = pdf_filter_Tf;
1187
proc->super.op_Tr = pdf_filter_Tr;
1188
proc->super.op_Ts = pdf_filter_Ts;
1189
1190
/* text positioning */
1191
proc->super.op_Td = pdf_filter_Td;
1192
proc->super.op_TD = pdf_filter_TD;
1193
proc->super.op_Tm = pdf_filter_Tm;
1194
proc->super.op_Tstar = pdf_filter_Tstar;
1195
1196
/* text showing */
1197
proc->super.op_TJ = pdf_filter_TJ;
1198
proc->super.op_Tj = pdf_filter_Tj;
1199
proc->super.op_squote = pdf_filter_squote;
1200
proc->super.op_dquote = pdf_filter_dquote;
1201
1202
/* type 3 fonts */
1203
proc->super.op_d0 = pdf_filter_d0;
1204
proc->super.op_d1 = pdf_filter_d1;
1205
1206
/* color */
1207
proc->super.op_CS = pdf_filter_CS;
1208
proc->super.op_cs = pdf_filter_cs;
1209
proc->super.op_SC_color = pdf_filter_SC_color;
1210
proc->super.op_sc_color = pdf_filter_sc_color;
1211
proc->super.op_SC_pattern = pdf_filter_SC_pattern;
1212
proc->super.op_sc_pattern = pdf_filter_sc_pattern;
1213
proc->super.op_SC_shade = pdf_filter_SC_shade;
1214
proc->super.op_sc_shade = pdf_filter_sc_shade;
1215
1216
proc->super.op_G = pdf_filter_G;
1217
proc->super.op_g = pdf_filter_g;
1218
proc->super.op_RG = pdf_filter_RG;
1219
proc->super.op_rg = pdf_filter_rg;
1220
proc->super.op_K = pdf_filter_K;
1221
proc->super.op_k = pdf_filter_k;
1222
1223
/* shadings, images, xobjects */
1224
proc->super.op_BI = pdf_filter_BI;
1225
proc->super.op_sh = pdf_filter_sh;
1226
proc->super.op_Do_image = pdf_filter_Do_image;
1227
proc->super.op_Do_form = pdf_filter_Do_form;
1228
1229
/* marked content */
1230
proc->super.op_MP = pdf_filter_MP;
1231
proc->super.op_DP = pdf_filter_DP;
1232
proc->super.op_BMC = pdf_filter_BMC;
1233
proc->super.op_BDC = pdf_filter_BDC;
1234
proc->super.op_EMC = pdf_filter_EMC;
1235
1236
/* compatibility */
1237
proc->super.op_BX = pdf_filter_BX;
1238
proc->super.op_EX = pdf_filter_EX;
1239
1240
proc->super.op_END = pdf_filter_END;
1241
}
1242
1243
proc->chain = chain;
1244
proc->doc = doc;
1245
proc->old_rdb = old_rdb;
1246
proc->new_rdb = new_rdb;
1247
1248
proc->gstate = fz_malloc_struct(ctx, filter_gstate);
1249
proc->gstate->ctm = fz_identity;
1250
proc->gstate->current_ctm = fz_identity;
1251
1252
proc->gstate->stroke = proc->gstate->stroke;
1253
proc->gstate->current_stroke = proc->gstate->stroke;
1254
1255
return (pdf_processor*)proc;
1256
}
1257
1258