Coverage Report

Created: 2025-06-24 07:01

/src/ghostpdl/devices/vector/gdevpdtw.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2025 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.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
16
17
/* Font resource writing for pdfwrite text */
18
#include "memory_.h"
19
#include "gx.h"
20
#include "gserrors.h"
21
#include "gxfcmap.h"
22
#include "gxfont.h"
23
#include "gxfcopy.h"
24
#include "gscencs.h"
25
#include "gdevpsf.h"
26
#include "gdevpdfx.h"
27
#include "gdevpdfo.h"   /* for object->written */
28
#include "gdevpdtd.h"   /* for writing FontDescriptor */
29
#include "gdevpdtf.h"
30
#include "gdevpdti.h"   /* for writing bitmap fonts Encoding */
31
#include "gdevpdtw.h"
32
#include "gdevpdtv.h"
33
#include "sarc4.h"
34
35
static const char *const encoding_names[] = {
36
    KNOWN_REAL_ENCODING_NAMES
37
};
38
39
/* ================ Font resource writing ================ */
40
41
/* ---------------- Private ---------------- */
42
43
/* Write the Widths for a font. */
44
static int
45
pdf_write_Widths(gx_device_pdf *pdev, int first, int last, const double *widths)
46
24.1k
{
47
24.1k
    stream *s = pdev->strm;
48
24.1k
    int i;
49
50
24.1k
    if (first > last)
51
0
        first = last = 0;
52
24.1k
    pprintd2(s, "/FirstChar %d/LastChar %d/Widths[", first, last);
53
1.86M
    for (i = first; i <= last; ++i)
54
1.83M
        pprintg1(s, (i & 15 ? " %g" : "\n%g"), psdf_round(widths[i], 100, 10));
55
24.1k
    stream_puts(s, "]\n");
56
24.1k
    return 0;
57
24.1k
}
58
59
/* Check strings equality. */
60
static bool
61
strings_equal(const gs_const_string *str0, const gs_const_string *str1)
62
555k
{
63
555k
    return str0->size == str1->size &&
64
555k
           !memcmp(str0->data, str1->data, str0->size);
65
555k
}
66
67
/* Check if an encoding element differs from a standard one. */
68
static int
69
pdf_different_encoding_element(const pdf_font_resource_t *pdfont, int ch, int encoding_index)
70
6.40M
{
71
6.40M
    if (pdfont->u.simple.Encoding[ch].is_difference)
72
23.7k
        return 1;
73
6.38M
    else if (encoding_index != ENCODING_INDEX_UNKNOWN) {
74
6.27M
        gs_glyph glyph0 = gs_c_known_encode(ch, encoding_index);
75
6.27M
        gs_glyph glyph1 = pdfont->u.simple.Encoding[ch].glyph;
76
6.27M
        gs_const_string str;
77
6.27M
        int code = gs_c_glyph_name(glyph0, &str);
78
79
6.27M
        if (code < 0)
80
0
            return code; /* Must not happen */
81
6.27M
        if (glyph1 != GS_NO_GLYPH) {
82
555k
            gs_const_string str2;
83
555k
            str2.data = pdfont->u.simple.Encoding[ch].data;
84
555k
            str2.size = pdfont->u.simple.Encoding[ch].size;
85
555k
            if (!strings_equal(&str, &str2))
86
71.2k
                return 1;
87
555k
        }
88
6.27M
    }
89
6.31M
    return 0;
90
6.40M
}
91
92
/* Find an index of a different encoding element. */
93
int
94
pdf_different_encoding_index(const pdf_font_resource_t *pdfont, int ch0)
95
24.0k
{
96
24.0k
    gs_encoding_index_t base_encoding = pdfont->u.simple.BaseEncoding;
97
24.0k
    int ch, code;
98
99
5.06M
    for (ch = ch0; ch < 256; ++ch) {
100
5.04M
        code = pdf_different_encoding_element(pdfont, ch, base_encoding);
101
5.04M
        if (code < 0)
102
0
            return code; /* Must not happen */
103
5.04M
        if (code)
104
5.91k
            break;
105
5.04M
    }
106
24.0k
    return ch;
107
24.0k
}
108
109
/* Check for unknown encode (simple fonts only). */
110
static bool
111
pdf_simple_font_needs_ToUnicode(gx_device_pdf *pdev, const pdf_font_resource_t *pdfont)
112
2.42k
{
113
2.42k
    int ch;
114
2.42k
    unsigned char mask = (pdfont->FontType == ft_encrypted || pdfont->FontType == ft_encrypted2
115
2.42k
                ? GS_C_PDF_GOOD_GLYPH_MASK : GS_C_PDF_GOOD_NON_SYMBOL_MASK);
116
117
2.42k
    if (pdfont->u.simple.Encoding == NULL)
118
0
        return true; /* Bitmap Type 3 fonts have no pdfont->u.simple.Encoding . */
119
2.42k
    if (pdfont->FontType == ft_TrueType)
120
        /*
121
            TrueType fonts are always written as symbolic, and so they do not have
122
            an Encoding entry (SVN revision 11735, bugs #690744, #691036, #691319).
123
            In this circumstance, write the ToUnicode map to get a searchable PDF.
124
        */
125
825
        return true;
126
127
1.59k
    if (!pdev->ToUnicodeForStdEnc) {
128
0
        for (ch = 0; ch < 256; ++ch) {
129
0
            pdf_encoding_element_t *pet = &pdfont->u.simple.Encoding[ch];
130
0
            gs_glyph glyph = pet->glyph;
131
132
0
            if (glyph == GS_NO_GLYPH)
133
0
                continue;
134
0
            if (glyph < gs_c_min_std_encoding_glyph || glyph >= GS_MIN_CID_GLYPH) {
135
0
                if (pet->size == 0)
136
0
                    return true;
137
0
                glyph = gs_c_name_glyph(pet->data, pet->size);
138
0
                if (glyph == GS_NO_GLYPH)
139
0
                    return true;
140
0
            }
141
0
            glyph -= gs_c_min_std_encoding_glyph;
142
0
            if( glyph > GS_C_PDF_MAX_GOOD_GLYPH ||
143
0
               !(gs_c_pdf_glyph_type[glyph >> 2] & (mask << (( glyph & 3 )<<1) )))
144
0
              return true;
145
146
0
        }
147
0
        return false;
148
0
    } else
149
1.59k
        return true;
150
1.59k
}
151
152
/* Write Encoding differencrs. */
153
int
154
pdf_write_encoding(gx_device_pdf *pdev, const pdf_font_resource_t *pdfont, int64_t id, int ch)
155
6.83k
{
156
    /* Note : this truncates extended glyph names to original names. */
157
6.83k
    stream *s;
158
6.83k
    gs_encoding_index_t base_encoding = pdfont->u.simple.BaseEncoding;
159
6.83k
    const int sl = strlen(gx_extendeg_glyph_name_separator);
160
6.83k
    int prev = 256, code, cnt = 0;
161
162
6.83k
    pdf_open_separate(pdev, id, resourceEncoding);
163
6.83k
    s = pdev->strm;
164
6.83k
    stream_puts(s, "<</Type/Encoding");
165
6.83k
    if (base_encoding < 0 && pdev->ForOPDFRead)
166
0
        base_encoding = ENCODING_INDEX_STANDARD;
167
6.83k
    if (base_encoding > 0)
168
2.69k
        pprints1(s, "/BaseEncoding/%s", encoding_names[base_encoding]);
169
6.83k
    stream_puts(s, "/Differences[");
170
1.36M
    for (; ch < 256; ++ch) {
171
1.36M
        code = pdf_different_encoding_element(pdfont, ch, base_encoding);
172
1.36M
        if (code < 0)
173
0
            return code; /* Must not happen */
174
1.36M
        if (code == 0 && (pdfont->FontType == ft_user_defined ||
175
1.27M
            pdfont->FontType == ft_PCL_user_defined ||
176
1.27M
            pdfont->FontType == ft_MicroType ||
177
1.27M
            pdfont->FontType == ft_GL2_stick_user_defined ||
178
1.27M
            pdfont->FontType == ft_GL2_531)) {
179
            /* PDF 1.4 spec Appendix H Note 42 says that
180
             * Acrobat 4 can't properly handle Base Encoding.
181
             * Enforce writing differences against that.
182
             */
183
220k
            if (pdfont->used[ch >> 3] & 0x80 >> (ch & 7))
184
0
                if (pdfont->u.simple.Encoding[ch].size)
185
0
                    code = 1;
186
220k
        }
187
1.36M
        if (code) {
188
89.1k
            const byte *d = pdfont->u.simple.Encoding[ch].data;
189
89.1k
            int i, l = pdfont->u.simple.Encoding[ch].size;
190
191
89.1k
            if (pdev->HavePDFWidths) {
192
34.6k
                for (i = 0; i + sl < l; i++)
193
18.1k
                    if (!memcmp(d + i, gx_extendeg_glyph_name_separator, sl)) {
194
0
                        l = i;
195
0
                        break;
196
0
                    }
197
16.4k
            }
198
89.1k
            if (ch != prev + 1) {
199
24.5k
                pprintd1(s, "\n%d", ch);
200
24.5k
                cnt = 1;
201
64.5k
            } else if (!(cnt++ & 15))
202
2.17k
                stream_puts(s, "\n");
203
89.1k
            pdf_put_name(pdev, d, l);
204
89.1k
            prev = ch;
205
89.1k
        }
206
1.36M
    }
207
6.83k
    stream_puts(s, "]>>\n");
208
6.83k
    pdf_end_separate(pdev, resourceEncoding);
209
6.83k
    return 0;
210
6.83k
}
211
212
/* Write Encoding reference. */
213
int
214
pdf_write_encoding_ref(gx_device_pdf *pdev,
215
          const pdf_font_resource_t *pdfont, int64_t id)
