Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/devices/vector/gdevpsf1.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
/* Write an embedded Type 1 font */
18
#include "math.h"
19
#include "memory_.h"
20
#include "gx.h"
21
#include "gserrors.h"
22
#include "gsccode.h"
23
#include "gsmatrix.h"
24
#include "gxfixed.h"
25
#include "gxfont.h"
26
#include "gxfont1.h"
27
#include "gxmatrix.h"   /* for gxtype1.h */
28
#include "gxtype1.h"
29
#include "strimpl.h"    /* required by Watcom compiler (why?) */
30
#include "stream.h"
31
#include "sfilter.h"
32
#include "spsdf.h"
33
#include "sstring.h"
34
#include "spprint.h"
35
#include "gdevpsf.h"
36
37
/* ------ Utilities shared with CFF writer ------ */
38
39
/* Gather glyph information for a Type 1 or Type 2 font. */
40
int
41
psf_type1_glyph_data(gs_font_base *pbfont, gs_glyph glyph,
42
                     gs_glyph_data_t *pgd, gs_font_type1 **ppfont)
43
1.06M
{
44
1.06M
    gs_font_type1 *const pfont = (gs_font_type1 *)pbfont;
45
46
1.06M
    *ppfont = pfont;
47
1.06M
    return pfont->data.procs.glyph_data(pfont, glyph, pgd);
48
1.06M
}
49
int
50
psf_get_type1_glyphs(psf_outline_glyphs_t *pglyphs, gs_font_type1 *pfont,
51
                     gs_glyph *subset_glyphs, uint subset_size)
52
7.65k
{
53
7.65k
    return psf_get_outline_glyphs(pglyphs, (gs_font_base *)pfont,
54
7.65k
                                  subset_glyphs, subset_size,
55
7.65k
                                  psf_type1_glyph_data);
56
7.65k
}
57
58
/* ------ Main program ------ */
59
60
/* Write a (named) array of floats. */
61
static int
62
write_float_array(gs_param_list *plist, const char *key, const float *values,
63
                  int count)
64
24.2k
{
65
24.2k
    if (count != 0) {
66
12.0k
        gs_param_float_array fa;
67
68
12.0k
        fa.persistent = false;
69
12.0k
        fa.size = count;
70
12.0k
        fa.data = values;
71
12.0k
        return param_write_float_array(plist, key, &fa);
72
12.0k
    }
73
12.2k
    return 0;
74
24.2k
}
75
76
/* Write a UniqueID and/or XUID. */
77
static void
78
write_uid(stream *s, const gs_uid *puid, int options)
79
6.05k
{
80
6.05k
    if (uid_is_UniqueID(puid))
81
0
        pprintld1(s, "/UniqueID %ld def\n", puid->id);
82
6.05k
    else if (uid_is_XUID(puid) && (options & WRITE_TYPE1_XUID) != 0) {
83
0
        uint i, n = uid_XUID_size(puid);
84
85
        /* Adobe products (specifically Acrobat but the same limitation is mentioned
86
         * in the PLRM) cannot handle XUIDs > 16 entries.
87
         */
88
0
        if (n > 16)
89
0
            n = 16;
90
91
0
        stream_puts(s, "/XUID [");
92
0
        for (i = 0; i < n; ++i)
93
0
            pprintld1(s, "%ld ", uid_XUID_values(puid)[i]);
94
0
        stream_puts(s, "] readonly def\n");
95
0
    }
96
6.05k
}
97
98
/* Write the font name. */
99
static void
100
write_font_name(stream *s, const gs_font_type1 *pfont,
101
                const gs_const_string *alt_font_name, bool as_name)
102
6.05k
{
103
6.05k
    const byte *c;
104
6.05k
    const byte *name = (alt_font_name ? alt_font_name->data : pfont->font_name.chars);
105
6.05k
    int         n    = (alt_font_name ? alt_font_name->size : pfont->font_name.size);
106
107
6.05k
    if (n == 0)
108
        /* empty name, may need to write it as empty string */
109
0
        stream_puts(s, (as_name ? "/" : "()"));
110
6.05k
    else {
111
114k
        for (c = (byte *)"()<>[]{}/% \n\r\t\b\f\004\033"; *c; c++)
112
108k
            if (memchr(name, *c, n))
113
16
                break;
114
6.05k
        if (*c || memchr(name, 0, n)) {
115
            /* name contains whitespace (NUL included) or a PostScript separator */
116
16
            byte pssebuf[1 + 4 * gs_font_name_max + 1]; /* "(" + "\ooo" * gs_font_name_max + ")" */
117
16
            stream_cursor_read  r;
118
16
            stream_cursor_write w;
119
120
16
            pssebuf[0] = '(';
121
16
            r.limit = (r.ptr = name - 1) + n;
122
16
            w.limit = (w.ptr = pssebuf) + sizeof pssebuf - 1;
123
16
            s_PSSE_template.process(NULL, &r, &w, true);
124
16
            stream_write(s, pssebuf, w.ptr - pssebuf + 1);
125
16
            if (as_name)
126
8
                stream_puts(s, " cvn");
127
6.04k
        } else {
128
            /* name without any special characters */
129
6.04k
            if (as_name)
130
3.02k
                stream_putc(s, '/');
131
6.04k
            stream_write(s, name, n);
132
6.04k
        }
133
6.05k
    }
134
6.05k
}
135
/*
136
 * Write the Encoding array.  This is a separate procedure only for
137
 * readability.
138
 */
139
static int
140
write_Encoding(stream *s, gs_font_type1 *pfont, int options,
141
              gs_glyph *subset_glyphs, uint subset_size, gs_glyph notdef)
