Coverage Report

Created: 2025-11-16 07:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/devices/vector/gdevpsft.c
Line
Count
Source
1
/* Copyright (C) 2001-2024 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
/* Write an embedded TrueType font */
18
#include "memory_.h"
19
#include <stdlib.h>   /* for qsort */
20
#include <math.h>   /* for floor */
21
#include "gx.h"
22
#include "gscencs.h"
23
#include "gserrors.h"
24
#include "gsmatrix.h"
25
#include "gsutil.h"
26
#include "gxfcid.h"
27
#include "gxfont.h"
28
#include "gxfont42.h"
29
#include "gxttf.h"
30
#include "stream.h"
31
#include "spprint.h"
32
#include "gdevpsf.h"
33
34
/* Internally used options */
35
140k
#define WRITE_TRUETYPE_STRIPPED 0x1000  /* internal */
36
160k
#define WRITE_TRUETYPE_CID 0x2000 /* internal */
37
38
#define MAX_COMPOSITE_PIECES 3  /* adhoc */
39
40
/*
41
 * The following are only for debugging.  They force various format choices
42
 * in the output.  The normal (non-debugging) values for all of these are
43
 * as indicated in the comments.
44
 *
45
 * Note that these options interact.  Here is the complete list of settings
46
 * that make sense.
47
        0 -1,0,1  N/A 0,1 0,1
48
        0xf000  -1  N/A 1 0,1
49
        0xf000  0,1 0,1 1 0,1
50
 */
51
/* Define whether to use the 0xf000 character bias for generated tables. */
52
24.7k
#define TT_BIAS 0xf000    /* 0xf000 */
53
/* Define whether to use cmap format 6 never(-1), sometimes(0), always(1). */
54
#define TT_FORCE_CMAP_6 0 /* 0 */
55
/* Define whether to use the bias for the cmap format 6 "first code". */
56
#define TT_BIAS_CMAP_6 0  /* 0 */
57
/* Define whether to generate an OS/2 table if none is supplied. */
58
#define TT_GENERATE_OS_2 1  /* 1 */
59
/* Define whether to adjust the OS/2 range bits. */
60
#define TT_ADJUST_OS_2 1  /* 1 */
61
/*
62
 * End of options.
63
 */
64
65
/* ---------------- Utilities ---------------- */
66
67
/* Pad to a multiple of 4 bytes. */
68
static void
69
put_pad(stream *s, uint length)
70
688k
{
71
688k
    static const byte pad_to_4[3] = {0, 0, 0};
72
73
688k
    stream_write(s, pad_to_4, (uint)(-(int)length & 3));
74
688k
}
75
76
/* Put short and long values on a stream. */
77
static void
78
put_ushort(stream *s, uint v)
79
61.2M
{
80
61.2M
    stream_putc(s, (byte)(v >> 8));
81
61.2M
    stream_putc(s, (byte)v);
82
61.2M
}
83
static void
84
put_short(stream *s, short v)
85
71.7M
{
86
71.7M
    stream_putc(s, (byte)(v >> 8));
87
71.7M
    stream_putc(s, (byte)v);
88
71.7M
}
89
static void
90
put_ulong(stream *s, ulong v)
91
0
{
92
0
    put_ushort(s, (uint)(v >> 16));
93
0
    put_ushort(s, (uint)v);
94
0
}
95
static void
96
put_loca(stream *s, ulong offset, int indexToLocFormat)
97
60.9M
{
98
60.9M
    if (indexToLocFormat)
99
0
        put_ulong(s, offset);
100
60.9M
    else
101
60.9M
        put_ushort(s, (uint)(offset >> 1));
102
60.9M
}
103
104
/* Get or put 2- or 4-byte quantities from/into a table. */
105
#define U8(p) ((uint)((p)[0]))
106
#define S8(p) (int)((U8(p) ^ 0x80) - 0x80)
107
3.21M
#define U16(p) (((uint)((p)[0]) << 8) + (p)[1])
108
#define S16(p) (int)((U16(p) ^ 0x8000) - 0x8000)
109
9.98M
#define u32(p) get_u32_msb(p)
110
static void
111
put_u16(byte *p, uint v)
112
6.48M
{
113
6.48M
    p[0] = (byte)(v >> 8);
114
6.48M
    p[1] = (byte)v;
115
6.48M
}
116
static void
117
put_u32(byte *p, ulong v)
118
1.07M
{
119
1.07M
    put_u16(p, (ushort)(v >> 16));
120
1.07M
    put_u16(p + 2, (ushort)v);
121
1.07M
}
122
static ulong
123
put_table(byte tab[16], const char *tname, ulong checksum, ulong offset,
124
          uint length)
125
122k
{
126
122k
    memcpy(tab, (const byte *)tname, 4);
127
122k
    put_u32(tab + 4, checksum);
128
122k
    put_u32(tab + 8, offset + 0x40000000);
129
122k
    put_u32(tab + 12, (ulong)length);
130
122k
    return offset + round_up(length, 4);
131
122k
}
132
133
/* Write one range of a TrueType font. */
134
static int
135
write_range(stream *s, gs_font_type42 *pfont, ulong start, uint length)
136
634k
{
137
634k
    ulong base = start, size = length;
138
139
634k
    if_debug3m('l', s->memory, "[l]write_range pos = %"PRId64", start = %lu, length = %u\n",
140
634k
               stell(s), start, length);
141
1.25M
    while (size > 0) {
142
634k
        const byte *ptr;
143
634k
        int code;
144
145
634k
        code = pfont->data.string_proc(pfont, base, size, &ptr);
146
634k
        if (code < 0)
147
13.7k
            return code;
148
620k
        if (!code)
149
620k
            code = size;
150
620k
        stream_write(s, ptr, code);
151
620k
        base += code;
152
620k
        size -= code;
153
620k
    }
154
620k
    return 0;
155
634k
}
156
157
/*
158
 * Determine the Macintosh glyph number for a given character, if any.
159
 * If no glyph can be found, return -1 and store the name in *pstr.
160
 */