216
27.3k
{
217
27.3k
    stream *s = pdev->strm;
218
219
27.3k
    if (id != 0) {
220
9.21k
        pprinti64d1(s, "/Encoding %"PRId64" 0 R", id);
221
9.21k
        pdf_record_usage_by_parent(pdev, id, pdfont->object->id);
222
9.21k
    }
223
18.1k
    else if (pdfont->u.simple.BaseEncoding > 0) {
224
5.37k
        gs_encoding_index_t base_encoding = pdfont->u.simple.BaseEncoding;
225
5.37k
        pprints1(s, "/Encoding/%s", encoding_names[base_encoding]);
226
5.37k
    }
227
27.3k
    return 0;
228
27.3k
}
229
230
/* Write the Subtype and Encoding for a simple font. */
231
static int
232
pdf_write_simple_contents(gx_device_pdf *pdev,
233
                          const pdf_font_resource_t *pdfont)
234
24.0k
{
235
24.0k
    stream *s = pdev->strm;
236
24.0k
    int64_t diff_id = 0;
237
24.0k
    int ch = (pdfont->u.simple.Encoding ? 0 : 256);
238
24.0k
    int code = 0;
239
240
24.0k
    ch = pdf_different_encoding_index(pdfont, ch);
241
24.0k
    if (ch < 256)
242
5.91k
        diff_id = pdf_obj_ref(pdev);
243
24.0k
    code = pdf_write_encoding_ref(pdev, pdfont, diff_id);
244
24.0k
    if (code < 0)
245
0
        return code;
246
24.0k
    if (pdfont->FontDescriptor == NULL || pdfont->FontDescriptor->embed)
247
24.0k
        pprints1(s, "/Subtype/%s>>\n",
248
24.0k
             (pdfont->FontType == ft_TrueType ? "TrueType" : "Type1"));
249
13
    else
250
13
        pprints1(s, "/Subtype/%s>>\n",
251
13
             (pdfont->FontDescriptor->FontType == ft_TrueType ? "TrueType" : "Type1"));
252
24.0k
    pdf_end_separate(pdev, resourceFont);
253
24.0k
    if (diff_id) {
254
5.91k
        mark_font_descriptor_symbolic(pdfont);
255
5.91k
        code = pdf_write_encoding(pdev, pdfont, diff_id, ch);
256
5.91k
        if (code < 0)
257
0
            return code;
258
5.91k
    }
259
24.0k
    return 0;
260
24.0k
}
261
262
/*
263
 * Write the W[2] entries for a CIDFont.  *pdfont is known to be a
264
 * CIDFont (type 0 or 2).
265
 */