142
3.02k
{
143
3.02k
    stream_puts(s, "/Encoding ");
144
3.02k
    switch (pfont->encoding_index) {
145
0
        case ENCODING_INDEX_STANDARD:
146
0
            stream_puts(s, "StandardEncoding");
147
0
            break;
148
0
        case ENCODING_INDEX_ISOLATIN1:
149
            /* ATM only recognizes StandardEncoding. */
150
0
            if (options & WRITE_TYPE1_POSTSCRIPT) {
151
0
                stream_puts(s, "ISOLatin1Encoding");
152
0
                break;
153
0
            }
154
3.02k
        default:{
155
3.02k
                gs_char i;
156
157
3.02k
                stream_puts(s, "256 array\n");
158
3.02k
                stream_puts(s, "0 1 255 {1 index exch /.notdef put} for\n");
159
778k
                for (i = 0; i < 256; ++i) {
160
775k
                    gs_glyph glyph =
161
775k
                        (*pfont->procs.encode_char)
162
775k
                        ((gs_font *)pfont, (gs_char)i, GLYPH_SPACE_NAME);
163
775k
                    gs_const_string namestr;
164
165
775k
                    if (subset_glyphs && subset_size) {
166
                        /*
167
                         * Only write Encoding entries for glyphs in the
168
                         * subset.  Use binary search to check each glyph,
169
                         * since subset_glyphs are sorted.
170
                         */
171
0
                        if (!psf_sorted_glyphs_include(subset_glyphs,
172
0
                                                        subset_size, glyph))
173
0
                            continue;
174
0
                    }
175
775k
                    if (glyph != GS_NO_GLYPH && glyph != notdef &&
176
775k
                        pfont->procs.glyph_name((gs_font *)pfont, glyph,
177
103k
                                                &namestr) >= 0
178
775k
                        ) {
179
103k
                        pprintd1(s, "dup %d /", (int)i);
180
103k
                        stream_write(s, namestr.data, namestr.size);
181
103k
                        stream_puts(s, " put\n");
182
103k
                    }
183
775k
                }
184
3.02k
                stream_puts(s, "readonly");
185
3.02k
            }
186
3.02k
    }
187
3.02k
    stream_puts(s, " def\n");
188
3.02k
    return 0;
189
3.02k
}
190
191
static int WriteNumber (byte *dest, int value)
192
0
{
193
0
    if (value >= -107 && value <= 107) {
194
0
        *dest = value + 139;
195
0
        return 1;
196
0
    } else {
197
0
        if (value >= 108 && value <= 1131) {
198
0
            int quotient = (int)floor((value - 108) / (double)256);
199
0
            dest[0] = quotient + 247;
200
0
            dest[1] = value - 108 - quotient * 256;
201
0
            return 2;
202
0
        } else {
203
0
            if (value <= -108 && value >= -1131) {
204
0
                int quotient = (int)floor((value + 108) / -256);
205
0
                int newval = value + 256 * quotient + 108;
206
0
                dest[0] = quotient + 251;
207
0
                dest[1] = newval * -1;
208
0
                return 2;
209
0
            } else {
210
0
                dest[0] = 255;
211
0
                dest[1] = value >> 24;
212
0
                dest[2] = (value & 0xFF0000) >> 16;
213
0
                dest[3] = (value & 0xFF00) >> 8;
214
0
                dest[4] = value & 0xFF;
215
0
                return 5;
216
0
            }
217
0
        }
218
0
    }
219
0
    return 0;
220
0
}
221
222
/* The following 2 routines attempt to parse out Multiple Master 'OtherSubrs'
223
 * calls, and replace the multiple arguments to $Blend with the two 'base'
224
 * parameters. This works reasonably well but can be defeated. FOr example a
225
 * CharString which puts some parameters on the operand stack, then calls a
226
 * Subr which puts the remaining parameters on the stack, and calls a MM
227
 * OtherSubr (constructions like this have been observed). In general we
228
 * work around this by storing the operands on the stack, but it is possible
229
 * that the values are calculated (eg x y div) which is a common way to get
230
 * float values into the interpreter. This will defeat the code below.
231
 *
232
 * The only way to solve this is to actually fully interpret the CharString
233
 * and any /Subrs it calls, and then emit the result as a non-MM CharString
234
 * by blending the values. This would mean writing a new routine like
235
 * 'psf_convert_type1_to_type2' (see gdevpsfx.c) or modifying that routine
236
 * so that it outputs type 1 CharStrings (which is probably simpler to do).
237
 */
