Coverage Report

Created: 2022-10-31 07:00

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