266
static bool
267
pdf_compute_CIDFont_default_widths(const pdf_font_resource_t *pdfont, int wmode, int *pdw, int *pdv)
268
328
{
269
328
    psf_glyph_enum_t genum;
270
328
    gs_glyph glyph;
271
328
    ushort counts[1500]; /* Some CID fonts use vertical widths 1026 .*/
272
328
    int dw_count = 0, i, dwi = 0, neg_count = 0, pos_count = 0;
273
328
    double *w = (wmode ? pdfont->u.cidfont.Widths2 : pdfont->Widths);
274
275
    /* We don't wont to scan for both negative and positive widths,
276
     * to save the C stack space.
277
     * Doubtly they both are used in same font.
278
     * So just count positive and negative widths separately
279
     * and use the corresponding sign.
280
     * fixme : implement 2 hystograms.
281
     */
282
328
    psf_enumerate_bits_begin(&genum, NULL,
283
328
                             wmode ? pdfont->u.cidfont.used2 : pdfont->used,
284
328
                             pdfont->count, GLYPH_SPACE_INDEX);
285
328
    memset(counts, 0, sizeof(counts));
286
6.53k
    while (!psf_enumerate_glyphs_next(&genum, &glyph)) {
287
6.20k
        int i = glyph - GS_MIN_CID_GLYPH;
288
289
6.20k
        if ( i < pdfont->count) { /* safety */
290
6.20k
            int width = (int)(w[i] + 0.5);
291
292
6.20k
            counts[min(any_abs(width), countof(counts) - 1)]++;
293
6.20k
            if (width > 0)
294
5.88k
                pos_count++;
295
320
            else if (width < 0)
296
55
                neg_count++;
297
6.20k
        }
298
6.20k
    }
299
492k
    for (i = 1; i < countof(counts); ++i)
300
491k
        if (counts[i] > dw_count)
301
639
            dwi = i, dw_count = counts[i];
302
328
    *pdw = (neg_count > pos_count ? -dwi : dwi);
303
328
    *pdv = 0;
304
328
    if (wmode) {
305
9
        psf_enumerate_glyphs_reset(&genum);
306
9
        while (!psf_enumerate_glyphs_next(&genum, &glyph)) {
307
9
            int i = glyph - GS_MIN_CID_GLYPH;
308
309
9
            if ( i < pdfont->count) { /* safety */
310
9
                int width = (int)(w[i] + 0.5);
311
312
9
                if (min(any_abs(width), countof(counts) - 1) == any_abs(dwi)) {
313
9
                    *pdv = (int)(pdfont->u.cidfont.v[i * 2 + 1] + 0.5);
314
9
                    break;
315
9
                }
316
9
            }
317
9
        }
318
9
    }
319
328
    return (dw_count + counts[0] > 0);
320
328
}
321
322
/*
323
 * Write the [D]W[2] entries for a CIDFont.  *pdfont is known to be a
324
 * CIDFont (type 0 or 2).
325
 */
326
static int
327
pdf_write_CIDFont_widths(gx_device_pdf *pdev,
328
                         const pdf_font_resource_t *pdfont, int wmode)
