Coverage Report

Created: 2025-02-15 06:18

/src/libspectre/ghostscript/devices/vector/gdevpdtt.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2020 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  1305 Grant Avenue - Suite 200, Novato,
13
   CA 94945, U.S.A., +1(415)492-9861, for further information.
14
*/
15
16
17
/* Text processing for pdfwrite. */
18
#include "math_.h"
19
#include "string_.h"
20
#include <stdlib.h> /* abs() */
21
#include "gx.h"
22
#include "gserrors.h"
23
#include "gscencs.h"
24
#include "gscedata.h"
25
#include "gsmatrix.h"
26
#include "gzstate.h"
27
#include "gxfcache.h"                /* for orig_fonts list */
28
#include "gxfont.h"
29
#include "gxfont0.h"
30
#include "gxfcid.h"
31
#include "gxfcopy.h"
32
#include "gxfcmap.h"
33
#include "gxpath.h"                /* for getting current point */
34
#include "gxchar.h"
35
#include "gxstate.h"
36
#include "gdevpdfx.h"
37
#include "gdevpdfg.h"
38
#include "gdevpdfo.h"
39
#include "gdevpdtx.h"
40
#include "gdevpdtd.h"
41
#include "gdevpdtf.h"
42
#include "gdevpdts.h"
43
#include "gdevpdtt.h"
44
#include "gdevpdti.h"
45
#include "gxhldevc.h"
46
#include "gzpath.h"
47
48
/* ================ Text enumerator ================ */
49
50
/* GC descriptor */
51
private_st_pdf_text_enum();
52
53
/* Define the auxiliary procedures for text processing. */
54
static int
55
pdf_text_resync(gs_text_enum_t *pte, const gs_text_enum_t *pfrom)
56
0
{
57
0
    pdf_text_enum_t *const penum = (pdf_text_enum_t *)pte;
58
59
0
    if ((pte->text.operation ^ pfrom->text.operation) & ~TEXT_FROM_ANY)
60
0
        return_error(gs_error_rangecheck);
61
0
    if (penum->pte_default) {
62
0
        int code = gs_text_resync(penum->pte_default, pfrom);
63
64
0
        if (code < 0)
65
0
            return code;
66
0
    }
67
0
    pte->text = pfrom->text;
68
0
    gs_text_enum_copy_dynamic(pte, pfrom, false);
69
0
    return 0;
70
0
}
71
static bool
72
pdf_text_is_width_only(const gs_text_enum_t *pte)
73
0
{
74
0
    const pdf_text_enum_t *const penum = (const pdf_text_enum_t *)pte;
75
76
0
    if (penum->pte_default)
77
0
        return gs_text_is_width_only(penum->pte_default);
78
0
    return false;
79
0
}
80
static int
81
pdf_text_current_width(const gs_text_enum_t *pte, gs_point *pwidth)
82
0
{
83
0
    const pdf_text_enum_t *const penum = (const pdf_text_enum_t *)pte;
84
85
0
    if (penum->pte_default)
86
0
        return gs_text_current_width(penum->pte_default, pwidth);
87
0
    return_error(gs_error_rangecheck); /* can't happen */
88
0
}
89
static int
90
pdf_text_set_cache(gs_text_enum_t *pte, const double *pw,
91
                   gs_text_cache_control_t control)
92
0
{
93
0
    pdf_text_enum_t *penum;
94
0
    gs_text_enum_t *pgste;
95
0
    gx_device_pdf *pdev = (gx_device_pdf *)pte->dev;
96
0
    gs_matrix m;
97
98
0
    if (pdev->pte != NULL)
99
0
        penum = (pdf_text_enum_t *)pdev->pte;
100
0
    else {
101
0
        if (gs_object_type(pte->memory, pte) == &st_pdf_text_enum)
102
0
            penum = (pdf_text_enum_t *)pte;
103
0
        else
104
0
            return_error(gs_error_typecheck);
105
0
    }
106
107
0
    if (pdev->type3charpath)
108
0
        return gs_text_set_cache(penum->pte_default, pw, control);
109
110
0
    switch (control) {
111
0
    case TEXT_SET_CHAR_WIDTH:
112
0
    case TEXT_SET_CACHE_DEVICE:
113
        /* See comments in pdf_text_process. We are using a 100x100 matrix
114
         * NOT the identity, but we want the cache device values to be in
115
         * font co-ordinate space, so we need to undo that scale here.
116
         */
117
0
        if (pdev->PS_accumulator){
118
0
            gs_matrix_scale(&ctm_only(pte->pgs), .01, .01, &m);
119
0
            gs_distance_transform(pw[0], pw[1], &m, &pdev->char_width);
120
0
        } else {
121
0
            pdev->char_width.x = pw[0];
122
0
            pdev->char_width.y = pw[1];
123
0
        }
124
0
        break;
125
0
    case TEXT_SET_CACHE_DEVICE2:
126
        /*
127
         * pdev->char_width is used with synthesized Type 3 fonts only.
128
         * Since they are simple fonts, we only need the horisontal
129
         * width for Widths array. Therefore we don't check
130
         * gs_rootfont(pgs)->WMode and don't use pw[6:7].
131
         */
132
        /* See comments in pdf_text_process. We are using a 100x100 matrix
133
         * NOT the identity, but we want the cache device values to be in
134
         * font co-ordinate space, so we need to undo that scale here.
135
         */
136
0
        if (pdev->PS_accumulator){
137
0
            gs_matrix_scale(&ctm_only(pte->pgs), .01, .01, &m);
138
0
            gs_distance_transform(pw[0], pw[1], &m, &pdev->char_width);
139
0
        } else {
140
0
            pdev->char_width.x = pw[0];
141
0
            pdev->char_width.y = pw[1];
142
0
        }
143
0
        if (penum->cdevproc_callout) {
144
0
            memcpy(penum->cdevproc_result, pw, sizeof(penum->cdevproc_result));
145
0
            return 0;
146
0
        }
147
0
        break;
148
0
    default:
149
0
        return_error(gs_error_rangecheck);
150
0
    }
151
0
    if (!pdev->PS_accumulator)
152
0
        pgste = (gs_text_enum_t *)penum;
153
0
    else
154
0
        pgste = penum->pte_default;
155
156
0
    if ((penum->current_font->FontType == ft_user_defined ||
157
0
        penum->current_font->FontType == ft_PDF_user_defined ||
158
0
        penum->current_font->FontType == ft_PCL_user_defined ||
159
0
        penum->current_font->FontType == ft_MicroType ||
160
0
        penum->current_font->FontType == ft_GL2_stick_user_defined ||
161
0
        penum->current_font->FontType == ft_GL2_531) &&
162
0
            penum->outer_CID == GS_NO_GLYPH &&
163
0
            !(pgste->text.operation & TEXT_DO_CHARWIDTH)) {
164
0
        int code;
165
0
        gs_glyph glyph;
166
167
0
        glyph = pte->returned.current_glyph;
168
0
        if ((glyph != GS_NO_GLYPH && penum->output_char_code != GS_NO_CHAR) || !pdev->PS_accumulator) {
169
0
            gs_show_enum *penum_s;
170
0
            gs_fixed_rect clip_box;
171
0
            double pw1[10];
172
0
            int narg = (control == TEXT_SET_CHAR_WIDTH ? 2 :
173
0
                        control == TEXT_SET_CACHE_DEVICE ? 6 : 10), i;
174
175
0
            penum_s = (gs_show_enum *)pgste;
176
            /* BuildChar could change the scale before calling setcachedevice (Bug 687290).
177
               We must scale the setcachedevice arguments because we assumed
178
               identity scale before entering the charproc.
179
               For now we only handle scaling matrices.
180
            */
181
0
            for (i = 0; i < narg; i += 2) {
182
0
                gs_point p;
183
184
0
                gs_point_transform(pw[i], pw[i + 1], &ctm_only(penum_s->pgs), &p);
185
0
                pw1[i] = p.x;
186
0
                pw1[i + 1] = p.y;
187
0
            }
188
0
            if (control != TEXT_SET_CHAR_WIDTH) {
189
0
                clip_box.p.x = float2fixed(pw1[2]);
190
0
                clip_box.p.y = float2fixed(pw1[3]);
191
0
                clip_box.q.x = float2fixed(pw1[4]);
192
0
                clip_box.q.y = float2fixed(pw1[5]);
193
0
            } else {
194
                /*
195
                 * We have no character bbox, but we need one to install the clipping
196
                 * to the graphic state of the PS interpreter. Since some fonts don't
197
                 * provide a proper FontBBox (Bug 687239 supplies a zero one),
198
                 * we set an "infinite" clipping here.
199
                 * We also detected that min_int, max_int don't work here with
200
                 * comparefiles/Bug687044.ps, therefore we divide them by 2.
201
                 */
202
0
                clip_box.p.x = clip_box.p.y = min_int / 2;
203
0
                clip_box.q.x = clip_box.q.y = max_int / 2;
204
0
            }
205
0
            code = gx_clip_to_rectangle(penum_s->pgs, &clip_box);
206
0
            if (code < 0)
207
0
                return code;
208
209
            /* See comments in pdf_text_process. We are using a 100x100 matrix
210
             * NOT the identity, but we want the cache device values to be in
211
             * font co-ordinate space, so we need to undo that scale here. We
212
             * can't do it above, where we take any scaling from the BuildChar
213
             * into account, because that would get the clip path wrong, that
214
             * needs to be in the 100x100 space so that it doesn't clip
215
             * out marking operations.
216
             */
217
0
            if (pdev->PS_accumulator)
218
0
                gs_matrix_scale(&ctm_only(penum_s->pgs), .01, .01, &m);
219
0
            else
220
0
                m = ctm_only(penum_s->pgs);
221
0
            for (i = 0; i < narg; i += 2) {
222
0
                gs_point p;
223
224
0
                gs_point_transform(pw[i], pw[i + 1], &m, &p);
225
0
                pw1[i] = p.x;
226
0
                pw1[i + 1] = p.y;
227
0
            }
228
0
            if (!pdev->PS_accumulator)
229
0
                code = pdf_set_charproc_attrs(pdev, pte->current_font,
230
0
                        pw1, narg, control, penum->returned.current_char, false);
231
0
            else
232
0
                code = pdf_set_charproc_attrs(pdev, pte->current_font,
233
0
                        pw1, narg, control, penum->output_char_code, true);
234
0
            if (code < 0)
235
0
                return code;
236
            /* Prevent writing the clipping path to charproc.
237
               See the comment above and bugs 687678, 688327.
238
               Note that the clipping in the graphic state will be used while
239
               fallbacks to default implementations of graphic objects.
240
               Hopely such fallbacks are rare. */
241
0
            pdev->clip_path_id = gx_get_clip_path_id(penum_s->pgs);
242
0
            return code;
243
0
        } else {
244
0
            gs_matrix m;
245
0
            pdf_resource_t *pres = pdev->accumulating_substream_resource;
246
247
            /* pdf_text_process started a charproc stream accumulation,
248
               but now we re-decided to go with the default implementation.
249
               Cancel the stream now.
250
             */
251
0
            code = pdf_exit_substream(pdev);
252
0
            if (code < 0)
253
0
                return code;
254
0
            code = pdf_cancel_resource(pdev, pres, resourceCharProc);
255
0
            if (code < 0)
256
0
                return code;
257
0
            pdf_forget_resource(pdev, pres, resourceCharProc);
258
            /* pdf_text_process had set an identity CTM for the
259
               charproc stream accumulation, but now we re-decided
260
               to go with the default implementation.
261
               Need to restore the correct CTM and add
262
               changes, which the charproc possibly did. */
263
            /* See comments in pdf_text_process. We are using a 100x100 matrix
264
             * NOT the identity,  so we need to undo that scale here.
265
             */
266
0
            gs_matrix_scale(&ctm_only(penum->pgs), .01, .01, (gs_matrix *)&ctm_only(penum->pgs));
267
            /* We also scaled the page height and width. Because we
268
             * don't go through the accumulator 'close' in pdf_text_process
269
             * we must also undo that scale.
270
             */
271
0
            pdev->width /= 100;
272
0
            pdev->height /= 100;
273
274
0
            gs_matrix_multiply((gs_matrix *)&pdev->charproc_ctm, (gs_matrix *)&penum->pgs->ctm, &m);
275
0
            gs_matrix_fixed_from_matrix(&penum->pgs->ctm, &m);
276
0
            penum->charproc_accum = false;
277
0
            pdev->accumulating_charproc = false;
278
0
        }
279
0
    }
280
0
    if (pdev->PS_accumulator && penum->pte_default) {
281
0
        if (penum->pte_default->text.operation & TEXT_DO_CHARWIDTH /* See process_cmap_text.*/)
282
0
            return gs_text_set_cache(penum->pte_default, pw, TEXT_SET_CHAR_WIDTH);
283
0
        else
284
0
            return gs_text_set_cache(penum->pte_default, pw, control);
285
0
    }
286
0
    return_error(gs_error_unregistered); /* can't happen */
287
0
}
288
289
static int
290
pdf_text_retry(gs_text_enum_t *pte)
291
0
{
292
0
    pdf_text_enum_t *const penum = (pdf_text_enum_t *)pte;
293
294
0
    if (penum->pte_default)
295
0
        return gs_text_retry(penum->pte_default);
296
0
    return_error(gs_error_rangecheck); /* can't happen */
297
0
}
298
static void
299
pdf_text_release(gs_text_enum_t *pte, client_name_t cname)
300
0
{
301
0
    pdf_text_enum_t *const penum = (pdf_text_enum_t *)pte;
302
303
0
    if (penum->pte_default) {
304
0
        gs_text_release(penum->pte_default, cname);
305
0
        penum->pte_default = 0;
306
0
    }
307
0
    pdf_text_release_cgp(penum);
308
0
    gx_default_text_release(pte, cname);
309
0
}
310
void
311
pdf_text_release_cgp(pdf_text_enum_t *penum)
312
0
{
313
0
    if (penum->cgp) {
314
0
        gs_free_object(penum->memory, penum->cgp, "pdf_text_release");
315
0
        penum->cgp = 0;
316
0
    }
317
0
}
318
319
/* Begin processing text. */
320
static text_enum_proc_process(pdf_text_process);
321
static const gs_text_enum_procs_t pdf_text_procs = {
322
    pdf_text_resync, pdf_text_process,
323
    pdf_text_is_width_only, pdf_text_current_width,
324
    pdf_text_set_cache, pdf_text_retry,
325
    pdf_text_release
326
};
327
328
/* Ideally we would set the stroke and fill colours in pdf_prepare_text_drawing
329
 * but this is called from pdf_process_text, not pdf_begin_text. The problem is
330
 * that if we get a pattern colour we need to exit to the interpreter and run
331
 * the PaintProc, we do this by retunring e_ReampColor. But the 'process' routines
332
 * aren't set up to accept this, and just throw an error. Trying to rework the
333
 * interpreter routines began turning into a gigantic task, so I chose instead
334
 * to 'set' the colours here, which is called from text_begin, where the code
335
 * allows us to return_error(gs_error_RemapColor. Attempting to write the colour to the PDF file
336
 * in this routine as well caused trouble keeping the graphics states synchronised,
337
 * so this functionality was left in pdf_prepare_text_drawing.
338
 */
339
static int
340
pdf_prepare_text_color(gx_device_pdf *const pdev, gs_gstate *pgs, const gs_text_params_t *text, gs_font *font)
341
0
{
342
0
    int code=0;
343
0
    if (text->operation & TEXT_DO_DRAW) {
344
0
        if (!pdev->ForOPDFRead) {
345
0
            if (pgs->text_rendering_mode != 3 && pgs->text_rendering_mode != 7) {
346
0
                if (font->PaintType == 2) {
347
                    /* Bit awkward, if the PaintType is 2 then we want to set the
348
                     * current ie 'fill' colour, but as a stroke colour because we
349
                     * will later change the text rendering mode to 1 (stroke).
350
                     */
351
0
                    code = gx_set_dev_color(pgs);
352
0
                    if (code != 0)
353
0
                        return code;
354
0
                    code = pdf_set_drawing_color(pdev, pgs, pgs->color[0].dev_color, &pdev->saved_stroke_color,
355
0
                                 &pdev->stroke_used_process_color,
356
0
                                 &psdf_set_stroke_color_commands);
357
0
                    if (code < 0)
358
0
                        return code;
359
0
                } else {
360
0
                    if ((pgs->text_rendering_mode == 0 || pgs->text_rendering_mode == 2 ||
361
0
                        pgs->text_rendering_mode == 4 || pgs->text_rendering_mode == 6) &&
362
0
                        !pdev->remap_stroke_color) {
363
0
                        code = gx_set_dev_color(pgs);
364
0
                        if (code != 0)
365
0
                            return code;
366
0
                    }
367
0
                    if (pgs->text_rendering_mode == 1 || pgs->text_rendering_mode == 2 ||
368
0
                        pgs->text_rendering_mode == 5 || pgs->text_rendering_mode == 6) {
369
0
                        if (!pdev->remap_fill_color) {
370
0
                            if (pdev->remap_stroke_color) {
371
0
                                pdev->remap_stroke_color = false;
372
0
                            } else {
373
0
                                gs_swapcolors_quick(pgs);
374
0
                                code = gx_set_dev_color(pgs);
375
0
                                if (code == gs_error_Remap_Color)
376
0
                                    pdev->remap_stroke_color = true;
377
0
                                if (code != 0)
378
0
                                    return code;
379
0
                            }
380
0
                        } else
381
0
                            pdev->remap_fill_color = false;
382
0
                        gs_swapcolors_quick(pgs);
383
0
                        code = gx_set_dev_color(pgs);
384
0
                        if (code == gs_error_Remap_Color)
385
0
                            pdev->remap_fill_color = true;
386
0
                        if (code != 0)
387
0
                            return code;
388
0
                    }
389
0
                }
390
0
            }
391
0
        }
392
0
    }
393
0
    return code;
394
0
}
395
396
static int
397
pdf_prepare_text_drawing(gx_device_pdf *const pdev, gs_text_enum_t *pte)
398
0
{
399
0
    gs_gstate * pgs = pte->pgs;
400
0
    const gx_clip_path * pcpath = pte->pcpath;
401
0
    const gs_text_params_t *text = &pte->text;
402
0
    bool new_clip = false; /* Quiet compiler. */
403
0
    int code;
404
0
    gs_font *font = pte->current_font;
405
406
0
    if (!(text->operation & TEXT_DO_NONE) || pgs->text_rendering_mode == 3) {
407
0
        code = pdf_check_soft_mask(pdev, pte->pgs);
408
0
        if (code < 0)
409
0
            return code;
410
0
        new_clip = pdf_must_put_clip_path(pdev, pcpath);
411
0
        if (new_clip)
412
0
            code = pdf_unclip(pdev);
413
0
        else if (pdev->context == PDF_IN_NONE)
414
0
            code = pdf_open_page(pdev, PDF_IN_STREAM);
415
0
        else
416
0
            code = 0;
417
0
        if (code < 0)
418
0
            return code;
419
0
        code = pdf_prepare_fill(pdev, pgs, true);
420
0
        if (code < 0)
421
0
            return code;
422
0
    }
423
0
    if (text->operation & TEXT_DO_DRAW) {
424
        /*
425
         * Set the clipping path and drawing color.  We set both the fill
426
         * and stroke color, because we don't know whether the fonts will be
427
         * filled or stroked, and we can't set a color while we are in text
428
         * mode.  (This is a consequence of the implementation, not a
429
         * limitation of PDF.)
430
         */
431
432
0
        if (new_clip) {
433
0
            code = pdf_put_clip_path(pdev, pcpath);
434
0
            if (code < 0)
435
0
                return code;
436
0
        }
437
438
0
        if (!pdev->ForOPDFRead) {
439
0
            if (pgs->text_rendering_mode != 3 && pgs->text_rendering_mode != 7) {
440
0
                if (font->PaintType == 2) {
441
                    /* Bit awkward, if the PaintType is 2 then we want to set the
442
                     * current ie 'fill' colour, but as a stroke colour because we
443
                     * will later change the text rendering mode to 1 (stroke).
444
                     */
445
0
                    code = gx_set_dev_color(pgs);
446
0
                    if (code != 0)
447
0
                        return code;
448
0
                    code = pdf_set_drawing_color(pdev, pgs, pgs->color[0].dev_color, &pdev->saved_stroke_color,
449
0
                                 &pdev->stroke_used_process_color,
450
0
                                 &psdf_set_stroke_color_commands);
451
0
                    if (code < 0)
452
0
                        return code;
453
0
                } else {
454
0
                    if (pgs->text_rendering_mode == 0 || pgs->text_rendering_mode == 2 ||
455
0
                        pgs->text_rendering_mode == 4 || pgs->text_rendering_mode == 6) {
456
0
                        code = gx_set_dev_color(pgs);
457
0
                        if (code != 0)
458
0
                            return code;
459
0
                        code = pdf_set_drawing_color(pdev, pgs, pgs->color[0].dev_color, &pdev->saved_fill_color,
460
0
                                     &pdev->fill_used_process_color,
461
0
                                     &psdf_set_fill_color_commands);
462
0
                        if (code < 0)
463
0
                            return code;
464
0
                    }
465
0
                    if (pgs->text_rendering_mode == 1 || pgs->text_rendering_mode == 2 ||
466
0
                        pgs->text_rendering_mode == 5 || pgs->text_rendering_mode == 6) {
467
0
                        gs_swapcolors_quick(pgs);
468
0
                        code = gx_set_dev_color(pgs);
469
0
                        if (code != 0)
470
0
                            return code;
471
0
                        code = pdf_set_drawing_color(pdev, pgs, pgs->color[0].dev_color, &pdev->saved_stroke_color,
472
0
                                     &pdev->stroke_used_process_color,
473
0
                                     &psdf_set_stroke_color_commands);
474
0
                        if (code < 0)
475
0
                            return code;
476
477
0
                        gs_swapcolors_quick(pgs);
478
0
                    }
479
0
                }
480
0
            }
481
0
        } else {
482
0
            code = gx_set_dev_color(pgs);
483
0
            if (code != 0)
484
0
                return code;
485
486
0
            if ((code =
487
0
                 pdf_set_drawing_color(pdev, pgs, pgs->color[0].dev_color, &pdev->saved_stroke_color,
488
0
                                       &pdev->stroke_used_process_color,
489
0
                                       &psdf_set_stroke_color_commands)) < 0 ||
490
0
                (code =
491
0
                 pdf_set_drawing_color(pdev, pgs, pgs->color[0].dev_color, &pdev->saved_fill_color,
492
0
                                       &pdev->fill_used_process_color,
493
0
                                       &psdf_set_fill_color_commands)) < 0
494
0
                )
495
0
                return code;
496
0
        }
497
0
    }
498
0
    return 0;
499
0
}
500
501
int
502
gdev_pdf_text_begin(gx_device * dev, gs_gstate * pgs,
503
                    const gs_text_params_t *text, gs_font * font,
504
                    gx_path * path0, const gx_device_color * pdcolor,
505
                    const gx_clip_path * pcpath,
506
                    gs_memory_t * mem, gs_text_enum_t ** ppte)