238
static int CheckSubrForMM (gs_glyph_data_t *gdata, gs_font_type1 *pfont)
239
0
{
240
0
    crypt_state state = crypt_charstring_seed;
241
0
    int code = 0;
242
0
    gs_bytestring *data = (gs_bytestring *)&gdata->bits;
243
0
    byte *source = data->data, *end = source + data->size;
244
0
    int CurrentNumberIndex = 0, Stack[32];
245
246
0
    memset(Stack, 0x00, sizeof(Stack));
247
0
    gs_type1_decrypt(source, source, data->size, &state);
248
249
0
    if(pfont->data.lenIV)
250
0
        source += pfont->data.lenIV;
251
252
0
    while (source < end) {
253
0
        if (*source < 32) {
254
            /* Command */
255
0
            switch (*source) {
256
0
                case 12:
257
0
                    if (*(source + 1) == 16) {
258
0
                        if (CurrentNumberIndex < 1)
259
0
        return_error(gs_error_rangecheck);
260
0
                        switch(Stack[CurrentNumberIndex-1]) {
261
0
                            case 18:
262
0
                                code = 6;
263
0
                                break;
264
0
                            case 17:
265
0
                                code = 4;
266
0
                                break;
267
0
                            case 16:
268
0
                                code = 3;
269
0
                                break;
270
0
                            case 15:
271
0
                                code = 2;
272
0
                                break;
273
0
                            case 14:
274
0
                                code = 1;
275
0
                                break;
276
0
                            default:
277
0
                                code = 0;
278
0
                                break;
279
0
                        }
280
0
                        source += 2;
281
0
                    } else {
282
0
                        source +=2;
283
0
                    }
284
0
                    break;
285
0
                default:
286
0
                    source++;
287
0
                    break;
288
0
            }
289
0
            CurrentNumberIndex = 0;
290
0
        } else {
291
            /* Number */
292
0
            if (*source < 247) {
293
0
                Stack[CurrentNumberIndex++] = *source++ - 139;
294
0
            } else {
295
0
                if (*source < 251) {
296
0
                    Stack[CurrentNumberIndex] = ((*source++ - 247) * 256) + 108;
297
0
                    Stack[CurrentNumberIndex++] += *source++;
298
0
                } else {
299
0
                    if (*source < 255) {
300
0
                        Stack[CurrentNumberIndex] = ((*source++ - 251) * -256) - 108;
301
0
                        Stack[CurrentNumberIndex++] -= *source++;
302
0
                    } else {
303
0
                        Stack[CurrentNumberIndex] = *source++ << 24;
304
0
                        Stack[CurrentNumberIndex] += *source++ << 16;
305
0
                        Stack[CurrentNumberIndex] += *source++ << 8;
306
0
                        Stack[CurrentNumberIndex] += *source++;
307
0
                    }
308
0
                }
309
0
            }
310
0
        }
311
0
    }
312
0
    state = crypt_charstring_seed;
313
0
    source = data->data;
314
0
    gs_type1_encrypt(source, source, data->size, &state);
315
0
    return code;
316
0
}
317
318
static int strip_othersubrs(gs_glyph_data_t *gdata, gs_font_type1 *pfont, byte *stripped, byte *SubrsWithMM)
319
0
{
320
0
    crypt_state state = crypt_charstring_seed;
321
0
    gs_bytestring *data = (gs_bytestring *)&gdata->bits;
322
0
    byte *source = data->data, *dest = stripped, *end = source + data->size;
323
0
    int i, dest_length = 0, CurrentNumberIndex = 0, Stack[64], written;
324
0
    int OnlyCalcLength = 0;
325
0
    char Buffer[16];
326
327
0
    memset(Stack, 0x00, 64 * sizeof(int));
328
0
    if (stripped == NULL) {
329
0
        OnlyCalcLength = 1;
330
0
        dest = (byte *)&Buffer;
331
0
    }
332
333
0
    gs_type1_decrypt(source, source, data->size, &state);
334
335
0
    if(pfont->data.lenIV >= 0) {
336
0
        for (i=0;i<pfont->data.lenIV;i++) {
337
0
            if (!OnlyCalcLength)
338
0
                *dest++ = *source++;
339
0
        }
340
0
        dest_length += pfont->data.lenIV;
341
0
    }
342
0
    while (source < end) {
343
0
        if (*source < 32) {
344
            /* Command */
345
0
            switch (*source) {
346
0
                case 12:
347
0
                    if (*(source + 1) == 16) {
348
                        /* Callothersubsr, the only thing we care about */
349
0
                        switch(Stack[CurrentNumberIndex-1]) {
350
                            /* If we find a Multiple Master call, remove all but the
351
                             * first set of arguments. Mimics the result of a call.
352
                             * Adobe 'encourages' the use of Subrs to do MM, but
353
                             * the spec doens't say you have to, so we need to be
354
                             * prepared, just in case. I doubt we will ever execute
355
                             * this code.
356
                             */
357
0
                            case 14:
358
0
                                CurrentNumberIndex -= pfont->data.WeightVector.count - 1;
359
0
                                for (i = 0;i < CurrentNumberIndex;i++) {
360
0
                                    written = WriteNumber(dest, Stack[i]);
361
0
                                    dest_length += written;
362
0
                                    if (!OnlyCalcLength)
363
0
                                        dest += written;
364
0
                                }
365
0
                                source += 2;
366
0
                                break;
367
0
                            case 15:
368
0
                                CurrentNumberIndex -= (pfont->data.WeightVector.count - 1) * 2;
369
0
                                for (i = 0;i < CurrentNumberIndex;i++) {
370
0
                                    written = WriteNumber(dest, Stack[i]);
371
0
                                    dest_length += written;
372
0
                                    if (!OnlyCalcLength)
373
0
                                        dest += written;
374
0
                                }
375
0
                                source += 2;
376
0
                                break;
377
0
                            case 16:
378
0
                                CurrentNumberIndex -= (pfont->data.WeightVector.count - 1) * 3;
379
0
                                for (i = 0;i < CurrentNumberIndex;i++) {
380
0
                                    written = WriteNumber(dest, Stack[i]);
381
0
                                    dest_length += written;
382
0
                                    if (!OnlyCalcLength)
383
0
                                        dest += written;
384
0
                                }
385
0
                                source += 2;
386
0
                                break;
387
0
                            case 17:
388
0
                                CurrentNumberIndex -= (pfont->data.WeightVector.count - 1) * 4;
389
0
                                for (i = 0;i < CurrentNumberIndex;i++) {
390
0
                                    written = WriteNumber(dest, Stack[i]);
391
0
                                    dest_length += written;
392
0
                                    if (!OnlyCalcLength)
393
0
                                        dest += written;
394
0
                                }
395
0
                                source += 2;
396
0
                                break;
397
0
                            case 18:
398
0
                                CurrentNumberIndex -= (pfont->data.WeightVector.count - 1) * 6;
399
0
                                for (i = 0;i < CurrentNumberIndex;i++) {
400
0
                                    written = WriteNumber(dest, Stack[i]);
401
0
                                    dest_length += written;
402
0
                                    if (!OnlyCalcLength)
403
0
                                        dest += written;
404
0
                                }
405
0
                                source += 2;
406
0
                                break;
407
0
                            default:
408
0
                                for (i = 0;i < CurrentNumberIndex;i++) {
409
0
                                    written = WriteNumber(dest, Stack[i]);
410
0
                                    dest_length += written;
411
0
                                    if (!OnlyCalcLength)
412
0
                                        dest += written;
413
0
                                }
414
0
                                if (!OnlyCalcLength) {
415
0
                                    *dest++ = *source++;
416
0
                                    *dest++ = *source++;
417
0
                                } else {
418
0
                                    source += 2;
419
0
                                }
420
0
                                dest_length += 2;
421
0
                                break;
422
0
                        }
423
0
                    } else {
424
0
                        for (i = 0;i < CurrentNumberIndex;i++) {
425
0
                            written = WriteNumber(dest, Stack[i]);
426
0
                            dest_length += written;
427
0
                            if (!OnlyCalcLength)
428
0
                                dest += written;
429
0
                        }
430
0
                        if (!OnlyCalcLength) {
431
0
                            *dest++ = *source++;
432
0
                            *dest++ = *source++;
433
0
                        } else {
434
0
                            source += 2;
435
0
                        }
436
0
                        dest_length += 2;
437
0
                    }
438
0
                    break;
439
0
                case 10:
440
0
                    if (CurrentNumberIndex != 0 && SubrsWithMM[Stack[CurrentNumberIndex - 1]] != 0) {
441
0
                        int index = Stack[CurrentNumberIndex - 1];
442
0
                        int StackBase = CurrentNumberIndex - 1 - pfont->data.WeightVector.count * SubrsWithMM[index];
443
444
0
                        CurrentNumberIndex--; /* Remove the subr index */
445
446
0
                        for (i=0;i < StackBase; i++) {
447
0
                            written = WriteNumber(dest, Stack[i]);
448
0
                            dest_length += written;
449
0
                            if (!OnlyCalcLength)
450
0
                                dest += written;
451
0
                        }
452
0
                        for (i=0;i<SubrsWithMM[index];i++) {
453
                            /* See above, it may be that we don't have enough numbers on the stack
454
                             * (due to constructs such as x y div), if we don't have enough parameters
455
                             * just write a 0 instead. We know this is incorrect.....
456
                             */
457
0
                            if (StackBase + i >= 0)
458
0
                                written = WriteNumber(dest, Stack[StackBase + i]);
459
0
                            else
460
0
                                written = WriteNumber(dest, 0);
461
0
                            dest_length += written;
462
0
                            if (!OnlyCalcLength)
463
0
                                dest += written;
464
0
                        }
465
0
                        source++;
466
0
                    } else {
467
0
                        for (i = 0;i < CurrentNumberIndex;i++) {
468
0
                            written = WriteNumber(dest, Stack[i]);
469
0
                            dest_length += written;
470
0
                            if (!OnlyCalcLength)
471
0
                                dest += written;
472
0
                        }
473
0
                        if (!OnlyCalcLength)
474
0
                            *dest++ = *source++;
475
0
                        else
476
0
                            source++;
477
0
                        dest_length++;
478
0
                    }
479
0
                    break;
480
0
                default:
481
0
                    for (i = 0;i < CurrentNumberIndex;i++) {
482
0
                        written = WriteNumber(dest, Stack[i]);
483
0
                        dest_length += written;
484
0
                        if (!OnlyCalcLength)
485
0
                            dest += written;
486
0
                    }
487
0
                    if (!OnlyCalcLength)
488
0
                        *dest++ = *source++;
489
0
                    else
490
0
                        source++;
491
0
                    dest_length++;
492
0
            }
493
0
            CurrentNumberIndex = 0;
494
0
        } else {
495
            /* Number */
496
0
            if (*source < 247) {
497
0
                Stack[CurrentNumberIndex++] = *source++ - 139;
498
0
            } else {
499
0
                if (*source < 251) {
500
0
                    Stack[CurrentNumberIndex] = ((*source++ - 247) * 256) + 108;
501
0
                    Stack[CurrentNumberIndex++] += *source++;
502
0
                } else {
503
0
                    if (*source < 255) {
504
0
                        Stack[CurrentNumberIndex] = ((*source++ - 251) * -256) - 108;
505
0
                        Stack[CurrentNumberIndex++] -= *source++;
506
0
                    } else {
507
0
                        source++;
508
0
                        Stack[CurrentNumberIndex] = *source++ << 24;
509
0
                        Stack[CurrentNumberIndex] += *source++ << 16;
510
0
                        Stack[CurrentNumberIndex] += *source++ << 8;
511
0
                        Stack[CurrentNumberIndex++] += *source++;
512
0
                    }
513
0
                }
514
0
            }
515
0
        }
516
0
    }
517
0
    source = data->data;
518
0
    state = crypt_charstring_seed;
519
0
    gs_type1_encrypt(source, source, data->size, &state);
520
521
0
    if (!OnlyCalcLength) {
522
0
        state = crypt_charstring_seed;
523
0
        gs_type1_encrypt(stripped, stripped, dest_length, &state);
524
0
    }
525
0
    return dest_length;
526
0
}
527
528
/*
529
 * Write the Private dictionary.  This is a separate procedure only for
530
 * readability.  write_CharString is a parameter so that we can encrypt
531
 * Subrs and CharStrings when the font's lenIV == -1 but we are writing
532
 * the font with lenIV = 0.
533
 */
