Coverage Report

Created: 2025-11-07 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/mupdf/source/pdf/pdf-op-vectorize.c
Line
Count
Source
1
// Copyright (C) 2025 Artifex Software, Inc.
2
//
3
// This file is part of MuPDF.
4
//
5
// MuPDF is free software: you can redistribute it and/or modify it under the
6
// terms of the GNU Affero General Public License as published by the Free
7
// Software Foundation, either version 3 of the License, or (at your option)
8
// any later version.
9
//
10
// MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
11
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12
// FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
13
// details.
14
//
15
// You should have received a copy of the GNU Affero General Public License
16
// along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
17
//
18
// Alternative licensing terms are available from the licensor.
19
// For commercial licensing, see <https://www.artifex.com/> or contact
20
// Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
21
// CA 94129, USA, for further information.
22
23
#include "mupdf/fitz.h"
24
#include "mupdf/pdf.h"
25
26
#include "pdf-imp.h"
27
28
#include <string.h>
29
30
typedef struct vectorize_gstate
31
{
32
  struct vectorize_gstate *next;
33
  pdf_text_state text;
34
} vectorize_gstate;
35
36
typedef struct
37
{
38
  pdf_processor super;
39
  pdf_document *doc;
40
  vectorize_gstate *gstate;
41
  pdf_text_object_state tos;
42
  int bidi;
43
  pdf_vectorize_filter_options *options;
44
  pdf_filter_options *global_options;
45
  pdf_resource_stack *new_rstack;
46
} pdf_vectorize_processor;
47
48
static void
49
send_moveto(fz_context *ctx, void *arg, float x, float y)
50
0
{
51
0
  pdf_vectorize_processor *p = (pdf_vectorize_processor *)arg;
52
53
0
  if (p->super.chain->op_m)
54
0
    p->super.chain->op_m(ctx, p->super.chain, x, y);
55
0
}
56
57
static void
58
send_lineto(fz_context *ctx, void *arg, float x, float y)
59
0
{
60
0
  pdf_vectorize_processor *p = (pdf_vectorize_processor *)arg;
61
62
0
  if (p->super.chain->op_l)
63
0
    p->super.chain->op_l(ctx, p->super.chain, x, y);
64
0
}
65
66
static void
67
send_curveto(fz_context *ctx, void *arg, float x1, float y1, float x2, float y2, float x3, float y3)
68
0
{
69
0
  pdf_vectorize_processor *p = (pdf_vectorize_processor *)arg;
70
71
0
  if (p->super.chain->op_c)
72
0
    p->super.chain->op_c(ctx, p->super.chain, x1, y1, x2, y2, x3, y3);
73
0
}
74
75
static void
76
send_closepath(fz_context *ctx, void *arg)
77
0
{
78
0
  pdf_vectorize_processor *p = (pdf_vectorize_processor *)arg;
79
80
0
  if (p->super.chain->op_h)
81
0
    p->super.chain->op_h(ctx, p->super.chain);
82
0
}
83
84
static void
85
send_curvetov(fz_context *ctx, void *arg, float x2, float y2, float x3, float y3)
86
0
{
87
0
  pdf_vectorize_processor *p = (pdf_vectorize_processor *)arg;
88
89
0
  if (p->super.chain->op_v)
90
0
    p->super.chain->op_v(ctx, p->super.chain, x2, y2, x3, y3);
91
0
}
92
93
static void
94
send_curvetoy(fz_context *ctx, void *arg, float x1, float y1, float x3, float y3)
95
0
{
96
0
  pdf_vectorize_processor *p = (pdf_vectorize_processor *)arg;
97
98
0
  if (p->super.chain->op_y)
99
0
    p->super.chain->op_y(ctx, p->super.chain, x1, y1, x3, y3);
100
0
}
101
102
static void
103
send_rectto(fz_context *ctx, void *arg, float x1, float y1, float x2, float y2)
104
0
{
105
0
  pdf_vectorize_processor *p = (pdf_vectorize_processor *)arg;
106
107
0
  if (p->super.chain->op_re)
108
0
    p->super.chain->op_re(ctx, p->super.chain, x1, y1, x2, y2);
109
0
}
110
111
static void
112
send_path(fz_context *ctx, pdf_vectorize_processor *pr, fz_path *path)
113
0
{
114
0
  static const fz_path_walker sender =
115
0
  {
116
    /* Compulsory ones */
117
0
    send_moveto,
118
0
    send_lineto,
119
0
    send_curveto,
120
0
    send_closepath,
121
0
    NULL,
122
0
    send_curvetov,
123
0
    send_curvetoy,
124
0
    send_rectto
125
0
  };
126
127
0
  fz_walk_path(ctx, path, &sender, pr);
128
0
}
129
130
static void
131
vectorize_push(fz_context *ctx, pdf_vectorize_processor *p)
132
0
{
133
0
  vectorize_gstate *gnew = fz_malloc_struct(ctx, vectorize_gstate);
134
135
0
  gnew->next = p->gstate;
136
0
  gnew->text = p->gstate->text;
137
0
  p->gstate = gnew;
138
0
  if (gnew->text.font)
139
0
    pdf_keep_font(ctx, gnew->text.font);
140
0
  if (gnew->text.fontname)
141
0
    fz_keep_string(ctx, gnew->text.fontname);
142
143
0
  if (p->super.chain->op_q)
144
0
    p->super.chain->op_q(ctx, p->super.chain);
145
0
}
146
147
static int
148
vectorize_pop(fz_context *ctx, pdf_vectorize_processor *p)
149
0
{
150
0
  vectorize_gstate *gstate = p->gstate;
151
0
  vectorize_gstate *old = gstate->next;
152
153
  /* We are at the top, so nothing to pop! */
154
0
  if (old == NULL)
155
0
    return 1;
156
157
0
  if (p->super.chain->op_Q)
158
0
    p->super.chain->op_Q(ctx, p->super.chain);
159
160
0
  pdf_drop_font(ctx, gstate->text.font);
161
0
  fz_drop_string(ctx, gstate->text.fontname);
162
0
  fz_free(ctx, gstate);
163
0
  p->gstate = old;
164
0
  return 0;
165
0
}
166
167
static void
168
show_char(fz_context *ctx, pdf_vectorize_processor *pr, int cid)
169
0
{
170
0
  vectorize_gstate *gstate = pr->gstate;
171
0
  pdf_font_desc *fontdesc = gstate->text.font;
172
0
  fz_matrix trm;
173
0
  float adv;
174
0
  int gid;
175
0
  fz_path *path;
176
177
0
  if (gstate->text.render == 3)
178
0
    return;
179
180
0
  gid = pdf_tos_make_trm(ctx, &pr->tos, &gstate->text, fontdesc, cid, &trm, &adv);
181
182
0
  if (gid < 0 || gid >= fontdesc->font->glyph_count)
183
0
    return;
184
185
0
  if (fontdesc->font->t3procs != NULL)
186
0
  {
187
    /* Type 3 font */
188
    /* PDF spec: ISO 32000-2 latest version at the time of writing:
189
     * Section 9.3.6:
190
     * Where text is drawn using a Type 3 font:
191
     *  + if text rendering mode is set to a value of 3 or 7, the text shall not be rendered.
192
     *  + if text rendering mode is set to a value other than 3 or 7, the text shall be rendered using the glyph descriptions in the Type 3 font.
193
     *  + If text rendering mode is set to a value of 4, 5, 6 or 7, nothing shall be added to the clipping path.
194
     */
195
0
    if ((gstate->text.render & 3) != 3)
196
0
    {
197
0
      fz_matrix tfm = fz_concat(fontdesc->font->t3matrix, trm);
198
0
      vectorize_push(ctx, pr);
199
0
      if (pr->super.chain->op_cm)
200
0
        pr->super.chain->op_cm(ctx, pr->super.chain, tfm.a, tfm.b, tfm.c, tfm.d, tfm.e, tfm.f);
201
0
      pdf_process_glyph(ctx, &pr->super, fontdesc->font->t3doc, pr->super.rstack->resources, fontdesc->font->t3procs[gid]);
202
0
      vectorize_pop(ctx, pr);
203
0
    }
204
0
  }
205
0
  else
206
0
  {
207
0
    path = fz_outline_glyph(ctx, fontdesc->font, gid, trm);
208
0
    if (fz_path_is_empty(ctx, path))
209
0
    {
210
0
      if (!path)
211
0
        fz_warn(ctx, "cannot render glyph");
212
0
    }
213
0
    else
214
0
    {
215
0
      if (gstate->text.render != 7)
216
0
      {
217
0
        if (pr->super.chain->op_q)
218
0
          pr->super.chain->op_q(ctx, pr->super.chain);
219
0
        send_path(ctx, pr, path);
220
0
        if ((gstate->text.render & 1) == 0)
221
0
          if (pr->super.chain->op_f)
222
0
            pr->super.chain->op_f(ctx, pr->super.chain);
223
0
        if (((gstate->text.render-1) & 2) == 0)
224
0
          if (pr->super.chain->op_S)
225
0
            pr->super.chain->op_S(ctx, pr->super.chain);
226
0
        if (pr->super.chain->op_Q)
227
0
          pr->super.chain->op_Q(ctx, pr->super.chain);
228
0
      }
229
0
      if (gstate->text.render > 3)
230
0
      {
231
0
        send_path(ctx, pr, path);
232
0
        if (pr->super.chain->op_W)
233
0
          pr->super.chain->op_W(ctx, pr->super.chain);
234
0
        if (pr->super.chain->op_n)
235
0
          pr->super.chain->op_n(ctx, pr->super.chain);
236
0
      }
237
0
    }
238
0
  }
239
240
0
  pdf_tos_move_after_char(ctx, &pr->tos);
241
0
}
242
243
static void
244
show_space(fz_context *ctx, pdf_vectorize_processor *pr, float tadj)
245
0
{
246
0
  vectorize_gstate *gstate = pr->gstate;
247
0
  pdf_font_desc *fontdesc = gstate->text.font;
248
249
0
  if (fontdesc->wmode == 0)
250
0
    pr->tos.tm = fz_pre_translate(pr->tos.tm, tadj * gstate->text.scale, 0);
251
0
  else
252
0
    pr->tos.tm = fz_pre_translate(pr->tos.tm, 0, tadj);
253
0
}
254
255
static void
256
do_show_string(fz_context *ctx, pdf_vectorize_processor *pr, unsigned char *buf, size_t len)
257
0
{
258
0
  vectorize_gstate *gstate = pr->gstate;
259
0
  pdf_font_desc *fontdesc = gstate->text.font;
260
0
  unsigned char *end = buf + len;
261
0
  unsigned int cpt;
262
0
  int cid;
263
264
0
  while (buf < end)
265
0
  {
266
0
    int w = pdf_decode_cmap(fontdesc->encoding, buf, end, &cpt);
267
0
    buf += w;
268
269
0
    cid = pdf_lookup_cmap(fontdesc->encoding, cpt);
270
0
    if (cid >= 0)
271
0
      show_char(ctx, pr, cid);
272
0
    else
273
0
      fz_warn(ctx, "cannot encode character");
274
0
    if (cpt == 32 && w == 1)
275
0
    {
276
      /* Bug 703151: pdf_show_char can realloc gstate. */
277
0
      gstate = pr->gstate;
278
0
      show_space(ctx, pr, gstate->text.word_space);
279
0
    }
280
0
  }
281
0
}
282
283
static void
284
show_string(fz_context *ctx, pdf_vectorize_processor *pr, unsigned char *buf, size_t len)
285
0
{
286
0
  vectorize_gstate *gstate = pr->gstate;
287
0
  pdf_font_desc *fontdesc = gstate->text.font;
288
289
0
  if (!fontdesc)
290
0
  {
291
0
    fz_warn(ctx, "cannot draw text since font and size not set");
292
0
    return;
293
0
  }
294
295
0
  do_show_string(ctx, pr, buf, len);
296
0
}
297
298
static void
299
show_text(fz_context *ctx, pdf_vectorize_processor *pr, pdf_obj *text)
300
0
{
301
0
  vectorize_gstate *gstate = pr->gstate;
302
0
  pdf_font_desc *fontdesc = gstate->text.font;
303
0
  int i;
304
305
0
  if (!fontdesc)
306
0
  {
307
0
    fz_warn(ctx, "cannot draw text since font and size not set");
308
0
    return;
309
0
  }
310
311
0
  if (pdf_is_array(ctx, text))
312
0
  {
313
0
    int n = pdf_array_len(ctx, text);
314
0
    for (i = 0; i < n; i++)
315
0
    {
316
0
      pdf_obj *item = pdf_array_get(ctx, text, i);
317
0
      if (pdf_is_string(ctx, item))
318
0
        do_show_string(ctx, pr, (unsigned char *)pdf_to_str_buf(ctx, item), pdf_to_str_len(ctx, item));
319
0
      else
320
0
      {
321
0
        gstate = pr->gstate;
322
0
        show_space(ctx, pr, - pdf_to_real(ctx, item) * gstate->text.size * 0.001f);
323
0
      }
324
0
    }
325
0
  }
326
0
  else if (pdf_is_string(ctx, text))
327
0
  {
328
0
    do_show_string(ctx, pr, (unsigned char *)pdf_to_str_buf(ctx, text), pdf_to_str_len(ctx, text));
329
0
  }
330
0
}
331
332
static void
333
pdf_vectorize_BT(fz_context *ctx, pdf_processor *proc)
334
0
{
335
0
  pdf_vectorize_processor *p = (pdf_vectorize_processor*)proc;
336
337
0
  p->tos.tm = fz_identity;
338
0
  p->tos.tlm = fz_identity;
339
0
  p->bidi = 0;
340
0
}
341
342
static void pdf_vectorize_q(fz_context *ctx, pdf_processor *proc)
343
0
{
344
0
  pdf_vectorize_processor *pr = (pdf_vectorize_processor *)proc;
345
346
0
  vectorize_push(ctx, pr);
347
0
}
348
349
350
static void
351
pdf_vectorize_Q(fz_context *ctx, pdf_processor *proc)
352
0
{
353
0
  pdf_vectorize_processor *p = (pdf_vectorize_processor*)proc;
354
355
0
  vectorize_pop(ctx, p);
356
0
}
357
358
/* text state */
359
360
static void
361
pdf_vectorize_Tc(fz_context *ctx, pdf_processor *proc, float charspace)
362
0
{
363
0
  pdf_vectorize_processor *p = (pdf_vectorize_processor*)proc;
364
0
  vectorize_gstate *gstate = p->gstate;
365
366
0
  gstate->text.char_space = charspace;
367
0
}
368
369
static void
370
pdf_vectorize_Tw(fz_context *ctx, pdf_processor *proc, float wordspace)
371
0
{
372
0
  pdf_vectorize_processor *p = (pdf_vectorize_processor*)proc;
373
0
  vectorize_gstate *gstate = p->gstate;
374
375
0
  gstate->text.word_space = wordspace;
376
0
}
377
378
static void
379
pdf_vectorize_Tz(fz_context *ctx, pdf_processor *proc, float scale)
380
0
{
381
0
  pdf_vectorize_processor *p = (pdf_vectorize_processor*)proc;
382
0
  vectorize_gstate *gstate = p->gstate;
383
384
0
  gstate->text.scale = scale / 100;
385
0
}
386
387
static void
388
pdf_vectorize_TL(fz_context *ctx, pdf_processor *proc, float leading)
389
0
{
390
0
  pdf_vectorize_processor *p = (pdf_vectorize_processor*)proc;
391
0
  vectorize_gstate *gstate = p->gstate;
392
393
0
  gstate->text.leading = leading;
394
0
}
395
396
static void
397
pdf_vectorize_Tf(fz_context *ctx, pdf_processor *proc, const char *name, pdf_font_desc *font, float size)
398
0
{
399
0
  pdf_vectorize_processor *p = (pdf_vectorize_processor*)proc;
400
0
  vectorize_gstate *gstate = p->gstate;
401
402
0
  pdf_drop_font(ctx, gstate->text.font);
403
0
  gstate->text.font = pdf_keep_font(ctx, font);
404
0
  gstate->text.size = size;
405
0
}
406
407
static void
408
pdf_vectorize_Tr(fz_context *ctx, pdf_processor *proc, int render)
409
0
{
410
0
  pdf_vectorize_processor *p = (pdf_vectorize_processor*)proc;
411
0
  vectorize_gstate *gstate = p->gstate;
412
413
0
  gstate->text.render = render;
414
0
}
415
416
static void
417
pdf_vectorize_Ts(fz_context *ctx, pdf_processor *proc, float rise)
418
0
{
419
0
  pdf_vectorize_processor *p = (pdf_vectorize_processor*)proc;
420
0
  vectorize_gstate *gstate = p->gstate;
421
422
0
  gstate->text.rise = rise;
423
0
}
424
425
/* text positioning */
426
427
static void
428
pdf_vectorize_Td(fz_context *ctx, pdf_processor *proc, float tx, float ty)
429
0
{
430
0
  pdf_vectorize_processor *p = (pdf_vectorize_processor*)proc;
431
432
0
  pdf_tos_translate(&p->tos, tx, ty);
433
0
}
434
435
static void
436
pdf_vectorize_TD(fz_context *ctx, pdf_processor *proc, float tx, float ty)
437
0
{
438
0
  pdf_vectorize_processor *p = (pdf_vectorize_processor*)proc;
439
0
  vectorize_gstate *gstate = p->gstate;
440
441
0
  gstate->text.leading = -ty;
442
0
  pdf_tos_translate(&p->tos, tx, ty);
443
0
}
444
445
static void
446
pdf_vectorize_Tm(fz_context *ctx, pdf_processor *proc, float a, float b, float c, float d, float e, float f)
447
0
{
448
0
  pdf_vectorize_processor *p = (pdf_vectorize_processor*)proc;
449
450
0
  pdf_tos_set_matrix(&p->tos, a, b, c, d, e, f);
451
0
}
452
453
static void
454
pdf_vectorize_Tstar(fz_context *ctx, pdf_processor *proc)
455
0
{
456
0
  pdf_vectorize_processor *p = (pdf_vectorize_processor*)proc;
457
0
  vectorize_gstate *gstate = p->gstate;
458
459
0
  pdf_tos_newline(&p->tos, gstate->text.leading);
460
0
}
461
462
/* text showing */
463
464
static void
465
pdf_vectorize_TJ(fz_context *ctx, pdf_processor *proc, pdf_obj *obj)
466
0
{
467
0
  pdf_vectorize_processor *p = (pdf_vectorize_processor*)proc;
468
469
0
  show_text(ctx, p, obj);
470
0
}
471
472
static void
473
pdf_vectorize_Tj(fz_context *ctx, pdf_processor *proc, char *str, size_t len)
474
0
{
475
0
  pdf_vectorize_processor *p = (pdf_vectorize_processor*)proc;
476
477
0
  show_string(ctx, p, (unsigned char *)str, len);
478
0
}
479
480
static void
481
pdf_vectorize_squote(fz_context *ctx, pdf_processor *proc, char *str, size_t len)
482
0
{
483
0
  pdf_vectorize_processor *p = (pdf_vectorize_processor*)proc;
484
485
0
  show_string(ctx, p, (unsigned char*)str, len);
486
0
}
487
488
static void
489
pdf_vectorize_dquote(fz_context *ctx, pdf_processor *proc, float aw, float ac, char *str, size_t len)
490
0
{
491
0
  pdf_vectorize_processor *p = (pdf_vectorize_processor*)proc;
492
493
0
  show_string(ctx, p, (unsigned char*)str, len);
494
0
}
495
496
static void
497
pdf_close_vectorize_processor(fz_context *ctx, pdf_processor *proc)
498
0
{
499
0
  pdf_vectorize_processor *p = (pdf_vectorize_processor*)proc;
500
0
  while (!vectorize_pop(ctx, p))
501
0
  {
502
    /* Nothing to do in the loop, all work done above */
503
0
  }
504
0
  pdf_close_processor(ctx, p->super.chain);
505
0
}
506
507
static void
508
pdf_drop_vectorize_processor(fz_context *ctx, pdf_processor *proc)
509
0
{
510
0
  pdf_vectorize_processor *p = (pdf_vectorize_processor*)proc;
511
0
  vectorize_gstate *gs = p->gstate;
512
0
  while (gs)
513
0
  {
514
0
    vectorize_gstate *next = gs->next;
515
0
    pdf_drop_font(ctx, gs->text.font);
516
0
    fz_drop_string(ctx, gs->text.fontname);
517
0
    fz_free(ctx, gs);
518
0
    gs = next;
519
0
  }
520
0
  fz_drop_text(ctx, p->tos.text);
521
0
  pdf_drop_document(ctx, p->doc);
522
0
}
523
524
static void
525
pdf_vectorize_push_resources(fz_context *ctx, pdf_processor *proc, pdf_obj *res)
526
0
{
527
0
  pdf_vectorize_processor *p = (pdf_vectorize_processor *)proc;
528
0
  pdf_resource_stack *stk = fz_malloc_struct(ctx, pdf_resource_stack);
529
0
  int i, n;
530
531
0
  stk->next = p->new_rstack;
532
0
  p->new_rstack = stk;
533
0
  fz_try(ctx)
534
0
  {
535
0
    n = pdf_dict_len(ctx, res);
536
0
    stk->resources = pdf_new_dict(ctx, p->doc, n);
537
0
    for (i = 0; i < n; i++)
538
0
    {
539
0
      pdf_obj *key = pdf_dict_get_key(ctx, res, i);
540
0
      if (pdf_name_eq(ctx, key, PDF_NAME(Font)))
541
0
        continue;
542
0
      pdf_dict_put(ctx, stk->resources, key, pdf_dict_get_val(ctx, res, i));
543
0
    }
544
0
    pdf_processor_push_resources(ctx, p->super.chain, stk->resources);
545
0
  }
546
0
  fz_catch(ctx)
547
0
  {
548
0
    pdf_drop_obj(ctx, stk->resources);
549
0
    p->new_rstack = stk->next;
550
0
    fz_free(ctx, stk);
551
0
    fz_rethrow(ctx);
552
0
  }
553
0
}
554
555
static pdf_obj *
556
pdf_vectorize_pop_resources(fz_context *ctx, pdf_processor *proc)
557
0
{
558
0
  pdf_vectorize_processor *p = (pdf_vectorize_processor *)proc;
559
0
  pdf_resource_stack *stk = p->new_rstack;
560
561
0
  p->new_rstack = stk->next;
562
0
  pdf_drop_obj(ctx, stk->resources);
563
0
  fz_free(ctx, stk);
564
565
0
  return pdf_processor_pop_resources(ctx, p->super.chain);
566
0
}
567
568
pdf_processor *
569
pdf_new_vectorize_filter(
570
  fz_context *ctx,
571
  pdf_document *doc,
572
  pdf_processor *chain,
573
  int structparents,
574
  fz_matrix transform,
575
  pdf_filter_options *options,
576
  void *vopts_)