161
static int
162
mac_glyph_index(gs_font *font, int ch, gs_const_string *pstr, int *index)
163
0
{
164
0
    gs_glyph glyph = font->procs.encode_char(font, (gs_char)ch,
165
0
                                             GLYPH_SPACE_NAME);
166
0
    int code;
167
168
0
    if (glyph == GS_NO_GLYPH) {
169
0
        *index = 0;
170
0
        return 0;   /* .notdef */
171
0
    }
172
0
    code = font->procs.glyph_name(font, glyph, pstr);
173
0
    if (code < 0)
174
0
        return code;
175
0
    if (glyph < GS_MIN_CID_GLYPH) {
176
0
        gs_char mac_char;
177
0
        gs_glyph mac_glyph;
178
0
        gs_const_string mstr;
179
180
        /* Look (not very hard) for a match in the Mac glyph space. */
181
0
        if (ch >= 32 && ch <= 126)
182
0
            mac_char = ch - 29;
183
0
        else if (ch >= 128 && ch <= 255)
184
0
            mac_char = ch - 30;
185
0
        else {
186
0
            *index = -1;
187
0
            return 0;
188
0
        }
189
0
        mac_glyph = gs_c_known_encode(mac_char, ENCODING_INDEX_MACGLYPH);
190
0
        if (mac_glyph == GS_NO_GLYPH) {
191
0
            *index = -1;
192
0
            return 0;
193
0
        }
194
0
        code = gs_c_glyph_name(mac_glyph, &mstr);
195
0
        if (code < 0)
196
0
            return code;
197
0
        if (!bytes_compare(pstr->data, pstr->size, mstr.data, mstr.size)) {
198
0
            *index = (int)mac_char;
199
0
            return 0;
200
0
        }
201
0
    }
202
0
    *index = -1;
203
0
    return 0;
204
0
}
205
206
/* ---------------- Individual tables ---------------- */
207
208
/* ------ cmap ------ */
209
210
/* Write a generated cmap table. */
211
static const byte cmap_initial_0[] = {
212
    0, 0,   /* table version # = 0 */
213
    0, 2,   /* # of encoding tables = 2 */
214
215
        /* First table, Macintosh */
216
    0, 1,   /* platform ID = Macintosh */
217
    0, 0,   /* platform encoding ID = ??? */
218
    0, 0, 0, 4+8+8, /* offset to table start */
219
        /* Second table, Windows */
220
    0, 3,   /* platform ID = Microsoft */
221
    0, 0,   /* platform encoding ID = unknown */
222
    0, 0, 1, 4+8+8+6, /* offset to table start */
223
224
        /* Start of Macintosh format 0 table */
225
    0, 0,   /* format = 0, byte encoding table */
226
    1, 6,   /* length */
227
    0, 0    /* version number */
228
};
229
static const byte cmap_initial_6[] = {
230
    0, 0,   /* table version # = 0 */
231
    0, 2,   /* # of encoding tables = 2 */
232
233
        /* First table, Macintosh */
234
    0, 1,   /* platform ID = Macintosh */
235
    0, 0,   /* platform encoding ID = ??? */
236
    0, 0, 0, 4+8+8, /* offset to table start */
237
        /* Second table, Windows */
238
    0, 3,   /* platform ID = Microsoft */
239
    0, 0,   /* platform encoding ID = unknown */
240
    0, 0, 0, 4+8+8+10,  /* offset to table start */
241
                        /* *VARIABLE*, add 2 x # of entries */
242
243
        /* Start of Macintosh format 6 table */
244
    0, 6,   /* format = 6, trimmed table mapping */
245
    0, 10,    /* length *VARIABLE*, add 2 x # of entries */
246
    0, 0,   /* version number */
247
    0, 0,   /* first character code */
248
    0, 0    /* # of entries *VARIABLE* */
249
};
250
static const byte cmap_unicode_initial_6[] = {
251
    0, 0,   /* table version # = 0 */
252
    0, 2,   /* # of encoding tables = 2 */
253
254
        /* First table, Macintosh */
255
    0, 1,   /* platform ID = Macintosh */
256
    0, 0,   /* platform encoding ID = ??? */
257
    0, 0, 0, 4+8+8, /* offset to table start */
258
        /* Second table, Windows */
259
    0, 3,   /* platform ID = Microsoft */
260
    0, 1,   /* platform encoding ID = Unicode */
261
    0, 0, 0, 4+8+8+10,  /* offset to table start */
262
                        /* *VARIABLE*, add 2 x # of entries */
263
264
        /* Start of Macintosh format 6 table */
265
    0, 6,   /* format = 6, trimmed table mapping */
266
    0, 10,    /* length *VARIABLE*, add 2 x # of entries */
267
    0, 0,   /* version number */
268
    0, 0,   /* first character code */
269
    0, 0    /* # of entries *VARIABLE* */
270
};
271
static const byte cmap_initial_4[] = {
272
    0, 0,   /* table version # = 0 */
273
    0, 1,   /* # of encoding tables = 2 */
274
275
        /* Single table, Windows */
276
    0, 3,   /* platform ID = Microsoft */
277
    0, 0,   /* platform encoding ID = unknown */
278
    0, 0, 0, 4+8  /* offset to table start */
279
};
280
static const byte cmap_sub_initial[] = {
281
    0, 4,   /* format = 4, segment mapping */
282
    0, 32,    /* length ** VARIABLE, add 2 x # of glyphs ** */
283
    0, 0,   /* version # */
284
    0, 4,   /* 2 x segCount */
285
    0, 4,   /* searchRange = 2 x 2 ^ floor(log2(segCount)) */
286
    0, 1,   /* floor(log2(segCount)) */
287
    0, 0,   /* 2 x segCount - searchRange */
288
289
    0, 0,   /* endCount[0] **VARIABLE** */
290
    255, 255,   /* endCount[1] */
291
    0, 0,   /* reservedPad */
292
    0, 0,   /* startCount[0] **VARIABLE** */
293
    255, 255,   /* startCount[1] */
294
    0, 0,   /* idDelta[0] */
295
    0, 1,   /* idDelta[1] */
296
    0, 4,   /* idRangeOffset[0] */
297
    0, 0    /* idRangeOffset[1] */
298
};
299
/*
300
 * The following nonsense is required because C defines sizeof()
301
 * inconsistently.
302
 */
303
14.5k
#define CMAP_ENTRIES_SIZE (256 * 2)
304
static void
305
write_cmap_0(stream *s, byte* entries /*[CMAP_ENTRIES_SIZE]*/, uint num_glyphs)
306
14.5k
{
307
14.5k
    int i;
308
309
14.5k
    if (CMAP_ENTRIES_SIZE - 2 * num_glyphs>0)
310
0
      memset(entries + 2 * num_glyphs, 0, CMAP_ENTRIES_SIZE - 2 * num_glyphs);
311
14.5k
    stream_write(s, cmap_initial_0, sizeof(cmap_initial_0));
312
3.74M
    for (i = 0; i <= 0xff; ++i)
313
3.73M
        sputc(s, (byte)entries[2 * i + 1]);
314
14.5k
}
315
static void
316
write_cmap_6(stream *s, byte *entries /*[CMAP_ENTRIES_SIZE]*/, uint first_code,
317
             uint first_entry, uint num_entries)
318
1.58k
{
319
1.58k
    byte cmap_data[sizeof(cmap_initial_6)];
320
321
1.58k
    memcpy(cmap_data, cmap_initial_6, sizeof(cmap_initial_6));
322
1.58k
    put_u16(cmap_data + 18,
323
1.58k
            U16(cmap_data + 18) + num_entries * 2);  /* offset */
324
1.58k
    put_u16(cmap_data + 22,
325
1.58k
            U16(cmap_data + 22) + num_entries * 2);  /* length */
326
1.58k
    put_u16(cmap_data + 26,
327
#if TT_BIAS_CMAP_6
328
            first_code +
329
#endif
330
1.58k
            first_entry);
331
1.58k
    put_u16(cmap_data + 28, num_entries);
332
1.58k
    stream_write(s, cmap_data, sizeof(cmap_data));
333
1.58k
    stream_write(s, entries + first_entry * 2, num_entries * 2);
334
1.58k
}
335
static void write_unicode_cmap_6(stream *s, byte *entries, uint first_code,
336
             uint first_entry, uint num_entries)
337
0
{
338
0
    byte cmap_data[sizeof(cmap_unicode_initial_6)];
339
340
0
    memcpy(cmap_data, cmap_unicode_initial_6, sizeof(cmap_unicode_initial_6));
341
0
    put_u16(cmap_data + 18,
342
0
            U16(cmap_data + 18) + num_entries * 2);  /* offset */
343
0
    put_u16(cmap_data + 22,
344
0
            U16(cmap_data + 22) + num_entries * 2);  /* length */
345
0
    put_u16(cmap_data + 26, first_entry);
346
0
    put_u16(cmap_data + 28, num_entries);
347
0
    stream_write(s, cmap_data, sizeof(cmap_data));
348
0
    stream_write(s, entries + first_entry * 2, num_entries * 2);
349
0
}
350
static void
351
write_cmap(stream *s, gs_font *font, uint first_code, int num_glyphs,
352
           gs_glyph max_glyph, int options, uint cmap_length)