329
328
{
330
    /*
331
     * The values of the CIDFont width keys are as follows:
332
     *   DW = w (default 0)
333
     *   W = [{c [w ...] | cfirst clast w}*]
334
     *   DW2 = [vy w1y] (default [880 -1000])
335
     *   W2 = [{c [w1y vx vy ...] | cfirst clast w1y vx vy}*]
336
     */
337
328
    stream *s = pdev->strm;
338
328
    psf_glyph_enum_t genum;
339
328
    gs_glyph glyph;
340
328
    int dw = 0, dv = 0, prev = -2;
341
328
    const char *Widths_key = (wmode ? "/W2" : "/W");
342
328
    double *w = (wmode ? pdfont->u.cidfont.Widths2 : pdfont->Widths);
343
344
    /* Compute and write default width : */
345
328
    if (pdf_compute_CIDFont_default_widths(pdfont, wmode, &dw, &dv)) {
346
328
        if (wmode) {
347
9
            pprintd2(s, "/DW2 [%d %d]\n", dv, dw);
348
9
        } else
349
319
            pprintd1(s, "/DW %d\n", dw);
350
328
    }
351
352
    /*
353
     * Now write all widths different from the default one.  Currently we make no
354
     * attempt to optimize this: we write every width individually.
355
     */
356
328
    psf_enumerate_bits_begin(&genum, NULL,
357
328
                             wmode ? pdfont->u.cidfont.used2 : pdfont->used,
358
328
                             pdfont->count, GLYPH_SPACE_INDEX);
359
328
    {
360
6.53k
        while (!psf_enumerate_glyphs_next(&genum, &glyph)) {
361
6.20k
            int cid = glyph - GS_MIN_CID_GLYPH;
362
6.20k
            int width = (int)(w[cid] + 0.5);
363
364
      /* Must write zero widths - see test file of the bug Bug 687681. */
365
      /* We don't enumerate unused glyphs here due to pdfont->used. */
366
      /* if (width == 0)
367
                continue; */ /* Don't write for unused glyphs. */
368
6.20k
            { /* Check whether copied font really have this glyph.
369
                   debugged with 401-01.ps, which uses undefined CIDs. */
370
6.20k
                gs_font_base *pfont = pdf_font_resource_font(pdfont, false);
371
6.20k
                gs_glyph_info_t info;
372
373
6.20k
                if (pfont->FontType == ft_TrueType) {
374
                    /* We're converting a Type 42 into CIDFontType2. */
375
                    /* We know that CIDs equal to char codes. */
376
0
                    gs_glyph glyph1;
377
0
                    int ch = glyph & 0xff;
378
379
0
                    glyph1 = pfont->procs.encode_char((gs_font *)pfont, ch, GLYPH_SPACE_NAME);
380
0
                    if (cid == 0 && glyph1 == GS_NO_GLYPH)
381
0
                        glyph1 = copied_get_notdef((gs_font *)pdf_font_resource_font(pdfont, false));
382
0
                    if (glyph1 == GS_NO_GLYPH)
383
0
                        continue;
384
0
                    if (pfont->procs.glyph_info((gs_font *)pfont, glyph1, NULL, 0, &info) < 0)
385
0
                        continue;
386
6.20k
                } else if (pfont->procs.glyph_info((gs_font *)pfont, glyph, NULL, 0, &info) < 0)
387
120
                    continue;
388
6.20k
            }
389
6.08k
            if (cid == prev + 1) {
390
2.08k
                if (wmode) {
391
0
                    int vx = (int)(pdfont->u.cidfont.v[cid * 2 + 0] + 0.5);
392
0
                    int vy = (int)(pdfont->u.cidfont.v[cid * 2 + 1] + 0.5);
393
394
0
                    pprintd3(s, "\n%d %d %d", width, vx, vy);
395
0
                } else
396
2.08k
                    pprintd1(s, "\n%d", width);
397
4.00k
            } else if (pdev->PDFA == 0 && width == dw &&
398
4.00k
                    (!wmode || (int)(pdfont->u.cidfont.v[cid * 2 + 0] + 0.5) ==
399
12
                                (int)(pdfont->Widths[cid] / 2 + 0.5)) &&
400
4.00k
                    (!wmode || (int)(pdfont->u.cidfont.v[cid * 2 + 1] + 0.5) == dv))
401
1.84k
                continue;
402
2.16k
            else {
403
2.16k
                if (prev >= 0)
404
1.90k
                    stream_puts(s, "]\n");
405
265
                else {
406
265
                    stream_puts(s, Widths_key);
407
265
                    stream_puts(s, "[");
408
265
                }
409
2.16k
                if (wmode) {
410
51
                    int vx = (int)(pdfont->u.cidfont.v[cid * 2 + 0] + 0.5);
411
51
                    int vy = (int)(pdfont->u.cidfont.v[cid * 2 + 1] + 0.5);
412
413
51
                    pprintd4(s, "%d[%d %d %d", cid, width, vx, vy);
414
51
                } else
415
2.11k
                    pprintd2(s, "%d[%d", cid, width);
416
2.16k
            }
417
4.24k
            prev = cid;
418
4.24k
        }
419
328
        if (prev >= 0)
420
265
            stream_puts(s, "]]\n");
421
328
    }
422
423
328
    return 0;
424
328
}
425
426
/* ---------------- Specific FontTypes ---------------- */
427
428
/* Write the contents of a Type 0 font resource. */
429
int
430
pdf_write_contents_type0(gx_device_pdf *pdev, pdf_font_resource_t *pdfont)
431
320
{
432
320
    stream *s = pdev->strm;
433
434
    /*
435
     * The Encoding name might be missing if an error occurred when
436
     * creating the font resource.
437
     */
438
320
    if (pdfont->u.type0.Encoding_name[0])
439
320
        pprints1(s, "/Encoding %s", pdfont->u.type0.Encoding_name);
440
320
    pprinti64d1(s, "/DescendantFonts[%"PRId64" 0 R]",
441
320
              pdf_font_id(pdfont->u.type0.DescendantFont));
442
320
    stream_puts(s, "/Subtype/Type0>>\n");
443
320
    pdf_end_separate(pdev, resourceFont);
444
320
    return 0;
445
320
}
446
447
/*
448
 * Finish writing the contents of a Type 3 font resource (FontBBox, Widths,
449
 * Subtype).
450
 */
451
int
452
pdf_finish_write_contents_type3(gx_device_pdf *pdev,
453
                                pdf_font_resource_t *pdfont)
454
3.29k
{
455
3.29k
    stream *s = pdev->strm;
456
457
3.29k
    pdf_write_font_bbox_float(pdev, &pdfont->u.simple.s.type3.FontBBox);
458
3.29k
    pdf_write_Widths(pdev, pdfont->u.simple.FirstChar,
459
3.29k
                    pdfont->u.simple.LastChar, pdfont->Widths);
460
3.29k
    stream_puts(s, "/Subtype/Type3>>\n");
461
3.29k
    pdf_end_separate(pdev, resourceFont);
462
3.29k
    return 0;
463
3.29k
}
464
465
/* Write the contents of a standard (base 14) font resource. */
466
int
467
pdf_write_contents_std(gx_device_pdf *pdev, pdf_font_resource_t *pdfont)
468
3.21k
{
469
3.21k
    return pdf_write_simple_contents(pdev, pdfont);
470
3.21k
}
471
472
/* Write the contents of a simple (Type 1 or Type 42) font resource. */
473
int
474
pdf_write_contents_simple(gx_device_pdf *pdev, pdf_font_resource_t *pdfont)
475
20.8k
{
476
20.8k
    pdf_write_Widths(pdev, pdfont->u.simple.FirstChar,
477
20.8k
                     pdfont->u.simple.LastChar, pdfont->Widths);
478
20.8k
    return pdf_write_simple_contents(pdev, pdfont);
479
20.8k
}
480
481
/* Write the contents of a CIDFont resource. */
482
static int
483
write_contents_cid_common(gx_device_pdf *pdev, pdf_font_resource_t *pdfont,
484
                          int subtype)