534
static int
535
write_Private(stream *s, gs_font_type1 *pfont,
536
              gs_glyph *subset_glyphs, uint subset_size,
537
              gs_glyph notdef, int lenIV,
538
              int (*write_CharString)(stream *, const void *, uint),
539
              const param_printer_params_t *ppp, int options)
540
3.02k
{
541
3.02k
    const gs_type1_data *const pdata = &pfont->data;
542
3.02k
    printer_param_list_t rlist;
543
3.02k
    gs_param_list *const plist = (gs_param_list *)&rlist;
544
3.02k
    int code = s_init_param_printer(&rlist, ppp, s);
545
3.02k
    byte *SubrsWithMM = 0;
546
547
3.02k
    if (code < 0)
548
0
        return 0;
549
3.02k
    stream_puts(s, "dup /Private 17 dict dup begin\n");
550
3.02k
    stream_puts(s, "/-|{string currentfile exch readstring pop}executeonly def\n");
551
3.02k
    stream_puts(s, "/|-{noaccess def}executeonly def\n");
552
3.02k
    stream_puts(s, "/|{noaccess put}executeonly def\n");
553
3.02k
    {
554
3.02k
        static const gs_param_item_t private_items[] = {
555
3.02k
            {"BlueFuzz", gs_param_type_int,
556
3.02k
             offset_of(gs_type1_data, BlueFuzz)},
557
3.02k
            {"BlueScale", gs_param_type_float,
558
3.02k
             offset_of(gs_type1_data, BlueScale)},
559
3.02k
            {"BlueShift", gs_param_type_float,
560
3.02k
             offset_of(gs_type1_data, BlueShift)},
561
3.02k
            {"ExpansionFactor", gs_param_type_float,
562
3.02k
             offset_of(gs_type1_data, ExpansionFactor)},
563
3.02k
            {"ForceBold", gs_param_type_bool,
564
3.02k
             offset_of(gs_type1_data, ForceBold)},
565
3.02k
            {"LanguageGroup", gs_param_type_int,
566
3.02k
             offset_of(gs_type1_data, LanguageGroup)},
567
3.02k
            {"RndStemUp", gs_param_type_bool,
568
3.02k
             offset_of(gs_type1_data, RndStemUp)},
569
3.02k
            gs_param_item_end
570
3.02k
        };
571
3.02k
        gs_type1_data defaults;
572
573
3.02k
        defaults.BlueFuzz = 1;
574
3.02k
        defaults.BlueScale = (float)0.039625;
575
3.02k
        defaults.BlueShift = 7.0;
576
3.02k
        defaults.ExpansionFactor = (float)0.06;
577
3.02k
        defaults.ForceBold = false;
578
3.02k
        defaults.LanguageGroup = 0;
579
3.02k
        defaults.RndStemUp = true;
580
3.02k
        code = gs_param_write_items(plist, pdata, &defaults, private_items);
581
3.02k
        if (code < 0)
582
0
            return code;
583
3.02k
        if (lenIV != 4) {
584
5
            code = param_write_int(plist, "lenIV", &lenIV);
585
5
            if (code < 0)
586
0
                return code;
587
5
        }
588
3.02k
        write_float_array(plist, "BlueValues", pdata->BlueValues.values,
589
3.02k
                          pdata->BlueValues.count);
590
3.02k
        write_float_array(plist, "OtherBlues", pdata->OtherBlues.values,
591
3.02k
                          pdata->OtherBlues.count);
592
3.02k
        write_float_array(plist, "FamilyBlues", pdata->FamilyBlues.values,
593
3.02k
                          pdata->FamilyBlues.count);
594
3.02k
        write_float_array(plist, "FamilyOtherBlues", pdata->FamilyOtherBlues.values,
595
3.02k
                          pdata->FamilyOtherBlues.count);
596
3.02k
        write_float_array(plist, "StdHW", pdata->StdHW.values,
597
3.02k
                          pdata->StdHW.count);
598
3.02k
        write_float_array(plist, "StdVW", pdata->StdVW.values,
599
3.02k
                          pdata->StdVW.count);
600
3.02k
        write_float_array(plist, "StemSnapH", pdata->StemSnapH.values,
601
3.02k
                          pdata->StemSnapH.count);
602
3.02k
        write_float_array(plist, "StemSnapV", pdata->StemSnapV.values,
603
3.02k
                          pdata->StemSnapV.count);
604
3.02k
    }
605
0
    write_uid(s, &pfont->UID, options);
606
3.02k
    stream_puts(s, "/MinFeature{16 16} def\n");
607
3.02k
    stream_puts(s, "/password 5839 def\n");
608
609
    /*
610
     * Write the Subrs.  We always write them all, even for subsets.
611
     * (We will fix this someday.)
612
     */
613
614
3.02k
    {
615
3.02k
        int n, i;
616
3.02k
        gs_glyph_data_t gdata;
617
3.02k
        int code;
618
619
3.02k
        gdata.memory = pfont->memory;
620
3.02k
        for (n = 0;
621
46.9k
             (code = pdata->procs.subr_data(pfont, n, false, &gdata)) !=
622
46.9k
                 gs_error_rangecheck;
623
43.8k
             ) {
624
43.8k
            ++n;
625
43.8k
            if (code >= 0)
626
43.8k
                gs_glyph_data_free(&gdata, "write_Private(Subrs)");
627
43.8k
        }
628
3.02k
        if (pfont->data.WeightVector.count != 0)
629
0
            SubrsWithMM = gs_alloc_bytes(pfont->memory, n, "Subrs record");
630
631
3.02k
        pprintd1(s, "/Subrs %d array\n", n);
632
633
        /* prescan the /Subrs array to see if any of the Subrs call out to OtherSubrs */
634
3.02k
        if (pfont->data.WeightVector.count != 0) {
635
0
            for (i = 0; i < n; ++i) {
636
0
                if ((code = pdata->procs.subr_data(pfont, i, false, &gdata)) >= 0) {
637
0
                        code = CheckSubrForMM(&gdata, pfont);
638
0
                        if (code < 0) {
639
0
                            if (SubrsWithMM != 0)
640
0
                                gs_free_object(pfont->memory, SubrsWithMM, "free Subrs record");
641
0
                            return code;
642
0
                        }
643
0
                        if (SubrsWithMM != 0)
644
0
                            SubrsWithMM[i] = code;
645
0
                }
646
0
            }
647
0
        }
648
649
46.9k
        for (i = 0; i < n; ++i)
650
43.8k
            if ((code = pdata->procs.subr_data(pfont, i, false, &gdata)) >= 0) {
651
43.8k
                char buf[50];
652
653
43.8k
                if (gdata.bits.size) {
654
43.8k
                    if (pfont->data.WeightVector.count != 0) {
655
0
                        byte *stripped;
656
0
                        int length;
657
658
0
                        length = strip_othersubrs(&gdata, pfont, NULL, SubrsWithMM);
659
0
                        stripped = gs_alloc_bytes(pfont->memory, length, "Subrs copy for OtherSubrs");
660
0
                        code = strip_othersubrs(&gdata, pfont, stripped, SubrsWithMM);
661
0
                        if (code < 0) {
662
0
                            if (SubrsWithMM != 0)
663
0
                                gs_free_object(pfont->memory, SubrsWithMM, "free Subrs record");
664
0
                            return code;
665
0
                        }
666
0
                        gs_snprintf(buf, sizeof(buf), "dup %d %u -| ", i, code);
667
0
                        stream_puts(s, buf);
668
0
                        write_CharString(s, stripped, code);
669
0
                        gs_free_object(pfont->memory, stripped, "free Subrs copy for OtherSubrs");
670
43.8k
                    } else {
671
43.8k
                        gs_snprintf(buf, sizeof(buf), "dup %d %u -| ", i, gdata.bits.size);
672
43.8k
                        stream_puts(s, buf);
673
43.8k
                        write_CharString(s, gdata.bits.data, gdata.bits.size);
674
43.8k
                    }
675
43.8k
                    stream_puts(s, " |\n");
676
43.8k
                }
677
43.8k
                gs_glyph_data_free(&gdata, "write_Private(Subrs)");
678
43.8k
            }
679
3.02k
        stream_puts(s, "|-\n");
680
3.02k
    }
681
682
    /* We don't write OtherSubrs -- there had better not be any! */
683
684
    /* Write the CharStrings. */
685
686
0
    {
687
3.02k
        int num_chars = 0;
688
3.02k
        gs_glyph glyph;
689
3.02k
        psf_glyph_enum_t genum;
690
3.02k
        gs_glyph_data_t gdata;
691
3.02k
        int code;
692
693
3.02k
        gdata.memory = pfont->memory;
694
3.02k
        psf_enumerate_glyphs_begin(&genum, (gs_font *)pfont, subset_glyphs,
695
3.02k
                                    (subset_glyphs ? subset_size : 0),
696
3.02k
                                    GLYPH_SPACE_NAME);
697
3.02k
        for (glyph = GS_NO_GLYPH;
698
109k
             (code = psf_enumerate_glyphs_next(&genum, &glyph)) != 1;
699
3.02k
             )
700
106k
            if (code == 0 &&
701
106k
                (code = pdata->procs.glyph_data(pfont, glyph, &gdata)) >= 0
702
106k
                ) {
703
106k
                ++num_chars;
704
106k
                gs_glyph_data_free(&gdata, "write_Private(CharStrings)");
705
106k
            }
706
3.02k
        pprintd1(s, "2 index /CharStrings %d dict dup begin\n", num_chars);
707
3.02k
        psf_enumerate_glyphs_reset(&genum);
708
3.02k
        for (glyph = GS_NO_GLYPH;
709
109k
             (code = psf_enumerate_glyphs_next(&genum, &glyph)) != 1;
710
3.02k
            )
711
106k
            if (code == 0 &&
712
106k
                (code = pdata->procs.glyph_data(pfont, glyph, &gdata)) >= 0
713
106k
                ) {
714
106k
                gs_const_string gstr;
715
106k
                int code;
716
106k
                byte *stripped;
717
718
106k
                code = pfont->procs.glyph_name((gs_font *)pfont, glyph, &gstr);
719
106k
                if (code < 0) {
720
0
                    if (SubrsWithMM != 0)
721
0
                        gs_free_object(pfont->memory, SubrsWithMM, "free Subrs record");
722
0
                    return code;
723
0
                }
724
725
106k
                stream_puts(s, "/");
726
106k
                stream_write(s, gstr.data, gstr.size);
727
728
106k
                if (pfont->data.WeightVector.count != 0) {
729
0
                    gs_bytestring *data = (gs_bytestring *)&gdata.bits;
730
731
0
                    stripped = gs_alloc_bytes(pfont->memory, data->size, "CharStrings copy for OtherSubrs");
732
0
                    code = strip_othersubrs(&gdata, pfont, stripped, SubrsWithMM);
733
0
                    if (code < 0) {
734
0
                        if (SubrsWithMM != 0)
735
0
                            gs_free_object(pfont->memory, SubrsWithMM, "free Subrs record");
736
0
                        return code;
737
0
                    }
738
0
                    pprintd1(s, " %d -| ", code);
739
0
                    write_CharString(s, stripped, code);
740
0
                    gs_free_object(pfont->memory, stripped, "free CharStrings copy for OtherSubrs");
741
106k
                } else {
742
106k
                    pprintd1(s, " %d -| ", gdata.bits.size);
743
106k
                    write_CharString(s, gdata.bits.data, gdata.bits.size);
744
106k
                }
745
746
106k
                stream_puts(s, " |-\n");
747
106k
                gs_glyph_data_free(&gdata, "write_Private(CharStrings)");
748
106k
            }
749
3.02k
    }
750
3.02k
    if (SubrsWithMM != 0)
751
0
        gs_free_object(pfont->memory, SubrsWithMM, "free Subrs record");
752
753
    /* Wrap up. */
754
755
3.02k
    stream_puts(s, "end\nend\nreadonly put\nnoaccess put\n");
756
3.02k
    s_release_param_printer(&rlist);
757
3.02k
    return 0;
758
3.02k
}
759
760
/* Encrypt and write a CharString. */
761
static int
762
stream_write_encrypted(stream *s, const void *ptr, uint count)
763
0
{
764
0
    const byte *const data = ptr;
765
0
    crypt_state state = crypt_charstring_seed;
766
0
    byte buf[50];   /* arbitrary */
767
0
    uint left, n;
768
0
    int code = 0;
769
770
0
    for (left = count; left > 0; left -= n) {
771
0
        n = min(left, sizeof(buf));
772
0
        gs_type1_encrypt(buf, data + count - left, n, &state);
773
0
        code = stream_write(s, buf, n);
774
0
    }
775
0
    return code;
776
0
}
777
778
/* Write one FontInfo entry. */
779
static void
780
write_font_info(stream *s, const char *key, const gs_const_string *pvalue,
781
                int do_write)