353
16.5k
{
354
16.5k
    byte cmap_sub[sizeof(cmap_sub_initial)];
355
16.5k
    byte entries[CMAP_ENTRIES_SIZE];
356
16.5k
    int first_entry = 0, end_entry = num_glyphs;
357
16.5k
    bool can_use_trimmed = !(options & WRITE_TRUETYPE_NO_TRIMMED_TABLE);
358
16.5k
    uint merge = 0;
359
16.5k
    uint num_entries;
360
16.5k
    int i;
361
362
    /* Collect the table entries. */
363
364
4.24M
    for (i = 0; i < num_glyphs; ++i) {
365
4.22M
        gs_glyph glyph =
366
4.22M
            font->procs.encode_char(font, (gs_char)i, GLYPH_SPACE_INDEX);
367
4.22M
        uint glyph_index;
368
369
4.22M
        if (glyph == GS_NO_GLYPH || glyph < GS_MIN_GLYPH_INDEX ||
370
394k
            glyph > max_glyph
371
4.22M
            )
372
3.83M
            glyph = GS_MIN_GLYPH_INDEX;
373
4.22M
        glyph_index = (uint)(glyph - GS_MIN_GLYPH_INDEX);
374
4.22M
        merge |= glyph_index;
375
4.22M
        put_u16(entries + 2 * i, glyph_index);
376
4.22M
    }
377
2.41M
    while (end_entry > first_entry && !U16(entries + 2 * end_entry - 2))
378
2.39M
        --end_entry;
379
631k
    while (first_entry < end_entry && !U16(entries + 2 * first_entry))
380
615k
        ++first_entry;
381
16.5k
    num_entries = end_entry - first_entry;
382
383
    /* Write the table header and Macintosh sub-table (if any). */
384
385
16.5k
    if (options & WRITE_TRUETYPE_UNICODE_CMAP) {
386
0
        write_unicode_cmap_6(s, entries, first_code, first_entry, num_entries);
387
388
        /* Write the Windows sub-table. */
389
0
        memcpy(cmap_sub, cmap_sub_initial, sizeof(cmap_sub_initial));
390
0
        put_u16(cmap_sub + 2, U16(cmap_sub + 2) + num_entries * 2); /* length */
391
0
        put_u16(cmap_sub + 14, end_entry - 1); /* endCount[0] */
392
0
        put_u16(cmap_sub + 20, first_entry); /* startCount[0] */
393
0
        stream_write(s, cmap_sub, sizeof(cmap_sub));
394
0
        stream_write(s, entries + first_entry * 2, num_entries * 2);
395
0
        put_pad(s, cmap_length);
396
0
        return;
397
0
    }
398
#if TT_FORCE_CMAP_6 > 0
399
    /* Always use format 6. */
400
    write_cmap_6(s, entries, first_code, first_entry, num_entries);
401
#else
402
# if TT_FORCE_CMAP_6 < 0
403
    /* Never use format 6.  Use format 0 if possible. */
404
    if (merge == (byte)merge)
405
        write_cmap_0(s, entries, num_glyphs);
406
    else
407
# else /* TT_FORCE_CMAP == 0 */
408
    /*
409
     * Use format 0 if possible and (economical or format 6 disallowed),
410
     * otherwise format 6 if allowed.
411
     */
412
16.5k
    if (merge == (byte)merge && (num_entries <= 127 || !can_use_trimmed))
413
14.5k
        write_cmap_0(s, entries, num_glyphs);
414
1.92k
    else if (can_use_trimmed)
415
1.58k
        write_cmap_6(s, entries, first_code, first_entry, num_entries);
416
340
    else
417
340
# endif
418
340
    {
419
        /*
420
         * Punt.  Acrobat Reader 3 can't handle any other Mac table format.
421
         * (AR3 for Linux doesn't seem to be able to handle Windows format,
422
         * either, but maybe AR3 for Windows can.)
423
         */
424
340
        stream_write(s, cmap_initial_4, sizeof(cmap_initial_4));
425
340
    }
426
16.5k
#endif
427
428
    /* Write the Windows sub-table. */
429
430
16.5k
    memcpy(cmap_sub, cmap_sub_initial, sizeof(cmap_sub_initial));
431
16.5k
    put_u16(cmap_sub + 2, U16(cmap_sub + 2) + num_entries * 2); /* length */
432
16.5k
    put_u16(cmap_sub + 14, first_code + end_entry - 1); /* endCount[0] */
433
16.5k
    put_u16(cmap_sub + 20, first_code + first_entry); /* startCount[0] */
434
16.5k
    stream_write(s, cmap_sub, sizeof(cmap_sub));
435
16.5k
    stream_write(s, entries + first_entry * 2, num_entries * 2);
436
16.5k
    put_pad(s, cmap_length);
437
16.5k
}
438
static uint
439
size_cmap(gs_font *font, uint first_code, int num_glyphs, gs_glyph max_glyph,
440
          int options)
441
8.25k
{
442
8.25k
    stream poss;
443
444
8.25k
    s_init(&poss, NULL);
445
8.25k
    swrite_position_only(&poss);
446
8.25k
    write_cmap(&poss, font, first_code, num_glyphs, max_glyph, options, 0);
447
8.25k
    return stell(&poss);
448
8.25k
}
449
450
/* ------ hmtx/vmtx ------ */
451
452
/* We must include mtx data for every single glyph, even if we don't
453
 * actually write the glyph data. If we don't, the font will be invalid (cf bug 697376)
454
 * We also must not simply copy the table from the original font, because its possible
455
 * that we are combining two different fonts, and the metrics in each font may not
456
 * be the same (or at least, not in the same position) cf bug 700099.
457
 * Originally we only wrote the metrics for the glyphs we copy, then we disabled
458
 * generat_mtx so that we copied the table. This solution; generating all the metrics
459
 * we need and dummies for the glyphs we don't actually embed, works best so far.
460
 */
461
static void
462
write_mtx(stream *s, gs_font_type42 *pfont, const gs_type42_mtx_t *pmtx,
463
          int wmode)
464
9.79k
{
465
9.79k
    uint num_metrics = pmtx->numMetrics;
466
9.79k
    uint len = num_metrics * 4;
467
9.79k
    double factor = (double)pfont->data.unitsPerEm * (wmode ? -1 : 1);
468
9.79k
    float sbw[4];
469
9.79k
    uint i;
470
471
9.79k
    sbw[0] = sbw[1] = sbw[2] = sbw[3] = 0; /* in case of failures */
472
5.56M
    for (i = 0; i < pmtx->numMetrics; ++i) {
473
5.55M
        float f;
474
5.55M
        DISCARD(pfont->data.get_metrics(pfont, i, wmode, sbw));
475
        /* the temporary assignment to a float is necessary for AIX else the result is always 0 if sbw[] < 0
476
           this happens even with gcc and I'm not sure why it happens at all nor why only on AIX */
477
5.55M
        f = (float) (sbw[wmode + 2] * factor); /* width */
478
5.55M
        put_short(s, (short) floor(f + 0.5));
479
5.55M
        f = (float) (sbw[wmode] * factor); /* lsb, may be <0 */
480
5.55M
        put_short(s, (short) floor(f + 0.5));
481
5.55M
    }
482
60.6M
    for (; len < pmtx->length; ++i, len += 2) {
483
60.5M
        float f;
484
60.5M
        DISCARD(pfont->data.get_metrics(pfont, i, wmode, sbw));
485
60.5M
        f = (float) (sbw[wmode] * factor); /* lsb, may be <0 */
486
60.5M
        put_short(s, (short) floor(f + 0.5));
487
60.5M
    }
488
9.79k
}
489
490
/* Compute the metrics from the glyph_info. */
491
static uint
492
size_mtx(gs_font_type42 *pfont, gs_type42_mtx_t *pmtx, uint max_glyph, uint numGlyphs,
493
         int wmode)
