Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/devices/vector/gdevpdti.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2022 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
/* Bitmap font implementation for pdfwrite */
18
#include "memory_.h"
19
#include "gx.h"
20
#include "gxpath.h"
21
#include "gserrors.h"
22
#include "gsutil.h"
23
#include "gdevpdfx.h"
24
#include "gdevpdfg.h"
25
#include "gdevpdtf.h"
26
#include "gdevpdti.h"
27
#include "gdevpdts.h"
28
#include "gdevpdtw.h"
29
#include "gdevpdtt.h"
30
#include "gdevpdfo.h"
31
#include "gxchar.h"        /* For gs_show_enum */
32
33
/* ---------------- Private ---------------- */
34
35
/* Define the structure for a CharProc pseudo-resource. */
36
/*typedef struct pdf_char_proc_s pdf_char_proc_t;*/  /* gdevpdfx.h */
37
struct pdf_char_proc_s {
38
    pdf_resource_common(pdf_char_proc_t);
39
    pdf_char_proc_ownership_t *owner_fonts; /* fonts using this charproc. */
40
    int y_offset;                /* of character (0,0) */
41
    int x_offset;                /* of character (0,0) */
42
    gs_point real_width;        /* Not used with synthesised bitmap fonts. */
43
    gs_point v;                        /* Not used with synthesised bitmap fonts. */
44
};
45
46
/* The descriptor is public for pdf_resource_type_structs. */
47
gs_public_st_suffix_add1(st_pdf_char_proc, pdf_char_proc_t,
48
  "pdf_char_proc_t", pdf_char_proc_enum_ptrs, pdf_char_proc_reloc_ptrs,
49
  st_pdf_resource, owner_fonts);
50
51
struct pdf_char_proc_ownership_s {
52
    pdf_char_proc_t *char_proc;
53
    pdf_char_proc_ownership_t *font_next;        /* next char_proc for same font */
54
    pdf_char_proc_ownership_t *char_next;        /* next char_proc for same charproc */
55
    pdf_font_resource_t *font;
56
    gs_char char_code;                /* Character code in PDF font. */
57
    gs_glyph glyph;                /* Glyph id in Postscript font. */
58
    gs_string char_name;
59
    bool duplicate_char_name;
60
};
61
gs_private_st_strings1_ptrs4(st_pdf_char_proc_ownership, pdf_char_proc_ownership_t,
62
  "pdf_char_proc_ownership_t", pdf_char_proc_ownership_enum_ptrs,
63
  pdf_char_proc_ownership_reloc_ptrs, char_name, char_proc, char_next, font_next, font);
64
65
gs_private_st_ptrs1(st_pdf_bitmap_fonts, pdf_bitmap_fonts_t,
66
  "pdf_bitmap_fonts_t", pdf_bitmap_fonts_enum_ptrs,
67
  pdf_bitmap_fonts_reloc_ptrs, open_font);
68
69
static inline long
70
pdf_char_proc_id(const pdf_char_proc_t *pcp)
71
55.3k
{
72
55.3k
    return pdf_resource_id((const pdf_resource_t *)pcp);
73
55.3k
}
74
75
/* Assign a code for a char_proc. */
76
static int
77
assign_char_code(gx_device_pdf * pdev, gs_text_enum_t *pte)
78
25.6k
{
79
25.6k
    pdf_bitmap_fonts_t *pbfs = pdev->text->bitmap_fonts;
80
25.6k
    pdf_font_resource_t *pdfont = pbfs->open_font; /* Type 3 */
81
25.6k
    int i, c = 0, code;
82
25.6k
    uint operation = pte->text.operation;
83
84
25.6k
    if (pbfs->bitmap_encoding_id == 0)
85
90
        pbfs->bitmap_encoding_id = pdf_obj_ref(pdev);
86
25.6k
    if (pdfont == 0 || pdfont->u.simple.LastChar == 255 ||
87
25.6k
        !pbfs->use_open_font
88
25.6k
        ) {
89
        /* Start a new synthesized font. */
90
364
        char *pc;
91
92
364
        code = pdf_font_type3_alloc(pdev, &pdfont, pdf_write_contents_bitmap);
93
364
        if (code < 0)
94
0
            return code;
95
364
        pdfont->u.simple.s.type3.bitmap_font = true;
96
364
        if (pbfs->open_font == 0)
97
90
            pdfont->rname[0] = 0;
98
274
        else
99
274
            strcpy(pdfont->rname, pbfs->open_font->rname);
100
364
        pdfont->u.simple.s.type3.FontBBox.p.x = 0;
101
364
        pdfont->u.simple.s.type3.FontBBox.p.y = 0;
102
364
        pdfont->u.simple.s.type3.FontBBox.q.x = 0;
103
364
        pdfont->u.simple.s.type3.FontBBox.q.y = 0;
104
364
        pdfont->mark_glyph = NULL;
105
364
        gs_make_identity(&pdfont->u.simple.s.type3.FontMatrix);
106
        /*
107
         * We "increment" the font name as a radix-26 "number".
108
         * This cannot possibly overflow.
109
         */
110
364
        for (pc = pdfont->rname; *pc == 'Z'; ++pc)
111
0
            *pc = '@';
112
364
        if ((*pc)++ == 0)
113
90
            *pc = 'A', pc[1] = 0;
114
364
        pbfs->open_font = pdfont;
115
364
        pbfs->use_open_font = true;
116
364
        pdfont->u.simple.FirstChar = 255;
117
364
    }
118
25.6k
    if ((operation & (TEXT_FROM_STRING | TEXT_FROM_BYTES)) ||
119
25.6k
        (operation & (TEXT_FROM_CHARS | TEXT_FROM_SINGLE_CHAR))) {
120
25.6k
        unsigned char p = *pte->text.data.bytes;
121
25.6k
        unsigned char index = p / 8, bit = 0x01 << (p % 8);
122
123
25.6k
        if (pdfont->used[index] & bit) {
124
2.38M
            for (i = 0;i < 256;i++) {
125
2.38M
                index = i / 8;
126
2.38M
                bit = 0x01 << (i % 8);
127
2.38M
                if (!(pdfont->used[index] & bit)) {
128
23.2k
                    c = i;
129
23.2k
                    break;
130
23.2k
                }
131
2.38M
            }
132
23.2k
        } else
133
2.35k
            c = p;
134
25.6k
        pdfont->used[index] |= bit;
135
25.6k
        if (c > pdfont->u.simple.LastChar)
136
17.5k
            pdfont->u.simple.LastChar = c;
137
138
25.6k
    } else {
139
0
        unsigned char index, bit;
140
0
        c = ++(pdfont->u.simple.LastChar);
141
0
        index = c / 8;
142
0
        bit = 0x01 << (c % 8);
143
0
        pdfont->used[index] |= bit;
144
0
    }
145
25.6k
    if (c < pdfont->u.simple.FirstChar)
146
651
        pdfont->u.simple.FirstChar = c;
147
148
25.6k
    pdfont->Widths[c] = psdf_round(pdev->char_width.x, 100, 10); /* See
149
                        pdf_write_Widths about rounding. We need to provide
150
                        a compatible data for Tj. */
151
25.6k
    if (c > pbfs->max_embedded_code)
152
7.58k
        pbfs->max_embedded_code = c;
153
154
25.6k
    return c;
155
25.6k
}
156
157
/* Write the contents of a Type 3 bitmap or vector font resource. */
158
int
159
pdf_write_contents_bitmap(gx_device_pdf *pdev, pdf_font_resource_t *pdfont)
160
518
{
161
518
    stream *s = pdev->strm;
162
518
    const pdf_char_proc_ownership_t *pcpo;
163
518
    long diff_id = 0;
164
518
    int code;
165
166
518
    if (pdfont->u.simple.s.type3.bitmap_font)
167
364
        diff_id = pdev->text->bitmap_fonts->bitmap_encoding_id;
168
154
    else {
169
        /* See comment in pdf_write_encoding. */
170
154
        diff_id = pdf_obj_ref(pdev);
171
154
    }
172
518
    code = pdf_write_encoding_ref(pdev, pdfont, diff_id);
173
518
    if (code < 0)
174
0
        return code;
175
518
    stream_puts(s, "/CharProcs <<");
176
    /* Write real characters. */
177
28.1k
    for (pcpo = pdfont->u.simple.s.type3.char_procs; pcpo;
178
27.6k
         pcpo = pcpo->char_next
179
27.6k
         ) {
180
27.6k
        if (pdfont->u.simple.s.type3.bitmap_font)
181
25.6k
            pprintld2(s, "/a%ld %ld 0 R\n", (long)pcpo->char_code,
182
25.6k
                      pdf_char_proc_id(pcpo->char_proc));
183
2.03k
        else if (!pcpo-> duplicate_char_name) {
184
2.00k
            pdf_put_name(pdev, pcpo->char_name.data, pcpo->char_name.size);
185
2.00k
            pprintld1(s, " %ld 0 R\n", pdf_char_proc_id(pcpo->char_proc));
186
2.00k
        }
187
27.6k
        pdf_record_usage_by_parent(pdev, pdf_char_proc_id(pcpo->char_proc), pdfont->object->id);
188
27.6k
    }
189
518
    stream_puts(s, ">>");
190
518
    pprintg6(s, "/FontMatrix[%g %g %g %g %g %g]",
191
518
            (float)pdfont->u.simple.s.type3.FontMatrix.xx,
192
518
            (float)pdfont->u.simple.s.type3.FontMatrix.xy,
193
518
            (float)pdfont->u.simple.s.type3.FontMatrix.yx,
194
518
            (float)pdfont->u.simple.s.type3.FontMatrix.yy,
195
518
            (float)pdfont->u.simple.s.type3.FontMatrix.tx,
196
518
            (float)pdfont->u.simple.s.type3.FontMatrix.ty);
197
518
    code = pdf_finish_write_contents_type3(pdev, pdfont);
198
518
    if (code < 0)
199
0
        return code;
200
518
    if (!pdfont->u.simple.s.type3.bitmap_font && diff_id > 0) {
201
154
        code = pdf_write_encoding(pdev, pdfont, diff_id, 0);
202
154
        if (code < 0)
203
0
            return code;
204
154
    }
205
518
    return 0;
206
518
}
207
208
/* ---------------- Public ---------------- */
209
210
/*
211
 * Allocate and initialize bookkeeping for bitmap fonts.
212
 */