507
0
{
508
0
    gx_device_pdf *const pdev = (gx_device_pdf *)dev;
509
0
    gx_path *path = path0;
510
0
    pdf_text_enum_t *penum;
511
0
    int code, user_defined = 0;
512
513
    /* should we "flatten" the font to "normal" marking operations */
514
0
    if (pdev->FlattenFonts) {
515
0
        font->dir->ccache.upper = 0;
516
0
        return gx_default_text_begin(dev, pgs, text, font, path, pdcolor,
517
0
                                         pcpath, mem, ppte);
518
0
    }
519
520
    /* Track the dominant text rotation. */
521
0
    {
522
0
        gs_matrix tmat;
523
0
        gs_point p;
524
0
        int i;
525
526
0
        gs_matrix_multiply(&font->FontMatrix, &ctm_only(pgs), &tmat);
527
0
        gs_distance_transform(1, 0, &tmat, &p);
528
0
        if (p.x > fabs(p.y))
529
0
            i = 0;
530
0
        else if (p.x < -fabs(p.y))
531
0
            i = 2;
532
0
        else if (p.y > fabs(p.x))
533
0
            i = 1;
534
0
        else if (p.y < -fabs(p.x))
535
0
            i = 3;
536
0
        else
537
0
            i = 4;
538
0
        pdf_current_page(pdev)->text_rotation.counts[i] += text->size;
539
0
    }
540
541
0
    pdev->last_charpath_op = 0;
542
0
    if ((text->operation & TEXT_DO_ANY_CHARPATH) && !path0->first_subpath) {
543
0
        if (pdf_compare_text_state_for_charpath(pdev->text->text_state, pdev, pgs, font, text))
544
0
            pdev->last_charpath_op = text->operation & TEXT_DO_ANY_CHARPATH;
545
0
    }
546
547
0
    if(font->FontType == ft_user_defined ||
548
0
       font->FontType == ft_PDF_user_defined ||
549
0
       font->FontType == ft_PCL_user_defined ||
550
0
       font->FontType == ft_MicroType ||
551
0
       font->FontType == ft_GL2_stick_user_defined ||
552
0
       font->FontType == ft_GL2_531)
553
0
        user_defined = 1;
554
555
    /* We need to know whether any of the glyphs in a string using a composite font
556
     * use a descendant font which is a type 3 (user-defined) so that we can properly
557
     * skip the caching below.
558
     */
559
0
    if(font->FontType == ft_composite && ((gs_font_type0 *)font)->data.FMapType != fmap_CMap) {
560
0
        int font_code;
561
0
        gs_char chr;
562
0
        gs_glyph glyph;
563
564
0
        rc_alloc_struct_1(penum, pdf_text_enum_t, &st_pdf_text_enum, mem,
565
0
                      return_error(gs_error_VMerror), "gdev_pdf_text_begin");
566
0
        penum->rc.free = rc_free_text_enum;
567
0
        penum->pte_default = 0;
568
0
        penum->charproc_accum = false;
569
0
        pdev->accumulating_charproc = false;
570
0
        penum->cdevproc_callout = false;
571
0
        penum->returned.total_width.x = penum->returned.total_width.y = 0;
572
0
        penum->cgp = NULL;
573
0
        penum->output_char_code = GS_NO_CHAR;
574
0
        code = gs_text_enum_init((gs_text_enum_t *)penum, &pdf_text_procs,
575
0
                             dev, pgs, text, font, path, pdcolor, pcpath, mem);
576
0
        if (code < 0) {
577
0
            gs_free_object(mem, penum, "gdev_pdf_text_begin");
578
0
            return code;
579
0
        }
580
0
        do {
581
0
            font_code = penum->orig_font->procs.next_char_glyph
582
0
                ((gs_text_enum_t *)penum, &chr, &glyph);
583
0
            if (font_code == 1){
584
0
                if (penum->fstack.items[penum->fstack.depth].font->FontType == 3) {
585
0
                    user_defined = 1;
586
0
                    break;
587
0
                }
588
0
            }
589
0
        } while(font_code != 2 && font_code >= 0);
590
0
        if (!user_defined) {
591
0
            if (penum->fstack.items[penum->fstack.depth].font->FontType == 3)
592
0
                user_defined = 1;
593
0
        }
594
0
        gs_text_release((gs_text_enum_t *)penum, "pdf_text_process");
595
0
    }
596
597
0
    if (!user_defined || !(text->operation & TEXT_DO_ANY_CHARPATH)) {
598
0
        if (user_defined &&
599
0
            (text->operation & TEXT_DO_NONE) && (text->operation & TEXT_RETURN_WIDTH)
600
0
            && pgs->text_rendering_mode != 3) {
601
            /* This is stringwidth, see gx_default_text_begin.
602
             * We need to prevent writing characters to PS cache,
603
             * otherwise the font converts to bitmaps.
604
             * So pass through even with stringwidth.
605
             */
606
0
            code = gx_hld_stringwidth_begin(pgs, &path);
607
0
            if (code < 0)
608
0
                return code;
609
0
        } else if ((!(text->operation & TEXT_DO_DRAW) && pgs->text_rendering_mode != 3)
610
0
                    || path == 0 || !path_position_valid(path)
611
0
                    || pdev->type3charpath)
612
0
            return gx_default_text_begin(dev, pgs, text, font, path, pdcolor,
613
0
                                         pcpath, mem, ppte);
614
0
        else if (text->operation & TEXT_DO_ANY_CHARPATH)
615
0
            return gx_default_text_begin(dev, pgs, text, font, path, pdcolor,
616
0
                                         pcpath, mem, ppte);
617
0
    }
618
619
0
    if (!pdev->ForOPDFRead) {
620
0
    code = pdf_prepare_text_color(pdev, pgs, text, font);
621
0
    if (code != 0)
622
0
        return code;
623
0
    }
624
625
    /* Allocate and initialize the enumerator. */
626
627
0
    rc_alloc_struct_1(penum, pdf_text_enum_t, &st_pdf_text_enum, mem,
628
0
                      return_error(gs_error_VMerror), "gdev_pdf_text_begin");
629
0
    penum->rc.free = rc_free_text_enum;
630
0
    penum->pte_default = 0;
631
0
    penum->charproc_accum = false;
632
0
    pdev->accumulating_charproc = false;
633
0
    penum->cdevproc_callout = false;
634
0
    penum->returned.total_width.x = penum->returned.total_width.y = 0;
635
0
    penum->cgp = NULL;
636
0
    penum->output_char_code = GS_NO_CHAR;
637
0
    code = gs_text_enum_init((gs_text_enum_t *)penum, &pdf_text_procs,
638
0
                             dev, pgs, text, font, path, pdcolor, pcpath, mem);
639
0
    if (code < 0) {
640
0
        gs_free_object(mem, penum, "gdev_pdf_text_begin");
641
0
        return code;
642
0
    }
643
0
    if (pdev->font3 != 0) {
644
        /* A text operation happens while accumulating a charproc.
645
           This is a case when source document uses a Type 3 font,
646
           which's charproc uses another font.
647
           Since the text operation is handled by the device,
648
           the font isn't converting to a raster (i.e. to a bitmap font).
649
           Disable the grid fitting for the convertion to get a proper outlines,
650
           because the viewer resolution is not known during the accumulation.
651
           Note we set identity CTM in pdf_text_set_cache for the accumilation,
652
           and therefore the font may look too small while the source charproc
653
           interpretation. The document tpc2.ps of the bug 687087 is an example.
654
        */
655
0
        penum->device_disabled_grid_fitting = true;
656
0
    }
657
658
0
    *ppte = (gs_text_enum_t *)penum;
659
660
0
    return 0;
661
0
}
662
663
/* ================ Font cache element ================ */
664
665
/* GC descriptor */
666
private_st_pdf_font_cache_elem();
667
668
/*
669
 * Compute id for a font cache element.
670
 */
671
static ulong
672
pdf_font_cache_elem_id(gs_font *font)
673
0
{
674
0
    return font->id;
675
0
}
676
677
pdf_font_cache_elem_t **
678
pdf_locate_font_cache_elem(gx_device_pdf *pdev, gs_font *font)
679
0
{
680
0
    pdf_font_cache_elem_t **e = &pdev->font_cache;
681
0
    long id = pdf_font_cache_elem_id(font);
682
683
0
    for (; *e != 0; e = &(*e)->next)
684
0
        if ((*e)->font_id == id) {
685
0
            return e;
686
0
        }
687
0
    return 0;
688
0
}
689
690
static void
691
pdf_remove_font_cache_elem(gx_device_pdf *pdev, pdf_font_cache_elem_t *e0)
692
0
{
693
0
    pdf_font_cache_elem_t **e = &pdev->font_cache;
694
695
0
    for (; *e != 0; e = &(*e)->next)
696
0
        if (*e == e0) {
697
0
            *e = e0->next;
698
0
            gs_free_object(pdev->pdf_memory, e0->glyph_usage,
699
0
                                "pdf_remove_font_cache_elem");
700
0
            gs_free_object(pdev->pdf_memory, e0->real_widths,
701
0
                                "pdf_remove_font_cache_elem");
702
            /* Clean pointers, because gs_free_object below may work idle
703
               when this function is called by a garbager notification.
704
               Leaving unclean pointers may cause
705
               a further heap validation to fail
706
               since the unfreed structure points to freed areas.
707
               For instance, e0->next may point to an element,
708
               which is really freed with a subsequent 'restore'.
709
               Bug 688837. */
710
0
            e0->next = 0;
711
0
            e0->glyph_usage = 0;
712
0
            e0->real_widths = 0;
713
0
            gs_free_object(pdev->pdf_memory, e0,
714
0
                                "pdf_remove_font_cache_elem");
715
0
            return;
716
0
        }
717
0
}
718
719
static void
720
font_cache_elem_array_sizes(gx_device_pdf *pdev, gs_font *font,
721
                            int *num_widths, int *num_chars)
722
0
{
723
0
    switch (font->FontType) {
724
0
    case ft_composite:
725
0
        *num_widths = 0; /* Unused for Type 0 */
726
0
        *num_chars = 65536; /* No chance to determine, use max. */
727
0
        break;
728
0
    case ft_encrypted:
729
0
    case ft_encrypted2:
730
0
    case ft_user_defined:
731
0
    case ft_PDF_user_defined:
732
0
    case ft_GL2_stick_user_defined:
733
0
    case ft_PCL_user_defined:
734
0
    case ft_MicroType:
735
0
    case ft_GL2_531:
736
0
    case ft_disk_based:
737
0
    case ft_Chameleon:
738
0
    case ft_TrueType:
739
0
        *num_widths = *num_chars = 256; /* Assuming access to glyph_usage by character codes */
740
0
        break;
741
0
    case ft_CID_encrypted:
742
0
        *num_widths = *num_chars = ((gs_font_cid0 *)font)->cidata.common.MaxCID + 1;
743
0
        break;
744
0
    case ft_CID_TrueType:
745
0
        *num_widths = *num_chars = ((gs_font_cid2 *)font)->cidata.common.CIDCount;
746
0
        break;
747
0
    default:
748
0
        *num_widths = *num_chars = 65536; /* No chance to determine, use max. */
749
0
    }
750
0
}
751
752
static int
753
alloc_font_cache_elem_arrays(gx_device_pdf *pdev, pdf_font_cache_elem_t *e,
754
                             gs_font *font)
755
0
{
756
0
    int num_widths, num_chars, len;
757
758
0
    font_cache_elem_array_sizes(pdev, font, &num_widths, &num_chars);
759
0
    len = (num_chars + 7) / 8;
760
0
    e->glyph_usage = gs_alloc_bytes(pdev->pdf_memory,
761
0
                        len, "alloc_font_cache_elem_arrays");
762
763
0
    e->real_widths = (num_widths > 0 ? (double *)gs_alloc_bytes(pdev->pdf_memory,
764
0
                        num_widths * sizeof(*e->real_widths) *
765
0
                            ((font->FontType == ft_user_defined ||
766
0
                            font->FontType == ft_PDF_user_defined ||
767
0
                            font->FontType == ft_GL2_stick_user_defined ||
768
0
                            font->FontType == ft_PCL_user_defined ||
769
0
                            font->FontType == ft_MicroType ||
770
0
                            font->FontType == ft_GL2_531) ? 2 : 1),
771
0
                        "alloc_font_cache_elem_arrays") : NULL);
772
0
    if (e->glyph_usage == NULL || (num_widths !=0 && e->real_widths == NULL)) {
773
0
        gs_free_object(pdev->pdf_memory, e->glyph_usage,
774
0
                            "pdf_attach_font_resource");
775
0
        gs_free_object(pdev->pdf_memory, e->real_widths,
776
0
                            "alloc_font_cache_elem_arrays");
777
0
        return_error(gs_error_VMerror);
778
0
    }
779
0
    e->num_chars = num_chars;
780
0
    e->num_widths = num_widths;
781
0
    memset(e->glyph_usage, 0, len);
782
0
    if (e->real_widths != NULL)
783
0
        memset(e->real_widths, 0, num_widths * sizeof(*e->real_widths));
784
0
    return 0;
785
0
}
786
787
int
788
pdf_free_font_cache(gx_device_pdf *pdev)
789
0
{
790
0
    pdf_font_cache_elem_t *e = pdev->font_cache, *next;
791
792
    /* fixed! fixme : release elements.
793
     * We no longer track font_cache elements in the original font, which is where
794
     * the memory used to be released. So now we must release it ourselves.
795
     */
796
797
0
    while (e != NULL) {
798
0
        next = e->next;
799
0
        pdf_remove_font_cache_elem(pdev, e);
800
0
        e = next;
801
0
    }
802
0
    pdev->font_cache = NULL;
803
0
    return 0;
804
0
}
805
806
/*
807
 * Retrive font resource attached to a font,
808
 * allocating glyph_usage and real_widths on request.
809
 */
810
int
811
pdf_attached_font_resource(gx_device_pdf *pdev, gs_font *font,
812
                            pdf_font_resource_t **pdfont, byte **glyph_usage,
813
                            double **real_widths, int *num_chars, int *num_widths)
814
0
{
815
0
    pdf_font_cache_elem_t **e = pdf_locate_font_cache_elem(pdev, font);
816
817
0
    if (e != NULL && (((*e)->glyph_usage == NULL && glyph_usage !=NULL) ||
818
0
                      ((*e)->real_widths == NULL && real_widths !=NULL))) {
819
0
        int code = alloc_font_cache_elem_arrays(pdev, *e, font);
820
821
0
        if (code < 0)
822
0
            return code;
823
0
    }
824
0
    *pdfont = (e == NULL ? NULL : (*e)->pdfont);
825
0
    if (glyph_usage != NULL)
826
0
        *glyph_usage = (e == NULL ? NULL : (*e)->glyph_usage);
827
0
    if (real_widths != NULL)
828
0
        *real_widths = (e == NULL ? NULL : (*e)->real_widths);
829
0
    if (num_chars != NULL)
830
0
        *num_chars = (e == NULL ? 0 : (*e)->num_chars);
831
0
    if (num_widths != NULL)
832
0
        *num_widths = (e == NULL ? 0 : (*e)->num_widths);
833
0
    return 0;
834
0
}
835
836
/*
837
 * Attach font resource to a font.
838
 */
839
int
840
pdf_attach_font_resource(gx_device_pdf *pdev, gs_font *font,
841
                         pdf_font_resource_t *pdfont)
842
0
{
843
0
    int num_chars, num_widths, len;
844
0
    pdf_font_cache_elem_t *e, **pe = pdf_locate_font_cache_elem(pdev, font);
845
846
    /* Allow the HPGL2 stick font to be attached to a type 3 font, it *is* a
847
     * type 3 font, its just identified differently so that we can choose not
848
     * to capture it elsewhere. Same for PCL bitmap fonts.
849
     */
850
0
    if (pdfont->FontType != font->FontType &&
851
0
        (pdfont->FontType != ft_user_defined ||
852
0
        (font->FontType != ft_PCL_user_defined &&
853
0
        font->FontType != ft_PDF_user_defined &&
854
0
        font->FontType != ft_MicroType &&
855
0
        font->FontType != ft_GL2_stick_user_defined &&
856
0
        font->FontType != ft_GL2_531)))
857
0
        return_error(gs_error_unregistered); /* Must not happen. */
858
0
    font_cache_elem_array_sizes(pdev, font, &num_widths, &num_chars);
859
0
    len = (num_chars + 7) / 8;
860
0
    if (pe != NULL) {
861
0
        e = *pe;
862
0
        if (e->pdfont == pdfont)
863
0
            return 0;
864
0
        e->pdfont = pdfont;
865
        /* Reset glyph cache because e->pdfont had changed. */
866
0
        memset(e->glyph_usage, 0, len);
867
0
        memset(e->real_widths, 0, num_widths * sizeof(*e->real_widths));
868
0
    } else {
869
0
        e = (pdf_font_cache_elem_t *)gs_alloc_struct(pdev->pdf_memory,
870
0
                pdf_font_cache_elem_t, &st_pdf_font_cache_elem,
871
0
                            "pdf_attach_font_resource");
872
0
        if (e == NULL)
873
0
            return_error(gs_error_VMerror);
874
0
        e->pdfont = pdfont;
875
0
        e->font_id = pdf_font_cache_elem_id(font);
876
0
        e->num_chars = 0;
877
0
        e->glyph_usage = NULL;
878
0
        e->real_widths = NULL;
879
0
        e->next = pdev->font_cache;
880
0
        pdev->font_cache = e;
881
0
        return 0;
882
0
    }
883
0
    return 0;
884
0
}
885
886
/* ================ Process text ================ */
887
888
/* ---------------- Internal utilities ---------------- */
889
890
/*
891
 * Compute and return the orig_matrix of a font.
892
 */
893
int
894
pdf_font_orig_matrix(const gs_font *font, gs_matrix *pmat)
895
0
{
896
0
    switch (font->FontType) {
897
0
    case ft_composite:                /* subfonts have their own FontMatrix */
898
0
    case ft_TrueType:
899
0
    case ft_CID_TrueType:
900
        /* The TrueType FontMatrix is 1 unit per em, which is what we want. */
901
0
        gs_make_identity(pmat);
902
0
        return 0;
903
0
    case ft_encrypted:
904
0
    case ft_encrypted2:
905
0
    case ft_CID_encrypted:
906
0
    case ft_user_defined:
907
0
    case ft_PCL_user_defined:
908
0
    case ft_PDF_user_defined:
909
0
    case ft_MicroType:
910
0
    case ft_GL2_stick_user_defined:
911
0
    case ft_GL2_531:
912
        /*
913
         * Type 1 fonts are supposed to use a standard FontMatrix of
914
         * [0.001 0 0 0.001 0 0], with a 1000-unit cell.  However,
915
         * Windows NT 4.0 creates Type 1 fonts, apparently derived from
916
         * TrueType fonts, that use a 2048-unit cell and corresponding
917
         * FontMatrix.  Also, some PS programs perform font scaling by
918
         * replacing FontMatrix like this :
919
         *
920
         *   /f12 /Times-Roman findfont
921
         *   copyfont          % (remove FID)
922
         *   dup /FontMatrix [0.012 0 0 0.012 0 0] put
923
         *   definefont
924
         *   /f12 1 selectfont
925
         *
926
         * Such fonts are their own "base font", but the orig_matrix
927
         * must still be set to 0.001, not 0.012 .
928
         *
929
         * The old code used a heuristic to detect and correct for this here.
930
         * Unfortunately it doesn't work properly when it meets a font
931
         * with FontMatrix like this :
932
         *
933
         *   /FontMatrix [1 2288 div 0 0 1 2288 div 0 0 ] def
934
         *
935
         * (the bug 686970). Also comparefiles\455690.pdf appears to
936
         * have similar problem. Therefore we added a support to lib/gs_fonts.ps,
937
         * src/zbfont.c, src/gsfont.c that provides an acces to the original
938
         * font via a special key OrigFont added to the font dictionary while definefont.
939
         * Now we work through this access with PS interpreter,
940
         * but keep the old heuristic for other clients.
941
         */
942
0
        {
943
0
            const gs_font *base_font = font;
944
945
0
            while (base_font->base != base_font)
946
0
                base_font = base_font->base;
947
0
            if (font->FontType == ft_user_defined ||
948
0
                font->FontType == ft_PDF_user_defined ||
949
0
                font->FontType == ft_PCL_user_defined ||
950
0
                font->FontType == ft_MicroType ||
951
0
                font->FontType == ft_GL2_stick_user_defined ||
952
0
                font->FontType == ft_GL2_531)
953
0
                *pmat = base_font->FontMatrix;
954
0
            else if (base_font->orig_FontMatrix.xx != 0 || base_font->orig_FontMatrix.xy != 0 ||
955
0
                base_font->orig_FontMatrix.yx != 0 || base_font->orig_FontMatrix.yy != 0)
956
0
                *pmat = base_font->orig_FontMatrix;
957
0
            else {
958
                /*  Must not happen with PS interpreter.
959
                    Provide a hewuristic for other clients.
960
                */
961
0
                if (base_font->FontMatrix.xx == 1.0/2048 &&
962
0
                    base_font->FontMatrix.xy == 0 &&
963
0
                    base_font->FontMatrix.yx == 0 &&
964
0
                    any_abs(base_font->FontMatrix.yy) == 1.0/2048
965
0
                    )
966
0
                    *pmat = base_font->FontMatrix;
967
0
                else
968
0
                    gs_make_scaling(0.001, 0.001, pmat);
969
0
            }
970
0
        }
971
0
        return 0;
972
0
    default:
973
0
        return_error(gs_error_rangecheck);
974
0
    }
975
0
}
976
977
/*
978
 * Special version of pdf_font_orig_matrix(), that cares FDArray font's FontMatrix too.
979
 * Called only by pdf_glyph_width().
980
 * 'cid' is only consulted if 'font' is a CIDFontType 0 CID font.
981
 */