485
319
{
486
    /* Write [D]W[2], CIDSystemInfo, and Subtype, and close the object. */
487
319
    stream *s = pdev->strm;
488
319
    int code;
489
490
319
    if (pdfont->Widths != 0) {
491
319
        code = pdf_write_CIDFont_widths(pdev, pdfont, 0);
492
319
        if (code < 0)
493
0
            return code;
494
319
    } else {
495
        /* With a vertical font, the viewer uses /DW
496
           to determine glyph width to compute its v-vector. */
497
0
        stream_puts(s, "/DW 0\n");
498
0
    }
499
319
    if (pdfont->u.cidfont.Widths2 != 0) {
500
9
        code = pdf_write_CIDFont_widths(pdev, pdfont, 1);
501
9
        if (code < 0)
502
0
            return code;
503
9
    }
504
319
    if (pdfont->u.cidfont.CIDSystemInfo_id)
505
319
        pprinti64d1(s, "/CIDSystemInfo %"PRId64" 0 R",
506
319
                  pdfont->u.cidfont.CIDSystemInfo_id);
507
319
    pprintd1(s, "/Subtype/CIDFontType%d>>\n", subtype);
508
319
    pdf_end_separate(pdev, resourceFont);
509
319
    return 0;
510
319
}
511
int
512
pdf_write_contents_cid0(gx_device_pdf *pdev, pdf_font_resource_t *pdfont)
513
21
{
514
21
    return write_contents_cid_common(pdev, pdfont, 0);
515
21
}
516
int
517
pdf_write_contents_cid2(gx_device_pdf *pdev, pdf_font_resource_t *pdfont)
518
298
{
519
298
    int count = pdfont->count;
520
298
    int64_t map_id = 0;
521
298
    psf_glyph_enum_t genum;
522
298
    gs_glyph glyph;
523
298
    int code;
524
525
    /* Check for the identity CIDMap. */
526
298
    psf_enumerate_bits_begin(&genum, NULL, pdfont->used, count,
527
298
                             GLYPH_SPACE_INDEX);
528
5.28k
    while (!psf_enumerate_glyphs_next(&genum, &glyph)) {
529
5.03k
        int cid = glyph - GS_MIN_CID_GLYPH;
530
5.03k
        int gid = pdfont->u.cidfont.CIDToGIDMap[cid];
531
532
5.03k
        if (gid != cid) { /* non-identity map */
533
48
            map_id = pdf_obj_ref(pdev);
534
48
            pprinti64d1(pdev->strm, "/CIDToGIDMap %"PRId64" 0 R\n", map_id);
535
48
            break;
536
48
        }
537
5.03k
    }
538
539
298
    if (map_id == 0 && pdf_font_descriptor_embedding(pdfont->FontDescriptor)) {
540
250
        code = stream_puts(pdev->strm, "/CIDToGIDMap /Identity\n");
541
250
        if (code < 0)
542
0
            return code;
543
250
    }
544
545
298
    code = write_contents_cid_common(pdev, pdfont, 2);
546
298
    if (code < 0)
547
0
        return code;
548
549
298
    if (map_id && pdf_font_descriptor_embedding(pdfont->FontDescriptor)) {
550
48
        pdf_data_writer_t writer;
551
48
        int i;
552
553
48
        pdf_begin_data_stream(pdev, &writer,
554
48
            DATA_STREAM_BINARY | (pdev->CompressFonts ? DATA_STREAM_COMPRESS : 0),
555
                    /* Don't set DATA_STREAM_ENCRYPT since we write to a temporary file.
556
                       See comment in pdf_begin_encrypt. */
557
48
                    map_id);
558
1.63M
        for (i = 0; i < pdfont->u.cidfont.CIDToGIDMapLength; ++i) {
559
1.63M
            uint gid = pdfont->u.cidfont.CIDToGIDMap[i];
560
561
1.63M
            stream_putc(writer.binary.strm, (byte)(gid >> 8));
562
1.63M
            stream_putc(writer.binary.strm, (byte)(gid));
563
1.63M
        }
564
48
        code = pdf_end_data(&writer);
565
48
    }
566
298
    return code;
567
298
}
568
569
/* ---------------- External entries ---------------- */
570
571
/* Write a font resource. */
572
static int
573
pdf_write_font_resource(gx_device_pdf *pdev, pdf_font_resource_t *pdfont)
574
28.0k
{
575
28.0k
    stream *s;
576
28.0k
    cos_dict_t *pcd_Resources = NULL;
577
28.0k
    char *base14_name = NULL;
578
28.0k
    int64_t id;
579
580
28.0k
    if (pdfont->cmap_ToUnicode != NULL && pdfont->res_ToUnicode == NULL)
581
2.62k
        if (pdfont->FontType == ft_composite ||
582
2.62k
            ((pdfont->FontType == ft_encrypted || pdfont->FontType == ft_encrypted2 ||
583
2.42k
                pdfont->FontType == ft_TrueType || pdfont->FontType == ft_user_defined ||
584
2.42k
                pdfont->FontType == ft_GL2_stick_user_defined || pdfont->FontType == ft_PCL_user_defined ||
585
2.42k
                pdfont->FontType == ft_MicroType || pdfont->FontType == ft_GL2_531) &&
586
2.42k
                pdf_simple_font_needs_ToUnicode(pdev, pdfont))
587
2.62k
           ) {
588
2.62k
            pdf_resource_t *prcmap;
589
2.62k
            int code = pdf_cmap_alloc(pdev, pdfont->cmap_ToUnicode, &prcmap, -1);
590
591
2.62k
            if (code < 0)
592
0
                return code;
593
2.62k
            pdfont->res_ToUnicode = prcmap;
594
2.62k
        }
595
28.0k
    if (pdev->CompatibilityLevel >= 1.2 &&
596
28.0k
            (pdfont->FontType == ft_user_defined ||
597
28.0k
            pdfont->FontType == ft_PCL_user_defined ||
598
28.0k
            pdfont->FontType == ft_MicroType ||
599
28.0k
            pdfont->FontType == ft_GL2_stick_user_defined ||
600
28.0k
            pdfont->FontType == ft_GL2_531) &&
601
28.0k
            pdfont->u.simple.s.type3.Resources != NULL &&
602
28.0k
            pdfont->u.simple.s.type3.Resources->elements != NULL) {
603
155
        int code;
604
605
155
        pcd_Resources = pdfont->u.simple.s.type3.Resources;
606
155
        pcd_Resources->id = pdf_obj_ref(pdev);
607
155
        pdf_open_separate(pdev, pcd_Resources->id, resourceFont);
608
155
        code = COS_WRITE(pcd_Resources, pdev);
609
155
        if (code < 0)
610
0
            return code;
611
155
        pdf_end_separate(pdev, resourceFont);
612
155
    }
613
28.0k
    pdf_open_separate(pdev, pdf_font_id(pdfont), resourceFont);
614
28.0k
    s = pdev->strm;
615
28.0k
    stream_puts(s, "<<");
616
28.0k
    if (pdfont->BaseFont.size > 0) {
617
24.7k
        stream_puts(s, "/BaseFont");
618
24.7k
        if (pdfont->FontDescriptor && !pdf_font_descriptor_embedding(pdfont->FontDescriptor)
619
24.7k
            && (base14_name = (char *)pdf_find_base14_name((byte *)pdfont->BaseFont.data, (unsigned int)pdfont->BaseFont.size)))
620
0
            pdf_put_name(pdev, (byte *)base14_name, (unsigned int)strlen(base14_name));
621
24.7k
        else
622
24.7k
            pdf_put_name(pdev, (byte *)pdfont->BaseFont.data, pdfont->BaseFont.size);
623
24.7k
    }
624
28.0k
    if (pdfont->FontDescriptor) {
625
21.1k
        id = pdf_font_descriptor_id(pdfont->FontDescriptor);
626
21.1k
        pprinti64d1(s, "/FontDescriptor %"PRId64" 0 R", id);
627
21.1k
        if (pdev->Linearise) {
628
0
            pdf_set_font_descriptor_usage(pdev, pdfont->object->id, pdfont->FontDescriptor);
629
0
        }
630
21.1k
    }
631
28.0k
    if (pdfont->res_ToUnicode) {
632
2.62k
        id = pdf_resource_id((const pdf_resource_t *)pdfont->res_ToUnicode);
633
2.62k
        pprinti64d1(s, "/ToUnicode %"PRId64" 0 R", id);
634
2.62k
        pdf_record_usage_by_parent(pdev, id, pdfont->object->id);
635
2.62k
    }
636
28.0k
    if (pdev->CompatibilityLevel > 1.0)
637
28.0k
        stream_puts(s, "/Type/Font\n");
638
0
    else
639
0
        pprinti64d1(s, "/Type/Font/Name/R%"PRId64"\n", pdf_font_id(pdfont));
640
28.0k
    if (pdev->ForOPDFRead && pdfont->global)
641
0
        stream_puts(s, "/.Global true\n");
642
28.0k
    if (pcd_Resources != NULL) {
643
155
        id = pcd_Resources->id;
644
155
        pprinti64d1(s, "/Resources %"PRId64" 0 R\n", id);
645
155
        pdf_record_usage_by_parent(pdev, id, pdfont->object->id);
646
155
    }
647
28.0k
    return pdfont->write_contents(pdev, pdfont);
648
28.0k
}
649
650
/*
651
 * Close the text-related parts of a document, including writing out font
652
 * and related resources.
653
 */