213
pdf_bitmap_fonts_t *
214
pdf_bitmap_fonts_alloc(gs_memory_t *mem)
215
16.0k
{
216
16.0k
    pdf_bitmap_fonts_t *pbfs =
217
16.0k
        gs_alloc_struct(mem, pdf_bitmap_fonts_t, &st_pdf_bitmap_fonts,
218
16.0k
                        "pdf_bitmap_fonts_alloc");
219
220
16.0k
    if (pbfs == 0)
221
0
        return 0;
222
16.0k
    memset(pbfs, 0, sizeof(*pbfs));
223
16.0k
    pbfs->max_embedded_code = -1;
224
16.0k
    return pbfs;
225
16.0k
}
226
227
/*
228
 * Update text state at the end of a page.
229
 */
230
void
231
pdf_close_text_page(gx_device_pdf *pdev)
232
19.9k
{
233
    /*
234
     * When Acrobat Reader 3 prints a file containing a Type 3 font with a
235
     * non-standard Encoding, it apparently only emits the subset of the
236
     * font actually used on the page.  Thus, if the "Download Fonts Once"
237
     * option is selected, characters not used on the page where the font
238
     * first appears will not be defined, and hence will print as blank if
239
     * used on subsequent pages.  Thus, we can't allow a Type 3 font to
240
     * add additional characters on subsequent pages.
241
     */
242
19.9k
    if (pdev->CompatibilityLevel <= 1.2)
243
6.37k
        pdev->text->bitmap_fonts->use_open_font = false;
244
19.9k
}
245
246
int
247
pdf_charproc_y_offset(pdf_char_proc_t *pcp)
248
482k
{
249
482k
    return pcp->y_offset;
250
482k
}
251
252
int
253
pdf_charproc_x_offset(pdf_char_proc_t *pcp)
254
482k
{
255
482k
    return pcp->x_offset;
256
482k
}
257
258
/* Attach a CharProc to a font. */
259
static int
260
pdf_attach_charproc(gx_device_pdf * pdev, pdf_font_resource_t *pdfont, pdf_char_proc_t *pcp,
261
                    gs_glyph glyph, gs_char char_code, const gs_const_string *gnstr)
262
30.0k
{
263
30.0k
    pdf_char_proc_ownership_t *pcpo;
264
30.0k
    bool duplicate_char_name = false;
265
266
2.53M
    for (pcpo = pdfont->u.simple.s.type3.char_procs; pcpo != NULL; pcpo = pcpo->char_next) {
267
2.50M
        if (pcpo->glyph == glyph && pcpo->char_code == char_code)
268
2.42k
            return 0;
269
2.50M
    }
270
27.6k
    if (!pdfont->u.simple.s.type3.bitmap_font) {
271
22.0k
        for (pcpo = pdfont->u.simple.s.type3.char_procs; pcpo != NULL; pcpo = pcpo->char_next) {
272
20.0k
            if (!bytes_compare(pcpo->char_name.data, pcpo->char_name.size, gnstr->data, gnstr->size)) {
273
26
                duplicate_char_name = true;
274
26
                break;
275
26
            }
276
20.0k
        }
277
2.03k
    }
278
27.6k
    pcpo = gs_alloc_struct(pdev->pdf_memory,
279
27.6k
            pdf_char_proc_ownership_t, &st_pdf_char_proc_ownership, "pdf_attach_charproc");
280
281
27.6k
    if (pcpo == NULL)
282
0
        return_error(gs_error_VMerror);
283
27.6k
    pcpo->font = pdfont;
284
27.6k
    pcpo->char_next = pdfont->u.simple.s.type3.char_procs;
285
27.6k
    pdfont->u.simple.s.type3.char_procs = pcpo;
286
27.6k
    pcpo->char_proc = pcp;
287
27.6k
    pcpo->font_next = pcp->owner_fonts;
288
27.6k
    pcp->owner_fonts = pcpo;
289
27.6k
    pcpo->char_code = char_code;
290
27.6k
    pcpo->glyph = glyph;
291
27.6k
    if (gnstr == NULL) {
292
25.6k
        pcpo->char_name.data = 0;
293
25.6k
        pcpo->char_name.size = 0;
294
25.6k
    } else {
295
2.03k
        if (gnstr->size > 0) {
296
2.03k
            pcpo->char_name.data = gs_alloc_bytes(pdev->pdf_memory->non_gc_memory, gnstr->size, "storage for charproc name");
297
2.03k
            memcpy(pcpo->char_name.data, gnstr->data, gnstr->size);
298
2.03k
        }
299
2.03k
        pcpo->char_name.size = gnstr->size;
300
2.03k
    }
301
27.6k
    pcpo->duplicate_char_name = duplicate_char_name;
302
27.6k
    return 0;
303
27.6k
}
304
305
int
306
pdf_free_charproc_ownership(gx_device_pdf * pdev, pdf_resource_t *pres)
307
520
{
308
520
    pdf_char_proc_ownership_t *next, *pcpo = (pdf_char_proc_ownership_t *)pres;
309
310
28.1k
    while (pcpo) {
311
27.6k
        next = pcpo->char_next;
312
27.6k
        if(pcpo->char_name.size != 0 && pcpo->char_name.data) {
313
2.03k
            gs_free_object(pdev->pdf_memory->non_gc_memory, pcpo->char_name.data, "free storage for charproc naem");
314
            /* This causes PCL some trouble, don't know why yet FIXME-MEMORY
315
            gs_free_string(pdev->pdf_memory, (byte *)pcpo->char_name.data, pcpo->char_name.size, "Free CharProc name");*/
316
2.03k
            pcpo->char_name.data = (byte *)0L;
317
2.03k
            pcpo->char_name.size = 0;
318
2.03k
        }
319
27.6k
        gs_free_object(pdev->pdf_memory, pcpo, "Free CharProc");
320
27.6k
        pcpo = next;
321
27.6k
    }
322
520
    return 0;
323
520
}
324
325
/* Begin a CharProc for a synthesized (bitmap) font. */
326
int
327
pdf_begin_char_proc(gx_device_pdf * pdev, int w, int h, int x_width,
328
                    int y_offset, int x_offset, gs_id id, pdf_char_proc_t ** ppcp,
329
                    pdf_stream_position_t * ppos)