982
static int
983
glyph_orig_matrix(const gs_font *font, gs_glyph cid, gs_matrix *pmat)
984
0
{
985
0
    int code = pdf_font_orig_matrix(font, pmat);
986
0
    if (code >= 0) {
987
0
        if (font->FontType == ft_CID_encrypted) {
988
0
            int fidx;
989
990
0
            if (cid < GS_MIN_CID_GLYPH)
991
0
                cid = GS_MIN_CID_GLYPH;
992
0
            code = ((gs_font_cid0 *)font)->cidata.glyph_data((gs_font_base *)font,
993
0
                                cid, NULL, &fidx);
994
0
            if (code < 0) {
995
0
                code = ((gs_font_cid0 *)font)->cidata.glyph_data((gs_font_base *)font,
996
0
                                (gs_glyph)GS_MIN_CID_GLYPH, NULL, &fidx);
997
0
            }
998
0
            if (code >= 0) {
999
0
                gs_matrix_multiply(&(gs_cid0_indexed_font(font, fidx)->FontMatrix),
1000
0
                                pmat, pmat);
1001
0
            }
1002
0
        }
1003
0
    }
1004
0
    return code;
1005
0
}
1006
1007
/*
1008
 * Check the Encoding compatibility
1009
 */
1010
bool
1011
pdf_check_encoding_compatibility(const pdf_font_resource_t *pdfont,
1012
            const pdf_char_glyph_pair_t *pairs, int num_chars)
1013
0
{
1014
0
    int i;
1015
1016
0
    for (i = 0; i < num_chars; ++i) {
1017
0
        gs_char ch = pairs[i].chr;
1018
0
        pdf_encoding_element_t *pet = &pdfont->u.simple.Encoding[ch];
1019
1020
0
        if (pairs[i].glyph == pet->glyph)
1021
0
            continue;
1022
0
        if (pet->glyph != GS_NO_GLYPH) /* encoding conflict */
1023
0
            return false;
1024
0
    }
1025
0
    return true;
1026
0
}
1027
1028
/*
1029
 * Check whether the Encoding has listed glyphs.
1030
 */
1031
static bool
1032
pdf_check_encoding_has_glyphs(const pdf_font_resource_t *pdfont,
1033
            const pdf_char_glyph_pair_t *pairs, int num_chars)
1034
0
{
1035
    /* This function is pretty slow, but we can't find a better algorithm.
1036
       It works for the case of glyphshow with no proper encoding,
1037
       which we believe comes from poorly designed documents.
1038
     */
1039
0
    int i, ch;
1040
1041
0
    for (i = 0; i < num_chars; ++i) {
1042
0
        for (ch = 0; ch < 256; ch++) {
1043
0
            pdf_encoding_element_t *pet = &pdfont->u.simple.Encoding[ch];
1044
1045
0
            if (pairs[i].glyph == pet->glyph)
1046
0
                return true;
1047
0
        }
1048
0
    }
1049
0
    return false;
1050
0
}
1051
1052
/*
1053
 * Check font resource for encoding compatibility.
1054
 */
1055
static bool
1056
pdf_is_compatible_encoding(gx_device_pdf *pdev, pdf_font_resource_t *pdfont,
1057
                           gs_font *font, const pdf_char_glyph_pair_t *pairs, int num_chars)
1058
0
{
1059
    /*
1060
     * This crude version of the code ignores
1061
     * the possibility of re-encoding characters.
1062
     */
1063
0
    switch (pdfont->FontType) {
1064
0
    case ft_composite:
1065
0
        {   /*
1066
             * We assume that source document don't redefine CMap
1067
             * resources and that incremental CMaps do not exist.
1068
             * Therefore we don't maintain stable CMap copies,
1069
             * but just compare CMap names for equality.
1070
             * A better implementation should compare the chars->glyphs
1071
             * translation against the stable copy of CMap,
1072
             * which to be handled with PDF CMap resource.
1073
             */
1074
0
            gs_font_type0 *pfont = (gs_font_type0 *)font;
1075
1076
0
            if (pfont->data.FMapType == fmap_CMap) {
1077
0
                const gs_cmap_t *pcmap = pfont->data.CMap;
1078
0
                const gs_const_string *s0 = &pdfont->u.type0.CMapName;
1079
0
                const gs_const_string *s1 = &pcmap->CMapName;
1080
1081
0
                return (s0->size == s1->size &&
1082
0
                        !memcmp(s0->data, s1->data, s0->size));
1083
0
            }
1084
0
        }
1085
0
        return false;
1086
0
    case ft_user_defined:
1087
0
    case ft_PDF_user_defined:
1088
0
    case ft_PCL_user_defined:
1089
0
    case ft_MicroType:
1090
0
    case ft_GL2_stick_user_defined:
1091
0
    case ft_GL2_531:
1092
0
        if (pdfont->u.simple.Encoding == NULL)
1093
0
            return false; /* Not sure. Happens with 020-01.ps . */
1094
        /* fall through */
1095
0
    case ft_encrypted:
1096
0
    case ft_encrypted2:
1097
0
    case ft_TrueType:
1098
0
        return pdf_check_encoding_compatibility(pdfont, pairs, num_chars);
1099
0
    case ft_CID_encrypted:
1100
0
    case ft_CID_TrueType:
1101
0
        {
1102
0
            gs_font *font1 = (gs_font *)pdf_font_resource_font(pdfont, false);
1103
1104
0
            return gs_is_CIDSystemInfo_compatible(
1105
0
                                gs_font_cid_system_info(font),
1106
0
                                gs_font_cid_system_info(font1));
1107
0
        }
1108
0
    default:
1109
0
        return false;
1110
0
    }
1111
0
}
1112
1113
/*
1114
 * Check whethet the font resource has glyphs.
1115
 */
1116
static bool
1117
pdf_font_has_glyphs(gx_device_pdf *pdev, pdf_font_resource_t *pdfont,
1118
                           gs_font *font, const pdf_char_glyph_pair_t *pairs, int num_chars)
1119
0
{
1120
    /*
1121
     * This crude version of the code ignores
1122
     * the possibility of re-encoding characters.
1123
     */
1124
0
    switch (pdfont->FontType) {
1125
0
    case ft_composite:
1126
0
    case ft_user_defined:
1127
0
    case ft_PDF_user_defined:
1128
0
    case ft_PCL_user_defined:
1129
0
    case ft_MicroType:
1130
0
    case ft_GL2_stick_user_defined:
1131
0
    case ft_GL2_531:
1132
        /* Unused case. */
1133
0
        return false;
1134
0
    case ft_encrypted:
1135
0
    case ft_encrypted2:
1136
0
    case ft_TrueType:
1137
0
        return pdf_check_encoding_has_glyphs(pdfont, pairs, num_chars);
1138
0
    case ft_CID_encrypted:
1139
0
    case ft_CID_TrueType:
1140
        /* Unused case. */
1141
0
        return false;
1142
0
    default:
1143
0
        return false;
1144
0
    }
1145
0
}
1146
1147
/*
1148
 * Find a font resource compatible with a given font.
1149
 */
1150
static int
1151
pdf_find_font_resource(gx_device_pdf *pdev, gs_font *font,
1152
                       pdf_resource_type_t type,
1153
                       pdf_font_resource_t **ppdfont,
1154
                       pdf_char_glyph_pairs_t *cgp,
1155
                       bool compatible_encoding)
1156
0
{
1157
0
    pdf_resource_t **pchain = pdev->resources[type].chains;
1158
0
    pdf_resource_t *pres;
1159
0
    int i;
1160
1161
0
    for (i = 0; i < NUM_RESOURCE_CHAINS; i++) {
1162
0
        for (pres = pchain[i]; pres != 0; pres = pres->next) {
1163
0
            pdf_font_resource_t *pdfont = (pdf_font_resource_t *)pres;
1164
0
            const gs_font_base *cfont;
1165
0
            gs_font *ofont = font;
1166
0
            int code;
1167
1168
0
            cfont = (gs_font_base *)font;
1169
0
            if (uid_is_XUID(&cfont->UID)){
1170
0
                int size = uid_XUID_size(&cfont->UID);
1171
0
                long *xvalues = uid_XUID_values(&cfont->UID);
1172
0
                if (xvalues && size >= 2 && xvalues[0] == 1000000) {
1173
0
                    if (xvalues[size - 1] != pdfont->XUID)
1174
0
                        continue;
1175
0
                }
1176
0
            }
1177
1178
0
            if (font->FontType != pdfont->FontType)
1179
0
                continue;
1180
0
            if (pdfont->FontType == ft_composite) {
1181
0
                gs_font_type0 *font0 = (gs_font_type0 *)font;
1182
1183
0
                ofont = font0->data.FDepVector[0]; /* See pdf_make_font_resource. */
1184
0
                cfont = pdf_font_resource_font(pdfont->u.type0.DescendantFont, false);
1185
0
                if (font0->data.CMap->WMode != pdfont->u.type0.WMode)
1186
0
                    continue;
1187
0
            } else
1188
0
                cfont = pdf_font_resource_font(pdfont, false);
1189
0
            if (!pdf_is_CID_font(ofont) &&
1190
0
                (compatible_encoding
1191
0
                    ? !pdf_is_compatible_encoding(pdev, pdfont, font, cgp->s, cgp->num_all_chars)
1192
0
                    : !pdf_font_has_glyphs(pdev, pdfont, font, cgp->s, cgp->num_all_chars)))
1193
0
                continue;
1194
0
            if (cfont == 0)
1195
0
                continue;
1196
0
            code = gs_copied_can_copy_glyphs((const gs_font *)cfont, ofont,
1197
0
                            &cgp->s[cgp->unused_offset].glyph, cgp->num_unused_chars,
1198
0
                            sizeof(pdf_char_glyph_pair_t), true);
1199
0
            if (code == gs_error_unregistered) /* Debug purpose only. */
1200
0
                return code;
1201
0
            if(code > 0) {
1202
0
                *ppdfont = pdfont;
1203
0
                return 1;
1204
0
            }
1205
0
        }
1206
0
    }
1207
0
    return 0;
1208
0
}
1209
1210
/*
1211
 * Find a type0 font resource for a gived descendent name and CMap name.
1212
 */
1213
static int
1214
pdf_find_type0_font_resource(gx_device_pdf *pdev, const pdf_font_resource_t *pdsubf,
1215
            const gs_const_string *CMapName, uint font_index, pdf_font_resource_t **ppdfont)
1216
0
{
1217
0
    pdf_resource_t **pchain = pdev->resources[resourceFont].chains;
1218
0
    pdf_resource_t *pres;
1219
0
    int i;
1220
1221
0
    for (i = 0; i < NUM_RESOURCE_CHAINS; i++) {
1222
0
        for (pres = pchain[i]; pres != 0; pres = pres->next) {
1223
0
            pdf_font_resource_t *pdfont = (pdf_font_resource_t *)pres;
1224
1225
0
            if (pdfont->FontType != ft_composite)
1226
0
                continue;
1227
0
            if (pdfont->u.type0.DescendantFont != pdsubf)
1228
0
                continue;
1229
0
            if (pdfont->u.type0.font_index != font_index)
1230
0
                continue;
1231
1232
            /* Check to see if the PDF font name is of the form FontName-CMapName
1233
             * If it is, check the name and cmap against the BaseFont Name and CMap
1234
             * I'm not certain this is *ever* true.
1235
             */
1236
0
            if (pdfont->BaseFont.size == pdsubf->BaseFont.size + CMapName->size + 1) {
1237
0
                if (memcmp(pdfont->BaseFont.data + pdsubf->BaseFont.size + 1,
1238
0
                            CMapName->data, CMapName->size))
1239
0
                    continue;
1240
0
            } else {
1241
                /* Otherwise, check the PDF font name against the subfont name, and the
1242
                 * CMap used with the PDF font against the requested CMap. If either differs
1243
                 * then this PDF font is not usable.
1244
                 */
1245
0
                if (pdfont->BaseFont.size != pdsubf->BaseFont.size)
1246
0
                    continue;
1247
0
                if (pdfont->u.type0.CMapName.size != CMapName->size)
1248
0
                    continue;
1249
0
                if (memcmp(pdfont->u.type0.CMapName.data, CMapName->data, CMapName->size))
1250
0
                    continue;
1251
0
            }
1252
1253
0
            *ppdfont = pdfont;
1254
0
            return 1;
1255
0
        }
1256
0
    }
1257
0
    return 0;
1258
0
}
1259
1260
static int pdf_make_font_resource(gx_device_pdf *pdev, gs_font *font,
1261
                       pdf_font_resource_t **ppdfont,
1262
                       pdf_char_glyph_pairs_t *cgp);
1263
1264
/*
1265
 * Create or find a CID font resource object for a glyph set.
1266
 */
1267
int
1268
pdf_obtain_cidfont_resource(gx_device_pdf *pdev, gs_font *subfont,
1269
                            pdf_font_resource_t **ppdsubf,
1270
                            pdf_char_glyph_pairs_t *cgp)
1271
0
{
1272
0
    int code = 0;
1273
1274
0
    code = pdf_attached_font_resource(pdev, subfont, ppdsubf, NULL, NULL, NULL, NULL);
1275
0
    if (code < 0)
1276
0
        return code;
1277
0
    if (*ppdsubf != NULL) {
1278
0
        const gs_font_base *cfont = pdf_font_resource_font(*ppdsubf, false);
1279
1280
0
        code = gs_copied_can_copy_glyphs((const gs_font *)cfont, subfont,
1281
0
                        &cgp->s[cgp->unused_offset].glyph, cgp->num_unused_chars,
1282
0
                        sizeof(pdf_char_glyph_pair_t), true);
1283
0
        if (code > 0)
1284
0
            return 0;
1285
0
        if (code < 0)
1286
0
            return code;
1287
0
        *ppdsubf = NULL;
1288
0
    }
1289
0
    code = pdf_find_font_resource(pdev, subfont,
1290
0
                                  resourceCIDFont, ppdsubf, cgp, true);
1291
0
    if (code < 0)
1292
0
        return code;
1293
0
    if (*ppdsubf == NULL) {
1294
0
        code = pdf_make_font_resource(pdev, subfont, ppdsubf, cgp);
1295
0
        if (code < 0)
1296
0
            return code;
1297
0
    }
1298
0
    return pdf_attach_font_resource(pdev, subfont, *ppdsubf);
1299
0
}
1300
1301
/*
1302
 * Refine index of BaseEncoding.
1303
 */
1304
static int
1305
pdf_refine_encoding_index(const gx_device_pdf *pdev, int index, bool is_standard)
1306
0
{
1307
0
    if (pdev->ForOPDFRead) {
1308
        /*
1309
        * Allow Postscript encodings only.
1310
        * No, also allow MacRoman because if we have a TT font, and subset it, then opdfread
1311
        * will prefer thte MacRoman CMAP from the subset TT font.
1312
        */
1313
0
        switch (index) {
1314
1315
0
            case ENCODING_INDEX_STANDARD: return index;
1316
0
            case ENCODING_INDEX_MACROMAN: return index;
1317
0
            case ENCODING_INDEX_ISOLATIN1: return index;
1318
0
            default:
1319
0
                return ENCODING_INDEX_STANDARD;
1320
0
        }
1321
0
    }
1322
    /*
1323
     * Per the PDF 1.3 documentation, there are only 3 BaseEncoding
1324
     * values allowed for non-embedded fonts.  Pick one here.
1325
     */
1326
0
    switch (index) {
1327
0
    case ENCODING_INDEX_WINANSI:
1328
0
    case ENCODING_INDEX_MACROMAN:
1329
0
    case ENCODING_INDEX_MACEXPERT:
1330
0
        return index;
1331
0
    case ENCODING_INDEX_STANDARD:
1332
0
        if (is_standard)
1333
0
            return index;
1334
        /* Falls through. */
1335
0
    default:
1336
0
        return ENCODING_INDEX_WINANSI;
1337
0
    }
1338
0
}
1339
1340
/*
1341
 * Create a font resource object for a gs_font of Type 3.
1342
 */
1343
int
1344
pdf_make_font3_resource(gx_device_pdf *pdev, gs_font *font,
1345
                       pdf_font_resource_t **ppdfont)
1346
0
{
1347
0
    const gs_font_base *bfont = (const gs_font_base *)font;
1348
0
    pdf_font_resource_t *pdfont;
1349
0
    byte *cached;
1350
0
    int code;
1351
1352
0
    cached = gs_alloc_bytes(pdev->pdf_memory, 256/8, "pdf_make_font3_resource");
1353
0
    if (cached == NULL)
1354
0
        return_error(gs_error_VMerror);
1355
0
    code = font_resource_encoded_alloc(pdev, &pdfont, bfont->id,
1356
0
                    ft_user_defined, pdf_write_contents_bitmap);
1357
0
    if (code < 0) {
1358
0
        gs_free_object(pdev->pdf_memory, cached, "pdf_make_font3_resource");
1359
0
        return code;
1360
0
    }
1361
0
    memset(cached, 0, 256 / 8);
1362
0
    pdfont->mark_glyph = font->dir->ccache.mark_glyph; /* For pdf_font_resource_enum_ptrs. */
1363
0
    pdfont->u.simple.s.type3.bitmap_font = false;
1364
0
    pdfont->u.simple.BaseEncoding = pdf_refine_encoding_index(pdev,
1365
0
                        bfont->nearest_encoding_index, true);
1366
0
    pdfont->u.simple.s.type3.char_procs = NULL;
1367
0
    pdfont->u.simple.s.type3.cached = cached;
1368
0
    if ((pdfont->FontType == ft_user_defined  || pdfont->FontType == ft_PDF_user_defined) && bfont->FontBBox.p.x == 0.0 &&
1369
0
        bfont->FontBBox.p.y == 0.00 && bfont->FontBBox.q.x == 0.00 &&
1370
0
        bfont->FontBBox.q.y == 0.0) {
1371
        /* I think this can only happen with a type 3 (bitmap) font from PCL.
1372
         * If we leave the BBox as 0 then we end up putting a 0 0 1000 1000 in
1373
         * the PDF. This causes Acrobat to be unable to search or highlight
1374
         * the search results. I think that we will always get a consistent
1375
         * type of font from the PCL interpreter, and if so the correct BBox
1376
         * sould always is 0 0 1 -1.
1377
         */
1378
0
        pdfont->u.simple.s.type3.FontBBox.p.x = 0;
1379
0
        pdfont->u.simple.s.type3.FontBBox.p.y = 0;
1380
0
        pdfont->u.simple.s.type3.FontBBox.q.x = 1;
1381
0
        pdfont->u.simple.s.type3.FontBBox.q.y = -1;
1382
0
    } else {
1383
0
        pdfont->u.simple.s.type3.FontBBox.p.x = bfont->FontBBox.p.x;
1384
0
        pdfont->u.simple.s.type3.FontBBox.p.y = bfont->FontBBox.p.y;
1385
0
        pdfont->u.simple.s.type3.FontBBox.q.x = bfont->FontBBox.q.x;
1386
0
        pdfont->u.simple.s.type3.FontBBox.q.y = bfont->FontBBox.q.y;
1387
0
    }
1388
0
    pdfont->u.simple.s.type3.FontMatrix = bfont->FontMatrix;
1389
0
    pdfont->u.simple.s.type3.Resources = cos_dict_alloc(pdev, "pdf_make_font3_resource");
1390
0
    if (pdfont->u.simple.s.type3.Resources == NULL)
1391
0
        return_error(gs_error_VMerror);
1392
    /* Adobe viewers have a precision problem with small font matrices : */
1393
    /* Don't perform this test if all entries are 0, leads to infinite loop! */
1394
0
    if (pdfont->u.simple.s.type3.FontMatrix.xx != 0.0 ||
1395
0
        pdfont->u.simple.s.type3.FontMatrix.xy != 0.0 ||
1396
0
        pdfont->u.simple.s.type3.FontMatrix.yx != 0.0 ||
1397
0
        pdfont->u.simple.s.type3.FontMatrix.yy != 0.0) {
1398
0
        while (any_abs(pdfont->u.simple.s.type3.FontMatrix.xx) < 0.001 &&
1399
0
               any_abs(pdfont->u.simple.s.type3.FontMatrix.xy) < 0.001 &&
1400
0
               any_abs(pdfont->u.simple.s.type3.FontMatrix.yx) < 0.001 &&
1401
0
               any_abs(pdfont->u.simple.s.type3.FontMatrix.yy) < 0.001) {
1402
0
            pdfont->u.simple.s.type3.FontMatrix.xx *= 10;
1403
0
            pdfont->u.simple.s.type3.FontMatrix.xy *= 10;
1404
0
            pdfont->u.simple.s.type3.FontMatrix.yx *= 10;
1405
0
            pdfont->u.simple.s.type3.FontMatrix.yy *= 10;
1406
0
        }
1407
0
    }
1408
0
    *ppdfont = pdfont;
1409
0
    return 0;
1410
0
}
1411
1412
/*
1413
 * Create a font resource object for a gs_font.  Return 1 iff the
1414
 * font was newly created (it's a roudiment, keeping reverse compatibility).
1415
 * This procedure is only intended to be called
1416
 * from a few places in the text code.
1417
 */
1418
static int
1419
pdf_make_font_resource(gx_device_pdf *pdev, gs_font *font,
1420
                       pdf_font_resource_t **ppdfont,
1421
                       pdf_char_glyph_pairs_t *cgp)