577
0
{
578
0
  pdf_vectorize_processor *proc = pdf_new_processor(ctx, sizeof *proc);
579
0
  pdf_vectorize_filter_options *vopts = vopts_;
580
581
0
  proc->super.close_processor = pdf_close_vectorize_processor;
582
0
  proc->super.drop_processor = pdf_drop_vectorize_processor;
583
0
  proc->super.push_resources = pdf_vectorize_push_resources;
584
0
  proc->super.pop_resources = pdf_vectorize_pop_resources;
585
586
0
  proc->super.op_q = pdf_vectorize_q;
587
0
  proc->super.op_Q = pdf_vectorize_Q;
588
589
  /* text objects */
590
0
  proc->super.op_BT = pdf_vectorize_BT;
591
0
  proc->super.op_ET = NULL;
592
0
  proc->super.op_d0 = NULL;
593
0
  proc->super.op_d1 = NULL;
594
595
  /* text state */
596
0
  proc->super.op_Tc = pdf_vectorize_Tc;
597
0
  proc->super.op_Tw = pdf_vectorize_Tw;
598
0
  proc->super.op_Tz = pdf_vectorize_Tz;
599
0
  proc->super.op_TL = pdf_vectorize_TL;
600
0
  proc->super.op_Tf = pdf_vectorize_Tf;
601
0
  proc->super.op_Tr = pdf_vectorize_Tr;
602
0
  proc->super.op_Ts = pdf_vectorize_Ts;
603
604
  /* text positioning */
605
0
  proc->super.op_Td = pdf_vectorize_Td;
606
0
  proc->super.op_TD = pdf_vectorize_TD;
607
0
  proc->super.op_Tm = pdf_vectorize_Tm;
608
0
  proc->super.op_Tstar = pdf_vectorize_Tstar;
609
610
  /* text showing */
611
0
  proc->super.op_TJ = pdf_vectorize_TJ;
612
0
  proc->super.op_Tj = pdf_vectorize_Tj;
613
0
  proc->super.op_squote = pdf_vectorize_squote;
614
0
  proc->super.op_dquote = pdf_vectorize_dquote;
615
616
0
  proc->doc = pdf_keep_document(ctx, doc);
617
0
  proc->super.chain = chain;
618
619
0
  proc->global_options = options;
620
0
  proc->options = vopts;
621
622
0
  fz_try(ctx)
623
0
  {
624
0
    proc->gstate = fz_malloc_struct(ctx, vectorize_gstate);
625
0
    proc->gstate->text.scale = 1;
626
0
    proc->gstate->text.size = -1;
627
0
  }
628
0
  fz_catch(ctx)
629
0
  {
630
0
    pdf_drop_processor(ctx, (pdf_processor *) proc);
631
0
    fz_rethrow(ctx);
632
0
  }
633
634
0
  proc->super.requirements = proc->super.chain->requirements;
635
636
0
  return (pdf_processor*)proc;
637
0
}