330
25.6k
{
331
25.6k
    gs_char char_code = 0;
332
25.6k
    pdf_bitmap_fonts_t *const pbfs = pdev->text->bitmap_fonts;
333
25.6k
    pdf_font_resource_t *font;
334
25.6k
    pdf_resource_t *pres;
335
25.6k
    pdf_char_proc_t *pcp;
336
25.6k
    int code;
337
    /* This code added to store PCL bitmap glyphs in type 3 fonts where possible */
338
25.6k
    gs_glyph glyph = GS_NO_GLYPH;
339
25.6k
    gs_const_string str2, *str = NULL;
340
25.6k
    gs_show_enum *show_enum = (gs_show_enum *)pdev->pte;
341
25.6k
    pdf_encoding_element_t *pet = 0;
342
    /* Since this is for text searching, its only useful if the character code
343
     * lies in an ASCII range, so we only handle some kinds of text layout.
344
     */
345
25.6k
    int allowed_op = (show_enum->text.operation &
346
25.6k
        (TEXT_FROM_STRING | TEXT_FROM_BYTES | TEXT_FROM_CHARS | TEXT_FROM_SINGLE_CHAR));
347
348
    /* Check to see the current font is a type 3. We can get here if pdfwrite decides
349
     * it can't handle a font type, and renders to a bitmap instead. If that's the
350
     * case then we can't add the bitmap to the existing font (its not a type 3 font)
351
     * and must fall back to holding it in our fallback type 3 font 'collection'.
352
     */
353
    /* Because the bitmaps are stored directly in the cache they already have any
354
     * effects caused by non-identity FontMatrix entries applied. So if the type 3
355
     * font we created has a non-identity FontMatrix we can't use it and must
356
     * go back to collecting the bitmap into our fallback font.
357
     */
358
25.6k
    if ((show_enum->current_font->FontType == ft_user_defined ||
359
25.6k
        show_enum->current_font->FontType == ft_PDF_user_defined ||
360
25.6k
        show_enum->current_font->FontType == ft_PCL_user_defined ||
361
25.6k
        show_enum->current_font->FontType == ft_MicroType ||
362
25.6k
        show_enum->current_font->FontType == ft_GL2_stick_user_defined ||
363
25.6k
        show_enum->current_font->FontType == ft_GL2_531) && allowed_op &&
364
25.6k
        show_enum->current_font->FontMatrix.xx == 1 && show_enum->current_font->FontMatrix.xy == 0 &&
365
25.6k
        show_enum->current_font->FontMatrix.yx == 0 && show_enum->current_font->FontMatrix.yy == 1) {
366
0
        pdf_char_proc_ownership_t *pcpo;
367
368
0
        gs_font_base *base = (gs_font_base *)show_enum->current_font;
369
0
        code = pdf_attached_font_resource(pdev, show_enum->current_font, &font, NULL, NULL, NULL, NULL);
370
0
        if (code < 0)
371
0
            return code;
372
0
        if (font == NULL)
373
0
            return_error(gs_error_invalidfont);
374
375
        /* The text processing will have run past the glyph, so we need to 'back up'
376
         * by one and get it again in order to get the character code and glyph, and update
377
         * the pointer correctly.
378
         */
379
0
        show_enum->index--;
380
0
        code = gs_default_next_char_glyph((gs_text_enum_t *)show_enum, (gs_char *)&char_code, &glyph);
381
0
        if (code < 0)
382
0
            return code;
383
384
        /* If the returned character code is outside the possible Encoding for
385
         * a type 3 font, then set pet to NULL, this means we will fall back to
386
         * the 'collection' font, as pet is checked below.
387
         */
388
0
        if ((int)char_code >= 0 && (int)char_code <= 255) {
389
0
            pet = &font->u.simple.Encoding[char_code];
390
0
            if (pet) {
391
                /* Check to see if we *already* have this glyph in this font. If
392
                 * we do then we can't add it to this font. Setting pet to 0
393
                 * falls back to the collection method.
394
                 */
395
0
                for (pcpo = font->u.simple.s.type3.char_procs; pcpo != NULL; pcpo = pcpo->char_next) {
396
0
                    if (pcpo->glyph == pet->glyph && pcpo->char_code == char_code) {
397
0
                        pet = 0x00;
398
0
                        break;
399
0
                    }
400
0
                }
401
0
            }
402
0
        }
403
0
        else
404
0
            pet = 0x00;
405
406
        /* We need a glyph name for the type 3 font's Encoding, if we haven't got one
407
         * then we need to give up, something about the font or text is not acceptable
408
         * (see various comments above).
409
         */
410
0
        if (pet && pet->glyph != GS_NO_GLYPH && !(pet->size == 7 &&
411
0
            !strncmp((const char *)pet->data, ".notdef", 7))) {
412
0
            if (char_code < font->u.simple.FirstChar)
413
0
                font->u.simple.FirstChar = char_code;
414
0
            if ((int)char_code > font->u.simple.LastChar)
415
0
                font->u.simple.LastChar = char_code;
416
0
            base->FontBBox.q.x = max(base->FontBBox.q.x, w);
417
0
            base->FontBBox.q.y = max(base->FontBBox.q.y, y_offset + h);
418
0
            str2.data = pet->data;
419
0
            str2.size = pet->size;
420
0
            str = &str2;
421
0
            glyph = pet->glyph;
422
            /* This is to work around a weird Acrobat bug. If the Encoding of a type 3
423
             * (possibly other types) is simply a standard encoding (eg WinAnsiEncoding)
424
             * then Acrobat 4 & 8 just ignore the glyphs altogether. This forces us to write
425
             * all the used glyphs as /Differencess, and that makes it work <sigh>
426
             */
427
0
            pet->is_difference = 1;
428
0
            font->Widths[char_code] = psdf_round(pdev->char_width.x, 100, 10); /* See
429
                        pdf_write_Widths about rounding. We need to provide
430
                        a compatible data for Tj. */
431
0
        } else {
432
0
            char_code = assign_char_code(pdev, pdev->pte);
433
0
            font = pbfs->open_font; /* Type 3 */
434
0
        }
435
25.6k
    } else {
436
25.6k
        char_code = assign_char_code(pdev, pdev->pte);
437
25.6k
        font = pbfs->open_font; /* Type 3 */
438
25.6k
    }
439
440
25.6k
    code = pdf_begin_resource(pdev, resourceCharProc, id, &pres);
441
25.6k
    if (code < 0)
442
0
        return code;
443
25.6k
    pcp = (pdf_char_proc_t *) pres;
444
25.6k
    code = pdf_attach_charproc(pdev, font, pcp, glyph, char_code, str);
445
25.6k
    if (code < 0)
446
0
        return code;
447
25.6k
    pres->object->written = true;
448
25.6k
    {
449
25.6k
        stream *s = pdev->strm;
450
451
        /*
452
         * The resource file is positionable, so rather than use an
453
         * object reference for the length, we'll go back and fill it in
454
         * at the end of the definition.  Take 1M as the longest
455
         * definition we can handle.  (This used to be 10K, but there was
456
         * a real file that exceeded this limit.)
457
         */
458
25.6k
        stream_puts(s, "<</Length       >>stream\n");
459
25.6k
        ppos->start_pos = stell(s);
460
25.6k
    }
461
25.6k
    code = pdf_begin_encrypt(pdev, &pdev->strm, pres->object->id);
462
25.6k
    if (code < 0)
463
0
        return code;
464
25.6k
    pcp->y_offset = y_offset;
465
25.6k
    pcp->x_offset = x_offset;
466
25.6k
    font->u.simple.s.type3.FontBBox.q.x =
467
25.6k
        max(font->u.simple.s.type3.FontBBox.q.x, w);
468
25.6k
    font->u.simple.s.type3.FontBBox.q.y =
469
25.6k
        max(font->u.simple.s.type3.FontBBox.q.y, y_offset + h);
470
25.6k
    font->u.simple.s.type3.max_y_offset =
471
25.6k
        max(font->u.simple.s.type3.max_y_offset, h + (h >> 2));
472
25.6k
    pcp->real_width.x = w;
473
25.6k
    pcp->real_width.y = y_offset + h;
474
25.6k
    *ppcp = pcp;
475
25.6k
    return 0;
476
25.6k
}
477
478
/* End a CharProc. */
479
int
480
pdf_end_char_proc(gx_device_pdf * pdev, pdf_stream_position_t * ppos)
481
25.6k
{
482
25.6k
    stream *s;
483
25.6k
    gs_offset_t start_pos, end_pos, length;
484
485
25.6k
    if (pdf_end_encrypt(pdev))
486
0
        s_close_filters(&pdev->strm, pdev->strm->strm);
487
488
25.6k
    s = pdev->strm;
489
25.6k
    start_pos = ppos->start_pos;
490
25.6k
    end_pos = stell(s);
491
25.6k
    length = end_pos - start_pos;
492
25.6k
    if (length > 999999)
493
0
        return_error(gs_error_limitcheck);
494
25.6k
    sseek(s, start_pos - 15);
495
25.6k
    pprintd1(s, "%d", length);
496
25.6k
    sseek(s, end_pos);
497
25.6k
    if (pdev->PDFA != 0)
498
0
        stream_puts(s, "\n");
499
25.6k
    stream_puts(s, "endstream\n");
500
25.6k
    pdf_end_separate(pdev, resourceCharProc);
501
25.6k
    return 0;
502
25.6k
}
503
504
/* Mark glyph names for garbager. */
505
void
506
pdf_mark_glyph_names(const pdf_font_resource_t *pdfont, const gs_memory_t *memory)
507
14.0k
{
508
14.0k
    if (pdfont->mark_glyph == NULL) {
509
        /* Synthesised bitmap fonts pass here. */
510
368
        return;
511
368
    }
512
13.7k
    if (pdfont->u.simple.Encoding != NULL) {
513
13.7k
         int i;
514
515
3.52M
         for (i = 0; i < 256; i++)
516
3.50M
             if (pdfont->u.simple.Encoding[i].glyph != GS_NO_GLYPH)
517
297k
                pdfont->mark_glyph(memory, pdfont->u.simple.Encoding[i].glyph, pdfont->mark_glyph_data);
518
13.7k
     }
519
13.7k
    if (pdfont->FontType == ft_user_defined ||
520
13.7k
        pdfont->FontType == ft_PDF_user_defined ||
521
13.7k
        pdfont->FontType == ft_PCL_user_defined ||
522
13.7k
        pdfont->FontType == ft_MicroType ||
523
13.7k
        pdfont->FontType == ft_GL2_stick_user_defined ||
524
13.7k
        pdfont->FontType == ft_GL2_531) {
525
161
        const pdf_char_proc_ownership_t *pcpo = pdfont->u.simple.s.type3.char_procs;
526
527
1.40k
        for (; pcpo != NULL; pcpo = pcpo->font_next)
528
1.24k
            pdfont->mark_glyph(memory, pcpo->glyph, pdfont->mark_glyph_data);
529
161
    }
530
13.7k
}
531
532
/* Put out a reference to an image as a character in a synthesized font. */
533
int
534
pdf_do_char_image(gx_device_pdf * pdev, const pdf_char_proc_t * pcp,
535
                  const gs_matrix * pimat)