654
int
655
write_font_resources(gx_device_pdf *pdev, pdf_resource_list_t *prlist)
656
68.0k
{
657
68.0k
    int j;
658
68.0k
    pdf_resource_t *pres;
659
660
1.15M
    for (j = 0; j < NUM_RESOURCE_CHAINS; ++j)
661
1.12M
        for (pres = prlist->chains[j]; pres != 0; pres = pres->next) {
662
32.9k
            pdf_font_resource_t *const pdfont = (pdf_font_resource_t *)pres;
663
664
32.9k
            if (pdf_resource_id(pres) != -1) {
665
28.0k
                int code = pdf_compute_BaseFont(pdev, pdfont, true);
666
667
28.0k
                if (code < 0)
668
0
                    return code;
669
28.0k
                code = pdf_write_font_resource(pdev, pdfont);
670
28.0k
                if (code < 0)
671
0
                    return code;
672
28.0k
                pdfont->object->written = true;
673
28.0k
            }
674
32.9k
        }
675
68.0k
    return 0;
676
68.0k
}
677
int
678
pdf_finish_resources(gx_device_pdf *pdev, pdf_resource_type_t type,
679
                        int (*finish_proc)(gx_device_pdf *,
680
                                           pdf_resource_t *))
681
102k
{
682
102k
    int j, ecode = 0;
683
102k
    pdf_resource_t *pres;
684
685
1.73M
    for (j = 0; j < NUM_RESOURCE_CHAINS; ++j)
686
1.63M
        for (pres = pdev->resources[type].chains[j];
687
1.71M
             pres != 0; pres = pres->next
688
1.63M
             ) {
689
84.4k
            int code = finish_proc(pdev, pres);
690
691
84.4k
            if (code < 0)
692
30
                ecode = code;
693
84.4k
        }
694
102k
    return ecode;
695
102k
}
696
697
/* ================ CMap resource writing ================ */
698
699
/*
700
 * Write the CIDSystemInfo for a CIDFont or a CMap.
701
 */
702
static int
703
pdf_write_cid_system_info_to_stream(gx_device_pdf *pdev, stream *s,
704
                          const gs_cid_system_info_t *pcidsi, gs_id object_id)