494
9.79k
{
495
9.79k
    int prev_width = min_int;
496
9.79k
    uint last_width = 0; /* pacify compilers */
497
9.79k
    double factor = pfont->data.unitsPerEm * (wmode ? -1 : 1);
498
9.79k
    uint i;
499
500
10.7M
    for (i = 0; i <= max_glyph; ++i) {
501
10.7M
        float sbw[4];
502
10.7M
        int code = pfont->data.get_metrics(pfont, i, wmode, sbw);
503
10.7M
        int width;
504
505
10.7M
        if (code < 0)
506
10.5M
            continue;
507
238k
        width = (int)(sbw[wmode + 2] * factor + 0.5);
508
238k
        if (width != prev_width)
509
179k
            prev_width = width, last_width = i;
510
238k
    }
511
9.79k
    pmtx->numMetrics = last_width + 1;
512
9.79k
    pmtx->length = pmtx->numMetrics * 4 + (max_glyph - last_width) * 2;
513
9.79k
    pmtx->length += (numGlyphs - pmtx->numMetrics) * 2;
514
9.79k
    return pmtx->length;
515
9.79k
}
516
517
/* ------ name ------ */
518
519
/* Write a generated name table. */
520
static const byte name_initial[] = {
521
    0, 0,     /* format */
522
    0, 1,     /* # of records = 1 */
523
    0, 18,      /* start of string storage */
524
525
    0, 2,     /* platform ID = ISO */
526
    0, 2,     /* encoding ID = ISO 8859-1 */
527
    0, 0,     /* language ID (none) */
528
    0, 6,     /* name ID = PostScript name */
529
    0, 0,     /* length *VARIABLE* */
530
    0, 0      /* start of string within string storage */
531
};
532
static uint
533
size_name(const gs_const_string *font_name)
534
360
{
535
360
    return sizeof(name_initial) + font_name->size;
536
360
}
537
static void
538
write_name(stream *s, const gs_const_string *font_name)
539
180
{
540
180
    byte name_bytes[sizeof(name_initial)];
541
542
180
    memcpy(name_bytes, name_initial, sizeof(name_initial));
543
180
    put_u16(name_bytes + 14, font_name->size);
544
180
    stream_write(s, name_bytes, sizeof(name_bytes));
545
180
    stream_write(s, font_name->data, font_name->size);
546
180
    put_pad(s, size_name(font_name));
547
180
}
548
549
/* ------ OS/2 ------ */
550
551
/* Write a generated OS/2 table. */
552
74.9k
#define OS_2_LENGTH1 offset_of(ttf_OS_2_t, sxHeight[0]) /* OS/2 version 1. */
553
#define OS_2_LENGTH2 offset_of(ttf_OS_2_t, usLowerOpticalPointSize[0]) /* OS/2 version 2. */
554
48.8k
#define OS_2_LENGTH5 sizeof(ttf_OS_2_t) /* OS/2 version 5 (OpenType 1.7) */
555
556
static void
557
update_OS_2(ttf_OS_2_t *pos2, uint first_glyph, int num_glyphs)
558
8.25k
{
559
8.25k
    put_u16(pos2->usFirstCharIndex, first_glyph);
560
8.25k
    put_u16(pos2->usLastCharIndex, first_glyph + num_glyphs - 1);
561
8.25k
#if TT_ADJUST_OS_2
562
8.25k
    if (first_glyph >= 0xf000) {
563
        /* This font is being treated as a symbolic font. */
564
8.25k
        memset(pos2->ulUnicodeRanges, 0, sizeof(pos2->ulUnicodeRanges));
565
8.25k
        pos2->ulUnicodeRanges[7] = 8; /* bit 60, private use range */
566
8.25k
        memset(pos2->ulCodePageRanges, 0, sizeof(pos2->ulCodePageRanges));
567
8.25k
        pos2->ulCodePageRanges[3] = 1; /* bit 31, symbolic */
568
8.25k
    }
569
8.25k
#endif
570
8.25k
}
571
static void
572
write_OS_2(stream *s, gs_font *font, uint first_glyph, int num_glyphs)
573
8.25k
{
574
8.25k
    ttf_OS_2_t os2;
575
8.25k
    gs_font_info_t info;
576
8.25k
    int code;
577
578
    /*
579
     * We don't bother to set most of the fields.  The really important
580
     * ones, which affect character mapping, are usFirst/LastCharIndex.
581
     * We also need to set usWeightClass and usWidthClass to avoid
582
     * crashing ttfdump. Version 1 86-byte structure has all the fields
583
     * we need.
584
     */
585
8.25k
    memset(&os2, 0, sizeof(os2));
586
8.25k
    put_u16(os2.version, 1);
587
8.25k
    put_u16(os2.usWeightClass, 400); /* Normal */
588
8.25k
    put_u16(os2.usWidthClass, 5); /* Normal */
589
8.25k
    update_OS_2(&os2, first_glyph, num_glyphs);
590
591
    /*
592
     * We should also preserve the licensed embedding rights, to prevent
593
     * 'laundering' a TrueType font. These can be non-zero even when embedding is permitted.
594
     */
595
8.25k
    memset(&info, 0x00, sizeof(gs_font_info_t));
596
8.25k
    code = font->procs.font_info(font, NULL, FONT_INFO_EMBEDDING_RIGHTS, &info);
597
8.25k
    if (code == 0 && (info.members & FONT_INFO_EMBEDDING_RIGHTS)) {
598
5.43k
        put_u16(os2.fsType, info.EmbeddingRights);
599
5.43k
    }
600
601
8.25k
    stream_write(s, &os2, offset_of(ttf_OS_2_t, sxHeight[0]));
602
8.25k
    put_pad(s, offset_of(ttf_OS_2_t, sxHeight[0]));
603
8.25k
}
604
605
/* ------ post ------ */
606
607
/* Construct and then write the post table. */
608
typedef struct post_glyph_s {
609
    byte char_index;
610
    byte size;
611
    ushort glyph_index;
612
} post_glyph_t;
613
static int
614
compare_post_glyphs(const void *pg1, const void *pg2)
615
0
{
616
0
    gs_glyph g1 = ((const post_glyph_t *)pg1)->glyph_index,
617
0
        g2 = ((const post_glyph_t *)pg2)->glyph_index;
618
619
0
    return (g1 < g2 ? -1 : g1 > g2 ? 1 : 0);
620
0
}
621
typedef struct post_s {
622
    post_glyph_t glyphs[256 + 1];
623
    int count, glyph_count;
624
    uint length;
625
} post_t;
626
627
/*
628
 * If necessary, compute the length of the post table.  Note that we
629
 * only generate post entries for characters in the Encoding.
630
 */
631
static int
632
compute_post(gs_font *font, post_t *post)
633
0
{
634
0
    int i;
635
636
0
    for (i = 0, post->length = 32 + 2; i <= 255; ++i) {
637
0
        gs_const_string str;
638
0
        gs_glyph glyph = font->procs.encode_char(font, (gs_char)i,
639
0
                                                 GLYPH_SPACE_INDEX);
640
0
        int mac_index;
641
642
0
        int code = mac_glyph_index(font, i, &str, &mac_index);
643
0
        if (code < 0)
644
0
            return code;
645
0
        if (mac_index != 0) {
646
0
            post->glyphs[post->count].char_index = i;
647
0
            post->glyphs[post->count].size =
648
0
                (mac_index < 0 ? str.size + 1 : 0);
649
0
            post->glyphs[post->count].glyph_index = glyph - GS_MIN_GLYPH_INDEX;
650
0
            post->count++;
651
0
        }
652
0
    }
653
0
    if (post->count) {
654
0
        int j;
655
656
0
        qsort(post->glyphs, post->count, sizeof(post->glyphs[0]),
657
0
              compare_post_glyphs);
658
        /* Eliminate duplicate references to the same glyph. */
659
0
        for (i = j = 0; i < post->count; ++i) {
660
0
            if (i == 0 ||
661
0
                post->glyphs[i].glyph_index !=
662
0
                post->glyphs[i - 1].glyph_index
663
0
                ) {
664
0
                post->length += post->glyphs[i].size;
665
0
                post->glyphs[j++] = post->glyphs[i];
666
0
            }
667
0
        }
668
0
        post->count = j;
669
0
        post->glyph_count = post->glyphs[post->count - 1].glyph_index + 1;
670
0
    }
671
0
    post->length += post->glyph_count * 2;
672
0
    return 0;
673
0
}
674
675
/* Write the post table */
676
static int
677
write_post(stream *s, gs_font *font, post_t *post)
678
0
{
679
0
    byte post_initial[32 + 2];
680
0
    uint name_index;
681
0
    uint glyph_index;
682
0
    int i;
683
684
0
    memset(post_initial, 0, 32);
685
0
    put_u32(post_initial, 0x00020000);
686
0
    put_u16(post_initial + 32, post->glyph_count);
687
0
    stream_write(s, post_initial, sizeof(post_initial));
688
689
    /* Write the name index table. */
690
691
0
    for (i = 0, name_index = 258, glyph_index = 0; i < post->count; ++i) {
692
0
        gs_const_string str;
693
0
        int ch = post->glyphs[i].char_index;
694
0
        int mac_index;
695
0
        int code = mac_glyph_index(font, ch, &str, &mac_index);
696
697
0
        if (code < 0)
698
0
            return code;
699
0
        for (; glyph_index < post->glyphs[i].glyph_index; ++glyph_index)
700
0
            put_ushort(s, 0);
701
0
        glyph_index++;
702
0
        if (mac_index >= 0)
703
0
            put_ushort(s, mac_index);
704
0
        else {
705
0
            put_ushort(s, name_index);
706
0
            name_index++;
707
0
        }
708
0
    }
709
710
    /* Write the string names of the glyphs. */
711
712
0
    for (i = 0; i < post->count; ++i) {
713
0
        gs_const_string str;
714
0
        int ch = post->glyphs[i].char_index;
715
0
        int mac_index;
716
0
        int code = mac_glyph_index(font, ch, &str, &mac_index);
717
718
0
        if (code < 0)
719
0
            return code;
720
0
        if (mac_index < 0) {
721
0
            spputc(s, (byte)str.size);
722
0
            stream_write(s, str.data, str.size);
723
0
        }
724
0
    }
725
0
    put_pad(s, post->length);
726
0
    return 0;
727
0
}
728
729
static inline bool check_position(const gs_memory_t *mem, gs_offset_t pos1, gs_offset_t pos2)
730
122k
{
731
122k
    if (pos1 == pos2)
732
110k
        return false;
733
11.8k
    emprintf2(mem,
734
11.8k
              "Actual TT subtable offset %"PRId64" differs from one in the TT header %"PRId64".\n",
735
11.8k
              pos1,
736
11.8k
              pos2);
737
11.8k
    return true;
738
122k
}
739
740
static void remove_table(byte *tables, char *tag, uint *numTables)
741
132
{
742
    /* Not a high performance implementation because it is called seldom. */
743
132
    int i;
744
745
1.05k
    for (i = 0; i < *numTables;) {
746
924
        byte *tab = tables + i * 16;
747
748
924
        if (!memcmp(tab, tag, 4)) {
749
0
            memmove(tab, tab + 16, 16 * (*numTables - i - 1));
750
0
            --*numTables;
751
0
        } else
752
924
            ++i;
753
924
    }
754
132
}
755
756
/* ---------------- Main program ---------------- */
757
758
/* Write the definition of a TrueType font. */
759
static int
760
compare_table_tags(const void *pt1, const void *pt2)
761
1.44M
{
762
1.44M
    ulong t1 = u32(pt1), t2 = u32(pt2);
763
764
1.44M
    return (t1 < t2 ? -1 : t1 > t2 ? 1 : 0);
765
1.44M
}
766
static int
767
psf_write_truetype_data(stream *s, gs_font_type42 *pfont, int options,
768
                        psf_glyph_enum_t *penum, bool is_subset,
769
                        const gs_const_string *alt_font_name)