782
12.1k
{
783
12.1k
    if (do_write) {
784
188
        pprints1(s, "\n/%s ", key);
785
188
        s_write_ps_string(s, pvalue->data, pvalue->size, PRINT_HEX_NOT_OK);
786
188
        stream_puts(s, " def");
787
188
    }
788
12.1k
}
789
790
/* Write the definition of a Type 1 font. */
791
int
792
psf_write_type1_font(stream *s, gs_font_type1 *pfont, int options,
793
                      gs_glyph *orig_subset_glyphs, uint orig_subset_size,
794
                      const gs_const_string *alt_font_name, int lengths[3])
795
3.02k
{
796
3.02k
    stream *es = s;
797
3.02k
    gs_offset_t start = stell(s);
798
3.02k
    param_printer_params_t ppp;
799
3.02k
    printer_param_list_t rlist;
800
3.02k
    gs_param_list *const plist = (gs_param_list *)&rlist;
801
3.02k
    stream AXE_stream;
802
3.02k
    stream_AXE_state AXE_state;
803
3.02k
    byte AXE_buf[200];    /* arbitrary */
804
3.02k
    stream exE_stream;
805
3.02k
    stream_exE_state exE_state;
806
3.02k
    byte exE_buf[200];    /* arbitrary */
807
3.02k
    psf_outline_glyphs_t glyphs;
808
3.02k
    int lenIV = pfont->data.lenIV;
809
3.02k
    int (*write_CharString)(stream *, const void *, uint) = stream_write;
810
3.02k
    int code = psf_get_type1_glyphs(&glyphs, pfont, orig_subset_glyphs,
811
3.02k
                                     orig_subset_size);
812
813
3.02k
    if (code < 0)
814
0
        return code;
815
816
    /* Initialize the parameter printer. */
817
818
3.02k
    ppp = param_printer_params_default;
819
3.02k
    ppp.item_suffix = " def\n";
820
3.02k
    ppp.print_ok =
821
3.02k
        (options & WRITE_TYPE1_ASCIIHEX ? 0 : PRINT_BINARY_OK) |
822
3.02k
        PRINT_HEX_NOT_OK;
823
3.02k
    code = s_init_param_printer(&rlist, &ppp, s);
824
3.02k
    if (code < 0)
825
0
        return code;
826
827
    /* Write the font header. */
828
829
3.02k
    stream_puts(s, "%!FontType1-1.0: ");
830
3.02k
    write_font_name(s, pfont, alt_font_name, false);
831
3.02k
    stream_puts(s, "\n11 dict begin\n");
832
833
    /* Write FontInfo. */
834
835
3.02k
    stream_puts(s, "/FontInfo 5 dict dup begin");
836
3.02k
    {
837
3.02k
        gs_font_info_t info;
838
3.02k
        int code = pfont->procs.font_info((gs_font *)pfont, NULL,
839
3.02k
                        (FONT_INFO_COPYRIGHT | FONT_INFO_NOTICE |
840
3.02k
                         FONT_INFO_FAMILY_NAME | FONT_INFO_FULL_NAME),
841
3.02k
                                          &info);
842
843
3.02k
        if (code >= 0) {
844
3.02k
            write_font_info(s, "Copyright", &info.Copyright,
845
3.02k
                            info.members & FONT_INFO_COPYRIGHT);
846
3.02k
            write_font_info(s, "Notice", &info.Notice,
847
3.02k
                            info.members & FONT_INFO_NOTICE);
848
3.02k
            write_font_info(s, "FamilyName", &info.FamilyName,
849
3.02k
                            info.members & FONT_INFO_FAMILY_NAME);
850
3.02k
            write_font_info(s, "FullName", &info.FullName,
851
3.02k
                            info.members & FONT_INFO_FULL_NAME);
852
3.02k
        }
853
3.02k
    }
854
3.02k
    stream_puts(s, "\nend readonly def\n");
855
856
    /* Write the main font dictionary. */
857
858
3.02k
    stream_puts(s, "/FontName ");
859
3.02k
    write_font_name(s, pfont, alt_font_name, true);
860
3.02k
    stream_puts(s, " def\n");
861
3.02k
    code = write_Encoding(s, pfont, options, glyphs.subset_glyphs,
862
3.02k
                          glyphs.subset_size, glyphs.notdef);
863
3.02k
    if (code < 0)
864
0
        return code;
865
3.02k
    pprintg6(s, "/FontMatrix [%g %g %g %g %g %g] readonly def\n",
866
3.02k
             pfont->FontMatrix.xx, pfont->FontMatrix.xy,
867
3.02k
             pfont->FontMatrix.yx, pfont->FontMatrix.yy,
868
3.02k
             pfont->FontMatrix.tx, pfont->FontMatrix.ty);
869
3.02k
    write_uid(s, &pfont->UID, options);
870
3.02k
    pprintg4(s, "/FontBBox {%g %g %g %g} readonly def\n",
871
3.02k
             pfont->FontBBox.p.x, pfont->FontBBox.p.y,
872
3.02k
             pfont->FontBBox.q.x, pfont->FontBBox.q.y);
873
3.02k
    {
874
3.02k
        static const gs_param_item_t font_items[] = {
875
3.02k
            {"FontType", gs_param_type_int,
876
3.02k
             offset_of(gs_font_type1, FontType)},
877
3.02k
            {"PaintType", gs_param_type_int,
878
3.02k
             offset_of(gs_font_type1, PaintType)},
879
3.02k
            {"StrokeWidth", gs_param_type_float,
880
3.02k
             offset_of(gs_font_type1, StrokeWidth)},
881
3.02k
            gs_param_item_end
882
3.02k
        };
883
884
3.02k
        code = gs_param_write_items(plist, pfont, NULL, font_items);
885
3.02k
        if (code < 0)
886
0
            return code;
887
3.02k
    }
888
889
    /*
890
     * This is nonsense. We cna't write the WeightVector alonr from a Multiple
891
     * Master and expect any sensible results. Since its useless alone, there's
892
     * no point in emitting it at all. Leaving the code in place in case we
893
     * decide to write MM fonts one day.
894
    {
895
        const gs_type1_data *const pdata = &pfont->data;
896
897
        write_float_array(plist, "WeightVector", pdata->WeightVector.values,
898
                          pdata->WeightVector.count);
899
    }
900
    */
901
3.02k
    stream_puts(s, "currentdict end\n");
902
903
    /* Write the Private dictionary. */
904
905
3.02k
    if (lenIV < 0 && (options & WRITE_TYPE1_WITH_LENIV)) {
906
        /* We'll have to encrypt the CharStrings. */
907
0
        lenIV = 0;
908
0
        write_CharString = stream_write_encrypted;
909
0
    }
910
3.02k
    if (options & WRITE_TYPE1_EEXEC) {
911
3.02k
        stream_puts(s, "currentfile eexec\n");
912
3.02k
        lengths[0] = (int)(stell(s) - start);
913
3.02k
        start = stell(s);
914
3.02k
        if (options & WRITE_TYPE1_ASCIIHEX) {
915
3.02k
            s_init(&AXE_stream, s->memory);
916
3.02k
            s_init_state((stream_state *)&AXE_state, &s_AXE_template, NULL);
917
3.02k
            s_init_filter(&AXE_stream, (stream_state *)&AXE_state,
918
3.02k
                          AXE_buf, sizeof(AXE_buf), es);
919
            /* We have to set this after s_init_filter() as that function
920
             * sets it to true.
921
             */
922
3.02k
            AXE_state.EndOfData = false;
923
3.02k
            es = &AXE_stream;
924
3.02k
        }
925
3.02k
        s_init(&exE_stream, s->memory);
926
3.02k
        s_init_state((stream_state *)&exE_state, &s_exE_template, NULL);
927
3.02k
        exE_state.cstate = 55665;
928
3.02k
        s_init_filter(&exE_stream, (stream_state *)&exE_state,
929
3.02k
                      exE_buf, sizeof(exE_buf), es);
930
3.02k
        es = &exE_stream;
931
        /*
932
         * Note: eexec encryption always writes/skips 4 initial bytes, not
933
         * the number of initial bytes given by pdata->lenIV.
934
         */
935
3.02k
        stream_puts(es, "****");
936
3.02k
    }
937
3.02k
    code = write_Private(es, pfont, glyphs.subset_glyphs, glyphs.subset_size,
938
3.02k
                         glyphs.notdef, lenIV, write_CharString, &ppp, options);
939
3.02k
    if (code < 0)
940
0
        return code;
941
3.02k
    stream_puts(es, "dup/FontName get exch definefont pop\n");
942
3.02k
    if (options & WRITE_TYPE1_EEXEC) {
943
3.02k
        if (options & (WRITE_TYPE1_EEXEC_PAD | WRITE_TYPE1_EEXEC_MARK))
944
3.02k
            stream_puts(es, "mark ");
945
3.02k
        stream_puts(es, "currentfile closefile\n");
946
3.02k
        s_close_filters(&es, s);
947
3.02k
        lengths[1] = (int)(stell(s) - start);
948
3.02k
        start = stell(s);
949
3.02k
        if (options & WRITE_TYPE1_EEXEC_PAD) {
950
3.02k
            int i;
951
952
27.2k
            for (i = 0; i < 8; ++i)
953
24.2k
                stream_puts(s, "\n0000000000000000000000000000000000000000000000000000000000000000");
954
3.02k
            stream_puts(s, "\ncleartomark\n");
955
3.02k
        }
956
3.02k
        lengths[2] = (int)(stell(s) - start);
957
3.02k
    } else {
958
0
        lengths[0] = (int)(stell(s) - start);
959
0
        lengths[1] = lengths[2] = 0;
960
0
    }
961
962
    /* Wrap up. */
963
964
3.02k
    s_release_param_printer(&rlist);
965
3.02k
    return 0;
966
3.02k
}