705
351
{
706
351
    byte *Registry = NULL, *Ordering = NULL;
707
351
    int code = 0;
708
709
351
    Registry = gs_alloc_bytes(pdev->pdf_memory, pcidsi->Registry.size, "temporary buffer for Registry");
710
351
    if (!Registry)
711
0
        return(gs_note_error(gs_error_VMerror));
712
351
    Ordering = gs_alloc_bytes(pdev->pdf_memory, pcidsi->Ordering.size, "temporary buffer for Registry");
713
351
    if (!Ordering) {
714
0
        gs_free_object(pdev->pdf_memory, Registry, "free temporary Registry buffer");
715
0
        return(gs_note_error(gs_error_VMerror));
716
0
    }
717
351
    memcpy(Registry, pcidsi->Registry.data, pcidsi->Registry.size);
718
351
    memcpy(Ordering, pcidsi->Ordering.data, pcidsi->Ordering.size);
719
351
    if (pdev->KeyLength && object_id != 0) {
720
0
        stream_arcfour_state sarc4;
721
0
        int code;
722
723
0
        code = pdf_encrypt_init(pdev, object_id, &sarc4);
724
0
        if (code < 0) {
725
0
            gs_free_object(pdev->pdf_memory, Registry, "free temporary Registry buffer");
726
0
            gs_free_object(pdev->pdf_memory, Ordering, "free temporary Ordering buffer");
727
0
            return(gs_note_error(code));
728
0
        }
729
0
        s_arcfour_process_buffer(&sarc4, Registry, pcidsi->Registry.size);
730
0
        code = pdf_encrypt_init(pdev, object_id, &sarc4);
731
0
        if (code < 0) {
732
0
            gs_free_object(pdev->pdf_memory, Registry, "free temporary Registry buffer");
733
0
            gs_free_object(pdev->pdf_memory, Ordering, "free temporary Ordering buffer");
734
0
            return(gs_note_error(code));
735
0
        }
736
0
        s_arcfour_process_buffer(&sarc4, Ordering, pcidsi->Ordering.size);
737
0
    }
738
351
    code = stream_puts(s, "<<\n/Registry");
739
351
    if (code < 0)
740
0
        goto error;
741
351
    s_write_ps_string(s, Registry, pcidsi->Registry.size, PRINT_HEX_NOT_OK);
742
351
    code = stream_puts(s, "\n/Ordering");
743
351
    if(code < 0)
744
0
        goto error;
745
351
    s_write_ps_string(s, Ordering, pcidsi->Ordering.size, PRINT_HEX_NOT_OK);
746
351
    pprintd1(s, "\n/Supplement %d\n>>\n", pcidsi->Supplement);
747
351
error:
748
351
    gs_free_object(pdev->pdf_memory, Registry, "free temporary Registry buffer");
749
351
    gs_free_object(pdev->pdf_memory, Ordering, "free temporary Ordering buffer");
750
351
    return code;
751
351
}
752
753
int
754
pdf_write_cid_system_info(gx_device_pdf *pdev,
755
                          const gs_cid_system_info_t *pcidsi, gs_id object_id)
756
324
{
757
324
    return pdf_write_cid_system_info_to_stream(pdev, pdev->strm, pcidsi, object_id);
758
324
}
759
760
int
761
pdf_write_cid_systemInfo_separate(gx_device_pdf *pdev, const gs_cid_system_info_t *pcidsi, int64_t *id)
762
324
{
763
324
    int code;
764
765
324
    *id = pdf_begin_separate(pdev, resourceCIDSystemInfo);
766
324
    code = pdf_write_cid_system_info(pdev, pcidsi, *id);
767
324
    pdf_end_separate(pdev, resourceCIDSystemInfo);
768
324
    return code;
769
324
}
770
771
/*
772
 * Write a CMap resource.  We pass the CMap object as well as the resource,
773
 * because we write CMaps when they are created.
774
 */
775
int
776
pdf_write_cmap(gx_device_pdf *pdev, const gs_cmap_t *pcmap,
777
               pdf_resource_t **ppres /*CMap*/, int font_index_only)