536
507k
{
537
    /* We need to choose a font, which use the charproc.
538
       In most cases it is the last font, which the charproc is attached to.
539
       If the charproc is substituted, it causes a font change. */
540
507k
    const pdf_char_proc_ownership_t * pcpo = pcp->owner_fonts;
541
507k
    pdf_font_resource_t *pdfont = pcpo->font;
542
507k
    byte ch = pcpo->char_code;
543
507k
    pdf_text_state_values_t values;
544
545
507k
    values.character_spacing = 0;
546
507k
    values.pdfont = pdfont;
547
507k
    values.size = 1;
548
507k
    values.matrix = *pimat;
549
507k
    values.render_mode = pdev->pte->pgs->text_rendering_mode;
550
507k
    values.word_spacing = 0;
551
507k
    pdf_set_text_state_values(pdev, &values);
552
507k
    pdf_bitmap_char_update_bbox(pdev, pcp->x_offset, pcp->y_offset, pcp->real_width.x, pcp->real_width.y);
553
507k
    pdf_append_chars(pdev, &ch, 1, pdfont->Widths[ch] * pimat->xx, 0.0, false);
554
507k
    return 0;
555
507k
}
556
557
/*
558
 * Write the Encoding for bitmap fonts, if needed.
559
 */
560
int
561
pdf_write_bitmap_fonts_Encoding(gx_device_pdf *pdev)
562
16.0k
{
563
16.0k
    pdf_bitmap_fonts_t *pbfs;
564
565
16.0k
    if (pdev->text == NULL || pdev->text->bitmap_fonts == NULL)
566
0
        return 0;
567
568
16.0k
    pbfs = pdev->text->bitmap_fonts;
569
570
16.0k
    if (pbfs->bitmap_encoding_id) {
571
90
        stream *s;
572
90
        int i;
573
574
90
        pdf_open_separate(pdev, pbfs->bitmap_encoding_id, resourceEncoding);
575
90
        s = pdev->strm;
576
        /*
577
         * Even though the PDF reference documentation says that a
578
         * BaseEncoding key is required unless the encoding is
579
         * "based on the base font's encoding" (and there is no base
580
         * font in this case), Acrobat 2.1 gives an error if the
581
         * BaseEncoding key is present.
582
         */
583
90
        stream_puts(s, "<</Type/Encoding/Differences[0");
584
11.5k
        for (i = 0; i <= pbfs->max_embedded_code; ++i) {
585
11.4k
            if (!(i & 15))
586
753
                stream_puts(s, "\n");
587
11.4k
            pprintd1(s, "/a%d", i);
588
11.4k
        }
589
90
        stream_puts(s, "\n] >>\n");
590
90
        pdf_end_separate(pdev, resourceEncoding);
591
90
        pbfs->bitmap_encoding_id = 0;
592
90
    }
593
16.0k
    return 0;
594
16.0k
}
595
596
/*
597
 * Start charproc accumulation for a Type 3 font.
598
 */
599
int
600
pdf_start_charproc_accum(gx_device_pdf *pdev)
601
4.46k
{
602
4.46k
    pdf_char_proc_t *pcp;
603
4.46k
    pdf_resource_t *pres;
604
4.46k
    int id = gs_next_ids(pdev->memory, 1);
605
4.46k
    int code = pdf_enter_substream(pdev, resourceCharProc, id,
606
4.46k
                                   &pres, false, pdev->CompressFonts);
607
608
4.46k
    if (code < 0)
609
0
       return code;
610
4.46k
    pres->rid = id;
611
4.46k
    pcp = (pdf_char_proc_t *)pres;
612
4.46k
    pcp->owner_fonts = NULL;
613
4.46k
    return 0;
614
4.46k
}
615
616
/*
617
 * Install charproc accumulator for a Type 3 font.
618
 */
619
int
620
pdf_set_charproc_attrs(gx_device_pdf *pdev, gs_font *font, double *pw, int narg,
621
                gs_text_cache_control_t control, gs_char ch, bool scale_100)