1422
0
{
1423
0
    int index = -1;
1424
0
    int BaseEncoding = ENCODING_INDEX_UNKNOWN;
1425
0
    pdf_font_embed_t embed;
1426
0
    pdf_font_descriptor_t *pfd = 0;
1427
0
    int (*font_alloc)(gx_device_pdf *, pdf_font_resource_t **,
1428
0
                      gs_id, pdf_font_descriptor_t *);
1429
0
    gs_font *base_font = font; /* A roudiment from old code. Keep it for a while. */
1430
0
    pdf_font_resource_t *pdfont;
1431
0
    pdf_standard_font_t *const psfa =
1432
0
        pdev->text->outline_fonts->standard_fonts;
1433
0
    int code = 0;
1434
0
    long XUID = 0;
1435
0
    gs_font_base *bfont = (gs_font_base *)font;
1436
1437
0
    if (pdev->version < psdf_version_level2_with_TT) {
1438
0
        switch(font->FontType) {
1439
0
            case ft_TrueType:
1440
0
            case ft_CID_TrueType:
1441
0
                return_error(gs_error_undefined);
1442
0
            default:
1443
0
                break;
1444
0
        }
1445
0
    }
1446
0
    if (pdev->ForOPDFRead && !pdev->HaveCIDSystem) {
1447
0
        switch(font->FontType) {
1448
0
            case ft_CID_encrypted:
1449
0
            case ft_CID_TrueType:
1450
0
                return_error(gs_error_undefined);
1451
0
            default:
1452
0
                break;
1453
0
        }
1454
0
    }
1455
0
    if (!pdev->HaveCFF) {
1456
0
        if (font->FontType == ft_encrypted2)
1457
0
            return_error(gs_error_undefined);
1458
0
    }
1459
0
    embed = pdf_font_embed_status(pdev, base_font, &index, cgp->s, cgp->num_all_chars);
1460
0
    if (pdev->CompatibilityLevel < 1.3)
1461
0
        if (embed != FONT_EMBED_NO && font->FontType == ft_CID_TrueType)
1462
0
            return_error(gs_error_rangecheck);
1463
0
    if (embed == FONT_EMBED_STANDARD && pdev->CompatibilityLevel < 2.0) {
1464
0
        pdf_standard_font_t *psf = &psfa[index];
1465
1466
0
        if (psf->pdfont == NULL ||
1467
0
                !pdf_is_compatible_encoding(pdev, psf->pdfont, font,
1468
0
                        cgp->s, cgp->num_all_chars)) {
1469
0
            code = pdf_font_std_alloc(pdev, ppdfont, (psf->pdfont == NULL), base_font->id,
1470
0
                                      (gs_font_base *)base_font, index);
1471
0
            if (code < 0)
1472
0
                return code;
1473
0
            if (psf->pdfont == NULL)
1474
0
                psf->pdfont = *ppdfont;
1475
0
            (*ppdfont)->u.simple.BaseEncoding = pdf_refine_encoding_index(pdev,
1476
0
                ((const gs_font_base *)base_font)->nearest_encoding_index, true);
1477
0
            code = 1;
1478
0
        } else
1479
0
            *ppdfont = psf->pdfont;
1480
0
        return code;
1481
0
    }
1482
1483
0
    if (uid_is_XUID(&bfont->UID)){
1484
0
        int size = uid_XUID_size(&bfont->UID);
1485
0
        long *xvalues = uid_XUID_values(&bfont->UID);
1486
0
        if (xvalues && size >= 2 && xvalues[0] == 1000000) {
1487
0
            XUID = xvalues[size - 1];
1488
0
        }
1489
0
    }
1490
1491
0
    switch (font->FontType) {
1492
0
    case ft_CID_encrypted:
1493
0
    case ft_CID_TrueType:
1494
0
        font_alloc = pdf_font_cidfont_alloc;
1495
0
        break;
1496
0
    case ft_encrypted:
1497
0
    case ft_encrypted2:
1498
0
    case ft_TrueType:
1499
0
        font_alloc = pdf_font_simple_alloc;
1500
0
        break;
1501
0
    case ft_user_defined:
1502
0
    case ft_PDF_user_defined:
1503
0
    case ft_PCL_user_defined:
1504
0
    case ft_MicroType:
1505
0
    case ft_GL2_stick_user_defined:
1506
0
    case ft_GL2_531:
1507
0
        code = pdf_make_font3_resource(pdev, font, ppdfont);
1508
0
        if (code < 0)
1509
0
            return code;
1510
0
        (*ppdfont)->XUID = XUID;
1511
0
        return 1;
1512
0
    default:
1513
0
        return_error(gs_error_invalidfont);
1514
0
    }
1515
1516
    /* Create an appropriate font resource and descriptor. */
1517
0
    if (embed == FONT_EMBED_YES) {
1518
        /*
1519
         * HACK: Acrobat Reader 3 has a bug that makes cmap formats 4
1520
         * and 6 not work in embedded TrueType fonts.  Consequently, it
1521
         * can only handle embedded TrueType fonts if all the glyphs
1522
         * referenced by the Encoding have numbers 0-255.  Check for
1523
         * this now.
1524
         */
1525
0
        if (font->FontType == ft_TrueType &&
1526
0
            pdev->CompatibilityLevel <= 1.2 && !pdev->ForOPDFRead
1527
0
            ) {
1528
0
            int i;
1529
1530
0
            for (i = 0; i <= 0xff; ++i) {
1531
0
                gs_glyph glyph =
1532
0
                    font->procs.encode_char(font, (gs_char)i,
1533
0
                                            GLYPH_SPACE_INDEX);
1534
1535
0
                if (glyph == GS_NO_GLYPH ||
1536
0
                    (glyph >= GS_MIN_GLYPH_INDEX &&
1537
0
                     glyph <= GS_MIN_GLYPH_INDEX + 0xff)
1538
0
                    )
1539
0
                    continue;
1540
                /* Can't embed, punt. */
1541
0
                return_error(gs_error_rangecheck);
1542
0
            }
1543
0
        }
1544
0
    }
1545
0
    if ((code = pdf_font_descriptor_alloc(pdev, &pfd,
1546
0
                                          (gs_font_base *)base_font,
1547
0
                                          embed == FONT_EMBED_YES)) < 0 ||
1548
0
        (code = font_alloc(pdev, &pdfont, base_font->id, pfd)) < 0
1549
0
        )
1550
0
        return code;
1551
1552
0
    pdfont->XUID = XUID;
1553
0
    pdf_do_subset_font(pdev, pfd->base_font, -1);
1554
1555
    /* If we have a TrueType font to embed, and we're producing an (E)PS output
1556
     * file, and we are subsetting the font, then the font we produce will *NOT*
1557
     * have the CMAP from the original TrueType font, we will generate a Windows 3,1
1558
     * and a MacRoman 1,0 CMAP, and the opdfread.ps code will prefer to use the
1559
     * MacRoman one. So, in this case, use MacRoman otherwise we will end up
1560
     * with erroneous encodings. Of course, when we are not subssetting the font
1561
     * we do want ot use the original fonts encoding.
1562
     */
1563
0
    if ((font->FontType == ft_TrueType && pdev->ForOPDFRead)) {
1564
0
        if (pfd->base_font->do_subset == DO_SUBSET_YES)
1565
0
            BaseEncoding = pdf_refine_encoding_index(pdev,
1566
0
                ENCODING_INDEX_MACROMAN, false);
1567
0
        else
1568
0
            BaseEncoding = pdf_refine_encoding_index(pdev,
1569
0
                ((const gs_font_base *)base_font)->nearest_encoding_index, false);
1570
0
    }
1571
0
    if (font->FontType == ft_encrypted || font->FontType == ft_encrypted2
1572
0
        || (font->FontType == ft_TrueType && ((const gs_font_base *)base_font)->nearest_encoding_index != ENCODING_INDEX_UNKNOWN && pfd->base_font->do_subset == DO_SUBSET_NO)) {
1573
        /* Yet more crazy heuristics. If we embed a TrueType font and don't subset it, then
1574
         * we preserve the CMAP subtable(s) rather than generatng new ones. The problem is
1575
         * that if we ake the font symbolic, Acrobat uses the 1,0 CMAP, whereas if we don't
1576
         * It uses the 3,1 CMAP (and the Encoding). If these two are not compatible, then
1577
         * the result will be different. So, if we are not subsetting the font, and the original
1578
         * font wasn't symbolic (it has an Encoding) then we will create a new Encoding, and
1579
         * in pdf_write_font_descriptor we wil take back off the symbolic flag.
1580
         */
1581
        /* Removed the addition of Encodings to TrueType fonts as we always write
1582
         * these with the Symbolic flag set. The comment below explains why we
1583
         * previously wrote these, but as the comment notes this was incorrect.
1584
         * Removed as it is causing preflight problems, and is specifically
1585
         * disallowed with PDF/A output.
1586
         */
1587
        /*
1588
         * We write True Types with Symbolic flag set.
1589
         * PDF spec says that "symbolic font should not specify Encoding entry"
1590
         * (see section 5.5, the article "Encodings for True Type fonts", paragraph 3).
1591
         * However Acrobat Reader 4,5,6 fail when TT font with no Encoding
1592
         * appears in a document together with a CID font with a non-standard CMap
1593
         * (AR 4 and 5 claim "The encoding (CMap) specified by a font is corrupted."
1594
         * (we read it as "The encoding or CMap specified by a font is corrupted.",
1595
         * and apply the 1st alternative)). We believe that AR is buggy,
1596
         * and therefore we write an Encoding with non-CID True Type fonts.
1597
         * Hopely other viewers can ignore Encoding in such case. Actually in this case
1598
         * an Encoding doesn't add an useful information.
1599
         */
1600
0
        BaseEncoding = pdf_refine_encoding_index(pdev,
1601
0
            ((const gs_font_base *)base_font)->nearest_encoding_index, false);
1602
0
    }
1603
0
    if (!pdf_is_CID_font(font)) {
1604
0
        pdfont->u.simple.BaseEncoding = BaseEncoding;
1605
0
        pdfont->mark_glyph = font->dir->ccache.mark_glyph;
1606
0
    }
1607
1608
0
    if (pdev->PDFA != 0 && font->FontType == ft_TrueType) {
1609
        /* The Adobe preflight tool for PDF/A
1610
           checks whether Width or W include elements
1611
           for all characters in the True Type font.
1612
           Due to that we need to provide a width
1613
           for .notdef glyph.
1614
           (It's a part of the bug 688790).
1615
         */
1616
0
        gs_font_base *cfont = pdf_font_descriptor_font(pfd, false/*any*/);
1617
0
        gs_glyph notdef_glyph = copied_get_notdef((const gs_font *)cfont);
1618
0
        pdf_glyph_widths_t widths;
1619
0
        double cdevproc_result[10] = {0,0,0,0,0, 0,0,0,0,0};
1620
0
        double *w, *v, *w0;
1621
1622
0
        if (notdef_glyph != GS_NO_GLYPH) {
1623
0
            code = pdf_obtain_cidfont_widths_arrays(pdev, pdfont, font->WMode, &w, &w0, &v);
1624
0
            if (code < 0)
1625
0
                return code;
1626
0
            widths.Width.w = 0;
1627
0
            code = pdf_glyph_widths(pdfont, font->WMode, notdef_glyph,
1628
0
                 font, &widths, cdevproc_result);
1629
0
            if (code < 0)
1630
0
                return code;
1631
0
            w[0] = widths.Width.w;
1632
0
            pdfont->used[0] |= 0x80;
1633
0
        }
1634
0
    }
1635
0
    *ppdfont = pdfont;
1636
0
    return 1;
1637
0
}
1638
1639
/*
1640
 * Check for simple font.
1641
 */
1642
bool
1643
pdf_is_simple_font(gs_font *font)
1644
0
{
1645
0
    return (font->FontType == ft_encrypted ||
1646
0
            font->FontType == ft_encrypted2 ||
1647
0
            font->FontType == ft_TrueType ||
1648
0
            font->FontType == ft_user_defined ||
1649
0
            font->FontType == ft_PDF_user_defined ||
1650
0
            font->FontType == ft_PCL_user_defined ||
1651
0
            font->FontType == ft_MicroType ||
1652
0
            font->FontType == ft_GL2_stick_user_defined ||
1653
0
            font->FontType == ft_GL2_531);
1654
0
}
1655
1656
/*
1657
 * Check for CID font.
1658
 */
1659
bool
1660
pdf_is_CID_font(gs_font *font)
1661
0
{
1662
0
    return (font->FontType == ft_CID_encrypted ||
1663
0
            font->FontType == ft_CID_TrueType);
1664
0
}
1665
1666
/*
1667
 * Enumerate glyphs for a text.
1668
 */
1669
static int
1670
pdf_next_char_glyph(gs_text_enum_t *penum, const gs_string *pstr,
1671
               /* const */ gs_font *font, bool font_is_simple,
1672
               gs_char *char_code, gs_char *cid, gs_glyph *glyph)
1673
0
{
1674
0
    int code = font->procs.next_char_glyph(penum, char_code, glyph);
1675
1676
0
    if (code == 2)                /* end of string */
1677
0
        return code;
1678
0
    if (code < 0)
1679
0
        return code;
1680
0
    if (font_is_simple) {
1681
0
        *cid = *char_code;
1682
0
        *glyph = font->procs.encode_char(font, *char_code, GLYPH_SPACE_NAME);
1683
0
        if (*glyph == GS_NO_GLYPH)
1684
0
            return 3;
1685
0
    } else {
1686
0
        if (*glyph < GS_MIN_CID_GLYPH)
1687
0
            return 3; /* Not sure why, copied from scan_cmap_text. */
1688
0
        *cid = *glyph - GS_MIN_CID_GLYPH; /* CID */
1689
0
    }
1690
0
    return 0;
1691
0
}
1692
1693
static void
1694
store_glyphs(pdf_char_glyph_pairs_t *cgp,
1695
             byte *glyph_usage, int char_cache_size,
1696
             gs_char char_code, gs_char cid, gs_glyph glyph)
1697
0
{
1698
0
    int j;
1699
1700
0
    for (j = 0; j < cgp->num_all_chars; j++)
1701
0
        if (cgp->s[j].chr == cid)
1702
0
            break;
1703
0
    if (j < cgp->num_all_chars)
1704
0
        return;
1705
0
    cgp->s[cgp->num_all_chars].glyph = glyph;
1706
0
    cgp->s[cgp->num_all_chars].chr = char_code;
1707
0
    cgp->num_all_chars++;
1708
0
    if (glyph_usage == 0 || !(glyph_usage[cid / 8] & (0x80 >> (cid & 7)))) {
1709
0
        cgp->s[cgp->unused_offset + cgp->num_unused_chars].glyph = glyph;
1710
0
        cgp->s[cgp->unused_offset + cgp->num_unused_chars].chr = char_code;
1711
0
        cgp->num_unused_chars++;
1712
0
    }
1713
    /* We are disliked that gs_copied_can_copy_glyphs can get redundant
1714
     * glyphs, if Encoding specifies several codes for same glyph.
1715
     * But we need the positional correspondence
1716
     * of glyphs to codes for pdf_is_compatible_encoding.
1717
     * Redundant glyphs isn't a big payment for it
1718
     * because they happen seldom.
1719
     */
1720
0
}
1721
1722
static gs_char
1723
pdf_new_char_code_in_pdfont(pdf_char_glyph_pairs_t *cgp, gs_glyph glyph, int *last_reserved_char)
1724
0
{   /* Returns 256 if encoding overflows. */
1725
0
    int j, ch;
1726
1727
0
    for (j = 0; j < cgp->num_all_chars; j++)
1728
0
        if (cgp->s[j].glyph == glyph)
1729
0
            break;
1730
0
    if (j < cgp->num_all_chars)
1731
0
        return cgp->s[j].chr;
1732
0
    ch = ++*last_reserved_char;
1733
0
    cgp->s[cgp->num_all_chars].glyph = glyph;
1734
0
    cgp->s[cgp->num_all_chars].chr = ch;
1735
0
    cgp->num_all_chars++;
1736
0
    cgp->s[cgp->unused_offset + cgp->num_unused_chars].glyph = glyph;
1737
0
    cgp->s[cgp->unused_offset + cgp->num_unused_chars].chr = ch;
1738
0
    cgp->num_unused_chars++;
1739
0
    return ch;
1740
0
}
1741
1742
static gs_char
1743
pdf_reserve_char_code_in_pdfont(pdf_font_resource_t *pdfont, pdf_char_glyph_pairs_t *cgp, gs_glyph glyph,
1744
                                int *last_reserved_char)
1745
0
{   /* Returns 256 if encoding overflows. */
1746
    /* This function is pretty slow, but we can't find a better algorithm.
1747
       It works for the case of glyphshow with no proper encoding,
1748
       which we believe comes from poorly designed documents.
1749
     */
1750
0
    int j, ch;
1751
1752
0
    for (j = 0; j < cgp->num_all_chars; j++)
1753
0
        if (cgp->s[j].glyph == glyph)
1754
0
            break;
1755
0
    if (j < cgp->num_all_chars)
1756
0
        return cgp->s[j].chr;
1757
1758
0
    for (ch = 0; ch < 256; ch++) {
1759
0
        pdf_encoding_element_t *pet = &pdfont->u.simple.Encoding[ch];
1760
1761
0
        if (glyph == pet->glyph)
1762
0
            return ch;
1763
0
    }
1764
    /* If the font has a known encoding, prefer .notdef codes. */
1765
0
    if (pdfont->u.simple.preferred_encoding_index != -1) {
1766
0
        const ushort *enc = gs_c_known_encodings[pdfont->u.simple.preferred_encoding_index];
1767
1768
0
        for (ch = *last_reserved_char + 1; ch < 256; ch++) {
1769
0
            pdf_encoding_element_t *pet = &pdfont->u.simple.Encoding[ch];
1770
1771
0
            if (pet->glyph == GS_NO_GLYPH && enc[ch] == pdfont->u.simple.standard_glyph_code_for_notdef) {
1772
0
                *last_reserved_char = ch;
1773
0
                break;
1774
0
            }
1775
0
        }
1776
0
    }
1777
    /* Otherwise use any code unused in the font. */
1778
0
    if (ch > 255) {
1779
0
        ch = *last_reserved_char + 1;
1780
0
        for (; ch < 255; ch++) {
1781
0
            pdf_encoding_element_t *pet = &pdfont->u.simple.Encoding[ch];
1782
1783
0
            if (pet->glyph == GS_NO_GLYPH)
1784
0
                break;
1785
0
        }
1786
0
        *last_reserved_char = ch;
1787
0
    }
1788
0
    cgp->s[cgp->num_all_chars].glyph = glyph;
1789
0
    cgp->s[cgp->num_all_chars].chr = ch;
1790
0
    cgp->num_all_chars++;
1791
0
    cgp->s[cgp->unused_offset + cgp->num_unused_chars].glyph = glyph;
1792
0
    cgp->s[cgp->unused_offset + cgp->num_unused_chars].chr = ch;
1793
0
    cgp->num_unused_chars++;
1794
0
    return ch;
1795
0
}
1796
1797
/* Allocate storage for the glyph set of the text. */
1798
static int
1799
pdf_alloc_text_glyphs_table(gx_device_pdf *pdev, pdf_text_enum_t *penum, const gs_string *pstr)
1800
0
{
1801
0
    const int go = (pstr != NULL ? pstr->size : penum->text.size);
1802
0
    const int struct_size = sizeof(pdf_char_glyph_pairs_t) +
1803
0
                            sizeof(pdf_char_glyph_pair_t) * (2 * go - 1);
1804
0
    pdf_char_glyph_pairs_t *cgp = (pdf_char_glyph_pairs_t *)gs_alloc_bytes(penum->memory,
1805
0
                struct_size, "pdf_alloc_text_glyphs_table");
1806
0
    if (cgp == NULL)
1807
0
        return_error(gs_error_VMerror);
1808
0
    penum->cgp = cgp;
1809
0
    cgp->unused_offset = go;
1810
0
    cgp->num_all_chars = 0;
1811
0
    cgp->num_unused_chars = 0;
1812
0
    return 0;
1813
0
}
1814
1815
/* Build the glyph set of the text. */
1816
static int
1817
pdf_make_text_glyphs_table(pdf_text_enum_t *penum, const gs_string *pstr,
1818
                byte *glyph_usage, int char_cache_size)
1819
0
{
1820
0
    gs_text_enum_t scan = *(gs_text_enum_t *)penum;
1821
0
    gs_font *font = (gs_font *)penum->current_font;
1822
0
    bool font_is_simple = pdf_is_simple_font(font);
1823
0
    pdf_char_glyph_pairs_t *cgp = penum->cgp;
1824
0
    gs_char char_code, cid;
1825
0
    gs_glyph glyph;
1826
0
    int code;
1827
1828
0
    cgp->num_unused_chars = 0;
1829
0
    cgp->num_all_chars = 0;
1830
0
    if (pstr != NULL) {
1831
0
        scan.text.data.bytes = pstr->data;
1832
0
        scan.text.size = pstr->size;
1833
0
        scan.index = 0;
1834
        /* if TEXT_FROM_CHARS the data was converted to bytes earlier */
1835
0
        if ( scan.text.operation & TEXT_FROM_CHARS )
1836
0
            scan.text.operation = ((scan.text.operation & ~TEXT_FROM_CHARS) | TEXT_FROM_STRING);
1837
0
    }
1838
0
    for (;;) {
1839
0
        code = pdf_next_char_glyph(&scan, pstr, font, font_is_simple,
1840
0
                                   &char_code, &cid, &glyph);
1841
0
        if (code == 2)                /* end of string */
1842
0
            break;
1843
0
        if (code == 3)                /* no glyph */
1844
0
            continue;
1845
0
        if (code < 0)
1846
0
            return code;
1847
0
        if (cgp->num_all_chars > cgp->unused_offset)
1848
0
            return_error(gs_error_unregistered); /* Must not happen. */
1849
0
        if (glyph_usage != 0 && cid > char_cache_size)
1850
0
            continue;
1851
0
        store_glyphs(cgp, glyph_usage, char_cache_size,
1852
0
                     char_code, cid, glyph);
1853
0
    }
1854
0
    return 0;
1855
0
}
1856
1857
/* Build the glyph set of the glyphshow text, and re_encode the text. */
1858
static int
1859
pdf_make_text_glyphs_table_unencoded(gx_device_pdf *pdev, pdf_char_glyph_pairs_t *cgp,
1860
                gs_font *font, const gs_string *pstr, const gs_glyph *gdata,
1861
                int *ps_encoding_index)