778
2.65k
{
779
2.65k
    int code;
780
2.65k
    pdf_data_writer_t writer;
781
2.65k
    gs_const_string alt_cmap_name;
782
2.65k
    const gs_const_string *cmap_name = &pcmap->CMapName;
783
784
2.65k
    code = pdf_begin_data_stream(pdev, &writer,
785
2.65k
                                 DATA_STREAM_NOT_BINARY |
786
                            /* Don't set DATA_STREAM_ENCRYPT since we write to a temporary file.
787
                               See comment in pdf_begin_encrypt. */
788
2.65k
                                 (pdev->CompressFonts ?
789
2.65k
                                  DATA_STREAM_COMPRESS : 0), gs_no_id);
790
2.65k
    if (code < 0)
791
0
        return code;
792
2.65k
    *ppres = writer.pres;
793
2.65k
    writer.pres->where_used = 0; /* CMap isn't a PDF resource. */
794
2.65k
    if (!pcmap->ToUnicode) {
795
27
        byte *buf = NULL;
796
27
        uint64_t buflen = 0;
797
27
        cos_dict_t *pcd = (cos_dict_t *)writer.pres->object;
798
27
        stream s;
799
800
        /* We use 'buf' for the stream 's' below and that needs to have some extra
801
         * space for the CIDSystemInfo. We also need an extra byte for the leading '/'
802
         * 100 bytes is ample for the overhead.
803
         */
804
27
        buflen = pcmap->CIDSystemInfo->Registry.size + pcmap->CIDSystemInfo->Ordering.size + pcmap->CMapName.size + 100;
805
27
        if (buflen > max_uint)
806
0
            return_error(gs_error_limitcheck);
807
808
27
        buf = gs_alloc_bytes(pdev->memory, buflen, "pdf_write_cmap");
809
27
        if (buf == NULL)
810
0
            return_error(gs_error_VMerror);
811
812
27
        code = cos_dict_put_c_key_int(pcd, "/WMode", pcmap->WMode);
813
27
        if (code < 0) {
814
0
            gs_free_object(pdev->memory, buf, "pdf_write_cmap");
815
0
            return code;
816
0
        }
817
27
        buf[0] = '/';
818
27
        memcpy(buf + 1, pcmap->CMapName.data, pcmap->CMapName.size);
819
27
        code = cos_dict_put_c_key_string(pcd, "/CMapName",
820
27
                        buf, pcmap->CMapName.size + 1);
821
27
        if (code < 0) {
822
0
            gs_free_object(pdev->memory, buf, "pdf_write_cmap");
823
0
            return code;
824
0
        }
825
27
        s_init(&s, pdev->memory);
826
27
        swrite_string(&s, buf, buflen);
827
27
        code = pdf_write_cid_system_info_to_stream(pdev, &s, pcmap->CIDSystemInfo, 0);
828
27
        if (code < 0) {
829
0
            gs_free_object(pdev->memory, buf, "pdf_write_cmap");
830
0
            return code;
831
0
        }
832
27
        code = cos_dict_put_c_key_string(pcd, "/CIDSystemInfo",
833
27
                        buf, stell(&s));
834
27
        if (code < 0) {
835
0
            gs_free_object(pdev->memory, buf, "pdf_write_cmap");
836
0
            return code;
837
0
        }
838
27
        code = cos_dict_put_string_copy(pcd, "/Type", "/CMap");
839
27
        if (code < 0) {
840
0
            gs_free_object(pdev->memory, buf, "pdf_write_cmap");
841
0
            return code;
842
0
        }
843
27
        gs_free_object(pdev->memory, buf, "pdf_write_cmap");
844
27
    }
845
2.65k
    if (pcmap->CMapName.size == 0) {
846
        /* Create an arbitrary name (for ToUnicode CMap). */
847
2.62k
        alt_cmap_name.data = (byte *)(*ppres)->rname;
848
2.62k
        alt_cmap_name.size = strlen((*ppres)->rname);
849
2.62k
        cmap_name = &alt_cmap_name;
850
2.62k
    }
851
2.65k
    code = psf_write_cmap(pdev->memory, writer.binary.strm, pcmap,
852
2.65k
                          pdf_put_name_chars_proc(pdev),
853
2.65k
                          cmap_name, font_index_only);
854
2.65k
    if (code < 0)
855
0
        return code;
856
2.65k
    code = pdf_end_data(&writer);
857
2.65k
    if (code < 0)
858
0
        return code;
859
2.65k
    return code;
860
2.65k
}
861
862
static const char *OneByteIdentityH[] = {
863
    "/CIDInit /ProcSet findresource begin",
864
    "12 dict begin",
865
    "begincmap",
866
    "/CIDSystemInfo 3 dict dup begin",
867
      "/Registry (Adobe) def",
868
      "/Ordering (Identity) def",
869
      "/Supplement 0 def",
870
    "end def",
871
    "/CMapName /OneByteIdentityH def",
872
    "/CMapVersion 1.000 def",
873
    "/CMapType 1 def",
874
    "/UIDOffset 0 def",
875
    "/XUID [1 10 25404 9999] def",
876
    "/WMode 0 def",
877
    "1 begincodespacerange",
878
    "<00> <FF>",
879
    "endcodespacerange",
880
    "1 begincidrange",
881
    "<00> <FF> 0",
882
    "endcidrange",
883
    "endcmap",
884
    "CMapName currentdict /CMap defineresource pop",
885
    "end",
886
    "end",
887
NULL};
888
889
/*
890
 * Write OneByteIdentityH CMap.
891
 */
892
int
893
pdf_write_OneByteIdentityH(gx_device_pdf *pdev)
894
0
{
895
0
    int code, i;
896
0
    pdf_data_writer_t writer;
897
0
    cos_dict_t *pcd;
898
0
    char buf[200];
899
0
    static const gs_cid_system_info_t cidsi = {{(const byte *)"Adobe", 5}, {(const byte *)"Identity", 8}, 0};
900
0
    int64_t id;
901
902
0
    if (pdev->IdentityCIDSystemInfo_id == gs_no_id) {
903
0
        code = pdf_write_cid_systemInfo_separate(pdev, &cidsi, &id);
904
0
        if (code < 0)
905
0
            return code;
906
0
        pdev->IdentityCIDSystemInfo_id = id;
907
0
    }
908
0
    if (pdev->OneByteIdentityH != NULL)
909
0
        return 0;
910
0
    code = pdf_begin_data_stream(pdev, &writer,
911
0
                                 DATA_STREAM_NOT_BINARY |
912
                            /* Don't set DATA_STREAM_ENCRYPT since we write to a temporary file.
913
                               See comment in pdf_begin_encrypt. */
914
0
                                 (pdev->CompressFonts ?
915
0
                                  DATA_STREAM_COMPRESS : 0), gs_no_id);
916
0
    if (code < 0)
917
0
        return code;
918
0
    pdev->OneByteIdentityH = writer.pres;
919
0
    pcd = (cos_dict_t *)writer.pres->object;
920
0
    code = cos_dict_put_string_copy(pcd, "/CMapName", "/OneByteIdentityH");
921
0
    if (code < 0)
922
0
        return code;
923
0
    gs_snprintf(buf, sizeof(buf), "%ld 0 R", pdev->IdentityCIDSystemInfo_id);
924
0
    code = cos_dict_put_string_copy(pcd, "/CIDSystemInfo", buf);
925
0
    if (code < 0)
926
0
        return code;
927
0
    code = cos_dict_put_string_copy(pcd, "/Type", "/CMap");
928
0
    if (code < 0)
929
0
        return code;
930
0
    for (i = 0; OneByteIdentityH[i]; i++) {
931
0
        stream_puts(pdev->strm, OneByteIdentityH[i]);
932
0
        stream_putc(pdev->strm, '\n');
933
0
    }
934
0
    return pdf_end_data(&writer);
935
0
}