622
3.87k
{
623
3.87k
    pdf_font_resource_t *pdfont;
624
3.87k
    pdf_resource_t *pres = pdev->accumulating_substream_resource;
625
3.87k
    pdf_char_proc_t *pcp;
626
3.87k
    int code;
627
628
3.87k
    code = pdf_attached_font_resource(pdev, font, &pdfont, NULL, NULL, NULL, NULL);
629
3.87k
    if (code < 0)
630
0
        return code;
631
3.87k
    pcp = (pdf_char_proc_t *)pres;
632
3.87k
    pcp->owner_fonts = NULL;
633
3.87k
    pcp->real_width.x = pw[font->WMode && narg > 6 ? 6 : 0];
634
3.87k
    pcp->real_width.y = pw[font->WMode && narg > 6 ? 7 : 1];
635
3.87k
    pcp->v.x = (narg > 8 ? pw[8] : 0);
636
3.87k
    pcp->v.y = (narg > 8 ? pw[9] : 0);
637
3.87k
    if (control == TEXT_SET_CHAR_WIDTH) {
638
        /* PLRM 5.7.1 "BuildGlyph" reads : "Normally, it is unnecessary and
639
        undesirable to initialize the current color parameter, because show
640
        is defined to paint glyphs with the current color."
641
        However comparefiles/Bug687044.ps doesn't follow that. */
642
3.11k
        pdev->skip_colors = false;
643
3.11k
        pprintg1(pdev->strm, "%g 0 d0\n", (float)pw[0]);
644
        /* The colour change described above can't affect PCL fonts and we need
645
         * all glyphs to be noted as cached in order for the bitmap font cache
646
         * probing to work properly.
647
         */
648
3.11k
        if (font->FontType == ft_PCL_user_defined || font->FontType == ft_GL2_stick_user_defined
649
3.11k
            || font->FontType == ft_GL2_531 || font->FontType == ft_MicroType)
650
0
            pdfont->u.simple.s.type3.cached[ch >> 3] |= 0x80 >> (ch & 7);
651
3.11k
    } else {
652
766
        double d;
653
766
        pdev->skip_colors = true;
654
766
        if (pw[4] < pw[2]) {
655
0
            d = pw[2];
656
0
            pw[2] = pw[4];
657
0
            pw[4] = d;
658
0
        }
659
766
        if (pw[5] < pw[3]) {
660
0
            d = pw[5];
661
0
            pw[5] = pw[3];
662
0
            pw[3] = d;
663
0
        }
664
766
        pprintg6(pdev->strm, "%g %g %g %g %g %g d1\n",
665
766
            (float)pw[0], (float)0.0, (float)pw[2],
666
766
            (float)pw[3], (float)pw[4], (float)pw[5]);
667
766
        pdfont->u.simple.s.type3.cached[ch >> 3] |= 0x80 >> (ch & 7);
668
766
    }
669
    /* See comments in pdf_text_process regarding type 3 CharProc accumulation
670
     * Initially this matrix was emitted there, at the start of the accumulator
671
     * but if we do that then GS incorrectly applied the matrix to the 'd1'
672
     * operator. We write the scale matrix here because this is *after* the
673
     * 'd1' has been emitted above, and so does not affect it.
674
     */
675
3.87k
    if (scale_100) {
676
3.87k
    code = stream_puts(pdev->strm, "0.01 0 0 0.01 0 0 cm\n");
677
3.87k
    if (code < 0)
678
0
        return code;
679
3.87k
    }
680
3.87k
    return 0;
681
3.87k
}
682
683
/*
684
 * Open a stream object in the temporary file.
685
 */
686
687
int
688
pdf_open_aside(gx_device_pdf *pdev, pdf_resource_type_t rtype,
689
        gs_id id, pdf_resource_t **ppres, bool reserve_object_id, int options)
690
53.1k
{
691
53.1k
    int code;
692
53.1k
    pdf_resource_t *pres;
693
53.1k
    stream *s, *save_strm = pdev->strm;
694
53.1k
    pdf_data_writer_t writer;
695
53.1k
    static const pdf_filter_names_t fnames = {
696
53.1k
        PDF_FILTER_NAMES
697
53.1k
    };
698
699
53.1k
    pdev->streams.save_strm = pdev->strm;
700
701
53.1k
    if (rtype >= NUM_RESOURCE_TYPES)
702
22.2k
        rtype = resourceOther;
703
53.1k
    code = pdf_alloc_aside(pdev, PDF_RESOURCE_CHAIN(pdev, rtype, id),
704
53.1k
                pdf_resource_type_structs[rtype], &pres, reserve_object_id ? 0 : -1);
705
53.1k
    if (code < 0)
706
0
        return code;
707
53.1k
    cos_become(pres->object, cos_type_stream);
708
53.1k
    s = cos_write_stream_alloc((cos_stream_t *)pres->object, pdev, "pdf_enter_substream");
709
53.1k
    if (s == 0)
710
0
        return_error(gs_error_VMerror);
711
53.1k
    pdev->strm = s;
712
53.1k
    code = pdf_append_data_stream_filters(pdev, &writer,
713
53.1k
                             options | DATA_STREAM_NOLENGTH, pres->object->id);
714
53.1k
    if (code < 0) {
715
0
        pdev->strm = save_strm;
716
0
        return code;
717
0
    }
718
53.1k
    code = pdf_put_filters((cos_dict_t *)pres->object, pdev, writer.binary.strm, &fnames);
719
53.1k
    if (code < 0) {
720
0
        pdev->strm = save_strm;
721
0
        return code;
722
0
    }
723
53.1k
    pdev->strm = writer.binary.strm;
724
53.1k
    *ppres = pres;
725
53.1k
    return 0;
726
53.1k
}
727
728
/*
729
 * Close a stream object in the temporary file.
730
 */
731
int
732
pdf_close_aside(gx_device_pdf *pdev)
733
53.1k
{
734
    /* We should call pdf_end_data here, but we don't want to put pdf_data_writer_t
735
       into pdf_substream_save stack to simplify garbager descriptors.
736
       Use a lower level functions instead that. */
737
53.1k
    stream *s = pdev->strm;
738
53.1k
    cos_stream_t *pcs = cos_stream_from_pipeline(s);
739
53.1k
    int status = s_close_filters(&s, NULL);
740
741
53.1k
    pdev->strm = pdev->streams.save_strm;
742
53.1k
    if (status < 0)
743
0
         return(gs_note_error(gs_error_ioerror));
744
745
53.1k
    if (!pcs)
746
0
        return gs_note_error(gs_error_ioerror);
747
748
53.1k
    pcs->is_open = false;
749
53.1k
    return 0;
750
53.1k
}
751
752
/*
753
 * Enter the substream accumulation mode.
754
 */
755
int
756
pdf_enter_substream(gx_device_pdf *pdev, pdf_resource_type_t rtype,
757
        gs_id id, pdf_resource_t **ppres, bool reserve_object_id, bool compress)
758
30.8k
{
759
30.8k
    int sbstack_ptr = pdev->sbstack_depth;
760
30.8k
    pdf_resource_t *pres;
761
30.8k
    stream *save_strm = pdev->strm;
762
30.8k
    int code;
763
764
30.8k
    if (pdev->sbstack_depth >= pdev->sbstack_size)
765
0
        return_error(gs_error_unregistered); /* Must not happen. */
766
30.8k
    if (pdev->sbstack[sbstack_ptr].text_state == 0) {
767
30.8k
        pdev->sbstack[sbstack_ptr].text_state = pdf_text_state_alloc(pdev->pdf_memory);
768
30.8k
        if (pdev->sbstack[sbstack_ptr].text_state == 0)
769
0
            return_error(gs_error_VMerror);
770
30.8k
    }
771
30.8k
    code = pdf_open_aside(pdev, rtype, id, &pres, reserve_object_id,
772
30.8k
                    (compress ? DATA_STREAM_COMPRESS : 0));
773
30.8k
    if (code < 0)
774
0
        return code;
775
30.8k
    code = pdf_save_viewer_state(pdev, NULL);
776
30.8k
    if (code < 0) {
777
0
        pdev->strm = save_strm;
778
0
        return code;
779
0
    }
780
30.8k
    pdev->sbstack[sbstack_ptr].context = pdev->context;
781
30.8k
    pdf_text_state_copy(pdev->sbstack[sbstack_ptr].text_state, pdev->text->text_state);
782
30.8k
    pdf_set_text_state_default(pdev->text->text_state);
783
30.8k
    pdev->sbstack[sbstack_ptr].clip_path = pdev->clip_path;
784
30.8k
    pdev->clip_path = 0;
785
30.8k
    pdev->sbstack[sbstack_ptr].clip_path_id = pdev->clip_path_id;
786
30.8k
    pdev->clip_path_id = pdev->no_clip_path_id;
787
30.8k
    pdev->sbstack[sbstack_ptr].vgstack_bottom = pdev->vgstack_bottom;
788
30.8k
    pdev->vgstack_bottom = pdev->vgstack_depth;
789
30.8k
    pdev->sbstack[sbstack_ptr].strm = save_strm;
790
30.8k
    pdev->sbstack[sbstack_ptr].procsets = pdev->procsets;
791
30.8k
    pdev->sbstack[sbstack_ptr].substream_Resources = pdev->substream_Resources;
792
30.8k
    pdev->sbstack[sbstack_ptr].skip_colors = pdev->skip_colors;
793
30.8k
    pdev->sbstack[sbstack_ptr].font3 = pdev->font3;
794
30.8k
    pdev->sbstack[sbstack_ptr].accumulating_substream_resource = pdev->accumulating_substream_resource;
795
30.8k
    pdev->sbstack[sbstack_ptr].charproc_just_accumulated = pdev->charproc_just_accumulated;
796
30.8k
    pdev->sbstack[sbstack_ptr].accumulating_a_global_object = pdev->accumulating_a_global_object;
797
30.8k
    pdev->sbstack[sbstack_ptr].pres_soft_mask_dict = pdev->pres_soft_mask_dict;
798
30.8k
    pdev->sbstack[sbstack_ptr].objname = pdev->objname;
799
30.8k
    pdev->sbstack[sbstack_ptr].last_charpath_op = pdev->last_charpath_op;
800
30.8k
    pdev->skip_colors = false;
801
30.8k
    pdev->charproc_just_accumulated = false;
802
30.8k
    pdev->pres_soft_mask_dict = NULL;
803
30.8k
    pdev->objname.data = NULL;
804
30.8k
    pdev->objname.size = 0;
805
    /* Do not reset pdev->accumulating_a_global_object - it inherits. */
806
30.8k
    pdev->sbstack_depth++;
807
30.8k
    pdev->procsets = 0;
808
30.8k
    pdev->font3 = 0;
809
30.8k
    pdev->context = PDF_IN_STREAM;
810
30.8k
    pdev->accumulating_substream_resource = pres;
811
30.8k
    pdev->last_charpath_op = 0;
812
    /* Do not alter type3charpath, inherit the current value. We need to know if */
813
    /* we are inside a charpath operation, and only reset this when the charpath */
814
    /* is complete */
815
30.8k
    if (rtype != resourceXObject)
816
11.3k
        pdf_reset_graphics(pdev);
817
19.5k
    else {
818
19.5k
        if (pdev->vg_initial_set)
819
19.5k
            pdev->state.blend_mode = pdev->vg_initial.blend_mode;
820
19.5k
    }
821
30.8k
    *ppres = pres;
822
30.8k
    return 0;
823
30.8k
}
824
825
/*
826
 * Exit the substream accumulation mode.
827
 */