1862
0
{
1863
0
    int i, j, code;
1864
0
    gs_char ch;
1865
0
    gs_const_string gname;
1866
0
    gs_glyph *gid = (gs_glyph *)pstr->data; /* pdf_text_process allocs enough space. */
1867
0
    gs_font_base *bfont;
1868
0
    bool unknown = false;
1869
0
    pdf_font_resource_t *pdfont;
1870
0
    int ei, start_ei = -1;
1871
1872
0
    code = pdf_attached_font_resource(pdev, font, &pdfont, NULL, NULL, NULL, NULL);
1873
0
    if (code < 0)
1874
0
        return code;
1875
    /* Translate glyph name indices into gscencs.c indices. */
1876
0
    for (i = 0; i < pstr->size; i++) {
1877
0
        int code = font->procs.glyph_name(font, gdata[i], &gname);
1878
1879
0
        if (code < 0)
1880
0
            return code;
1881
0
        gid[i] = gs_c_name_glyph(gname.data, gname.size);
1882
0
        if (gid[i] == GS_NO_GLYPH) {
1883
            /* Use global glyph name. */
1884
            /* Assuming this can't fail in a middle of a text,
1885
               because TEXT_FROM_GLYPHS never works for Postscript. */
1886
0
            gid[i] = gdata[i];
1887
0
            unknown = true;
1888
0
        }
1889
0
    }
1890
0
do_unknown:
1891
0
    if (unknown) {
1892
0
        int last_reserved_char = -1;
1893
         /* Using global glyph names. */
1894
1895
        /* Try to find an existing font resource, which has necessary glyphs.
1896
           Doing so to prevent creating multiple font copies.
1897
         */
1898
0
        cgp->num_unused_chars = 0;
1899
0
        cgp->num_all_chars = 0;
1900
0
        for (i = 0; i < pstr->size; i++) {
1901
            /* Temporary stub gid instead cid and char_code : */
1902
0
            store_glyphs(cgp, NULL, 0, gdata[i], gdata[i], gdata[i]);
1903
0
        }
1904
0
        code = pdf_find_font_resource(pdev, font, resourceFont, &pdfont, cgp, false);
1905
0
        if (code < 0)
1906
0
            return code;
1907
0
        if (code) {
1908
            /* Found one - make it be current. */
1909
0
            code = pdf_attach_font_resource(pdev, font, pdfont);
1910
0
            if (code < 0)
1911
0
                return code;
1912
0
        }
1913
        /* Try to add glyphs to the current font resource. . */
1914
0
        cgp->num_unused_chars = 0;
1915
0
        cgp->num_all_chars = 0;
1916
1917
0
        if(pdfont != NULL)
1918
0
                last_reserved_char = pdfont->u.simple.last_reserved_char;
1919
1920
0
        for (i = 0; i < pstr->size; i++) {
1921
1922
0
            if (pdfont == NULL)
1923
0
                ch = 256; /* Force new encoding. */
1924
0
            else
1925
0
                ch = pdf_reserve_char_code_in_pdfont(pdfont, cgp, gdata[i], &last_reserved_char);
1926
0
            if (ch > 255) {
1927
0
                if(pdfont != NULL)
1928
0
                        last_reserved_char = pdfont->u.simple.last_reserved_char;
1929
                /* Start a new font/encoding. */
1930
0
                last_reserved_char = -1;
1931
1932
0
                cgp->num_unused_chars = 0;
1933
0
                cgp->num_all_chars = 0;
1934
0
                for (i = 0; i < pstr->size; i++) {
1935
0
                    ch = pdf_new_char_code_in_pdfont(cgp, gdata[i], &last_reserved_char);
1936
0
                    if (ch > 255) {
1937
                        /* More than 255 unknown characters in a text.
1938
                           It must not happen because TEXT_FROM_GLYPHS
1939
                           never works for Postscript. */
1940
0
                        return_error(gs_error_unregistered);
1941
0
                    }
1942
0
                }
1943
0
            }
1944
0
        }
1945
0
        if (pdfont != NULL)
1946
0
            pdfont->u.simple.last_reserved_char = last_reserved_char;
1947
        /* Change glyphs to char codes in the text : */
1948
0
        for (i = 0; i < pstr->size; i++) {
1949
            /* Picked up by Coverity, if pdfont is NULL then the call might dereference it */
1950
0
            if (pdfont != NULL) {
1951
                /* A trick : pdf_reserve_char_code_in_pdfont here simply encodes with cgp. */
1952
0
                ch = pdf_reserve_char_code_in_pdfont(pdfont, cgp, gdata[i], &pdfont->u.simple.last_reserved_char);
1953
0
                pstr->data[i] = ch;
1954
0
            } else {
1955
                /* So if pdffont is NULL, do the 'trick' code mentioned above.
1956
                 * If that fails (I believe it shouod not), then return an error.
1957
                 */
1958
0
                int j;
1959
1960
0
                for (j = 0; j < cgp->num_all_chars; j++)
1961
0
                    if (cgp->s[j].glyph == gdata[i])
1962
0
                        break;
1963
0
                if (j < cgp->num_all_chars)
1964
0
                    pstr->data[i] = cgp->s[j].chr;
1965
0
                else
1966
0
                    return_error(gs_error_unregistered);
1967
0
            }
1968
0
        }
1969
0
        return 0;
1970
0
    }
1971
    /* Now we know it's a base font, bcause it has glyph names. */
1972
0
    bfont = (gs_font_base *)font;
1973
0
    if (start_ei < 0)
1974
0
        start_ei = bfont->nearest_encoding_index;
1975
0
    if (start_ei < 0)
1976
0
        start_ei = 0;
1977
    /* Find an acceptable encodng, starting from start_ei.
1978
       We need a conservative search to minimize the probability
1979
       of encoding conflicts.
1980
     */
1981
0
    for (j = 0, ei = start_ei; gs_c_known_encodings[j]; j++, ei++) {
1982
0
        if (!gs_c_known_encodings[ei])
1983
0
            ei = 0;
1984
        /* Restrict with PDF encodings, because others give frequent conflicts. */
1985
0
        if (ei > 5) /* Hack : gscedata.c must provide a constant. */
1986
0
            continue;
1987
0
        cgp->num_unused_chars = 0;
1988
0
        cgp->num_all_chars = 0;
1989
0
        for (i = 0; i < pstr->size; i++) {
1990
0
            ch = gs_c_decode(gid[i], ei);
1991
0
            if (ch == GS_NO_CHAR)
1992
0
                break;
1993
0
            if (ch > 255)
1994
0
                break; /* MacGlyphEncoding defines extra glyphs. */
1995
            /* pstr->data[i] = (byte)ch; Can't do because pstr->data and gid
1996
               are same pointer. Will do in a separate pass below. */
1997
0
            store_glyphs(cgp, NULL, 0, ch, ch, gdata[i]);
1998
0
        }
1999
0
        *ps_encoding_index = ei;
2000
0
        if (i == pstr->size) {
2001
            /* Change glyphs to char codes in the text : */
2002
0
            for (i = 0; i < pstr->size; i++)
2003
0
                pstr->data[i] = (byte)gs_c_decode(gid[i], ei);
2004
0
            return 0;
2005
0
        }
2006
0
    }
2007
0
    unknown = true;
2008
0
    goto do_unknown;
2009
0
}
2010
2011
/* Get/make font resource for the font with a known encoding. */
2012
static int
2013
pdf_obtain_font_resource_encoded(gx_device_pdf *pdev, gs_font *font,
2014
        pdf_font_resource_t **ppdfont, pdf_char_glyph_pairs_t *cgp)
2015
0
{
2016
0
    int code;
2017
0
    pdf_font_resource_t *pdfont_not_allowed = NULL;
2018
2019
0
    if (*ppdfont != 0) {
2020
0
        gs_font_base *cfont = pdf_font_resource_font(*ppdfont, false);
2021
2022
0
        if (font->FontType != ft_user_defined &&
2023
0
            font->FontType != ft_PDF_user_defined &&
2024
0
            font->FontType != ft_PCL_user_defined &&
2025
0
            font->FontType != ft_MicroType &&
2026
0
            font->FontType != ft_GL2_stick_user_defined &&
2027
0
            font->FontType != ft_GL2_531) {
2028
0
            code = gs_copied_can_copy_glyphs((gs_font *)cfont, font,
2029
0
                        &cgp->s[cgp->unused_offset].glyph, cgp->num_unused_chars,
2030
0
                        sizeof(pdf_char_glyph_pair_t), true);
2031
0
            if (code < 0)
2032
0
                code = 1;
2033
0
        } else
2034
0
            code = 1;
2035
0
        if (code == 0) {
2036
0
            pdfont_not_allowed = *ppdfont;
2037
0
            *ppdfont = 0;
2038
0
        } else if(!pdf_is_compatible_encoding(pdev, *ppdfont, font,
2039
0
                        cgp->s, cgp->num_all_chars)) {
2040
0
            pdfont_not_allowed = *ppdfont;
2041
0
            *ppdfont = 0;
2042
0
        }
2043
0
    }
2044
0
    if (*ppdfont == 0) {
2045
0
        gs_font *base_font = font;
2046
0
        gs_font *below;
2047
0
        bool same_encoding = true;
2048
2049
        /*
2050
         * Find the "lowest" base font that has the same outlines.
2051
         * We use its FontName for font resource.
2052
         */
2053
0
        while ((below = base_font->base) != base_font &&
2054
0
               base_font->procs.same_font(base_font, below, FONT_SAME_OUTLINES))
2055
0
            base_font = below;
2056
0
        if (base_font != font)
2057
0
            same_encoding = ((base_font->procs.same_font(base_font, font,
2058
0
                              FONT_SAME_ENCODING) & FONT_SAME_ENCODING) != 0);
2059
        /* Find or make font resource. */
2060
0
        code = pdf_attached_font_resource(pdev, base_font, ppdfont, NULL, NULL, NULL, NULL);
2061
0
        if (code < 0)
2062
0
            return code;
2063
0
        if (base_font != font) {
2064
0
            if (pdfont_not_allowed == *ppdfont)
2065
0
                *ppdfont = NULL;
2066
0
        }
2067
0
        if(*ppdfont != NULL && !pdf_is_compatible_encoding(pdev, *ppdfont,
2068
0
                                    base_font, cgp->s, cgp->num_all_chars))
2069
0
                *ppdfont = NULL;
2070
0
        if (*ppdfont == NULL || *ppdfont == pdfont_not_allowed) {
2071
0
            pdf_resource_type_t type =
2072
0
                (pdf_is_CID_font(base_font) ? resourceCIDFont
2073
0
                                            : resourceFont);
2074
0
            *ppdfont = NULL;
2075
0
            code = pdf_find_font_resource(pdev, base_font, type, ppdfont, cgp, true);
2076
0
            if (code < 0)
2077
0
                return code;
2078
0
            if (*ppdfont == NULL) {
2079
0
                code = pdf_make_font_resource(pdev, base_font, ppdfont, cgp);
2080
0
                if (code < 0)
2081
0
                    return code;
2082
0
            }
2083
0
            if (base_font != font && same_encoding) {
2084
0
                code = pdf_attach_font_resource(pdev, base_font, *ppdfont);
2085
0
                if (code < 0)
2086
0
                    return code;
2087
0
            }
2088
0
        }
2089
0
        code = pdf_attach_font_resource(pdev, font, *ppdfont);
2090
0
        if (code < 0)
2091
0
            return code;
2092
0
    }
2093
0
    return 0;
2094
0
}
2095
2096
/* Mark glyphs used in the text with the font resource. */
2097
static int
2098
pdf_mark_text_glyphs(const gs_text_enum_t *penum, const gs_string *pstr,
2099
            byte *glyph_usage, int char_cache_size)
2100
0
{
2101
0
    gs_text_enum_t scan = *penum;
2102
0
    gs_font *font = (gs_font *)penum->current_font;
2103
0
    bool font_is_simple = pdf_is_simple_font(font);
2104
0
    gs_char char_code, cid;
2105
0
    gs_glyph glyph;
2106
2107
0
    if (glyph_usage == NULL)
2108
0
        return 0;
2109
2110
0
    if (pstr != NULL) {
2111
0
        scan.text.data.bytes = pstr->data;
2112
0
        scan.text.size = pstr->size;
2113
0
        scan.index = 0;
2114
        /* if TEXT_FROM_CHARS the data was converted to bytes earlier */
2115
0
        if ( scan.text.operation & TEXT_FROM_CHARS )
2116
0
            scan.text.operation =
2117
0
                ((scan.text.operation & ~TEXT_FROM_CHARS) | TEXT_FROM_STRING);
2118
0
    }
2119
0
    for (;;) {
2120
0
        int code = pdf_next_char_glyph(&scan, pstr, font, font_is_simple,
2121
0
                                       &char_code, &cid, &glyph);
2122
2123
0
        if (code == 2)                /* end of string */
2124
0
            break;
2125
0
        if (code == 3)                /* no glyph */
2126
0
            continue;
2127
0
        if (code < 0)
2128
0
            return code;
2129
0
        if (cid >= char_cache_size)
2130
0
            continue;
2131
0
        glyph_usage[cid / 8] |= 0x80 >> (cid & 7);
2132
0
    }
2133
0
    return 0;
2134
0
}
2135
2136
/* Mark glyphs used in the glyphshow text with the font resource. */
2137
static int
2138
pdf_mark_text_glyphs_unencoded(const gs_text_enum_t *penum, const gs_string *pstr,
2139
            byte *glyph_usage, int char_cache_size)
2140
0
{
2141
0
    int i;
2142
2143
0
    for(i = 0; i < pstr->size; i++) {
2144
0
        byte ch = pstr->data[i];
2145
2146
0
        if (ch >= char_cache_size)
2147
0
            return_error(gs_error_rangecheck);
2148
0
        glyph_usage[ch / 8] |= 0x80 >> (ch & 7);
2149
0
    }
2150
0
    return 0;
2151
0
}
2152
2153
/*
2154
 * Create or find a font resource object for a text.
2155
 */
2156
int
2157
pdf_obtain_font_resource(pdf_text_enum_t *penum,
2158
            const gs_string *pstr, pdf_font_resource_t **ppdfont)
2159
0
{
2160
0
    gx_device_pdf *pdev = (gx_device_pdf *)penum->dev;
2161
0
    gs_font *font = (gs_font *)penum->current_font;
2162
0
    byte *glyph_usage = 0;
2163
0
    double *real_widths;
2164
0
    int char_cache_size, width_cache_size;
2165
0
    int code;
2166
2167
0
    if (font->FontType == ft_composite) {
2168
        /* Must not happen, because we always split composite fonts into descendents. */
2169
0
        return_error(gs_error_unregistered);
2170
0
    }
2171
0
    code = pdf_attached_font_resource(pdev, font, ppdfont,
2172
0
                               &glyph_usage, &real_widths, &char_cache_size, &width_cache_size);
2173
    /* *ppdfont is NULL if no resource attached. */
2174
0
    if (code < 0)
2175
0
        return code;
2176
0
    if (penum->cgp == NULL) {
2177
0
        code = pdf_alloc_text_glyphs_table(pdev, penum, pstr);
2178
0
        if (code < 0)
2179
0
            return code;
2180
0
        code = pdf_make_text_glyphs_table(penum, pstr,
2181
0
                            glyph_usage, char_cache_size);
2182
0
        if (code < 0)
2183
0
            return code;
2184
0
    }
2185
0
    code = pdf_obtain_font_resource_encoded(pdev, font, ppdfont, penum->cgp);
2186
0
    if (code < 0)
2187
0
        return code;
2188
0
    code = pdf_attached_font_resource(pdev, font, ppdfont,
2189
0
                               &glyph_usage, &real_widths, &char_cache_size, &width_cache_size);
2190
0
    if (code < 0)
2191
0
        return code;
2192
0
    return pdf_mark_text_glyphs((const gs_text_enum_t *)penum, pstr, glyph_usage, char_cache_size);
2193
0
}
2194
2195
/*
2196
 * Create or find a font resource object for a glyphshow text.
2197
 */
2198
int
2199
pdf_obtain_font_resource_unencoded(pdf_text_enum_t *penum,
2200
            const gs_string *pstr, pdf_font_resource_t **ppdfont, const gs_glyph *gdata)
2201
0
{
2202
0
    gx_device_pdf *pdev = (gx_device_pdf *)penum->dev;
2203
0
    gs_font *font = (gs_font *)penum->current_font;
2204
0
    byte *glyph_usage = 0;
2205
0
    double *real_widths = 0;
2206
0
    int char_cache_size = 0, width_cache_size = 0;
2207
0
    int code, ps_encoding_index = -1;
2208
2209
0
    if (font->FontType == ft_composite) {
2210
        /* Must not happen, because we always split composite fonts into descendents. */
2211
0
        return_error(gs_error_unregistered);
2212
0
    }
2213
0
    code = pdf_attached_font_resource(pdev, font, ppdfont,
2214
0
                               &glyph_usage, &real_widths, &char_cache_size, &width_cache_size);
2215
0
    if (code < 0)
2216
0
        return code;
2217
    /* *ppdfont is NULL if no resource attached. */
2218
0
    if (*ppdfont != NULL)
2219
0
        ps_encoding_index = (*ppdfont)->u.simple.preferred_encoding_index;
2220
0
    if (penum->cgp == NULL) {
2221
0
        code = pdf_alloc_text_glyphs_table(pdev, penum, pstr);
2222
0
        if (code < 0)
2223
0
            return code;
2224
0
        code = pdf_make_text_glyphs_table_unencoded(pdev, penum->cgp, font, pstr, gdata, &ps_encoding_index);
2225
0
        if (code < 0)
2226
0
            return code;
2227
0
    }
2228
0
    code = pdf_obtain_font_resource_encoded(pdev, font, ppdfont, penum->cgp);
2229
0
    if (code < 0)
2230
0
        return code;
2231
0
    code = pdf_attached_font_resource(pdev, font, ppdfont,
2232
0
                               &glyph_usage, &real_widths, &char_cache_size, &width_cache_size);
2233
0
    if (code < 0)
2234
0
        return code;
2235
0
    (*ppdfont)->u.simple.preferred_encoding_index = ps_encoding_index;
2236
0
    return pdf_mark_text_glyphs_unencoded((const gs_text_enum_t *)penum,
2237
0
                    pstr, glyph_usage, char_cache_size);
2238
0
}
2239
2240
static inline bool
2241
strings_equal(const gs_const_string *s1, const gs_const_string *s2)
2242
0
{
2243
0
    return s1->size == s2->size &&
2244
0
            !memcmp(s1->data, s2->data, s1->size);
2245
0
}
2246
2247
/*
2248
 * Create or find a parent Type 0 font resource object for a CID font resource.
2249
 */
2250
int
2251
pdf_obtain_parent_type0_font_resource(gx_device_pdf *pdev, pdf_font_resource_t *pdsubf,
2252
                uint font_index, const gs_const_string *CMapName, pdf_font_resource_t **pdfont)
2253
0
{
2254
0
    if (pdsubf->u.cidfont.parent != 0 &&
2255
0
            font_index == pdsubf->u.cidfont.parent->u.type0.font_index &&
2256
0
            strings_equal(CMapName, &pdsubf->u.cidfont.parent->u.type0.CMapName))
2257
0
        *pdfont = pdsubf->u.cidfont.parent;
2258
0
    else {
2259
        /*
2260
         * PDF spec 1.4 section 5.6 "Composite Fonts" says :
2261
         *
2262
         * PDF 1.2 introduces a general architecture for composite fonts that theoretically
2263
         * allows a Type 0 font to have multiple descendants,which might themselves be
2264
         * Type 0 fonts.However,in versions up to and including PDF 1.4,only a single
2265
         * descendant is allowed,which must be a CIDFont (not a font).This restriction
2266
         * may be relaxed in a future PDF version.
2267
         */
2268
2269
0
        if (pdsubf->u.cidfont.parent == NULL ||
2270
0
                pdf_find_type0_font_resource(pdev, pdsubf, CMapName, font_index, pdfont) <= 0) {
2271
0
            int code = pdf_font_type0_alloc(pdev, pdfont, gs_no_id, pdsubf, CMapName);
2272
2273
0
            if (code < 0)
2274
0
                return code;
2275
0
            (*pdfont)->u.type0.font_index = font_index;
2276
0
        }
2277
0
        pdsubf->u.cidfont.parent = *pdfont;
2278
0
    }
2279
0
    return 0;
2280
0
}
2281
2282
gs_char
2283
pdf_find_glyph(pdf_font_resource_t *pdfont, gs_glyph glyph)
2284
0
{
2285
0
    if (pdfont->FontType != ft_user_defined &&
2286
0
        pdfont->FontType != ft_PDF_user_defined &&
2287
0
        pdfont->FontType != ft_PCL_user_defined &&
2288
0
        pdfont->FontType != ft_MicroType &&
2289
0
        pdfont->FontType != ft_GL2_stick_user_defined &&
2290
0
        pdfont->FontType != ft_GL2_531)
2291
0
        return GS_NO_CHAR;
2292
0
    else {
2293
0
        pdf_encoding_element_t *pet = pdfont->u.simple.Encoding;
2294
0
        int i, i0 = -1;
2295
2296
0
        if (pdfont->u.simple.FirstChar > pdfont->u.simple.LastChar)
2297
0
            return (gs_char)0;
2298
0
        for (i = pdfont->u.simple.FirstChar; i <= pdfont->u.simple.LastChar; i++, pet++) {
2299
0
            if (pet->glyph == glyph)
2300
0
                return (gs_char)i;
2301
0
            if (i0 == -1 && pet->glyph == GS_NO_GLYPH)
2302
0
                i0 = i;
2303
0
        }
2304
0
        if (i0 != -1)
2305
0
            return (gs_char)i0;
2306
0
        if (i < 256)
2307
0
            return (gs_char)i;
2308
0
        return GS_NO_CHAR;
2309
0
    }
2310
0
}
2311
2312
/*
2313
 * Compute the cached values in the text processing state from the text
2314
 * parameters, current_font, and pgs->ctm.  Return either an error code (<
2315
 * 0) or a mask of operation attributes that the caller must emulate.
2316
 * Currently the only such attributes are TEXT_ADD_TO_ALL_WIDTHS and
2317
 * TEXT_ADD_TO_SPACE_WIDTH.  Note that this procedure fills in all the
2318
 * values in ppts->values, not just the ones that need to be set now.
2319
 */
2320
static int
2321
transform_delta_inverse(const gs_point *pdelta, const gs_matrix *pmat,
2322
                        gs_point *ppt)
2323
0
{
2324
0
    int code = gs_distance_transform_inverse(pdelta->x, pdelta->y, pmat, ppt);
2325
0
    gs_point delta;
2326
2327
0
    if (code < 0)
2328
0
        return code;
2329
0
    if (ppt->y == 0)
2330
0
        return 0;
2331
    /* Check for numerical fuzz. */
2332
0
    code = gs_distance_transform(ppt->x, 0.0, pmat, &delta);
2333
0
    if (code < 0)
2334
0
        return 0;                /* punt */
2335
0
    if (fabs(delta.x - pdelta->x) < 0.01 && fabs(delta.y - pdelta->y) < 0.01) {
2336
        /* Close enough to y == 0: device space error < 0.01 pixel. */
2337
0
        ppt->y = 0;
2338
0
    }
2339
0
    return 0;
2340
0
}
2341
2342
float pdf_calculate_text_size(gs_gstate *pgs, pdf_font_resource_t *pdfont,
2343
                              const gs_matrix *pfmat, gs_matrix *smat, gs_matrix *tmat,
2344
                              gs_font *font, gx_device_pdf *pdev)