770
74.9k
{
771
74.9k
    gs_font *const font = (gs_font *)pfont;
772
74.9k
    gs_type42_data *d0 = &pfont->data;
773
74.9k
    gs_const_string font_name;
774
74.9k
    byte OffsetTable[12];
775
74.9k
    uint numTables_stored, numTables, numTables_out;
776
74.9k
    byte tables[MAX_NUM_TT_TABLES * 16];
777
74.9k
    uint i;
778
74.9k
    ulong offset;
779
74.9k
    gs_glyph glyph, glyph_prev;
780
74.9k
    ulong max_glyph;
781
74.9k
    uint glyf_length, loca_length;
782
74.9k
    ulong glyf_checksum = 0L; /****** NO CHECKSUM ******/
783
74.9k
    ulong loca_checksum[2] = {0L,0L};
784
74.9k
    ulong glyf_alignment = 0;
785
74.9k
    uint numGlyphs = 0;   /* original value from maxp */
786
74.9k
    byte head[56];    /* 0 mod 4 */
787
74.9k
    gs_type42_mtx_t mtx[2];
788
74.9k
    post_t post;
789
74.9k
    ulong head_checksum, file_checksum = 0;
790
74.9k
    int indexToLocFormat = 0;
791
74.9k
    bool
792
74.9k
        writing_cid = (options & WRITE_TRUETYPE_CID) != 0,
793
74.9k
        writing_stripped = (options & WRITE_TRUETYPE_STRIPPED) != 0,
794
74.9k
        generate_mtx = (options & WRITE_TRUETYPE_HVMTX) != 0,
795
74.9k
        no_generate = writing_cid | writing_stripped,
796
74.9k
        have_cmap = no_generate,
797
74.9k
        have_name = !(options & WRITE_TRUETYPE_NAME),
798
74.9k
        have_OS_2 = no_generate,
799
74.9k
        have_post = no_generate;
800
74.9k
    int have_hvhea[2];
801
74.9k
    uint cmap_length = 0;
802
74.9k
    ulong OS_2_start = 0;
803
74.9k
    uint OS_2_length = OS_2_LENGTH1;
804
74.9k
    ulong maxp_start = 0;
805
74.9k
    struct { int glyf, loca, cmap, name, os_2, mtx[2], post, head;
806
74.9k
           } subtable_positions;
807
74.9k
    gs_offset_t start_position = stell(s);
808
74.9k
    int enlarged_numGlyphs = 0;
809
74.9k
    int code;
810
74.9k
    int TTCFontOffset = 0;
811
812
74.9k
    memset(&subtable_positions, 0, sizeof(subtable_positions));
813
74.9k
    have_hvhea[0] = have_hvhea[1] = 0;
814
74.9k
    if (alt_font_name)
815
9.80k
        font_name = *alt_font_name;
816
65.1k
    else
817
65.1k
        font_name.data = font->font_name.chars,
818
65.1k
            font_name.size = font->font_name.size;
819
820
    /*
821
     * Count the number of tables, including the eventual glyf and loca
822
     * (which may not actually be present in the font), and copy the
823
     * table directory.
824
     */
825
826
74.9k
#define W(a,b,c,d)\
827
2.04M
  ( ((a) << 24) + ((b) << 16) + ((c) << 8) + (d))
828
829
74.9k
    TTCFontOffset = d0->subfontOffset;
830
74.9k
    READ_SFNTS(pfont, TTCFontOffset, 12, OffsetTable);
831
74.9k
    numTables_stored = U16(OffsetTable + 4);
832
1.00M
    for (i = numTables = 0; i < numTables_stored; ++i) {
833
933k
        byte tab[16];
834
933k
        byte data[54];
835
933k
        ulong start;
836
933k
        uint length;
837
838
933k
        if (numTables == MAX_NUM_TT_TABLES)
839
0
            return_error(gs_error_limitcheck);
840
933k
        READ_SFNTS(pfont, TTCFontOffset + 12 + i * 16, 16, tab);
841
933k
        start = u32(tab + 8);
842
933k
        length = u32(tab + 12);
843
        /* Copy the table data now (a rudiment of old code). */
844
933k
        memcpy(&tables[numTables * 16], tab, 16);
845
933k
        switch (u32(tab)) {
846
74.9k
        case W('h','e','a','d'):
847
74.9k
            if (length < 54)
848
0
                return_error(gs_error_invalidfont);
849
74.9k
            length = 54; /* bug 688409 fig2.eps has length=56. */
850
74.9k
            READ_SFNTS(pfont, start, length, data);
851
74.9k
            memcpy(head, data, length);
852
74.9k
            continue;
853
65.1k
        case W('g','l','y','f'): /* synthesized */
854
65.1k
        case W('g','l','y','x'): /* Adobe bogus */
855
130k
        case W('l','o','c','a'): /* synthesized */
856
130k
        case W('l','o','c','x'): /* Adobe bogus */
857
130k
        case W('g','d','i','r'): /* Adobe marker */
858
130k
            continue;
859
69.7k
        case W('c','m','a','p'):
860
69.7k
            if (options & (WRITE_TRUETYPE_CMAP | WRITE_TRUETYPE_CID))
861
12.3k
                continue;
862
57.3k
            have_cmap = true;
863
57.3k
            break;
864
74.5k
        case W('m','a','x','p'):
865
74.5k
            READ_SFNTS(pfont, start, length, data);
866
74.4k
            numGlyphs = U16(data + 4);
867
74.4k
            maxp_start = start;
868
74.4k
            break;
869
69.8k
        case W('n','a','m','e'):
870
69.8k
            if (writing_cid)
871
4.95k
                continue;
872
64.9k
            have_name = true;
873
64.9k
            break;
874
53.5k
        case W('O','S','/','2'):
875
53.5k
            if (writing_cid)
876
4.72k
                continue;
877
48.8k
            have_OS_2 = true;
878
48.8k
            if (length > OS_2_LENGTH5)
879
0
                return_error(gs_error_invalidfont);
880
48.8k
            OS_2_start = start;
881
48.8k
            OS_2_length = length;
882
48.8k
            continue;
883
68.0k
        case W('p','o','s','t'):
884
68.0k
            have_post = true;
885
68.0k
            break;
886
74.9k
        case W('h','h','e','a'):
887
74.9k
            have_hvhea[0] = 1;
888
74.9k
            break;
889
0
        case W('v','h','e','a'):
890
0
            have_hvhea[1] = 1;
891
0
            break;
892
74.7k
        case W('h','m','t','x'):
893
74.7k
        case W('v','m','t','x'):
894
74.7k
            if (generate_mtx)
895
9.78k
                continue;
896
            /* falls through */
897
139k
        case W('c','v','t',' '):
898
213k
        case W('f','p','g','m'):
899
286k
        case W('p','r','e','p'):
900
286k
            break;    /* always copy these if present */
901
744
        case W('D','S','I','G'):
902
822
        case W('E','B','D','T'):
903
900
        case W('E','B','L','C'):
904
900
        case W('E','B','S','C'):
905
1.57k
        case W('G','D','E','F'):
906
1.98k
        case W('G','P','O','S'):
907
6.63k
        case W('g','a','s','p'):
908
8.95k
        case W('k','e','r','n'):
909
8.95k
            continue;
910
12.4k
        default:
911
12.4k
            if (writing_cid)
912
2.98k
                continue;
913
9.46k
            break;
914
933k
        }
915
635k
        numTables++;
916
635k
    }
917
918
    /*
919
     * Enumerate the glyphs to get the size of glyf and loca,
920
     * and to compute the checksums for these tables.
921
     */
922
923
    /****** NO CHECKSUMS YET ******/
924
74.9k
    for (max_glyph = 0, glyf_length = 0;
925
313k
         (code = psf_enumerate_glyphs_next(penum, &glyph)) != 1;
926
238k
         ) {
927
238k
        uint glyph_index;
928
238k
        gs_glyph_data_t glyph_data;
929
930
238k
        if (glyph < GS_MIN_CID_GLYPH)
931
0
            return_error(gs_error_invalidfont);
932
238k
        glyph_index = glyph  & ~GS_GLYPH_TAG;
933
238k
        if_debug1m('L', s->memory, "[L]glyph_index %u\n", glyph_index);
934
238k
        glyph_data.memory = pfont->memory;
935
238k
        if ((code = pfont->data.get_outline(pfont, glyph_index, &glyph_data)) >= 0) {
936
            /* Since indexToLocFormat==0 assumes even glyph lengths,
937
               round it up here. If later we choose indexToLocFormat==1,
938
               subtract the glyf_alignment to compensate it. */
939
238k
            uint l = (glyph_data.bits.size + 1) & ~1;
940
941
238k
            max_glyph = max(max_glyph, glyph_index);
942
238k
            glyf_length += l;
943
238k
            if (l != glyph_data.bits.size)
944
148
                glyf_alignment++;
945
238k
            if_debug1m('L', s->memory, "[L]  size %u\n", glyph_data.bits.size);
946
238k
            gs_glyph_data_free(&glyph_data, "psf_write_truetype_data");
947
238k
        }
948
238k
    }
949
74.9k
    if (writing_stripped) {
950
65.1k
        glyf_length = 0;
951
65.1k
        loca_length = 0;
952
65.1k
    } else {
953
9.80k
        if (max_glyph + 1 > numGlyphs) {
954
            /* Either original font is wrong,
955
               or we added glyphs to it due to font merge.
956
               Need to adjust maxp, hmtx, vmtx, vdmx, hdmx,
957
               assuming that the merge doesn't change hhea
958
               and other tables.
959
               Since changing hdmx, vdmx is too difficult,
960
               and since they're not required for PDF,
961
               we'll simply skip them.
962
             */
963
66
            enlarged_numGlyphs = max_glyph + 1;
964
66
            if (enlarged_numGlyphs > 0xFFFF) {
965
0
                emprintf1(pfont->memory,
966
0
                          "The number of glyphs %d exceeds capability of True Type format.\n",
967
0
                          enlarged_numGlyphs);
968
0
                return_error(gs_error_unregistered);
969
0
            }
970
66
            loca_length = (enlarged_numGlyphs + 1) << 2;
971
66
            remove_table(tables, (char *)"hdmx", &numTables);
972
66
            remove_table(tables, (char *)"vdmx", &numTables);
973
66
        } else
974
9.73k
            loca_length = (numGlyphs + 1) << 2;
975
9.80k
        indexToLocFormat = (glyf_length > 0x1fffc);
976
9.80k
        if (!indexToLocFormat)
977
9.80k
            loca_length >>= 1;
978
0
        else
979
0
            glyf_length -= glyf_alignment;
980
        /* Acrobat Reader won't accept fonts with empty glyfs. */
981
9.80k
        if (glyf_length == 0)
982
862
            glyf_length = 1;
983
9.80k
    }
984
74.9k
    if_debug2m('l', s->memory, "[l]max_glyph = %lu, glyf_length = %lu\n",
985
74.9k
               (ulong)max_glyph, (ulong)glyf_length);
986
987
    /*
988
     * If necessary, compute the length of the post table.  Note that we
989
     * only generate post entries for characters in the Encoding.  */
990
991
74.9k
    if (!have_post) {
992
1.20k
        memset(&post, 0, sizeof(post));
993
1.20k
        if (options & WRITE_TRUETYPE_POST) {
994
0
            code = compute_post(font, &post);
995
0
            if (code < 0)
996
0
                return code;
997
0
        } else
998
1.20k
            post.length = 32; /* dummy table */
999
1.20k
    }
1000
1001
    /* Fix up the head table. */
1002
1003
74.9k
    memset(head + 8, 0, 4);
1004
74.9k
    head[50] = 0x00;
1005
74.9k
    head[51] = (byte)indexToLocFormat;
1006
74.9k
    memset(head + 54, 0, 2);
1007
1.12M
    for (head_checksum = 0, i = 0; i < 56; i += 4)
1008
1.04M
        head_checksum += u32(&head[i]);
1009
1010
    /*
1011
     * Construct the table directory, except for glyf, loca, head, OS/2,
1012
     * and, if necessary, generated cmap, name, and post tables.
1013
     * Note that the existing directory is already sorted by tag.
1014
     */
1015
1016
74.9k
    numTables_out = numTables + 1 /* head */
1017
74.9k
        + !writing_stripped * 2 /* glyf, loca */
1018
74.9k
        + generate_mtx * (have_hvhea[0] + have_hvhea[1]) /* hmtx, vmtx */
1019
74.9k
        + !have_OS_2    /* OS/2 */
1020
74.9k
        + !have_cmap + !have_name + !have_post;
1021
74.9k
    if (numTables_out >= MAX_NUM_TT_TABLES)
1022
0
        return_error(gs_error_limitcheck);
1023
74.9k
    offset = 12 + numTables_out * 16;
1024
710k
    for (i = 0; i < numTables; ++i) {
1025
635k
        byte *tab = &tables[i * 16];
1026
635k
        ulong length = u32(tab + 12);
1027
1028
635k
        offset += round_up(length, 4);
1029
635k
    }
1030
1031
    /* Make the table directory entries for generated tables. */
1032
1033
74.9k
    {
1034
74.9k
        byte *tab = &tables[numTables * 16];
1035
1036
74.9k
        if (!writing_stripped) {
1037
9.80k
            subtable_positions.glyf = offset;
1038
9.80k
            offset = put_table(tab, "glyf", glyf_checksum,
1039
9.80k
                               offset, glyf_length);
1040
9.80k
            tab += 16;
1041
9.80k
            subtable_positions.loca = offset;
1042
9.80k
            offset = put_table(tab, "loca", loca_checksum[indexToLocFormat],
1043
9.80k
                               offset, loca_length);
1044
9.80k
            tab += 16;
1045
9.80k
        }
1046
1047
74.9k
        if (!have_cmap) {
1048
8.25k
            cmap_length = size_cmap(font, TT_BIAS, 256,
1049
8.25k
                                    GS_MIN_GLYPH_INDEX + max_glyph, options);
1050
8.25k
            subtable_positions.cmap = offset;
1051
8.25k
            offset = put_table(tab, "cmap", 0L /****** NO CHECKSUM ******/,
1052
8.25k
                               offset, cmap_length);
1053
8.25k
            tab += 16;
1054
8.25k
        }
1055
1056
74.9k
        if (!have_name) {
1057
180
            subtable_positions.name = offset;
1058
180
            offset = put_table(tab, "name", 0L /****** NO CHECKSUM ******/,
1059
180
                               offset, size_name(&font_name));
1060
180
            tab += 16;
1061
180
        }
1062
1063
74.9k
        if (!no_generate) {
1064
8.25k
            subtable_positions.os_2 = offset;
1065
8.25k
            offset = put_table(tab, "OS/2", 0L /****** NO CHECKSUM ******/,
1066
8.25k
                               offset, OS_2_length);
1067
8.25k
            tab += 16;
1068
8.25k
        }
1069
1070
74.9k
        if (generate_mtx)
1071
29.4k
            for (i = 0; i < 2; ++i)
1072
19.6k
                if (have_hvhea[i]) {
1073
9.79k
                    subtable_positions.mtx[i] = offset;
1074
9.79k
                    offset = put_table(tab, (i ? "vmtx" : "hmtx"),
1075
9.79k
                                       0L /****** NO CHECKSUM ******/,
1076
9.79k
                                       offset,
1077
9.79k
                                       size_mtx(pfont, &mtx[i], max_glyph, numGlyphs, i));
1078
9.79k
                    tab += 16;
1079
9.79k
                }
1080
1081
74.9k
        if (!have_post) {
1082
1.20k
            subtable_positions.post = offset;
1083
1.20k
            offset = put_table(tab, "post", 0L /****** NO CHECKSUM ******/,
1084
1.20k
                               offset, post.length);
1085
1.20k
            tab += 16;
1086
1.20k
        }
1087
1088
        /*
1089
         * Note that the 'head' table must have length 54, even though
1090
         * it occupies 56 bytes on the file.
1091
         */
1092
74.9k
        subtable_positions.head = offset;
1093
74.9k
        (void)put_table(tab, "head", head_checksum, offset, 54);
1094
74.9k
    }
1095
74.9k
    numTables = numTables_out;
1096
1097
    /* Write the font header. */
1098
1099
74.9k
    {
1100
74.9k
        static const byte version[4] = {0, 1, 0, 0};
1101
1102
74.9k
        stream_write(s, version, 4);
1103
74.9k
    }
1104
74.9k
    put_ushort(s, numTables);
1105
372k
    for (i = 0; 1 << i <= numTables; ++i)
1106
297k
        DO_NOTHING;
1107
74.9k
    --i;
1108
74.9k
    put_ushort(s, 16 << i); /* searchRange */
1109
74.9k
    put_ushort(s, i);   /* entrySelectors */
1110
74.9k
    put_ushort(s, numTables * 16 - (16 << i)); /* rangeShift */
1111
1112
    /* Write the table directory. */
1113
1114
74.9k
    qsort(tables, numTables, 16, compare_table_tags);
1115
74.9k
    offset = 12 + numTables * 16;
1116
833k
    for (i = 0; i < numTables; ++i) {
1117
758k
        const byte *tab = &tables[i * 16];
1118
758k
        byte entry[16];
1119
1120
758k
        memcpy(entry, tab, 16);
1121
758k
        if (entry[8] < 0x40) {
1122
            /* Not a generated table. */
1123
634k
            uint length = u32(tab + 12);
1124
1125
634k
            put_u32(entry + 8, offset);
1126
634k
            offset += round_up(length, 4);
1127
634k
        } else {
1128
123k
            entry[8] -= 0x40;
1129
123k
        }
1130
758k
        stream_write(s, entry, 16);
1131
758k
    }
1132
1133
    /* Write tables other than the ones we generate here. */
1134
1135
833k
    for (i = 0; i < numTables; ++i) {
1136
758k
        const byte *tab = &tables[i * 16];
1137
1138
758k
        if (tab[8] < 0x40) {
1139
634k
            ulong start = u32(tab + 8);
1140
634k
            uint length = u32(tab + 12);
1141
1142
634k
            switch (u32(tab)) {
1143
0
            case W('O','S','/','2'):
1144
0
                if (!have_cmap) {
1145
                    /*
1146
                     * Adjust the first and last character indices in the OS/2
1147
                     * table to reflect the values in the generated cmap.
1148
                     */
1149
0
                    byte pos2[OS_2_LENGTH5];
1150
0
                    ttf_OS_2_t os2;
1151
1152
0
                    READ_SFNTS(pfont, OS_2_start, OS_2_length, pos2);
1153
0
                    memcpy(&os2, pos2, min(OS_2_length, sizeof(os2)));
1154
0
                    update_OS_2(&os2, TT_BIAS, 256);
1155
0
                    stream_write(s, &os2, OS_2_length);
1156
0
                    put_pad(s, OS_2_length);
1157
0
                } else {
1158
                    /* Just copy the existing OS/2 table. */
1159
0
                    write_range(s, pfont, OS_2_start, OS_2_length);
1160
0
                    put_pad(s, OS_2_length);
1161
0
                }
1162
0
            break;
1163
74.4k
            case W('m','a','x','p'):
1164
74.4k
                if (enlarged_numGlyphs) {
1165
                    /* Must keep the table size. */
1166
66
                    byte buf[6];
1167
1168
66
                    READ_SFNTS(pfont, maxp_start, sizeof(buf), buf);
1169
66
                    put_u16(buf + 4, enlarged_numGlyphs);
1170
66
                    stream_write(s, buf, min(length, sizeof(buf)));
1171
66
                    if (length > sizeof(buf)) /* Paranoid Safety */
1172
0
                        write_range(s, pfont, start + sizeof(buf), length - sizeof(buf));
1173
66
                } else
1174
74.4k
                    write_range(s, pfont, start, length);
1175
74.4k
                break;
1176
74.9k
            case W('h','h','e','a'):
1177
74.9k
            case W('v','h','e','a'):
1178
74.9k
                if (generate_mtx) {
1179
9.79k
                    write_range(s, pfont, start, length - 2); /* 34 */
1180
9.79k
                    put_ushort(s, mtx[tab[0] == 'v'].numMetrics);
1181
9.79k
                    break;
1182
9.79k
                }
1183
                /* falls through */
1184
550k
            default:
1185
550k
                write_range(s, pfont, start, length);
1186
634k
            }
1187
634k
            put_pad(s, length);
1188
634k
        }
1189
758k
    }
1190
1191
74.9k
    if (!writing_stripped) {
1192
9.80k
        int n = max(numGlyphs, enlarged_numGlyphs) + 1;
1193
1194
        /* Write glyf. */
1195
1196
9.80k
        if (check_position(pfont->memory,
1197
9.80k
                           subtable_positions.glyf + start_position,
1198
9.80k
                           stell(s)))
1199
0
            return_error(gs_error_unregistered);
1200
9.80k
        psf_enumerate_glyphs_reset(penum);
1201
248k
        for (offset = 0; psf_enumerate_glyphs_next(penum, &glyph) != 1; ) {
1202
238k
            gs_glyph_data_t glyph_data;
1203
1204
238k
            glyph_data.memory = pfont->memory;
1205
238k
            if ((code = pfont->data.get_outline(pfont,
1206
238k
                                                glyph & ~GS_GLYPH_TAG,
1207
238k
                                                &glyph_data)) >= 0
1208
238k
                ) {
1209
238k
                uint l = glyph_data.bits.size, zero = 0;
1210
1211
238k
                if (!indexToLocFormat)
1212
238k
                    l = (l + 1) & ~1;
1213
238k
                stream_write(s, glyph_data.bits.data, glyph_data.bits.size);
1214
238k
                if (glyph_data.bits.size < l)
1215
148
                    stream_write(s, &zero, 1);
1216
238k
                offset += l;
1217
238k
                if_debug2m('L', s->memory, "[L]glyf index = %u, size = %u\n",
1218
238k
                          i, glyph_data.bits.size);
1219
238k
                gs_glyph_data_free(&glyph_data, "psf_write_truetype_data");
1220
238k
            }
1221
238k
        }
1222
9.80k
        if_debug1m('l', s->memory, "[l]glyf final offset = %lu\n", offset);
1223
        /* Add a dummy byte if necessary to make glyf non-empty. */
1224
10.6k
        while (offset < glyf_length)
1225
862
            stream_putc(s, 0), ++offset;
1226
9.80k
        put_pad(s, (uint)offset);
1227
1228
        /* Write loca. */
1229
1230
9.80k
        if (check_position(pfont->memory,
1231
9.80k
                           subtable_positions.loca + start_position,
1232
9.80k
                           stell(s)))
1233
0
            return_error(gs_error_unregistered);
1234
9.80k
        psf_enumerate_glyphs_reset(penum);
1235
9.80k
        glyph_prev = 0;
1236
248k
        for (offset = 0; psf_enumerate_glyphs_next(penum, &glyph) != 1; ) {
1237
238k
            gs_glyph_data_t glyph_data;
1238
238k
            uint glyph_index = glyph & ~GS_GLYPH_TAG;
1239
1240
10.9M
            for (; glyph_prev <= glyph_index; ++glyph_prev)
1241
10.7M
                put_loca(s, offset, indexToLocFormat);
1242
238k
            glyph_data.memory = pfont->memory;
1243
238k
            if ((code = pfont->data.get_outline(pfont, glyph_index,
1244
238k
                                                &glyph_data)) >= 0
1245
238k
                ) {
1246
238k
                uint l = glyph_data.bits.size;
1247
1248
238k
                if (!indexToLocFormat)
1249
238k
                    l = (l + 1) & ~1;
1250
238k
                offset += l;
1251
238k
                gs_glyph_data_free(&glyph_data, "psf_write_truetype_data");
1252
238k
            }
1253
1254
238k
        }
1255
        /* Pad to numGlyphs + 1 entries (including the trailing entry). */
1256
50.2M
        for (; glyph_prev < n; ++glyph_prev)
1257
50.1M
            put_loca(s, offset, indexToLocFormat);
1258
9.80k
        put_pad(s, loca_length);
1259
1260
        /* If necessary, write cmap, name, and OS/2. */
1261
1262
9.80k
        if (!have_cmap) {
1263
8.25k
            if (check_position(pfont->memory,
1264
8.25k
                               subtable_positions.cmap + start_position,
1265
8.25k
                               stell(s)))
1266
0
                return_error(gs_error_unregistered);
1267
8.25k
            write_cmap(s, font, TT_BIAS, 256, GS_MIN_GLYPH_INDEX + max_glyph,
1268
8.25k
                       options, cmap_length);
1269
8.25k
        }
1270
9.80k
        if (!have_name) {
1271
180
            if (check_position(pfont->memory,
1272
180
                               subtable_positions.name + start_position,
1273
180
                               stell(s)))
1274
0
                return_error(gs_error_unregistered);
1275
180
            write_name(s, &font_name);
1276
180
        }
1277
9.80k
        if (!have_OS_2) {
1278
8.25k
            if (check_position(pfont->memory,
1279
8.25k
                               subtable_positions.os_2 + start_position,
1280
8.25k
                               stell(s)))
1281
0
                return_error(gs_error_unregistered);
1282
8.25k
            write_OS_2(s, font, TT_BIAS, 256);
1283
8.25k
        }
1284
1285
        /* If necessary, write [hv]mtx. */
1286
1287
9.80k
        if (generate_mtx)
1288
29.4k
            for (i = 0; i < 2; ++i)
1289
19.6k
                if (have_hvhea[i]) {
1290
9.79k
                    if (check_position(pfont->memory,
1291
9.79k
                                       subtable_positions.mtx[i] + start_position,
1292
9.79k
                                       stell(s)))
1293
0
                        return_error(gs_error_unregistered);
1294
9.79k
                    write_mtx(s, pfont, &mtx[i], i);
1295
9.79k
                    put_pad(s, mtx[i].length);
1296
9.79k
                }
1297
1298
        /* If necessary, write post. */
1299
1300
9.80k
        if (!have_post) {
1301
1.20k
            if (check_position(pfont->memory,
1302
1.20k
                               subtable_positions.post + start_position,
1303
1.20k
                               stell(s)))
1304
0
                return_error(gs_error_unregistered);
1305
1.20k
            if (options & WRITE_TRUETYPE_POST) {
1306
0
                code = write_post(s, font, &post);
1307
0
                if (code < 0)
1308
0
                    return code;
1309
1.20k
            } else {
1310
1.20k
                byte post_initial[32 + 2];
1311
1312
1.20k
                memset(post_initial, 0, 32);
1313
1.20k
                put_u32(post_initial, 0x00030000);
1314
1.20k
                stream_write(s, post_initial, 32);
1315
1.20k
            }
1316
1.20k
        }
1317
9.80k
    }
1318
1319
    /* Write head. */
1320
1321
    /****** CHECKSUM WAS NEVER COMPUTED ******/
1322
    /*
1323
     * The following nonsense is to avoid warnings about the constant
1324
     * 0xb1b0afbaL being "unsigned in ANSI C, signed with -traditional".
1325
     */
1326
74.9k
#if ARCH_SIZEOF_LONG > ARCH_SIZEOF_INT
1327
74.9k
#  define HEAD_MAGIC 0xb1b0afbaL
1328
#else
1329
#  define HEAD_MAGIC ((ulong)~0x4e4f5045)
1330
#endif
1331
74.9k
    put_u32(head + 8, HEAD_MAGIC - file_checksum); /* per spec */
1332
74.9k
#undef HEAD_MAGIC
1333
74.9k
    if (check_position(pfont->memory,
1334
74.9k
                       subtable_positions.head + start_position,
1335
74.9k
                       stell(s)))
1336
11.8k
        return_error(gs_error_unregistered);
1337
63.0k
    stream_write(s, head, 56);
1338
1339
63.0k
    return 0;
1340
74.9k
}
1341
1342
/* Write a TrueType font. */
1343
int
1344
psf_write_truetype_font(stream *s, gs_font_type42 *pfont, int options,
1345
                        gs_glyph *orig_subset_glyphs, uint orig_subset_size,
1346
                        const gs_const_string *alt_font_name)