828
int
829
pdf_exit_substream(gx_device_pdf *pdev)
830
30.8k
{
831
30.8k
    int code, code1;
832
30.8k
    int sbstack_ptr;
833
834
30.8k
    if (pdev->sbstack_depth <= 0)
835
4
        return_error(gs_error_unregistered); /* Must not happen. */
836
30.8k
    code = pdf_open_contents(pdev, PDF_IN_STREAM);
837
30.8k
    sbstack_ptr = pdev->sbstack_depth - 1;
838
49.8k
    while (pdev->vgstack_depth > pdev->vgstack_bottom) {
839
19.0k
        code1 = pdf_restore_viewer_state(pdev, pdev->strm);
840
19.0k
        if (code >= 0)
841
19.0k
            code = code1;
842
19.0k
    }
843
30.8k
    if (pdev->clip_path != 0)
844
19.0k
        gx_path_free(pdev->clip_path, "pdf_end_charproc_accum");
845
30.8k
    code1 = pdf_close_aside(pdev);
846
30.8k
    if (code1 < 0 && code >= 0)
847
0
        code = code1;
848
30.8k
    pdev->context = pdev->sbstack[sbstack_ptr].context;
849
30.8k
    pdf_text_state_copy(pdev->text->text_state, pdev->sbstack[sbstack_ptr].text_state);
850
30.8k
    gs_free_object(pdev->pdf_memory, pdev->sbstack[sbstack_ptr].text_state, "free text state for stream");
851
30.8k
    pdev->sbstack[sbstack_ptr].text_state = 0;
852
30.8k
    pdev->clip_path = pdev->sbstack[sbstack_ptr].clip_path;
853
30.8k
    pdev->sbstack[sbstack_ptr].clip_path = 0;
854
30.8k
    pdev->clip_path_id = pdev->sbstack[sbstack_ptr].clip_path_id;
855
30.8k
    pdev->vgstack_bottom = pdev->sbstack[sbstack_ptr].vgstack_bottom;
856
30.8k
    pdev->strm = pdev->sbstack[sbstack_ptr].strm;
857
30.8k
    pdev->sbstack[sbstack_ptr].strm = 0;
858
30.8k
    pdev->procsets = pdev->sbstack[sbstack_ptr].procsets;
859
30.8k
    pdev->substream_Resources = pdev->sbstack[sbstack_ptr].substream_Resources;
860
30.8k
    pdev->sbstack[sbstack_ptr].substream_Resources = 0;
861
30.8k
    pdev->skip_colors = pdev->sbstack[sbstack_ptr].skip_colors;
862
30.8k
    pdev->font3 = pdev->sbstack[sbstack_ptr].font3;
863
30.8k
    pdev->sbstack[sbstack_ptr].font3 = 0;
864
30.8k
    pdev->accumulating_substream_resource = pdev->sbstack[sbstack_ptr].accumulating_substream_resource;
865
30.8k
    pdev->sbstack[sbstack_ptr].accumulating_substream_resource = 0;
866
30.8k
    pdev->charproc_just_accumulated = pdev->sbstack[sbstack_ptr].charproc_just_accumulated;
867
30.8k
    pdev->accumulating_a_global_object = pdev->sbstack[sbstack_ptr].accumulating_a_global_object;
868
30.8k
    pdev->pres_soft_mask_dict = pdev->sbstack[sbstack_ptr].pres_soft_mask_dict;
869
30.8k
    pdev->objname = pdev->sbstack[sbstack_ptr].objname;
870
30.8k
    pdev->last_charpath_op = pdev->sbstack[sbstack_ptr].last_charpath_op;
871
30.8k
    pdev->sbstack_depth = sbstack_ptr;
872
30.8k
    code1 = pdf_restore_viewer_state(pdev, NULL);
873
30.8k
    if (code1 < 0 && code >= 0)
874
0
        code = code1;
875
30.8k
    return code;
876
30.8k
}
877
878
static bool
879
pdf_is_same_charproc_attrs1(gx_device_pdf *pdev, pdf_char_proc_t *pcp0, pdf_char_proc_t *pcp1)
880
11.9k
{
881
11.9k
    if (pcp0->real_width.x != pcp1->real_width.x)
882
6.85k
        return false;
883
5.06k
    if (pcp0->real_width.y != pcp1->real_width.y)
884
0
        return false;
885
5.06k
    if (pcp0->v.x != pcp1->v.x)
886
0
        return false;
887
5.06k
    if (pcp0->v.y != pcp1->v.y)
888
0
        return false;
889
5.06k
    return true;
890
5.06k
}
891
892
typedef struct charproc_compatibility_data_s {
893
    const pdf_char_glyph_pairs_t *cgp;
894
    pdf_font_resource_t *pdfont;
895
    gs_char char_code;
896
    gs_glyph glyph;
897
    gs_font *font;
898
} charproc_compatibility_data_t;
899
900
static bool
901
is_char_code_used(pdf_font_resource_t *pdfont, gs_char char_code)
902
17
{
903
17
    pdf_char_proc_ownership_t *pcpo;
904
905
223
    for (pcpo = pdfont->u.simple.s.type3.char_procs; pcpo != NULL; pcpo = pcpo->char_next) {
906
208
        if (pcpo->char_code == char_code) {
907
2
            return true;
908
2
        }
909
208
    }
910
15
    return false;
911
17
}
912
913
static int
914
pdf_is_charproc_compatible(gx_device_pdf * pdev, pdf_resource_t *pres0, pdf_resource_t *pres1)
915
17
{
916
17
    charproc_compatibility_data_t *data = (charproc_compatibility_data_t *)pdev->find_resource_param;
917
17
    pdf_char_proc_t *pcp0 = (pdf_char_proc_t *)pres0;
918
17
    pdf_char_proc_t *pcp1 = (pdf_char_proc_t *)pres1;
919
17
    pdf_font_resource_t *pdfont = data->pdfont;
920
17
    pdf_char_proc_ownership_t *pcpo;
921
17
    pdf_font_cache_elem_t **e;
922
17
    bool can_add_to_current_font = false, computed_can_add_to_current_font = false;
923
924
    /* Does it have same attributes ? */
925
17
    if (!pdf_is_same_charproc_attrs1(pdev, pcp0, pcp1))
926
0
        return 0;
927
    /* Is it from same font ? */
928
187
    for (pcpo = pcp1->owner_fonts; pcpo != NULL; pcpo = pcpo->char_next) {
929
170
        if (pdfont == pcpo->font) {
930
            /* Check for encoding conflict. */
931
0
            if (pcpo->char_code == data->char_code && pcpo->glyph == data->glyph)
932
0
                return 1; /* Same char code. */
933
0
            if (!computed_can_add_to_current_font) {
934
0
                can_add_to_current_font = !is_char_code_used(pdfont, data->char_code);
935
0
                computed_can_add_to_current_font = true;
936
0
            }
937
0
            if (can_add_to_current_font)
938
0
                return 1; /* No conflict. */
939
0
        }
940
170
    }
941
    /* Look for another font with same encoding,
942
       because we want to reduce the number of new fonts.
943
       We also restrict with ones attached to same PS font,
944
       otherwise it creates too mixed fonts and disturbs word breaks.
945
     */
946
17
    e = pdf_locate_font_cache_elem(pdev, data->font);
947
17
    if (e != NULL) {
948
187
        for (pcpo = pcp1->owner_fonts; pcpo != NULL; pcpo = pcpo->char_next) {
949
170
            if (pcpo->char_code != data->char_code || pcpo->glyph != data->glyph)
950
153
                continue; /* Need same Encoding to generate a proper ToUnicode. */
951
17
            if (pdfont->u.simple.s.type3.bitmap_font != pcpo->font->u.simple.s.type3.bitmap_font)
952
0
                continue;
953
17
            if (gs_matrix_compare(&pdfont->u.simple.s.type3.FontMatrix, &pcpo->font->u.simple.s.type3.FontMatrix))
954
10
                continue;
955
7
            if (data->cgp != NULL) {
956
7
                if (!pdf_check_encoding_compatibility(pcpo->font, data->cgp->s, data->cgp->num_all_chars))
957
0
                    continue;
958
7
            }
959
7
            if ((*e)->pdfont != pcpo->font)
960
7
                continue;
961
0
            data->pdfont = pcpo->font; /* Switch to the other font. */
962
0
            return 1;
963
7
        }
964
17
    }
965
    /* Check whether it can be added into the current font. */
966
17
    if (!computed_can_add_to_current_font)
967
17
        can_add_to_current_font = !is_char_code_used(pdfont, data->char_code);
968
17
    if (!can_add_to_current_font) {
969
        /* Can't substitute due to encoding conflict. */
970
2
        return 0;
971
2
    }
972
    /* The current font will share it with another font. */
973
15
    return 1;
974
17
}
975
976
static int
977
pdf_find_same_charproc_aux(gx_device_pdf *pdev,
978
            pdf_font_resource_t **ppdfont, pdf_char_proc_t **ppcp)