2345
0
{
2346
0
    gs_matrix orig_matrix;
2347
0
    double
2348
0
        sx = pdev->HWResolution[0] / 72.0,
2349
0
        sy = pdev->HWResolution[1] / 72.0;
2350
0
    float size;
2351
2352
    /* Get the original matrix of the base font. */
2353
2354
0
    {
2355
0
        gs_font_base *cfont = pdf_font_resource_font(pdfont, false);
2356
2357
0
        if (pdfont->FontType == ft_user_defined ||
2358
0
            pdfont->FontType == ft_PDF_user_defined ||
2359
0
            pdfont->FontType == ft_PCL_user_defined ||
2360
0
            pdfont->FontType == ft_MicroType ||
2361
0
            pdfont->FontType == ft_GL2_stick_user_defined ||
2362
0
            pdfont->FontType == ft_GL2_531)
2363
0
            orig_matrix = pdfont->u.simple.s.type3.FontMatrix;
2364
0
        else if (cfont != 0) {
2365
            /*
2366
             * The text matrix to be computed relatively to the
2367
             * embedded font matrix.
2368
             */
2369
0
            orig_matrix = cfont->FontMatrix;
2370
0
        } else {
2371
            /*
2372
             * We don't embed the font.
2373
             * The text matrix to be computed relatively to
2374
             * standard font matrix.
2375
             */
2376
0
            pdf_font_orig_matrix(font, &orig_matrix);
2377
0
        }
2378
0
    }
2379
2380
    /* Compute the scaling matrix and combined matrix. */
2381
2382
0
    if (gs_matrix_invert(&orig_matrix, smat) < 0) {
2383
0
        gs_make_identity(smat);
2384
0
        gs_make_identity(tmat);
2385
0
        return 1; /* Arbitrary */
2386
0
    }
2387
0
    gs_matrix_multiply(smat, pfmat, smat);
2388
0
    *tmat = ctm_only(pgs);
2389
0
    tmat->tx = tmat->ty = 0;
2390
0
    gs_matrix_multiply(smat, tmat, tmat);
2391
2392
    /* Try to find a reasonable size value.  This isn't necessary, */
2393
    /* but it's worth a little effort. */
2394
2395
0
    size = hypot(tmat->yx, tmat->yy) / sy;
2396
0
    if (size < 0.01)
2397
0
        size = hypot(tmat->xx, tmat->xy) / sx;
2398
0
    if (size < 0.01)
2399
0
        size = 1;
2400
2401
0
    return(size);
2402
0
}
2403
2404
int
2405
pdf_update_text_state(pdf_text_process_state_t *ppts,
2406
                      const pdf_text_enum_t *penum,
2407
                      pdf_font_resource_t *pdfont, const gs_matrix *pfmat)
2408
0
{
2409
0
    gx_device_pdf *const pdev = (gx_device_pdf *)penum->dev;
2410
0
    gs_font *font = penum->current_font;
2411
0
    gs_fixed_point cpt;
2412
0
    gs_matrix smat, tmat;
2413
0
    float size;
2414
0
    float c_s = 0, w_s = 0;
2415
0
    int mask = 0;
2416
0
    int code = gx_path_current_point(penum->path, &cpt);
2417
2418
0
    if (code < 0)
2419
0
        return code;
2420
2421
0
    size = pdf_calculate_text_size(penum->pgs, pdfont, pfmat, &smat, &tmat, penum->current_font, pdev);
2422
    /* Check for spacing parameters we can handle, and transform them. */
2423
2424
0
    if (penum->text.operation & TEXT_ADD_TO_ALL_WIDTHS) {
2425
0
        if (penum->current_font->WMode == 0) {
2426
0
            gs_point pt;
2427
2428
0
            code = transform_delta_inverse(&penum->text.delta_all, &smat, &pt);
2429
0
            if (code >= 0 && pt.y == 0)
2430
0
                c_s = pt.x * size;
2431
0
            else
2432
0
                mask |= TEXT_ADD_TO_ALL_WIDTHS;
2433
0
        }
2434
0
        else
2435
0
            mask |= TEXT_ADD_TO_ALL_WIDTHS;
2436
0
    }
2437
2438
0
    if (penum->text.operation & TEXT_ADD_TO_SPACE_WIDTH) {
2439
0
        gs_point pt;
2440
2441
0
        code = transform_delta_inverse(&penum->text.delta_space, &smat, &pt);
2442
0
        if (code >= 0 && pt.y == 0 && penum->text.space.s_char == 32)
2443
0
            w_s = pt.x * size;
2444
0
        else
2445
0
            mask |= TEXT_ADD_TO_SPACE_WIDTH;
2446
0
    }
2447
    /* Store the updated values. */
2448
2449
0
    tmat.xx /= size;
2450
0
    tmat.xy /= size;
2451
0
    tmat.yx /= size;
2452
0
    tmat.yy /= size;
2453
0
    tmat.tx += fixed2float(cpt.x);
2454
0
    tmat.ty += fixed2float(cpt.y);
2455
2456
0
    ppts->values.character_spacing = c_s;
2457
0
    ppts->values.pdfont = pdfont;
2458
0
    ppts->values.size = size;
2459
0
    ppts->values.matrix = tmat;
2460
0
    ppts->values.render_mode = penum->pgs->text_rendering_mode;
2461
0
    ppts->values.word_spacing = w_s;
2462
0
    ppts->font = font;
2463
2464
0
    if (font->PaintType == 2 && penum->pgs->text_rendering_mode == 0)
2465
0
    {
2466
0
        gs_gstate *pgs = penum->pgs;
2467
0
        gs_font *font = penum->current_font;
2468
0
        double scaled_width = font->StrokeWidth != 0 ? font->StrokeWidth : 0.001;
2469
0
        double saved_width = pgs->line_params.half_width;
2470
        /*
2471
         * See stream_to_text in gdevpdfu.c re the computation of
2472
         * the scaling value.
2473
         */
2474
0
        double scale = 72.0 / pdev->HWResolution[1];
2475
2476
0
        if (font->FontMatrix.yy != 0)
2477
0
            scaled_width *= fabs(font->orig_FontMatrix.yy) * size * scale;
2478
0
        else
2479
0
            scaled_width *= fabs(font->orig_FontMatrix.xy) * size * scale;
2480
2481
0
        if (tmat.yy != 0)
2482
0
            scaled_width *= tmat.yy;
2483
0
        else
2484
0
            scaled_width *= tmat.xy;
2485
2486
0
        ppts->values.render_mode = 1;
2487
2488
        /* Sort out any pending glyphs */
2489
0
        code = pdf_set_PaintType0_params(pdev, pgs, size, scaled_width, &ppts->values);
2490
0
        if (code < 0)
2491
0
            return code;
2492
2493
0
        pgs->line_params.half_width = scaled_width / 2;
2494
0
        code = pdf_set_text_process_state(pdev, (const gs_text_enum_t *)penum,
2495
0
                                      ppts);
2496
0
        if (code < 0)
2497
0
            return code;
2498
2499
0
        pgs->line_params.half_width = saved_width;
2500
0
    } else {
2501
0
        code = pdf_set_text_process_state(pdev, (const gs_text_enum_t *)penum,
2502
0
                                      ppts);
2503
0
    }
2504
0
    return (code < 0 ? code : mask);
2505
0
}
2506
2507
/*
2508
 * Set up commands to make the output state match the processing state.
2509
 * General graphics state commands are written now; text state commands
2510
 * are written later.
2511
 */
2512
int
2513
pdf_set_text_process_state(gx_device_pdf *pdev,
2514
                           const gs_text_enum_t *pte,        /* for pdcolor, pgs */
2515
                           pdf_text_process_state_t *ppts)
2516
0
{
2517
    /*
2518
     * Setting the stroke parameters may exit text mode, causing the
2519
     * settings of the text parameters to be lost.  Therefore, we set the
2520
     * stroke parameters first.
2521
     */
2522
0
    if (pdf_render_mode_uses_stroke(pdev, &ppts->values)) {
2523
        /* Write all the parameters for stroking. */
2524
0
        gs_gstate *pgs = pte->pgs;
2525
0
        float save_width = pgs->line_params.half_width;
2526
0
        int code;
2527
2528
0
        if (pdev->context == PDF_IN_STRING) {
2529
0
            code = sync_text_state(pdev);
2530
0
            if (code < 0)
2531
0
                return code;
2532
0
        }
2533
2534
0
        code = pdf_open_contents(pdev, PDF_IN_STREAM);
2535
0
        if (code < 0)
2536
0
            return code;
2537
2538
0
        code = pdf_prepare_stroke(pdev, pgs, true);
2539
0
        if (code >= 0) {
2540
0
            code = gdev_vector_prepare_stroke((gx_device_vector *)pdev,
2541
0
                                              pgs, NULL, NULL, 1);
2542
0
            if (code < 0)
2543
0
                return code;
2544
0
        }
2545
2546
0
        code = pdf_open_contents(pdev, PDF_IN_STRING);
2547
0
        if (code < 0)
2548
0
            return code;
2549
2550
0
        pgs->line_params.half_width = save_width;
2551
0
    }
2552
2553
    /* Now set all the other parameters. */
2554
2555
0
    return pdf_set_text_state_values(pdev, &ppts->values);
2556
0
}
2557
2558
static int
2559
store_glyph_width(pdf_glyph_width_t *pwidth, int wmode, const gs_matrix *scale,
2560
                  const gs_glyph_info_t *pinfo)
2561
0
{
2562
0
    double w, v;
2563
2564
0
    gs_distance_transform(pinfo->width[wmode].x, pinfo->width[wmode].y, scale, &pwidth->xy);
2565
0
    if (wmode)
2566
0
        w = pwidth->xy.y, v = pwidth->xy.x;
2567
0
    else
2568
0
        w = pwidth->xy.x, v = pwidth->xy.y;
2569
0
    pwidth->w = w;
2570
0
    if (v != 0)
2571
0
        return 1;
2572
0
    gs_distance_transform(pinfo->v.x, pinfo->v.y, scale, &pwidth->v);
2573
0
    return 0;
2574
0
}
2575
2576
static int
2577
get_missing_width(gs_font_base *cfont, int wmode, const gs_matrix *scale_c,
2578
                    pdf_glyph_widths_t *pwidths)
2579
0
{
2580
0
    gs_font_info_t finfo;
2581
0
    int code;
2582
2583
0
    code = cfont->procs.font_info((gs_font *)cfont, NULL,
2584
0
                                  FONT_INFO_MISSING_WIDTH, &finfo);
2585
0
    if (code < 0)
2586
0
        return code;
2587
0
    if (wmode) {
2588
0
        gs_distance_transform(0.0, -finfo.MissingWidth, scale_c, &pwidths->real_width.xy);
2589
0
        pwidths->Width.xy.x = 0;
2590
0
        pwidths->Width.xy.y = pwidths->real_width.xy.y;
2591
0
        pwidths->Width.w = pwidths->real_width.w =
2592
0
                pwidths->Width.xy.y;
2593
0
        pwidths->Width.v.x = - pwidths->Width.xy.y / 2;
2594
0
        pwidths->Width.v.y = - pwidths->Width.xy.y;
2595
0
    } else {
2596
0
        gs_distance_transform(finfo.MissingWidth, 0.0, scale_c, &pwidths->real_width.xy);
2597
0
        pwidths->Width.xy.x = pwidths->real_width.xy.x;
2598
0
        pwidths->Width.xy.y = 0;
2599
0
        pwidths->Width.w = pwidths->real_width.w =
2600
0
                pwidths->Width.xy.x;
2601
0
        pwidths->Width.v.x = pwidths->Width.v.y = 0;
2602
0
    }
2603
    /*
2604
     * Don't mark the width as known, just in case this is an
2605
     * incrementally defined font.
2606
     */
2607
0
    return 1;
2608
0
}
2609
2610
/*
2611
 * Get the widths (unmodified from the copied font,
2612
 * and possibly modified from the original font) of a given glyph.
2613
 * Return 1 if the width was defaulted to MissingWidth.
2614
 * Return TEXT_PROCESS_CDEVPROC if a CDevProc callout is needed.
2615
 * cdevproc_result != NULL if we restart after a CDevProc callout.
2616
 */
2617
int
2618
pdf_glyph_widths(pdf_font_resource_t *pdfont, int wmode, gs_glyph glyph,
2619
                 gs_font *orig_font, pdf_glyph_widths_t *pwidths,
2620
                 const double cdevproc_result[10])
2621
0
{
2622
0
    gs_font_base *cfont = pdf_font_resource_font(pdfont, false);
2623
0
    gs_font *ofont = orig_font;
2624
0
    gs_glyph_info_t info;
2625
0
    gs_matrix scale_c, scale_o;
2626
0
    int code, rcode = 0;
2627
0
    gs_point v;
2628
0
    int allow_cdevproc_callout = (orig_font->FontType == ft_CID_TrueType
2629
0
                || orig_font->FontType == ft_CID_encrypted
2630
0
                ? GLYPH_INFO_CDEVPROC : 0); /* fixme : allow more font types. */
2631
2632
0
    if (ofont->FontType == ft_composite)
2633
0
        return_error(gs_error_unregistered); /* Must not happen. */
2634
0
    code = glyph_orig_matrix((const gs_font *)cfont, glyph, &scale_c);
2635
0
    if (code < 0)
2636
0
        return code;
2637
0
    code = glyph_orig_matrix(ofont, glyph, &scale_o);
2638
0
    if (code < 0)
2639
0
        return code;
2640
0
    gs_matrix_scale(&scale_c, 1000.0, 1000.0, &scale_c);
2641
0
    gs_matrix_scale(&scale_o, 1000.0, 1000.0, &scale_o);
2642
0
    pwidths->Width.v.x = pwidths->Width.v.y = 0;
2643
0
    pwidths->real_width.v.x = pwidths->real_width.v.y = 0;
2644
0
    pwidths->real_width.w = pwidths->real_width.xy.x = pwidths->real_width.xy.y = 0;
2645
0
    pwidths->replaced_v = false;
2646
0
    pwidths->ignore_wmode = false;
2647
0
    if (glyph == GS_NO_GLYPH)
2648
0
        return get_missing_width(cfont, wmode, &scale_c, pwidths);
2649
0
    code = cfont->procs.glyph_info((gs_font *)cfont, glyph, NULL,
2650
0
                                    GLYPH_INFO_WIDTH0 |
2651
0
                                    (GLYPH_INFO_WIDTH0 << wmode) |
2652
0
                                    GLYPH_INFO_OUTLINE_WIDTHS |
2653
0
                                    (GLYPH_INFO_VVECTOR0 << wmode),
2654
0
                                    &info);
2655
    /* For CID fonts the PDF spec requires the x-component of v-vector
2656
       to be equal to half glyph width, and AR5 takes it from W, DW.
2657
       So make a compatibe data here.
2658
     */
2659
0
    if ((code == gs_error_undefined || !(info.members & (GLYPH_INFO_WIDTH0 << wmode)))) {
2660
        /* If we got an undefined error, and its a type 1/CFF font, try to
2661
         * find the /.notdef glyph and use its width instead (as this is the
2662
         * glyph which will be rendered). We don't do this for other font types
2663
         * as it seems Acrobat/Distiller may not do so either.
2664
         */
2665
0
        if (code == gs_error_undefined && (ofont->FontType == ft_encrypted || ofont->FontType == ft_encrypted2)) {
2666
0
            int index;
2667
0
            gs_glyph notdef_glyph;
2668
2669
0
            v.x = v.y = 0;
2670
2671
0
            for (index = 0;
2672
0
                (ofont->procs.enumerate_glyph((gs_font *)ofont, &index,
2673
0
                (GLYPH_SPACE_NAME), &notdef_glyph)) >= 0 &&
2674
0
                index != 0;) {
2675
0
                    if (gs_font_glyph_is_notdef((gs_font_base *)ofont, notdef_glyph)) {
2676
0
                        code = ofont->procs.glyph_info((gs_font *)ofont, notdef_glyph, NULL,
2677
0
                                            GLYPH_INFO_WIDTH0 << wmode,
2678
0
                                            &info);
2679
2680
0
                    if (code < 0)
2681
0
                        return code;
2682
0
                    code = store_glyph_width(&pwidths->Width, wmode, &scale_c, &info);
2683
0
                    if (code < 0)
2684
0
                        return code;
2685
0
                    rcode |= code;
2686
0
                    if (info.members  & (GLYPH_INFO_VVECTOR0 << wmode))
2687
0
                        gs_distance_transform(info.v.x, info.v.y, &scale_c, &v);
2688
0
                    else
2689
0
                        v.x = v.y = 0;
2690
0
                    break;
2691
0
                }
2692
0
            }
2693
0
        } else {
2694
0
        code = get_missing_width(cfont, wmode, &scale_c, pwidths);
2695
0
            if (code < 0)
2696
0
                v.y = 0;
2697
0
            else
2698
0
                v.y = pwidths->Width.v.y;
2699
0
            if (wmode) {
2700
0
                pdf_glyph_widths_t widths1;
2701
2702
0
                if (get_missing_width(cfont, 0, &scale_c, &widths1) < 0)
2703
0
                    v.x = 0;
2704
0
                else
2705
0
                    v.x = widths1.Width.w / 2;
2706
0
            } else
2707
0
                v.x = pwidths->Width.v.x;
2708
0
        }
2709
0
    } else if (code < 0)
2710
0
        return code;
2711
0
    else {
2712
0
        code = store_glyph_width(&pwidths->Width, wmode, &scale_c, &info);
2713
0
        if (code < 0)
2714
0
            return code;
2715
0
        rcode |= code;
2716
0
        if (info.members  & (GLYPH_INFO_VVECTOR0 << wmode))
2717
0
            gs_distance_transform(info.v.x, info.v.y, &scale_c, &v);
2718
0
        else
2719
0
            v.x = v.y = 0;
2720
0
        if (wmode && pdf_is_CID_font(ofont)) {
2721
0
            if (info.members & (GLYPH_INFO_WIDTH0 << wmode)) {
2722
0
                gs_point xy;
2723
2724
0
                gs_distance_transform(info.width[0].x, info.width[0].y, &scale_c, &xy);
2725
0
                v.x = xy.x / 2;
2726
0
            } else {
2727
0
                pdf_glyph_widths_t widths1;
2728
2729
0
                if (get_missing_width(cfont, 0, &scale_c, &widths1) < 0)
2730
0
                    v.x = 0;
2731
0
                else
2732
0
                    v.x = widths1.Width.w / 2;
2733
0
            }
2734
0
        }
2735
0
    }
2736
0
    pwidths->Width.v = v;
2737
0
    if (code > 0 && !pdf_is_CID_font(ofont))
2738
0
        pwidths->Width.xy.x = pwidths->Width.xy.y = pwidths->Width.w = 0;
2739
0
    if (cdevproc_result == NULL) {
2740
0
        info.members = 0;
2741
0
        code = ofont->procs.glyph_info(ofont, glyph, NULL,
2742
0
                                            (GLYPH_INFO_WIDTH0 << wmode) |
2743
0
                                            (GLYPH_INFO_VVECTOR0 << wmode) |
2744
0
                                            allow_cdevproc_callout,
2745
0
                                            &info);
2746
        /* fixme : Move this call before cfont->procs.glyph_info. */
2747
0
        if (info.members & GLYPH_INFO_CDEVPROC) {
2748
0
            if (allow_cdevproc_callout)
2749
0
                return TEXT_PROCESS_CDEVPROC;
2750
0
        else
2751
0
            return_error(gs_error_rangecheck);
2752
0
        }
2753
0
    } else {
2754
0
        info.width[0].x = cdevproc_result[0];
2755
0
        info.width[0].y = cdevproc_result[1];
2756
0
        info.width[1].x = cdevproc_result[6];
2757
0
        info.width[1].y = cdevproc_result[7];
2758
0
        info.v.x = (wmode ? cdevproc_result[8] : 0);
2759
0
        info.v.y = (wmode ? cdevproc_result[9] : 0);
2760
0
        info.members = (GLYPH_INFO_WIDTH0 << wmode) |
2761
0
                       (wmode ? GLYPH_INFO_VVECTOR1 : 0);
2762
0
        code = 0;
2763
0
    }
2764
0
    if (code == gs_error_undefined || !(info.members & (GLYPH_INFO_WIDTH0 << wmode)))
2765
0
        pwidths->real_width = pwidths->Width;
2766
0
    else if (code < 0)
2767
0
        return code;
2768
0
    else {
2769
0
        if ((info.members & (GLYPH_INFO_VVECTOR0 | GLYPH_INFO_VVECTOR1)) != 0) {
2770
0
            pwidths->replaced_v = true;
2771
0
            if ((info.members & GLYPH_INFO_VVECTOR1) == 0 && wmode == 1)
2772
0
                pwidths->ignore_wmode = true;
2773
0
        }
2774
0
        else
2775
0
            info.v.x = info.v.y = 0;
2776
0
        code = store_glyph_width(&pwidths->real_width, wmode, &scale_o, &info);
2777
0
        if (code < 0)
2778
0
            return code;
2779
0
        rcode |= code;
2780
0
        gs_distance_transform(info.v.x, info.v.y, &scale_o, &pwidths->real_width.v);
2781
0
    }
2782
0
    return rcode;
2783
0
}
2784
2785
static int
2786
pdf_choose_output_char_code(gx_device_pdf *pdev, pdf_text_enum_t *penum, gs_char *pch)
2787
0
{
2788
0
    gs_char ch;
2789
0
    gs_font *font = penum->current_font;
2790
2791
0
    if (penum->text.operation & TEXT_FROM_SINGLE_GLYPH) {
2792
0
        byte buf[1];
2793
0
        int char_code_length;
2794
0
        gs_glyph glyph = penum->text.data.d_glyph;
2795
0
        int code = pdf_encode_glyph((gs_font_base *)font, glyph,
2796
0
                    buf, sizeof(buf), &char_code_length);
2797
2798
0
        if (code < 0) {
2799
            /* Must not happen, becuse pdf_encode_glyph was passed in process_plain_text.*/
2800
0
            ch = GS_NO_CHAR;
2801
0
        } else if (char_code_length != 1) {
2802
            /* Must not happen with type 3 fonts.*/
2803
0
            ch = GS_NO_CHAR;
2804
0
        } else
2805
0
            ch = buf[0];
2806
0
    } else if (penum->orig_font->FontType == ft_composite) {
2807
0
        gs_font_type0 *font0 = (gs_font_type0 *)penum->orig_font;
2808
0
        gs_glyph glyph = penum->returned.current_glyph;
2809
2810
0
        if (font0->data.FMapType == fmap_CMap) {
2811
0
            pdf_font_resource_t *pdfont;
2812
0
            int code = pdf_attached_font_resource(pdev, font, &pdfont, NULL, NULL, NULL, NULL);
2813
2814
0
            if (code < 0)
2815
0
                return code;
2816
0
            ch = pdf_find_glyph(pdfont, glyph);
2817
0
        } else
2818
0
            ch = penum->returned.current_char;
2819
0
    } else {
2820
0
        ch = penum->returned.current_char;
2821
        /* Keep for records : glyph = font->procs.encode_char(font, ch, GLYPH_SPACE_NAME); */
2822
        /*
2823
         * If glyph == GS_NO_GLYPH, we should replace it with
2824
         * a notdef glyph, but we don't know how to do with Type 3 fonts.
2825
         */
2826
0
    }
2827
0
    *pch = ch;
2828
0
    return 0;
2829
0
}
2830
2831
static int
2832
pdf_choose_output_glyph_name(gx_device_pdf *pdev, pdf_text_enum_t *penum, gs_const_string *gnstr, gs_glyph glyph)
2833
0
{
2834
0
    if (penum->orig_font->FontType == ft_composite || penum->orig_font->procs.glyph_name(penum->orig_font, glyph, gnstr) < 0
2835
0
        || (penum->orig_font->FontType > 42 && gnstr->size == 7 && strcmp((const char *)gnstr->data, ".notdef")== 0)) {
2836
        /* If we're capturing a PCL bitmap, and the glyph comes back with a name of '/.notdef' then
2837
         * generate a name instead. There's nothing wrong technically with using /.notdef, but Acrobat does
2838
         * 'special stuff' with that name, and messes up the display. See bug #699102.
2839
         */
2840
        /* couldn't find a glyph name, so make one up! This can happen if we are handling PCL and the glyph
2841
         * (character code) is less than 29, the PCL glyph names start with /.notdef at 29. We also need to
2842
         * do this for composite fonts.
2843
         */
2844
0
        char buf[6];
2845
0
        byte *p;
2846
2847
0
        gnstr->size = 5;
2848
0
        p = (byte *)gs_alloc_string(pdev->pdf_memory, gnstr->size, "pdf_text_set_cache");
2849
0
        if (p == NULL)
2850
0
            return_error(gs_error_VMerror);
2851
0
        gs_sprintf(buf, "g%04x", (unsigned int)(glyph & 0xFFFF));
2852
0
        memcpy(p, buf, 5);
2853
0
        gnstr->data = p;
2854
0
    }
2855
0
    return 0;
2856
0
}
2857
2858
/* ---------------- Main entry ---------------- */
2859
2860
/*
2861
 * Fall back to the default text processing code when needed.
2862
 */