1347
8.25k
{
1348
8.25k
    gs_font *const font = (gs_font *)pfont;
1349
8.25k
    psf_glyph_enum_t genum;
1350
8.25k
    gs_glyph subset_data[256 * MAX_COMPOSITE_PIECES];
1351
8.25k
    gs_glyph *subset_glyphs = orig_subset_glyphs;
1352
8.25k
    uint subset_size = orig_subset_size;
1353
1354
    /* Sort the subset glyphs, if any. */
1355
1356
8.25k
    if (subset_glyphs) {
1357
        /* Add the component glyphs for composites. */
1358
0
        int code;
1359
1360
0
        memcpy(subset_data, orig_subset_glyphs,
1361
0
               sizeof(gs_glyph) * subset_size);
1362
0
        subset_glyphs = subset_data;
1363
0
        code = psf_add_subset_pieces(subset_glyphs, &subset_size,
1364
0
                                     countof(subset_data),
1365
0
                                     countof(subset_data),
1366
0
                                     font);
1367
0
        if (code < 0)
1368
0
            return code;
1369
0
        subset_size = psf_sort_glyphs(subset_glyphs, subset_size);
1370
0
    }
1371
8.25k
    psf_enumerate_glyphs_begin(&genum, font, subset_glyphs,
1372
8.25k
                               (subset_glyphs ? subset_size : 0),
1373
8.25k
                               GLYPH_SPACE_INDEX);
1374
8.25k
    return psf_write_truetype_data(s, pfont, options & ~WRITE_TRUETYPE_CID,
1375
8.25k
                                   &genum, subset_glyphs != 0, alt_font_name);
1376
8.25k
}
1377
/* Write a stripped TrueType font. */
1378
int
1379
psf_write_truetype_stripped(stream *s, gs_font_type42 *pfont)
1380
58.9k
{
1381
58.9k
    psf_glyph_enum_t genum;
1382
58.9k
    byte no_subset = 0;
1383
1384
58.9k
    psf_enumerate_bits_begin(&genum, (gs_font *)pfont, &no_subset, 0,
1385
58.9k
                             GLYPH_SPACE_INDEX);
1386
58.9k
    return psf_write_truetype_data(s, pfont, WRITE_TRUETYPE_STRIPPED,
1387
58.9k
                                   &genum, true, NULL);
1388
58.9k
}
1389
1390
/* Write a CIDFontType 2 font. */
1391
int
1392
psf_write_cid2_font(stream *s, gs_font_cid2 *pfont, int options,
1393
                    const byte *subset_bits, uint subset_size,
1394
                    const gs_const_string *alt_font_name)