979
4.46k
{
980
4.46k
    pdf_char_proc_ownership_t *pcpo;
981
4.46k
    int code;
982
983
    /* fixme: this passes parameters to pdf_is_charproc_compatible
984
       through special gx_device_pdf field pdev->find_resource_param
985
       due to prototype limitation of pdf_find_same_resource.
986
       It would be better to change the client data argument type in there to void. */
987
12.7k
    for (pcpo = (*ppdfont)->u.simple.s.type3.char_procs; pcpo != NULL; pcpo = pcpo->char_next) {
988
11.8k
        pdf_char_proc_t *pcp = pcpo->char_proc;
989
990
11.8k
        if (*ppcp != pcp && pdf_is_same_charproc_attrs1(pdev, *ppcp, pcp)) {
991
5.04k
            cos_object_t *pco0 = pcp->object;
992
5.04k
            cos_object_t *pco1 = (*ppcp)->object;
993
994
5.04k
            code = pco0->cos_procs->equal(pco0, pco1, pdev);
995
5.04k
            if (code < 0) {
996
0
                return code;
997
0
            }
998
5.04k
            if (code) {
999
3.59k
                *ppcp = pcp;
1000
3.59k
                return 1;
1001
3.59k
            }
1002
5.04k
        }
1003
11.8k
    }
1004
863
    return pdf_find_same_resource(pdev, resourceCharProc, (pdf_resource_t **)ppcp, pdf_is_charproc_compatible);
1005
4.46k
}
1006
static int
1007
pdf_find_same_charproc(gx_device_pdf *pdev,
1008
            pdf_font_resource_t **ppdfont, const pdf_char_glyph_pairs_t *cgp,
1009
            pdf_char_proc_t **ppcp, gs_glyph glyph, gs_char char_code,
1010
            gs_font *font)
1011
4.46k
{
1012
4.46k
    charproc_compatibility_data_t data;
1013
4.46k
    int code;
1014
1015
4.46k
    data.cgp = cgp;
1016
4.46k
    data.pdfont = *ppdfont;
1017
4.46k
    data.char_code = char_code;
1018
4.46k
    data.glyph = glyph;
1019
4.46k
    data.font = font;
1020
4.46k
    pdev->find_resource_param = &data;
1021
4.46k
    code = pdf_find_same_charproc_aux(pdev, ppdfont, ppcp);
1022
4.46k
    pdev->find_resource_param = NULL;
1023
4.46k
    *ppdfont = data.pdfont;
1024
4.46k
    return code;
1025
4.46k
}
1026
1027
static bool
1028
pdf_is_charproc_defined(gx_device_pdf *pdev, pdf_font_resource_t *pdfont, gs_char ch)
1029
848
{
1030
848
    pdf_char_proc_ownership_t *pcpo;
1031
1032
8.83k
    for (pcpo = pdfont->u.simple.s.type3.char_procs; pcpo != NULL; pcpo = pcpo->char_next) {
1033
7.99k
        if (pcpo->char_code == ch)
1034
4
            return true;
1035
7.99k
    }
1036
844
    return false;
1037
848
}
1038
1039
static int
1040
complete_adding_char(gx_device_pdf *pdev, gs_font *font,
1041
                     gs_glyph glyph, gs_char ch, pdf_char_proc_t *pcp,
1042
                     const gs_const_string *gnstr)
1043
4.46k
{
1044
4.46k
    pdf_font_resource_t *pdfont;
1045
4.46k
    double *real_widths;
1046
4.46k
    byte *glyph_usage;
1047
4.46k
    int char_cache_size, width_cache_size;
1048
4.46k
    pdf_encoding_element_t *pet;
1049
4.46k
    int code;
1050
1051
4.46k
    code = pdf_attached_font_resource(pdev, font, &pdfont,
1052
4.46k
                &glyph_usage, &real_widths, &char_cache_size, &width_cache_size);
1053
4.46k
    if (code < 0)
1054
0
        return code;
1055
4.46k
    code = pdf_attach_charproc(pdev, pdfont, pcp, glyph, ch, gnstr);
1056
4.46k
    if (code < 0)
1057
0
        return code;
1058
4.46k
    if (ch >= char_cache_size || ch >= width_cache_size)
1059
0
        return_error(gs_error_unregistered); /* Must not happen. */
1060
4.46k
    pet = &pdfont->u.simple.Encoding[ch];
1061
4.46k
    pdfont->Widths[ch] = pcp->real_width.x;
1062
4.46k
    real_widths[ch * 2    ] = pcp->real_width.x;
1063
4.46k
    real_widths[ch * 2 + 1] = pcp->real_width.y;
1064
4.46k
    glyph_usage[ch / 8] |= 0x80 >> (ch & 7);
1065
4.46k
    pdfont->used[ch >> 3] |= 0x80 >> (ch & 7);
1066
4.46k
    if (pdfont->u.simple.v != NULL && font->WMode) {
1067
0
        pdfont->u.simple.v[ch].x = pcp->v.x;
1068
0
        pdfont->u.simple.v[ch].y = pcp->v.x;
1069
0
    }
1070
4.46k
    pet->glyph = glyph;
1071
4.46k
    pet->is_difference = true;
1072
4.46k
    if (pdfont->u.simple.LastChar < (int)ch)
1073
512
        pdfont->u.simple.LastChar = (int)ch;
1074
4.46k
    if (pdfont->u.simple.FirstChar > (int)ch)
1075
370
        pdfont->u.simple.FirstChar = (int)ch;
1076
4.46k
    return pdf_copy_string_to_encoding(pdev, (gs_const_string *)gnstr, pet);
1077
4.46k
}
1078
1079
static int
1080
pdf_char_widths_from_charprocs(gx_device_pdf *pdev, gs_font *font)
1081
0
{
1082
0
    pdf_font_resource_t *pdfont;
1083
0
    double *real_widths;
1084
0
    byte *glyph_usage;
1085
0
    int char_cache_size, width_cache_size;
1086
0
    pdf_char_proc_ownership_t *pcpo;
1087
0
    int code;
1088
1089
0
    code = pdf_attached_font_resource(pdev, font, &pdfont,
1090
0
                &glyph_usage, &real_widths, &char_cache_size, &width_cache_size);
1091
0
    if (code < 0)
1092
0
        return code;
1093
0
    for (pcpo = pdfont->u.simple.s.type3.char_procs; pcpo != NULL; pcpo = pcpo->char_next) {
1094
0
        pdf_char_proc_t *pcp = pcpo->char_proc;
1095
0
        gs_char ch = pcpo->char_code;
1096
1097
0
        real_widths[ch * 2    ] = pcp->real_width.x;
1098
0
        real_widths[ch * 2 + 1] = pcp->real_width.y;
1099
0
        glyph_usage[ch / 8] |= 0x80 >> (ch & 7);
1100
0
    }
1101
0
    return 0;
1102
0
}
1103
1104
/*
1105
 * Complete charproc accumulation for a Type 3 font.
1106
 */