2863
int
2864
pdf_default_text_begin(gs_text_enum_t *pte, const gs_text_params_t *text,
2865
                       gs_text_enum_t **ppte)
2866
0
{
2867
0
    gs_text_params_t text1 = *text;
2868
2869
0
    if(pte->current_font->FontType == 3 && (text1.operation & TEXT_DO_NONE)) {
2870
        /* We need a real drawing to accumulate charproc. */
2871
0
        text1.operation &= ~TEXT_DO_NONE;
2872
0
        text1.operation |= TEXT_DO_DRAW;
2873
0
    }
2874
0
    return gx_default_text_begin(pte->dev, pte->pgs, &text1, pte->current_font,
2875
0
                                 pte->path, pte->pdcolor, pte->pcpath,
2876
0
                                 pte->memory, ppte);
2877
0
}
2878
2879
static int install_PS_charproc_accumulator(gx_device_pdf *pdev, gs_text_enum_t *pte,
2880
                             gs_text_enum_t *pte_default, pdf_text_enum_t *const penum)
2881
0
{
2882
0
    int code;
2883
2884
0
    penum->returned.current_char = pte_default->returned.current_char;
2885
0
    penum->returned.current_glyph = pte_default->returned.current_glyph;
2886
0
    pdev->charproc_ctm = penum->pgs->ctm;
2887
0
    if ((penum->current_font->FontType == ft_user_defined || penum->current_font->FontType == ft_PDF_user_defined)&&
2888
0
        penum->outer_CID == GS_NO_GLYPH &&
2889
0
            !(penum->pte_default->text.operation & TEXT_DO_CHARWIDTH)) {
2890
        /* The condition above must be consistent with one in pdf_text_set_cache,
2891
           which decides to apply pdf_set_charproc_attrs. */
2892
0
        gs_matrix m;
2893
0
        pdf_font_resource_t *pdfont;
2894
2895
0
        code = pdf_start_charproc_accum(pdev);
2896
0
        if (code < 0)
2897
0
            return code;
2898
2899
        /* We need to give FreeType some room for accuracy when
2900
         * retrieving the outline. We will use a scale factor of 100
2901
         * (see below). Because this appears to the regular path
2902
         * handling code as if it were at the page level, the co-ords
2903
         * would be clipped frequently, so we temporarily hack the
2904
         * width and height of the device here to ensure it doesn't.
2905
         * Note that this requires some careful manipulation of the
2906
         * CTM in various places, which want numbers in the font
2907
         * co-ordinate space, not the scaled user space.
2908
         */
2909
0
        pdev->width *= 100;
2910
0
        pdev->height *= 100;
2911
2912
0
        pdf_viewer_state_from_gs_gstate(pdev, pte->pgs, pte->pdcolor);
2913
        /* Set line params to unallowed values so that
2914
           they'll synchronize with writing them out on the first use.
2915
           Doing so because PDF viewer inherits them from the
2916
           contents stream when executing the charproc,
2917
           but at this moment we don't know in what contexts
2918
           it will be used. */
2919
0
        pdev->state.line_params.half_width = -1;
2920
0
        pdev->state.line_params.start_cap = gs_cap_unknown;
2921
0
        pdev->state.line_params.end_cap = gs_cap_unknown;
2922
0
        pdev->state.line_params.dash_cap = gs_cap_unknown;
2923
0
        pdev->state.line_params.join = gs_join_unknown;
2924
0
        pdev->state.line_params.miter_limit = -1;
2925
0
        pdev->state.line_params.dash.pattern_size = -1;
2926
        /* Must set an identity CTM for the charproc accumulation.
2927
           The function show_proceed (called from gs_text_process above)
2928
           executed gsave, so we are safe to change CTM now.
2929
           Note that BuildChar may change CTM before calling setcachedevice. */
2930
0
        gs_make_identity(&m);
2931
        /* See comment above, we actually want to use a scale factor
2932
         * of 100 in order to give FreeType some room in the fixed
2933
         * precision calculations when retrieing the outline. So in
2934
         * fact we don't use the identity CTM, but a 100x100 matrix
2935
         * Originally tried 1000, but that was too likely to cause
2936
         * clipping or arithmetic overflow.
2937
         */
2938
0
        gs_matrix_scale(&m, 100, 100, &m);
2939
0
        gs_matrix_fixed_from_matrix(&penum->pgs->ctm, &m);
2940
2941
        /* Choose a character code to use with the charproc. */
2942
0
        code = pdf_choose_output_char_code(pdev, penum, &penum->output_char_code);
2943
0
        if (code < 0)
2944
0
            return code;
2945
0
        code = pdf_attached_font_resource(pdev, penum->current_font, &pdfont, NULL, NULL, NULL, NULL);
2946
0
        if (code < 0)
2947
0
            return code;
2948
0
        pdev->font3 = (pdf_resource_t *)pdfont;
2949
0
        pdev->substream_Resources = pdfont->u.simple.s.type3.Resources;
2950
0
        penum->charproc_accum = true;
2951
0
        pdev->accumulating_charproc = true;
2952
0
        pdev->charproc_BBox.p.x = 10000;
2953
0
        pdev->charproc_BBox.p.y = 10000;
2954
0
        pdev->charproc_BBox.q.x = 0;
2955
0
        pdev->charproc_BBox.q.y = 0;
2956
0
        return TEXT_PROCESS_RENDER;
2957
0
    }
2958
0
    return 0;
2959
0
}
2960
2961
static int install_charproc_accumulator(gx_device_pdf *pdev, gs_text_enum_t *pte,
2962
                             gs_text_enum_t *pte_default, pdf_text_enum_t *const penum)
2963
0
{
2964
0
    int code;
2965
2966
0
    pdev->charproc_ctm = penum->pgs->ctm;
2967
0
    if ((penum->current_font->FontType == ft_user_defined ||
2968
0
        penum->current_font->FontType == ft_PDF_user_defined ||
2969
0
        penum->current_font->FontType == ft_PCL_user_defined ||
2970
0
        penum->current_font->FontType == ft_MicroType ||
2971
0
        penum->current_font->FontType == ft_GL2_stick_user_defined ||
2972
0
        penum->current_font->FontType == ft_GL2_531) &&
2973
0
            penum->outer_CID == GS_NO_GLYPH &&
2974
0
            !(penum->pte_default->text.operation & TEXT_DO_CHARWIDTH)) {
2975
        /* The condition above must be consistent with one in pdf_text_set_cache,
2976
           which decides to apply pdf_set_charproc_attrs. */
2977
0
        gs_matrix m;
2978
0
        pdf_font_resource_t *pdfont;
2979
2980
0
        pdev->PS_accumulator = false;
2981
0
        code = pdf_start_charproc_accum(pdev);
2982
0
        if (code < 0)
2983
0
            return code;
2984
2985
0
        pdf_viewer_state_from_gs_gstate(pdev, pte->pgs, pte->pdcolor);
2986
        /* Set line params to unallowed values so that
2987
           they'll synchronize with writing them out on the first use.
2988
           Doing so because PDF viewer inherits them from the
2989
           contents stream when executing the charproc,
2990
           but at this moment we don't know in what contexts
2991
           it will be used. */
2992
0
        pdev->state.line_params.half_width = -1;
2993
0
        pdev->state.line_params.start_cap = gs_cap_unknown;
2994
0
        pdev->state.line_params.end_cap = gs_cap_unknown;
2995
0
        pdev->state.line_params.dash_cap = gs_cap_unknown;
2996
0
        pdev->state.line_params.join = gs_join_unknown;
2997
0
        pdev->state.line_params.miter_limit = -1;
2998
0
        pdev->state.line_params.dash.pattern_size = -1;
2999
        /* Must set an identity CTM for the charproc accumulation.
3000
           The function show_proceed (called from gs_text_process above)
3001
           executed gsave, so we are safe to change CTM now.
3002
           Note that BuildChar may change CTM before calling setcachedevice. */
3003
0
        gs_make_identity(&m);
3004
0
        gs_matrix_fixed_from_matrix(&penum->pgs->ctm, &m);
3005
3006
        /* Choose a character code to use with the charproc. */
3007
0
        code = pdf_choose_output_char_code(pdev, penum, &penum->output_char_code);
3008
0
        if (code < 0) {
3009
0
            (void)pdf_exit_substream(pdev);
3010
0
            return code;
3011
0
        }
3012
0
        code = pdf_attached_font_resource(pdev, penum->current_font, &pdfont, NULL, NULL, NULL, NULL);
3013
0
        if (code < 0) {
3014
0
            (void)pdf_exit_substream(pdev);
3015
0
            return code;
3016
0
        }
3017
0
        pdev->font3 = (pdf_resource_t *)pdfont;
3018
0
        if (pdfont == 0L) {
3019
0
            (void)pdf_exit_substream(pdev);
3020
0
            return gs_note_error(gs_error_invalidfont);
3021
0
        }
3022
3023
0
        pdev->substream_Resources = pdfont->u.simple.s.type3.Resources;
3024
0
        penum->charproc_accum = true;
3025
0
        pdev->accumulating_charproc = true;
3026
0
        return TEXT_PROCESS_RENDER;
3027
0
    }
3028
0
    return 0;
3029
0
}
3030
3031
static int complete_charproc(gx_device_pdf *pdev, gs_text_enum_t *pte,
3032
                             gs_text_enum_t *pte_default, pdf_text_enum_t *const penum,
3033
                             bool was_PS_type3)
3034
0
{
3035
0
    gs_const_string gnstr;
3036
0
    int code;
3037
3038
0
    if (pte_default->returned.current_glyph == GS_NO_GLYPH)
3039
0
      return_error(gs_error_undefined);
3040
0
    code = pdf_choose_output_glyph_name(pdev, penum, &gnstr, pte_default->returned.current_glyph);
3041
0
    if (code < 0) {
3042
0
        return code;
3043
0
    }
3044
3045
0
    if ((penum->current_font->FontType == ft_user_defined ||
3046
0
       penum->current_font->FontType == ft_PDF_user_defined ||
3047
0
       penum->current_font->FontType == ft_PCL_user_defined ||
3048
0
       penum->current_font->FontType == ft_MicroType ||
3049
0
       penum->current_font->FontType == ft_GL2_stick_user_defined ||
3050
0
       penum->current_font->FontType == ft_GL2_531) &&
3051
0
       stell(pdev->strm) == 0)
3052
0
    {
3053
0
        char glyph[256], FontName[gs_font_name_max + 1], KeyName[256];
3054
0
        int len;
3055
3056
0
        len = min(gs_font_name_max, gnstr.size);
3057
0
        memcpy(glyph, gnstr.data, len);
3058
0
        glyph[len] = 0x00;
3059
0
        len = min(gs_font_name_max, penum->current_font->font_name.size);
3060
0
        memcpy(FontName, penum->current_font->font_name.chars, len);
3061
0
        FontName[len] = 0x00;
3062
0
        len = min(gs_font_name_max, penum->current_font->key_name.size);
3063
0
        memcpy(KeyName, penum->current_font->key_name.chars, len);
3064
0
        KeyName[len] = 0x00;
3065
3066
0
        emprintf4(pdev->memory,
3067
0
            "ERROR: Page %d used undefined glyph '%s' from type 3 font '%s', key '%s'\n",
3068
0
            pdev->next_page, glyph, FontName, KeyName);
3069
0
            stream_puts(pdev->strm, "0 0 0 0 0 0 d1\n");
3070
0
    }
3071
3072
0
    if (was_PS_type3) {
3073
        /* See below, we scaled the device height and width to prevent
3074
         * clipping of the CharProc operations, now we need to undo that.
3075
         */
3076
0
        pdev->width /= 100;
3077
0
        pdev->height /= 100;
3078
0
    }
3079
0
    code = pdf_end_charproc_accum(pdev, penum->current_font, penum->cgp,
3080
0
                pte_default->returned.current_glyph, penum->output_char_code, &gnstr);
3081
0
    if (code < 0)
3082
0
        return code;
3083
0
    pdev->accumulating_charproc = false;
3084
0
    penum->charproc_accum = false;
3085
0
    code = gx_default_text_restore_state(pte_default);
3086
0
    if (code < 0)
3087
0
        return code;
3088
0
    gs_text_release(pte_default, "pdf_text_process");
3089
0
    penum->pte_default = 0;
3090
3091
0
    return 0;
3092
0
}
3093
3094
/* Nasty hackery. The PCL 'stick font' is drawn by constructing a path, and then stroking it.
3095
 * The stroke width is calculated under the influence of the device default matrix, which
3096
 * ensures it is the same, no matter what size the font is drawn at. Of course we are
3097
 * capturing the glyph under an identity matrix, so using the device matrix blows it up.
3098
 * What we do is replace the get_initial_matrix method for the course of the charproc
3099
 * accumulation *only*, and return a more sensible 'device' matrix.
3100
 * We know that the Charproc CTM is a combination of the font point size, and the default device
3101
 * matrix, so we just take off the default matrix, and invert the font scaling.
3102
 * This will scale the linewidth nicely for us. It does mean that if we use the
3103
 * same font at a different size, then the width will not be 'correct', but I
3104
 * think this is good enough.
3105
 */
3106
static void pdf_type3_get_initial_matrix(gx_device * dev, gs_matrix * pmat)
3107
0
{
3108
0
    gx_device_pdf *pdev = (gx_device_pdf *)dev;
3109
3110
0
    pmat->xx = pdev->charproc_ctm.xx;
3111
0
    pmat->xy = pdev->charproc_ctm.xy;
3112
0
    pmat->yx = pdev->charproc_ctm.yx;
3113
0
    pmat->yy = pdev->charproc_ctm.yy;
3114
0
    pmat->tx = 0;
3115
0
    pmat->ty = 0;
3116
    /* FIXME: Handle error here? Or is the charproc_ctm guaranteed to be invertible? */
3117
0
    (void)gs_matrix_invert(pmat, pmat);
3118
0
    gs_matrix_scale(pmat, pdev->HWResolution[0] / 72.0, pdev->HWResolution[0] / 72.0, pmat);
3119
0
}
3120
3121
static int pdf_query_purge_cached_char(const gs_memory_t *mem, cached_char *cc, void *data)
3122
0
{
3123
0
    cached_char *to_purge = (cached_char *)data;
3124
3125
3126
0
    if (cc->code == to_purge->code && cc_pair(cc) == cc_pair(to_purge) &&
3127
0
        cc->subpix_origin.x == to_purge->subpix_origin.x &&
3128
0
        cc->subpix_origin.y == to_purge->subpix_origin.y &&
3129
0
        cc->wmode == to_purge->wmode && cc_depth(cc) == cc_depth(to_purge)
3130
0
        )
3131
0
        return 1;
3132
0
    return 0;
3133
0
}
3134
3135
/*
3136
 * Continue processing text.  This is the 'process' procedure in the text
3137
 * enumerator.  Per the check in pdf_text_begin, we know the operation is
3138
 * not a charpath, but it could be anything else.
3139
 */