1395
1.54k
{
1396
1.54k
    gs_font *const font = (gs_font *)pfont;
1397
1.54k
    psf_glyph_enum_t genum;
1398
1399
1.54k
    psf_enumerate_bits_begin(&genum, font, subset_bits,
1400
1.54k
                             (subset_bits ? subset_size : 0),
1401
1.54k
                             GLYPH_SPACE_INDEX);
1402
1.54k
    return psf_write_truetype_data(s, (gs_font_type42 *)font,
1403
1.54k
                                   options | WRITE_TRUETYPE_CID, &genum,
1404
1.54k
                                   subset_bits != 0, alt_font_name);
1405
1.54k
}
1406
1407
/* Write a stripped CIDFontType 2 font. */
1408
int
1409
psf_write_cid2_stripped(stream *s, gs_font_cid2 *pfont)
1410
6.17k
{
1411
6.17k
    gs_font *const font = (gs_font *)pfont;
1412
6.17k
    psf_glyph_enum_t genum;
1413
6.17k
    byte no_subset = 0;
1414
1415
6.17k
    psf_enumerate_bits_begin(&genum, font, &no_subset, 0,
1416
6.17k
                             GLYPH_SPACE_INDEX);
1417
6.17k
    return psf_write_truetype_data(s, (gs_font_type42 *)font,
1418
6.17k
                                   WRITE_TRUETYPE_STRIPPED |
1419
6.17k
                                     WRITE_TRUETYPE_CID,
1420
6.17k
                                   &genum, true, NULL);
1421
6.17k
}