1107
int
1108
pdf_end_charproc_accum(gx_device_pdf *pdev, gs_font *font, const pdf_char_glyph_pairs_t *cgp,
1109
                       gs_glyph glyph, gs_char output_char_code, const gs_const_string *gnstr)
1110
4.46k
{
1111
4.46k
    int code;
1112
4.46k
    pdf_resource_t *pres = (pdf_resource_t *)pdev->accumulating_substream_resource;
1113
    /* We could use pdfont->u.simple.s.type3.char_procs insted the thing above
1114
       unless the font is defined recursively.
1115
       But we don't want such assumption. */
1116
4.46k
    pdf_char_proc_t *pcp = (pdf_char_proc_t *)pres;
1117
4.46k
    pdf_font_resource_t *pdfont;
1118
4.46k
    gs_char ch = output_char_code;
1119
4.46k
    bool checking_glyph_variation = false;
1120
1121
4.46k
    if (ch == GS_NO_CHAR)
1122
0
        return_error(gs_error_unregistered); /* Must not happen. */
1123
4.46k
    if (ch >= 256)
1124
0
        return_error(gs_error_unregistered); /* Must not happen. */
1125
4.46k
    code = pdf_attached_font_resource(pdev, font, &pdfont, NULL, NULL, NULL, NULL);
1126
4.46k
    if (code < 0)
1127
0
        return code;
1128
4.46k
    if (pdfont != (pdf_font_resource_t *)pdev->font3)
1129
2
        return_error(gs_error_unregistered); /* Must not happen. */
1130
4.46k
    code = pdf_exit_substream(pdev);
1131
4.46k
    if (code < 0)
1132
0
        return code;
1133
4.46k
    if (!(pdfont->used[ch >> 3] & (0x80 >> (ch & 7))) ||
1134
4.46k
        !(pdfont->u.simple.s.type3.cached[ch >> 3] & (0x80 >> (ch & 7)))) {
1135
        /* First appearence or not cached - check for duplicates. */
1136
4.46k
        pdf_font_resource_t *pdfont1 = pdfont;
1137
1138
4.46k
        checking_glyph_variation = true;
1139
        /* CAUTION : a possible font change. */
1140
4.46k
        code = pdf_find_same_charproc(pdev, &pdfont, cgp, &pcp, glyph, ch, font);
1141
4.46k
        if (code < 0)
1142
0
            return code;
1143
4.46k
        if (code != 0) {
1144
3.61k
            code = pdf_cancel_resource(pdev, pres, resourceCharProc);
1145
3.61k
            if (code < 0)
1146
0
                return code;
1147
3.61k
            pdf_forget_resource(pdev, pres, resourceCharProc);
1148
3.61k
            if (pdfont1 != pdfont) {
1149
0
                code = pdf_attach_font_resource(pdev, font, pdfont);
1150
0
                if (code < 0)
1151
0
                    return code;
1152
0
                code = pdf_char_widths_from_charprocs(pdev, font);
1153
0
                if (code < 0)
1154
0
                    return code;
1155
0
            }
1156
3.61k
            pdev->charproc_just_accumulated = true;
1157
3.61k
            return complete_adding_char(pdev, font, glyph, ch, pcp, gnstr);
1158
3.61k
        }
1159
848
        if (pdf_is_charproc_defined(pdev, pdfont, ch)) {
1160
            /* Encoding conflict after a font change. */
1161
4
            gs_font *base_font = font, *below;
1162
1163
4
            while ((below = base_font->base) != base_font &&
1164
4
                    base_font->procs.same_font(base_font, below, FONT_SAME_OUTLINES))
1165
0
                base_font = below;
1166
4
            code = pdf_make_font3_resource(pdev, base_font, &pdfont);
1167
4
            if (code < 0)
1168
0
                return code;
1169
4
            code = pdf_attach_font_resource(pdev, font, pdfont);
1170
4
            if (code < 0)
1171
0
                return code;
1172
4
        }
1173
848
    }
1174
848
    pdf_reserve_object_id(pdev, pres, 0);
1175
848
    if (checking_glyph_variation)
1176
848
        pdev->charproc_just_accumulated = true;
1177
848
    return complete_adding_char(pdev, font, glyph, ch, pcp, gnstr);
1178
4.46k
}
1179
1180
/* Add procsets to substream Resources. */
1181
int
1182
pdf_add_procsets(cos_dict_t *pcd, pdf_procset_t procsets)
1183
19.5k
{
1184
19.5k
    char str[5 + 7 + 7 + 7 + 5 + 2];
1185
19.5k
    cos_value_t v;
1186
1187
19.5k
    strcpy(str, "[/PDF");
1188
19.5k
    if (procsets & ImageB)
1189
1
        strcat(str, "/ImageB");
1190
19.5k
    if (procsets & ImageC)
1191
152
        strcat(str, "/ImageC");
1192
19.5k
    if (procsets & ImageI)
1193
11
        strcat(str, "/ImageI");
1194
19.5k
    if (procsets & Text)
1195
367
        strcat(str, "/Text");
1196
19.5k
    strcat(str, "]");
1197
19.5k
    cos_string_value(&v, (byte *)str, strlen(str));
1198
19.5k
    return cos_dict_put_c_key(pcd, "/ProcSet", &v);
1199
19.5k
}
1200
1201
/* Add a resource to substream Resources. */
1202
int
1203
pdf_add_resource(gx_device_pdf *pdev, cos_dict_t *pcd, const char *key, pdf_resource_t *pres)
1204
533k
{
1205
533k
    if (pcd != 0) {
1206
17.8k
        const cos_value_t *v = cos_dict_find(pcd, (const byte *)key, strlen(key));
1207
17.8k
        cos_dict_t *list;
1208
17.8k
        int code;
1209
17.8k
        char buf[10 + (sizeof(long) * 8 / 3 + 1)], buf1[sizeof(pres->rname) + 1];
1210
1211
17.8k
        if (pdev->ForOPDFRead && !pres->global && pdev->accumulating_a_global_object) {
1212
0
            pres->global = true;
1213
0
            code = cos_dict_put_c_key_bool((cos_dict_t *)pres->object, "/.Global", true);
1214
0
            if (code < 0)
1215
0
                return code;
1216
0
        }
1217
17.8k
        gs_snprintf(buf, sizeof(buf), "%ld 0 R\n", pres->object->id);
1218
17.8k
        if (v != NULL) {
1219
14.5k
            if (v->value_type != COS_VALUE_OBJECT &&
1220
14.5k
                v->value_type != COS_VALUE_RESOURCE)
1221
0
                return_error(gs_error_unregistered); /* Must not happen. */
1222
14.5k
            list = (cos_dict_t *)v->contents.object;
1223
14.5k
            if (list->cos_procs != &cos_dict_procs)
1224
0
                return_error(gs_error_unregistered); /* Must not happen. */
1225
14.5k
        } else {
1226
3.35k
            list = cos_dict_alloc(pdev, "pdf_add_resource");
1227
3.35k
            if (list == NULL)
1228
0
                return_error(gs_error_VMerror);
1229
3.35k
            code = cos_dict_put_c_key_object((cos_dict_t *)pcd, key, (cos_object_t *)list);
1230
3.35k
            if (code < 0)
1231
0
                return code;
1232
3.35k
        }
1233
17.8k
        buf1[0] = '/';
1234
17.8k
        strcpy(buf1 + 1, pres->rname);
1235
17.8k
        return cos_dict_put_string(list, (const byte *)buf1, strlen(buf1),
1236
17.8k
                        (const byte *)buf, strlen(buf));
1237
17.8k
    }
1238
515k
    return 0;
1239
533k
}