3140
int
3141
pdf_text_process(gs_text_enum_t *pte)
3142
0
{
3143
0
    pdf_text_enum_t *const penum = (pdf_text_enum_t *)pte;
3144
0
    uint operation = pte->text.operation;
3145
0
    uint size = pte->text.size - pte->index;
3146
0
    gs_text_enum_t *pte_default;
3147
0
    PROCESS_TEXT_PROC((*process));
3148
0
    int code = 0, early_accumulator = 0;
3149
0
    gx_device_pdf *pdev = (gx_device_pdf *)penum->dev;
3150
0
    uint captured_pte_index = 0xFFFFFFFF;
3151
0
#define BUF_SIZE 100                /* arbitrary > 0 */
3152
    /* Use a union to ensure alignment. */
3153
0
    union bu_ {
3154
0
        byte bytes[BUF_SIZE];
3155
0
        gs_char chars[BUF_SIZE / sizeof(gs_char)];
3156
0
        gs_glyph glyphs[BUF_SIZE / sizeof(gs_glyph)];
3157
0
    } buf;
3158
3159
0
     if (!penum->pte_default) {
3160
        /* Don't need to sync before exiting charproc. */
3161
0
        code = pdf_prepare_text_drawing(pdev, pte);
3162
0
        if (code == gs_error_rangecheck) {
3163
            /* Fallback to the default implermentation for handling
3164
               a transparency with CompatibilityLevel<=1.3 . */
3165
0
            goto default_impl;
3166
0
        }
3167
0
        if (code < 0)
3168
0
            return code;
3169
0
    }
3170
0
    if (!penum->pte_default) {
3171
0
        pdev->charproc_just_accumulated = false;
3172
0
        if (penum->cdevproc_callout) {
3173
            /* Restore after TEXT_PROCESS_CDEVPROC in scan_cmap_text. */
3174
0
            penum->current_font = penum->orig_font;
3175
0
        }
3176
0
    }
3177
0
    if ((penum->current_font->FontType == ft_user_defined ||
3178
0
        penum->current_font->FontType == ft_PCL_user_defined ||
3179
0
        penum->current_font->FontType == ft_PDF_user_defined ||
3180
0
        penum->current_font->FontType == ft_MicroType ||
3181
0
        penum->current_font->FontType == ft_GL2_stick_user_defined ||
3182
0
        penum->current_font->FontType == ft_GL2_531) &&
3183
0
        (penum->text.operation & TEXT_DO_ANY_CHARPATH)
3184
0
        && !pdev->type3charpath) {
3185
0
        pdev->type3charpath = true;
3186
0
        if (!penum->charproc_accum)
3187
0
            goto default_impl;
3188
0
    }
3189
3190
0
    code = -1;                /* to force default implementation */
3191
3192
    /*
3193
     * If we fell back to the default implementation, continue using it.
3194
     */
3195
0
 top:
3196
0
    pte_default = penum->pte_default;
3197
    /* pte_default is a signal that we can't handle the glyph in the current
3198
     * font 'natively'. This means either a type 3 font (for PostScript we
3199
     * need to return to the PS interpreter to run the BuildChar), or a font
3200
     * type we can't or don't support in PDF. In the latter case we have the
3201
     * BuildChar render the glyph and store it in the cache, spot the usage
3202
     * in the pdfwrite image routine and we store the resluting bitmap in a
3203
     * Type 3 font. NB if the glyph is uncached then it just ends up in the
3204
     * output as a bitmap image.
3205
     */
3206
0
    if (pte_default) {
3207
0
        gs_char *cdata;
3208
3209
0
        cdata = (gs_char *)pte->text.data.chars;
3210
0
        if (penum->charproc_accum) {
3211
            /* We've been accumulating a Type 3 CharProc, so now we need to
3212
             * finish off and store it in the font.
3213
             */
3214
0
            code = complete_charproc(pdev, pte, pte_default, penum, true);
3215
0
            if (code < 0)
3216
0
                return code;
3217
            /* Record the current index of the text, this is the index for which we captured
3218
             * this charproc. We use this below to determine whether an error return is an
3219
             * error after we've already captured a CharProc. If it is, then we must not
3220
             * attempt to capture it again, this wil lead to an infinite loop.
3221
             */
3222
0
            captured_pte_index = pte->index;
3223
0
            if (!pdev->type3charpath)
3224
0
                goto top;
3225
0
            else
3226
0
                goto default_impl;
3227
0
        }
3228
3229
0
        if ((penum->current_font->FontType == ft_GL2_stick_user_defined ||
3230
0
            penum->current_font->FontType == ft_GL2_531 || penum->current_font->FontType == ft_MicroType)
3231
0
            && operation & TEXT_FROM_CHARS && !pdev->type3charpath) {
3232
            /* Check for anamorphic sacling, we msut not cache stick font
3233
             * in this case, as the stroke width will vary with the scaling.
3234
             */
3235
3236
            /* To test the scaling we'll map two unit vectors, calculate the
3237
             * length of the transformed vectors and see if they are the same
3238
             * x' = ax + cy + Tx
3239
             * y' = bx + dy + Ty
3240
             * We set Tx and Ty to zero (we only care about scale not translation)
3241
             * We then test 0,0->0,1 and 0,0 -> 1,0. Because one term is always 0
3242
             * this means we can simplify the math.
3243
             */
3244
            /* Vector 0,0 -> 0,1 x is always 0, Tx and Ty are 0 =>
3245
             * x' = cy = c
3246
             * y' = dy = d
3247
             */
3248
            /* Vector 0,0 -> 1,0 y is always 0, Tx and Ty are 0 =>
3249
             * x' = ax = a
3250
             * y' = bx = b
3251
             */
3252
            /* Length of hypotenuse squared = sum of squares We don't care
3253
             * about the length's actual magnitude, so we can compare the
3254
             * squared length
3255
             */
3256
0
            float x0y1, x1y0;
3257
3258
0
            x0y1 = (penum->pgs->ctm.yx * penum->pgs->ctm.yx) +
3259
0
                (penum->pgs->ctm.yy * penum->pgs->ctm.yy);
3260
0
            x1y0 = (penum->pgs->ctm.xx * penum->pgs->ctm.xx) +
3261
0
                (penum->pgs->ctm.xy * penum->pgs->ctm.xy);
3262
3263
0
            if (x0y1 == x1y0)
3264
0
                early_accumulator = 1;
3265
0
        }
3266
0
        if (penum->current_font->FontType == ft_PDF_user_defined) {
3267
0
            early_accumulator = 1;
3268
0
        }
3269
0
        if (early_accumulator) {
3270
0
            if (pte->text.operation & TEXT_FROM_BYTES || pte->text.operation & TEXT_FROM_STRING || (pte->text.operation & TEXT_FROM_CHARS && cdata[pte->index] <= 255)) {
3271
                /* The enumerator is created in pdf_default_text_begin and *is*
3272
                 * a show enumerator, so this is safe. We need to update the
3273
                 * graphics state pointer below which is why we need this.
3274
                 */
3275
0
                gs_show_enum psenum = *(gs_show_enum *)pte_default;
3276
0
                gs_gstate *pgs = (gs_gstate *)penum->pgs;
3277
0
                gs_text_enum_procs_t special_procs = *pte_default->procs;
3278
0
                void (*save_proc)(gx_device *, gs_matrix *) = pdev->procs.get_initial_matrix;
3279
0
                gs_matrix m, savem;
3280
3281
0
                special_procs.set_cache = pdf_text_set_cache;
3282
0
                pte_default->procs = &special_procs;
3283
3284
0
                {
3285
                    /* We should not come here if we already have a cached character (except for the special case
3286
                     * of redefined characters in PCL downloaded fonts). If we do, it means that we are doing
3287
                     * 'page bursting', ie each page is going to a separate file, and the cache has an entry
3288
                     * from previous pages, but the PDF font resource doesn't. So empty the cached character
3289
                     * from the cache, to ensure the character description gets executed.
3290
                     */
3291
0
                    gs_font *rfont = (pte->fstack.depth < 0 ? pte->current_font : pte->fstack.items[0].font);
3292
0
                    gs_font *pfont = (pte->fstack.depth < 0 ? pte->current_font :
3293
0
                        pte->fstack.items[pte->fstack.depth].font);
3294
0
                    int wmode = rfont->WMode;
3295
0
                    gs_log2_scale_point log2_scale = {0,0};
3296
0
                    gs_fixed_point subpix_origin = {0,0};
3297
0
                    cached_fm_pair *pair;
3298
0
                    cached_char *cc;
3299
3300
0
                    code = gx_lookup_fm_pair(pfont, &ctm_only(pte->pgs), &log2_scale, false, &pair);
3301
0
                    if (code < 0)
3302
0
                        return code;
3303
0
                    cc = gx_lookup_cached_char(pfont, pair, pte_default->text.data.chars[pte_default->index], wmode, 1, &subpix_origin);
3304
0
                    if (cc != 0) {
3305
0
                        gx_purge_selected_cached_chars(pfont->dir, pdf_query_purge_cached_char, (void *)cc);
3306
0
                    }
3307
0
                }
3308
                /* charproc completion will restore a gstate */
3309
0
                gs_gsave(pgs);
3310
                /* Assigning the gs_gstate pointer to the graphics state pointer
3311
                 * makes sure that when we make the CTM into the identity it
3312
                 * affects both.
3313
                 */
3314
0
                psenum.pgs = (gs_gstate *)psenum.pgs;
3315
                /* Save the current FontMatrix */
3316
0
                savem = pgs->font->FontMatrix;
3317
                /* Make the FontMatrix the identity otherwise we will apply
3318
                 * it twice, once in the glyph description and again in the
3319
                 * text matrix.
3320
                 */
3321
0
                gs_make_identity(&m);
3322
0
                pgs->font->FontMatrix = m;
3323
3324
0
                pgs->char_tm_valid = 0;
3325
0
                pgs->char_tm.txy_fixed_valid = 0;
3326
0
                pgs->current_point.x = pgs->current_point.y = 0;
3327
0
                pgs->char_tm.txy_fixed_valid = 0;
3328
3329
0
                if (pte->text.operation & TEXT_FROM_CHARS)
3330
0
                    pte_default->returned.current_char = penum->returned.current_char =
3331
0
                        pte->text.data.chars[pte->index];
3332
0
                else
3333
0
                    pte_default->returned.current_char = penum->returned.current_char =
3334
0
                        pte->text.data.bytes[pte->index];
3335
3336
0
                code = install_charproc_accumulator(pdev, pte, pte_default, penum);
3337
0
                if (code < 0) {
3338
0
                    gs_grestore(pgs);
3339
0
                    pgs->font->FontMatrix = savem;
3340
0
                    return code;
3341
0
                }
3342
3343
                /* We can't capture more than one glyph at a time, so amek this one
3344
                 * otherwise the gs_text_process would try to render all the glyphs
3345
                 * in the string.
3346
                 */
3347
0
                if (pte->text.size != 1)
3348
0
                    pte_default->text.size = pte->index + 1;
3349
                /* We need a special 'initial matrix' method for stick fonts,
3350
                 * See pdf_type3_get_initial_matrix above.
3351
                 */
3352
0
                pdev->procs.get_initial_matrix = pdf_type3_get_initial_matrix;
3353
3354
0
                pdev->pte = (gs_text_enum_t *)penum; /* CAUTION: See comment in gdevpdfx.h . */
3355
0
                code = gs_text_process(pte_default);
3356
0
                if (code < 0) {
3357
0
                    (void)complete_charproc(pdev, pte, pte_default, penum, false);
3358
0
                    gs_grestore(pgs);
3359
0
                    return code;
3360
0
                }
3361
0
                pdev->pte = NULL;         /* CAUTION: See comment in gdevpdfx.h . */
3362
0
                pdev->charproc_just_accumulated = false;
3363
3364
                /* Restore the saved FontMatrix, so that it gets applied
3365
                 * as part of the text matrix
3366
                 */
3367
0
                pgs->font->FontMatrix = savem;
3368
                /* Restore the default 'initial matrix' mathod. */
3369
0
                pdev->procs.get_initial_matrix = save_proc;
3370
0
                penum->returned.current_char = pte_default->returned.current_char;
3371
0
                penum->returned.current_glyph = pte_default->returned.current_glyph;
3372
0
                code = pdf_choose_output_char_code(pdev, penum, &penum->output_char_code);
3373
0
                if (code < 0) {
3374
0
                    (void)complete_charproc(pdev, pte, pte_default, penum, false);
3375
0
                    gs_grestore(pgs);
3376
0
                    return code;
3377
0
                }
3378
3379
                /* complete_charproc will release the text enumerator 'pte_default', we assume
3380
                 * that we are holding the only reference to it. Note that complete_charproc
3381
                 * also sets penum->pte_default to 0, so that we don't re-entre this  section of
3382
                 * code but process the text normally, now that we have captured the glyph description.
3383
                 */
3384
0
                code = complete_charproc(pdev, pte, pte_default, penum, false);
3385
0
                if (penum->current_font->FontType == ft_PCL_user_defined)
3386
0
                {
3387
                    /* PCL bitmap fonts can have glyphs 'reused'. We can't handle
3388
                     * handle this in a single PDF font, so we need to know when
3389
                     * it has happened and fall back to the 'default' implementation.
3390
                     * In order to do this, we create a cached character representation
3391
                     * and add it to the cache. If the glyph is reused then the
3392
                     * act of redefining it will remove this entry from the cache.
3393
                     * We check if the glyph is in the cache in process_text_return_width
3394
                     * and come back into this code. In the test above for PCL bitmap
3395
                     * fonts we also check to see if the PDF font already has a
3396
                     *'used' entry. If it does we know that its a redefinition, and
3397
                     * we don't try to capture the glyph.
3398
                     */
3399
0
                    cached_char *cc;
3400
0
                    cached_fm_pair *pair;
3401
0
                    gs_log2_scale_point log2_scale = {0,0};
3402
0
                    gs_font *rfont = (pte->fstack.depth < 0 ? pte->current_font : pte->fstack.items[0].font);
3403
0
                    int wmode = rfont->WMode;
3404
0
                    pdf_font_resource_t *pdfont;
3405
3406
                    /* This code copied from show_cache_setup */
3407
0
                    gs_memory_t *mem = penum->memory;
3408
0
                    gx_device_memory *dev =
3409
0
                        gs_alloc_struct(mem, gx_device_memory, &st_device_memory,
3410
0
                        "show_cache_setup(dev_cache)");
3411
3412
0
                    if (dev == 0) {
3413
0
                        gs_free_object(mem, dev, "show_cache_setup(dev_cache)");
3414
0
                        return_error(gs_error_VMerror);
3415
0
                    }
3416
0
                    gs_make_mem_mono_device(dev, mem, penum->dev);
3417
0
                    dev->HWResolution[0] = pgs->device->HWResolution[0];
3418
0
                    dev->HWResolution[1] = pgs->device->HWResolution[1];
3419
                    /* Retain these devices. */
3420
0
                    gx_device_retain((gx_device *)dev, true);
3421
                    /* end of code copied from show_cache_setup */
3422
3423
                    /* This copied from set_cache */
3424
0
                    code = gx_alloc_char_bits(pte->current_font->dir, dev, NULL,
3425
0
                                0, 0, &log2_scale, 1, &cc);
3426
0
                    if (code < 0)
3427
0
                        return code;
3428
3429
                    /* The following code is copied from show_update, case sws_cache */
3430
0
                    code = gx_lookup_fm_pair(pte->current_font, &ctm_only(pte->pgs),
3431
0
                            &log2_scale, false, &pair);
3432
0
                    if (code < 0)
3433
0
                        return code;
3434
3435
                    /* These members of the cached character are required
3436
                     * in order to find the cache entry later
3437
                     */
3438
0
                    cc->code = penum->returned.current_char;
3439
0
                    cc->wmode = wmode;
3440
0
                    cc->subpix_origin.x = cc->subpix_origin.y = 0;
3441
0
                    log2_scale.x = log2_scale.y = 0;
3442
0
                    code = gx_add_cached_char(pte->current_font->dir, dev,
3443
0
                               cc, pair, &log2_scale);
3444
0
                    if (code < 0)
3445
0
                        return code;
3446
                    /* End of code from show_update */
3447
3448
                    /* Finally, dispose of the device, which we don't actually need */
3449
0
                    gx_device_retain((gx_device *)dev, false);
3450
3451
                    /* Its possible for a bitmapped PCL font to not execute setcachedevice (invalid empty glyph)
3452
                     * which means that the pdfwrite override doesn't see it, and we don't note that the
3453
                     * glyph is 'cached' in the PDF font resource, but the 'used' flag does get set.
3454
                     * This causes our detection some problems, so mark it 'cached' here to make sure.
3455
                     */
3456
0
                    code = pdf_attached_font_resource(pdev, (gs_font *)penum->current_font, &pdfont, NULL, NULL, NULL, NULL);
3457
0
                    if (code < 0)
3458
0
                        return code;
3459
3460
0
                    pdfont->u.simple.s.type3.cached[cdata[pte->index] >> 3] |= 0x80 >> (cdata[pte->index] & 7);
3461
0
                }
3462
0
                size = pte->text.size - pte->index;
3463
0
                if (code < 0)
3464
0
                    return code;
3465
0
                if (!pdev->type3charpath)
3466
0
                    goto top;
3467
0
                else
3468
0
                    goto default_impl;
3469
0
            }
3470
0
        }
3471
3472
        /* Now we run the default text procedure to see what happens.
3473
         * PCL bitmap fonts and the HP/GL-2 stick font are handled above.
3474
         * If its a PostScript type 3 font (and some other kinds)
3475
         * then it will return TEXT_PROCESS_RENDER and we need to exit
3476
         * to the interpreter to run the glyph description. Otherwise we just
3477
         * run the BuildChar, and later capture the cached bitmap for incorporation
3478
         * into a type 3 font. Note that sometimes we will handle PCL or HP/GL-2
3479
         * fonts by not capturing them above, and they will come through here.
3480
         * The stick font will not be captured as a font at all, just vectors
3481
         * stored into the content stream (for osme kinds of scale/shear),
3482
         * bitmap fonts will be captured in the pdfwrite image routine. These
3483
         * are added to a type 3 font in the same way as glyphs which need to
3484
         * be rendered.
3485
         */
3486
0
        {
3487
0
            gs_show_enum *penum = (gs_show_enum *)pte_default;
3488
0
            int save_can_cache = penum->can_cache;
3489
0
            const gs_color_space *pcs;
3490
0
            const gs_client_color *pcc;
3491
0
            gs_gstate * pgs = pte->pgs;
3492
3493
            /* If we are using a high level pattern, we must not use the cached character, as the
3494
             * cache hasn't seen the pattern. So set can_cache to < 0, which prevents us consulting
3495
             * the cache, or storing the result in it.
3496
             * We actually don't want to use the cache for any Type 3 font where we're trying to
3497
             * capture the charproc - if we want to have a chance of capturing the charproc, we
3498
             * need it to execute, and not use a cache entry.
3499
             */
3500
0
            if (gx_hld_get_color_space_and_ccolor(pgs, (const gx_drawing_color *)pgs->color[0].dev_color, &pcs, &pcc) == pattern_color_space)
3501
0
                penum->can_cache = -1;
3502
0
            pdev->pte = pte_default; /* CAUTION: See comment in gdevpdfx.h . */
3503
0
            code = gs_text_process(pte_default);
3504
0
            if (code < 0)
3505
0
                return code;
3506
3507
0
            penum->can_cache = save_can_cache;
3508
3509
0
            pdev->pte = NULL;         /* CAUTION: See comment in gdevpdfx.h . */
3510
0
            pdev->charproc_just_accumulated = false;
3511
0
        }
3512
3513
        /* If the BuildChar returned TEXT_PROCESS_RENDER then we want to try and
3514
         * capture this as a type 3 font, so start the accumulator now. Note
3515
         * that the setcachedevice handling can still abort this later. In which
3516
         * case we get the rendered bitmap, just as for non type 3 fonts.
3517
         */
3518
0
        if (code == TEXT_PROCESS_RENDER && !pdev->type3charpath) {
3519
0
            int code1;
3520
3521
0
            code1 = install_PS_charproc_accumulator(pdev, pte, pte_default, penum);
3522
0
            if (code1 != 0)
3523
0
                return code1;
3524
0
        }
3525
3526
0
        gs_text_enum_copy_dynamic(pte, pte_default, true);
3527
0
        if (code)
3528
0
            return code;
3529
0
        gs_text_release(pte_default, "pdf_text_process");
3530
0
        penum->pte_default = 0;
3531
0
        if (pdev->type3charpath)
3532
0
            pdev->type3charpath = false;
3533
0
        return 0;
3534
0
    }
3535
0
    {
3536
0
        gs_font *font = pte->orig_font; /* Not sure. Changed for CDevProc callout. Was pte->current_font */
3537
3538
0
        switch (font->FontType) {
3539
0
        case ft_CID_encrypted:
3540
0
        case ft_CID_TrueType:
3541
0
            process = process_cid_text;
3542
0
            break;
3543
0
        case ft_encrypted:
3544
0
        case ft_encrypted2:
3545
0
        case ft_TrueType:
3546
0
        case ft_user_defined:
3547
0
        case ft_PDF_user_defined:
3548
0
        case ft_PCL_user_defined:
3549
0
        case ft_MicroType:
3550
0
        case ft_GL2_stick_user_defined:
3551
0
        case ft_GL2_531:
3552
            /* The data may be either glyphs or characters. */
3553
0
            process = process_plain_text;
3554
0
            break;
3555
0
        case ft_composite:
3556
0
            process =
3557
0
                (((gs_font_type0 *)font)->data.FMapType == fmap_CMap ?
3558
0
                 process_cmap_text :
3559
0
                 process_composite_text);
3560
0
            break;
3561
0
        default:
3562
0
            goto skip;
3563
0
        }
3564
0
    }
3565
3566
    /*
3567
     * We want to process the entire string in a single call, but we may
3568
     * need to modify it.  Copy it to a buffer.  Note that it may consist
3569
     * of bytes, gs_chars, or gs_glyphs.
3570
     */
3571
3572
0
    if (operation & (TEXT_FROM_STRING | TEXT_FROM_BYTES)) {
3573
0
        if (size < sizeof(gs_glyph))
3574
0
            size = sizeof(gs_glyph); /* for process_cid_text */
3575
0
    } else if (operation & TEXT_FROM_CHARS)
3576
0
        size *= sizeof(gs_char);
3577
0
    else if (operation & TEXT_FROM_SINGLE_CHAR)
3578
0
        size = sizeof(gs_char);
3579
0
    else if (operation & TEXT_FROM_GLYPHS)
3580
0
        size *= sizeof(gs_glyph);
3581
0
    else if (operation & TEXT_FROM_SINGLE_GLYPH)
3582
0
        size = sizeof(gs_glyph);
3583
0
    else
3584
0
        goto skip;
3585
3586
    /* Now that we are using the working buffer for text in composite fonts, we must make sure
3587
     * it is large enough. Each input character code may be promoted to a gs_glyph, in scan_cmap_text
3588
     * when processing a Type 0 font with a type 1 descendant font. This routine uses
3589
     * pdf_make_text_glyphs_table_unencoded (called from pdf_obtain_font_resource_unencoded) which
3590
     * also may require an identically sized buffer, so we need:
3591
     * num__input_characters * sizeof(gs_glyph) * 2.
3592
     */
3593
0
    if (pte->orig_font->FontType == ft_composite) {
3594
0
        if (size < (pte->text.size - pte->index) * sizeof(gs_glyph) * 2)
3595
0
            size = (pte->text.size - pte->index) * sizeof(gs_glyph) * 2;
3596
0
    }
3597
3598
0
    if (size <= sizeof(buf)) {
3599
0
        code = process(pte, buf.bytes, size);
3600
0
    } else {
3601
0
        byte *buf = gs_alloc_string(pte->memory, size, "pdf_text_process");
3602
3603
0
        if (buf == 0)
3604
0
            return_error(gs_error_VMerror);
3605
0
        code = process(pte, buf, size);
3606
0
        gs_free_string(pte->memory, buf, size, "pdf_text_process");
3607
0
    }
3608
0
 skip:
3609
0
    if (code < 0 ||
3610
0
            ((pte->current_font->FontType == ft_user_defined ||
3611
0
            pte->current_font->FontType == ft_PCL_user_defined ||
3612
0
            pte->current_font->FontType == ft_PDF_user_defined ||
3613
0
            pte->current_font->FontType == ft_MicroType ||
3614
0
            pte->current_font->FontType == ft_GL2_stick_user_defined ||
3615
0
            pte->current_font->FontType == ft_GL2_531 ||
3616
0
            pte->current_font->FontType == ft_TrueType) &&
3617
0
             code != TEXT_PROCESS_INTERVENE &&
3618
0
            penum->index < penum->text.size)) {
3619
0
        if (code == gs_error_unregistered) /* Debug purpose only. */
3620
0
            return code;
3621
0
        if (code == gs_error_VMerror)
3622
0
            return code;
3623
0
        if (code == gs_error_invalidfont) /* Bug 688370. */
3624
0
            return code;
3625
0
 default_impl:
3626
        /* If we have captured a CharProc, and the current index into the
3627
         * text is unchanged, then the capturing a CharProc for this text still
3628
         * resulted in a text error. So don't try to fix it by capturing the
3629
         * CharProc again, this causes an endless loop.
3630
         */
3631
0
        if (captured_pte_index == pte->index)
3632
0
            return code;
3633
        /* Fall back to the default implementation. */
3634
0
        code = pdf_default_text_begin(pte, &pte->text, &pte_default);
3635
0
        if (code < 0)
3636
0
            return code;
3637
0
        penum->pte_default = pte_default;
3638
0
        gs_text_enum_copy_dynamic(pte_default, pte, false);
3639
0
    }
3640
    /* The 'process' procedure might also have set pte_default itself. */
3641
0
    if (penum->pte_default && !code)
3642
0
        goto top;
3643
0
    return code;
3644
    /*
3645
     * This function uses an unobvious algorithm while handling type 3 fonts.
3646
     * It runs 'process' to copy text until a glyph, which was not copied to
3647
     * output font. Then it installs pte_default and falls back to default
3648
     * implementation with PS interpreter callout. The callout executes
3649
     * BuildChar/BuildGlyph with setcachedevice. The latter calls
3650
     * pdf_set_charproc_attrs, which sets up an accumulator
3651
     * of graphic objects to a pdf_begin_resource stream.
3652
     * When the callout completes, pdf_text_process calls pdf_end_charproc_accum
3653
     * and later resumes the normal (non-default) text enumeration, repeating the
3654
     * the "callouted" glyph AT SECOND TIME. We can't do without the second pass
3655
     * becauase in the first pass the glyph widths is unknown.
3656
     */
3657
     /*
3658
      * Another unobvious thing is a CDevProc callout.
3659
      * If 'process' returns with TEXT_PROCESS_CDEVPROC,
3660
      * an interpreter callout will happen, and the function will be called again
3661
      * with pte->cdevproc_result_valid = true. Then it restatrs with taking
3662
      * glyph metrics from pte->cdevproc_result instead obtaining them with
3663
      * font->procs.glyph_info .
3664
      */
3665
0
}