Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/devices/vector/gdevpsft.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 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
43.0k
#define WRITE_TRUETYPE_STRIPPED 0x1000  /* internal */
36
53.4k
#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
14.3k
#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
234k
{
71
234k
    static const byte pad_to_4[3] = {0, 0, 0};
72
73
234k
    stream_write(s, pad_to_4, (uint)(-(int)length & 3));
74
234k
}
75
76
/* Put short and long values on a stream. */
77
static void
78
put_ushort(stream *s, uint v)
79
12.5M
{
80
12.5M
    stream_putc(s, (byte)(v >> 8));
81
12.5M
    stream_putc(s, (byte)v);
82
12.5M
}
83
static void
84
put_short(stream *s, short v)
85
14.0M
{
86
14.0M
    stream_putc(s, (byte)(v >> 8));
87
14.0M
    stream_putc(s, (byte)v);
88
14.0M
}
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
12.4M
{
98
12.4M
    if (indexToLocFormat)
99
0
        put_ulong(s, offset);
100
12.4M
    else
101
12.4M
        put_ushort(s, (uint)(offset >> 1));
102
12.4M
}
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
1.91M
#define U16(p) (((uint)((p)[0]) << 8) + (p)[1])
108
#define S16(p) (int)((U16(p) ^ 0x8000) - 0x8000)
109
3.28M
#define u32(p) get_u32_msb(p)
110
static void
111
put_u16(byte *p, uint v)
112
3.25M
{
113
3.25M
    p[0] = (byte)(v >> 8);
114
3.25M
    p[1] = (byte)v;
115
3.25M
}
116
static void
117
put_u32(byte *p, ulong v)
118
374k
{
119
374k
    put_u16(p, (ushort)(v >> 16));
120
374k
    put_u16(p + 2, (ushort)v);
121
374k
}
122
static ulong
123
put_table(byte tab[16], const char *tname, ulong checksum, ulong offset,
124
          uint length)
125
48.6k
{
126
48.6k
    memcpy(tab, (const byte *)tname, 4);
127
48.6k
    put_u32(tab + 4, checksum);
128
48.6k
    put_u32(tab + 8, offset + 0x40000000);
129
48.6k
    put_u32(tab + 12, (ulong)length);
130
48.6k
    return offset + round_up(length, 4);
131
48.6k
}
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
204k
{
137
204k
    ulong base = start, size = length;
138
139
204k
    if_debug3m('l', s->memory, "[l]write_range pos = %"PRId64", start = %lu, length = %u\n",
140
204k
               stell(s), start, length);
141
408k
    while (size > 0) {
142
204k
        const byte *ptr;
143
204k
        int code;
144
145
204k
        code = pfont->data.string_proc(pfont, base, size, &ptr);
146
204k
        if (code < 0)
147
1.30k
            return code;
148
203k
        if (!code)
149
203k
            code = size;
150
203k
        stream_write(s, ptr, code);
151
203k
        base += code;
152
203k
        size -= code;
153
203k
    }
154
203k
    return 0;
155
204k
}
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
9.16k
#define CMAP_ENTRIES_SIZE (256 * 2)
304
static void
305
write_cmap_0(stream *s, byte* entries /*[CMAP_ENTRIES_SIZE]*/, uint num_glyphs)
306
9.16k
{
307
9.16k
    int i;
308
309
9.16k
    if (CMAP_ENTRIES_SIZE - 2 * num_glyphs>0)
310
0
      memset(entries + 2 * num_glyphs, 0, CMAP_ENTRIES_SIZE - 2 * num_glyphs);
311
9.16k
    stream_write(s, cmap_initial_0, sizeof(cmap_initial_0));
312
2.35M
    for (i = 0; i <= 0xff; ++i)
313
2.34M
        sputc(s, (byte)entries[2 * i + 1]);
314
9.16k
}
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
400
{
319
400
    byte cmap_data[sizeof(cmap_initial_6)];
320
321
400
    memcpy(cmap_data, cmap_initial_6, sizeof(cmap_initial_6));
322
400
    put_u16(cmap_data + 18,
323
400
            U16(cmap_data + 18) + num_entries * 2);  /* offset */
324
400
    put_u16(cmap_data + 22,
325
400
            U16(cmap_data + 22) + num_entries * 2);  /* length */
326
400
    put_u16(cmap_data + 26,
327
#if TT_BIAS_CMAP_6
328
            first_code +
329
#endif
330
400
            first_entry);
331
400
    put_u16(cmap_data + 28, num_entries);
332
400
    stream_write(s, cmap_data, sizeof(cmap_data));
333
400
    stream_write(s, entries + first_entry * 2, num_entries * 2);
334
400
}
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
9.57k
{
354
9.57k
    byte cmap_sub[sizeof(cmap_sub_initial)];
355
9.57k
    byte entries[CMAP_ENTRIES_SIZE];
356
9.57k
    int first_entry = 0, end_entry = num_glyphs;
357
9.57k
    bool can_use_trimmed = !(options & WRITE_TRUETYPE_NO_TRIMMED_TABLE);
358
9.57k
    uint merge = 0;
359
9.57k
    uint num_entries;
360
9.57k
    int i;
361
362
    /* Collect the table entries. */
363
364
2.46M
    for (i = 0; i < num_glyphs; ++i) {
365
2.45M
        gs_glyph glyph =
366
2.45M
            font->procs.encode_char(font, (gs_char)i, GLYPH_SPACE_INDEX);
367
2.45M
        uint glyph_index;
368
369
2.45M
        if (glyph == GS_NO_GLYPH || glyph < GS_MIN_GLYPH_INDEX ||
370
2.45M
            glyph > max_glyph
371
2.45M
            )
372
2.21M
            glyph = GS_MIN_GLYPH_INDEX;
373
2.45M
        glyph_index = (uint)(glyph - GS_MIN_GLYPH_INDEX);
374
2.45M
        merge |= glyph_index;
375
2.45M
        put_u16(entries + 2 * i, glyph_index);
376
2.45M
    }
377
1.50M
    while (end_entry > first_entry && !U16(entries + 2 * end_entry - 2))
378
1.49M
        --end_entry;
379
359k
    while (first_entry < end_entry && !U16(entries + 2 * first_entry))
380
349k
        ++first_entry;
381
9.57k
    num_entries = end_entry - first_entry;
382
383
    /* Write the table header and Macintosh sub-table (if any). */
384
385
9.57k
    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
9.57k
    if (merge == (byte)merge && (num_entries <= 127 || !can_use_trimmed))
413
9.16k
        write_cmap_0(s, entries, num_glyphs);
414
408
    else if (can_use_trimmed)
415
400
        write_cmap_6(s, entries, first_code, first_entry, num_entries);
416
8
    else
417
8
# endif
418
8
    {
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
8
        stream_write(s, cmap_initial_4, sizeof(cmap_initial_4));
425
8
    }
426
9.57k
#endif
427
428
    /* Write the Windows sub-table. */
429
430
9.57k
    memcpy(cmap_sub, cmap_sub_initial, sizeof(cmap_sub_initial));
431
9.57k
    put_u16(cmap_sub + 2, U16(cmap_sub + 2) + num_entries * 2); /* length */
432
9.57k
    put_u16(cmap_sub + 14, first_code + end_entry - 1); /* endCount[0] */
433
9.57k
    put_u16(cmap_sub + 20, first_code + first_entry); /* startCount[0] */
434
9.57k
    stream_write(s, cmap_sub, sizeof(cmap_sub));
435
9.57k
    stream_write(s, entries + first_entry * 2, num_entries * 2);
436
9.57k
    put_pad(s, cmap_length);
437
9.57k
}
438
static uint
439
size_cmap(gs_font *font, uint first_code, int num_glyphs, gs_glyph max_glyph,
440
          int options)
441
4.78k
{
442
4.78k
    stream poss;
443
444
4.78k
    s_init(&poss, NULL);
445
4.78k
    swrite_position_only(&poss);
446
4.78k
    write_cmap(&poss, font, first_code, num_glyphs, max_glyph, options, 0);
447
4.78k
    return stell(&poss);
448
4.78k
}
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
4.95k
{
465
4.95k
    uint num_metrics = pmtx->numMetrics;
466
4.95k
    uint len = num_metrics * 4;
467
4.95k
    double factor = (double)pfont->data.unitsPerEm * (wmode ? -1 : 1);
468
4.95k
    float sbw[4];
469
4.95k
    uint i;
470
471
4.95k
    sbw[0] = sbw[1] = sbw[2] = sbw[3] = 0; /* in case of failures */
472
656k
    for (i = 0; i < pmtx->numMetrics; ++i) {
473
651k
        float f;
474
651k
        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
651k
        f = (float) (sbw[wmode + 2] * factor); /* width */
478
651k
        put_short(s, (short) floor(f + 0.5));
479
651k
        f = (float) (sbw[wmode] * factor); /* lsb, may be <0 */
480
651k
        put_short(s, (short) floor(f + 0.5));
481
651k
    }
482
12.7M
    for (; len < pmtx->length; ++i, len += 2) {
483
12.7M
        float f;
484
12.7M
        DISCARD(pfont->data.get_metrics(pfont, i, wmode, sbw));
485
12.7M
        f = (float) (sbw[wmode] * factor); /* lsb, may be <0 */
486
12.7M
        put_short(s, (short) floor(f + 0.5));
487
12.7M
    }
488
4.95k
}
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
4.95k
{
495
4.95k
    int prev_width = min_int;
496
4.95k
    uint last_width = 0; /* pacify compilers */
497
4.95k
    double factor = pfont->data.unitsPerEm * (wmode ? -1 : 1);
498
4.95k
    uint i;
499
500
1.61M
    for (i = 0; i <= max_glyph; ++i) {
501
1.60M
        float sbw[4];
502
1.60M
        int code = pfont->data.get_metrics(pfont, i, wmode, sbw);
503
1.60M
        int width;
504
505
1.60M
        if (code < 0)
506
1.48M
            continue;
507
118k
        width = (int)(sbw[wmode + 2] * factor + 0.5);
508
118k
        if (width != prev_width)
509
94.9k
            prev_width = width, last_width = i;
510
118k
    }
511
4.95k
    pmtx->numMetrics = last_width + 1;
512
4.95k
    pmtx->length = pmtx->numMetrics * 4 + (max_glyph - last_width) * 2;
513
4.95k
    pmtx->length += (numGlyphs - pmtx->numMetrics) * 2;
514
4.95k
    return pmtx->length;
515
4.95k
}
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
32
{
535
32
    return sizeof(name_initial) + font_name->size;
536
32
}
537
static void
538
write_name(stream *s, const gs_const_string *font_name)
539
16
{
540
16
    byte name_bytes[sizeof(name_initial)];
541
542
16
    memcpy(name_bytes, name_initial, sizeof(name_initial));
543
16
    put_u16(name_bytes + 14, font_name->size);
544
16
    stream_write(s, name_bytes, sizeof(name_bytes));
545
16
    stream_write(s, font_name->data, font_name->size);
546
16
    put_pad(s, size_name(font_name));
547
16
}
548
549
/* ------ OS/2 ------ */
550
551
/* Write a generated OS/2 table. */
552
23.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
15.7k
#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
4.78k
{
559
4.78k
    put_u16(pos2->usFirstCharIndex, first_glyph);
560
4.78k
    put_u16(pos2->usLastCharIndex, first_glyph + num_glyphs - 1);
561
4.78k
#if TT_ADJUST_OS_2
562
4.78k
    if (first_glyph >= 0xf000) {
563
        /* This font is being treated as a symbolic font. */
564
4.78k
        memset(pos2->ulUnicodeRanges, 0, sizeof(pos2->ulUnicodeRanges));
565
4.78k
        pos2->ulUnicodeRanges[7] = 8; /* bit 60, private use range */
566
4.78k
        memset(pos2->ulCodePageRanges, 0, sizeof(pos2->ulCodePageRanges));
567
4.78k
        pos2->ulCodePageRanges[3] = 1; /* bit 31, symbolic */
568
4.78k
    }
569
4.78k
#endif
570
4.78k
}
571
static void
572
write_OS_2(stream *s, gs_font *font, uint first_glyph, int num_glyphs)
573
4.78k
{
574
4.78k
    ttf_OS_2_t os2;
575
4.78k
    gs_font_info_t info;
576
4.78k
    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
4.78k
    memset(&os2, 0, sizeof(os2));
586
4.78k
    put_u16(os2.version, 1);
587
4.78k
    put_u16(os2.usWeightClass, 400); /* Normal */
588
4.78k
    put_u16(os2.usWidthClass, 5); /* Normal */
589
4.78k
    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
4.78k
    memset(&info, 0x00, sizeof(gs_font_info_t));
596
4.78k
    code = font->procs.font_info(font, NULL, FONT_INFO_EMBEDDING_RIGHTS, &info);
597
4.78k
    if (code == 0 && (info.members & FONT_INFO_EMBEDDING_RIGHTS)) {
598
3.67k
        put_u16(os2.fsType, info.EmbeddingRights);
599
3.67k
    }
600
601
4.78k
    stream_write(s, &os2, offset_of(ttf_OS_2_t, sxHeight[0]));
602
4.78k
    put_pad(s, offset_of(ttf_OS_2_t, sxHeight[0]));
603
4.78k
}
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
48.6k
{
731
48.6k
    if (pos1 == pos2)
732
47.2k
        return false;
733
1.40k
    emprintf2(mem,
734
1.40k
              "Actual TT subtable offset %"PRId64" differs from one in the TT header %"PRId64".\n",
735
1.40k
              pos1,
736
1.40k
              pos2);
737
1.40k
    return true;
738
48.6k
}
739
740
static void remove_table(byte *tables, char *tag, uint *numTables)
741
298
{
742
    /* Not a high performance implementation because it is called seldom. */
743
298
    int i;
744
745
2.38k
    for (i = 0; i < *numTables;) {
746
2.08k
        byte *tab = tables + i * 16;
747
748
2.08k
        if (!memcmp(tab, tag, 4)) {
749
0
            memmove(tab, tab + 16, 16 * (*numTables - i - 1));
750
0
            --*numTables;
751
0
        } else
752
2.08k
            ++i;
753
2.08k
    }
754
298
}
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
494k
{
762
494k
    ulong t1 = u32(pt1), t2 = u32(pt2);
763
764
494k
    return (t1 < t2 ? -1 : t1 > t2 ? 1 : 0);
765
494k
}
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
23.9k
{
771
23.9k
    gs_font *const font = (gs_font *)pfont;
772
23.9k
    gs_const_string font_name;
773
23.9k
    byte OffsetTable[12];
774
23.9k
    uint numTables_stored, numTables, numTables_out;
775
23.9k
    byte tables[MAX_NUM_TT_TABLES * 16];
776
23.9k
    uint i;
777
23.9k
    ulong offset;
778
23.9k
    gs_glyph glyph, glyph_prev;
779
23.9k
    ulong max_glyph;
780
23.9k
    uint glyf_length, loca_length;
781
23.9k
    ulong glyf_checksum = 0L; /****** NO CHECKSUM ******/
782
23.9k
    ulong loca_checksum[2] = {0L,0L};
783
23.9k
    ulong glyf_alignment = 0;
784
23.9k
    uint numGlyphs = 0;   /* original value from maxp */
785
23.9k
    byte head[56];    /* 0 mod 4 */
786
23.9k
    gs_type42_mtx_t mtx[2];
787
23.9k
    post_t post;
788
23.9k
    ulong head_checksum, file_checksum = 0;
789
23.9k
    int indexToLocFormat = 0;
790
23.9k
    bool
791
23.9k
        writing_cid = (options & WRITE_TRUETYPE_CID) != 0,
792
23.9k
        writing_stripped = (options & WRITE_TRUETYPE_STRIPPED) != 0,
793
23.9k
        generate_mtx = (options & WRITE_TRUETYPE_HVMTX) != 0,
794
23.9k
        no_generate = writing_cid | writing_stripped,
795
23.9k
        have_cmap = no_generate,
796
23.9k
        have_name = !(options & WRITE_TRUETYPE_NAME),
797
23.9k
        have_OS_2 = no_generate,
798
23.9k
        have_post = no_generate;
799
23.9k
    int have_hvhea[2];
800
23.9k
    uint cmap_length = 0;
801
23.9k
    ulong OS_2_start = 0;
802
23.9k
    uint OS_2_length = OS_2_LENGTH1;
803
23.9k
    ulong maxp_start = 0;
804
23.9k
    struct { int glyf, loca, cmap, name, os_2, mtx[2], post, head;
805
23.9k
           } subtable_positions;
806
23.9k
    gs_offset_t start_position = stell(s);
807
23.9k
    int enlarged_numGlyphs = 0;
808
23.9k
    int code;
809
23.9k
    int TTCFontOffset = 0;
810
811
23.9k
    memset(&subtable_positions, 0, sizeof(subtable_positions));
812
23.9k
    have_hvhea[0] = have_hvhea[1] = 0;
813
23.9k
    if (alt_font_name)
814
4.95k
        font_name = *alt_font_name;
815
19.0k
    else
816
19.0k
        font_name.data = font->font_name.chars,
817
19.0k
            font_name.size = font->font_name.size;
818
819
    /*
820
     * Count the number of tables, including the eventual glyf and loca
821
     * (which may not actually be present in the font), and copy the
822
     * table directory.
823
     */
824
825
23.9k
#define W(a,b,c,d)\
826
659k
  ( ((a) << 24) + ((b) << 16) + ((c) << 8) + (d))
827
828
23.9k
    READ_SFNTS(pfont, 0, 12, OffsetTable);
829
23.9k
    if (u32(OffsetTable) == W('t','t','c','f')) {
830
0
        READ_SFNTS(pfont, 12, 4, OffsetTable);
831
0
        TTCFontOffset = u32(OffsetTable);
832
0
        READ_SFNTS(pfont, TTCFontOffset, 12, OffsetTable);
833
0
    }
834
23.9k
    numTables_stored = U16(OffsetTable + 4);
835
320k
    for (i = numTables = 0; i < numTables_stored; ++i) {
836
296k
        byte tab[16];
837
296k
        byte data[54];
838
296k
        ulong start;
839
296k
        uint length;
840
841
296k
        if (numTables == MAX_NUM_TT_TABLES)
842
0
            return_error(gs_error_limitcheck);
843
296k
        READ_SFNTS(pfont, TTCFontOffset + 12 + i * 16, 16, tab);
844
296k
        start = u32(tab + 8);
845
296k
        length = u32(tab + 12);
846
        /* Copy the table data now (a rudiment of old code). */
847
296k
        memcpy(&tables[numTables * 16], tab, 16);
848
296k
        switch (u32(tab)) {
849
23.9k
        case W('h','e','a','d'):
850
23.9k
            if (length < 54)
851
0
                return_error(gs_error_invalidfont);
852
23.9k
            length = 54; /* bug 688409 fig2.eps has length=56. */
853
23.9k
            READ_SFNTS(pfont, start, length, data);
854
23.9k
            memcpy(head, data, length);
855
23.9k
            continue;
856
19.0k
        case W('g','l','y','f'): /* synthesized */
857
19.0k
        case W('g','l','y','x'): /* Adobe bogus */
858
38.0k
        case W('l','o','c','a'): /* synthesized */
859
38.0k
        case W('l','o','c','x'): /* Adobe bogus */
860
38.0k
        case W('g','d','i','r'): /* Adobe marker */
861
38.0k
            continue;
862
23.6k
        case W('c','m','a','p'):
863
23.6k
            if (options & (WRITE_TRUETYPE_CMAP | WRITE_TRUETYPE_CID))
864
5.44k
                continue;
865
18.2k
            have_cmap = true;
866
18.2k
            break;
867
23.9k
        case W('m','a','x','p'):
868
23.9k
            READ_SFNTS(pfont, start, length, data);
869
23.9k
            numGlyphs = U16(data + 4);
870
23.9k
            maxp_start = start;
871
23.9k
            break;
872
23.7k
        case W('n','a','m','e'):
873
23.7k
            if (writing_cid)
874
700
                continue;
875
23.0k
            have_name = true;
876
23.0k
            break;
877
16.3k
        case W('O','S','/','2'):
878
16.3k
            if (writing_cid)
879
688
                continue;
880
15.7k
            have_OS_2 = true;
881
15.7k
            if (length > OS_2_LENGTH5)
882
0
                return_error(gs_error_invalidfont);
883
15.7k
            OS_2_start = start;
884
15.7k
            OS_2_length = length;
885
15.7k
            continue;
886
23.0k
        case W('p','o','s','t'):
887
23.0k
            have_post = true;
888
23.0k
            break;
889
23.9k
        case W('h','h','e','a'):
890
23.9k
            have_hvhea[0] = 1;
891
23.9k
            break;
892
0
        case W('v','h','e','a'):
893
0
            have_hvhea[1] = 1;
894
0
            break;
895
23.9k
        case W('h','m','t','x'):
896
23.9k
        case W('v','m','t','x'):
897
23.9k
            if (generate_mtx)
898
4.95k
                continue;
899
            /* falls through */
900
42.9k
        case W('c','v','t',' '):
901
66.7k
        case W('f','p','g','m'):
902
90.5k
        case W('p','r','e','p'):
903
90.5k
            break;    /* always copy these if present */
904
144
        case W('D','S','I','G'):
905
176
        case W('E','B','D','T'):
906
208
        case W('E','B','L','C'):
907
208
        case W('E','B','S','C'):
908
352
        case W('G','D','E','F'):
909
482
        case W('G','P','O','S'):
910
1.24k
        case W('g','a','s','p'):
911
1.54k
        case W('k','e','r','n'):
912
1.54k
            continue;
913
2.51k
        default:
914
2.51k
            if (writing_cid)
915
334
                continue;
916
2.17k
            break;
917
296k
        }
918
205k
        numTables++;
919
205k
    }
920
921
    /*
922
     * Enumerate the glyphs to get the size of glyf and loca,
923
     * and to compute the checksums for these tables.
924
     */
925
926
    /****** NO CHECKSUMS YET ******/
927
23.9k
    for (max_glyph = 0, glyf_length = 0;
928
142k
         (code = psf_enumerate_glyphs_next(penum, &glyph)) != 1;
929
118k
         ) {
930
118k
        uint glyph_index;
931
118k
        gs_glyph_data_t glyph_data;
932
933
118k
        if (glyph < GS_MIN_CID_GLYPH)
934
0
            return_error(gs_error_invalidfont);
935
118k
        glyph_index = glyph  & ~GS_GLYPH_TAG;
936
118k
        if_debug1m('L', s->memory, "[L]glyph_index %u\n", glyph_index);
937
118k
        glyph_data.memory = pfont->memory;
938
118k
        if ((code = pfont->data.get_outline(pfont, glyph_index, &glyph_data)) >= 0) {
939
            /* Since indexToLocFormat==0 assumes even glyph lengths,
940
               round it up here. If later we choose indexToLocFormat==1,
941
               subtract the glyf_alignment to compensate it. */
942
118k
            uint l = (glyph_data.bits.size + 1) & ~1;
943
944
118k
            max_glyph = max(max_glyph, glyph_index);
945
118k
            glyf_length += l;
946
118k
            if (l != glyph_data.bits.size)
947
26
                glyf_alignment++;
948
118k
            if_debug1m('L', s->memory, "[L]  size %u\n", glyph_data.bits.size);
949
118k
            gs_glyph_data_free(&glyph_data, "psf_write_truetype_data");
950
118k
        }
951
118k
    }
952
23.9k
    if (writing_stripped) {
953
19.0k
        glyf_length = 0;
954
19.0k
        loca_length = 0;
955
19.0k
    } else {
956
4.95k
        if (max_glyph + 1 > numGlyphs) {
957
            /* Either original font is wrong,
958
               or we added glyphs to it due to font merge.
959
               Need to adjust maxp, hmtx, vmtx, vdmx, hdmx,
960
               assuming that the merge doesn't change hhea
961
               and other tables.
962
               Since changing hdmx, vdmx is too difficult,
963
               and since they're not required for PDF,
964
               we'll simply skip them.
965
             */
966
149
            enlarged_numGlyphs = max_glyph + 1;
967
149
            if (enlarged_numGlyphs > 0xFFFF) {
968
0
                emprintf1(pfont->memory,
969
0
                          "The number of glyphs %d exceeds capability of True Type format.\n",
970
0
                          enlarged_numGlyphs);
971
0
                return_error(gs_error_unregistered);
972
0
            }
973
149
            loca_length = (enlarged_numGlyphs + 1) << 2;
974
149
            remove_table(tables, (char *)"hdmx", &numTables);
975
149
            remove_table(tables, (char *)"vdmx", &numTables);
976
149
        } else
977
4.80k
            loca_length = (numGlyphs + 1) << 2;
978
4.95k
        indexToLocFormat = (glyf_length > 0x1fffc);
979
4.95k
        if (!indexToLocFormat)
980
4.95k
            loca_length >>= 1;
981
0
        else
982
0
            glyf_length -= glyf_alignment;
983
        /* Acrobat Reader won't accept fonts with empty glyfs. */
984
4.95k
        if (glyf_length == 0)
985
1.08k
            glyf_length = 1;
986
4.95k
    }
987
23.9k
    if_debug2m('l', s->memory, "[l]max_glyph = %lu, glyf_length = %lu\n",
988
23.9k
               (ulong)max_glyph, (ulong)glyf_length);
989
990
    /*
991
     * If necessary, compute the length of the post table.  Note that we
992
     * only generate post entries for characters in the Encoding.  */
993
994
23.9k
    if (!have_post) {
995
166
        memset(&post, 0, sizeof(post));
996
166
        if (options & WRITE_TRUETYPE_POST) {
997
0
            code = compute_post(font, &post);
998
0
            if (code < 0)
999
0
                return code;
1000
0
        } else
1001
166
            post.length = 32; /* dummy table */
1002
166
    }
1003
1004
    /* Fix up the head table. */
1005
1006
23.9k
    memset(head + 8, 0, 4);
1007
23.9k
    head[50] = 0x00;
1008
23.9k
    head[51] = (byte)indexToLocFormat;
1009
23.9k
    memset(head + 54, 0, 2);
1010
359k
    for (head_checksum = 0, i = 0; i < 56; i += 4)
1011
335k
        head_checksum += u32(&head[i]);
1012
1013
    /*
1014
     * Construct the table directory, except for glyf, loca, head, OS/2,
1015
     * and, if necessary, generated cmap, name, and post tables.
1016
     * Note that the existing directory is already sorted by tag.
1017
     */
1018
1019
23.9k
    numTables_out = numTables + 1 /* head */
1020
23.9k
        + !writing_stripped * 2 /* glyf, loca */
1021
23.9k
        + generate_mtx * (have_hvhea[0] + have_hvhea[1]) /* hmtx, vmtx */
1022
23.9k
        + !have_OS_2    /* OS/2 */
1023
23.9k
        + !have_cmap + !have_name + !have_post;
1024
23.9k
    if (numTables_out >= MAX_NUM_TT_TABLES)
1025
0
        return_error(gs_error_limitcheck);
1026
23.9k
    offset = 12 + numTables_out * 16;
1027
229k
    for (i = 0; i < numTables; ++i) {
1028
205k
        byte *tab = &tables[i * 16];
1029
205k
        ulong length = u32(tab + 12);
1030
1031
205k
        offset += round_up(length, 4);
1032
205k
    }
1033
1034
    /* Make the table directory entries for generated tables. */
1035
1036
23.9k
    {
1037
23.9k
        byte *tab = &tables[numTables * 16];
1038
1039
23.9k
        if (!writing_stripped) {
1040
4.95k
            subtable_positions.glyf = offset;
1041
4.95k
            offset = put_table(tab, "glyf", glyf_checksum,
1042
4.95k
                               offset, glyf_length);
1043
4.95k
            tab += 16;
1044
4.95k
            subtable_positions.loca = offset;
1045
4.95k
            offset = put_table(tab, "loca", loca_checksum[indexToLocFormat],
1046
4.95k
                               offset, loca_length);
1047
4.95k
            tab += 16;
1048
4.95k
        }
1049
1050
23.9k
        if (!have_cmap) {
1051
4.78k
            cmap_length = size_cmap(font, TT_BIAS, 256,
1052
4.78k
                                    GS_MIN_GLYPH_INDEX + max_glyph, options);
1053
4.78k
            subtable_positions.cmap = offset;
1054
4.78k
            offset = put_table(tab, "cmap", 0L /****** NO CHECKSUM ******/,
1055
4.78k
                               offset, cmap_length);
1056
4.78k
            tab += 16;
1057
4.78k
        }
1058
1059
23.9k
        if (!have_name) {
1060
16
            subtable_positions.name = offset;
1061
16
            offset = put_table(tab, "name", 0L /****** NO CHECKSUM ******/,
1062
16
                               offset, size_name(&font_name));
1063
16
            tab += 16;
1064
16
        }
1065
1066
23.9k
        if (!no_generate) {
1067
4.78k
            subtable_positions.os_2 = offset;
1068
4.78k
            offset = put_table(tab, "OS/2", 0L /****** NO CHECKSUM ******/,
1069
4.78k
                               offset, OS_2_length);
1070
4.78k
            tab += 16;
1071
4.78k
        }
1072
1073
23.9k
        if (generate_mtx)
1074
14.8k
            for (i = 0; i < 2; ++i)
1075
9.91k
                if (have_hvhea[i]) {
1076
4.95k
                    subtable_positions.mtx[i] = offset;
1077
4.95k
                    offset = put_table(tab, (i ? "vmtx" : "hmtx"),
1078
4.95k
                                       0L /****** NO CHECKSUM ******/,
1079
4.95k
                                       offset,
1080
4.95k
                                       size_mtx(pfont, &mtx[i], max_glyph, numGlyphs, i));
1081
4.95k
                    tab += 16;
1082
4.95k
                }
1083
1084
23.9k
        if (!have_post) {
1085
166
            subtable_positions.post = offset;
1086
166
            offset = put_table(tab, "post", 0L /****** NO CHECKSUM ******/,
1087
166
                               offset, post.length);
1088
166
            tab += 16;
1089
166
        }
1090
1091
        /*
1092
         * Note that the 'head' table must have length 54, even though
1093
         * it occupies 56 bytes on the file.
1094
         */
1095
23.9k
        subtable_positions.head = offset;
1096
23.9k
        (void)put_table(tab, "head", head_checksum, offset, 54);
1097
23.9k
    }
1098
23.9k
    numTables = numTables_out;
1099
1100
    /* Write the font header. */
1101
1102
23.9k
    {
1103
23.9k
        static const byte version[4] = {0, 1, 0, 0};
1104
1105
23.9k
        stream_write(s, version, 4);
1106
23.9k
    }
1107
23.9k
    put_ushort(s, numTables);
1108
119k
    for (i = 0; 1 << i <= numTables; ++i)
1109
95.9k
        DO_NOTHING;
1110
23.9k
    --i;
1111
23.9k
    put_ushort(s, 16 << i); /* searchRange */
1112
23.9k
    put_ushort(s, i);   /* entrySelectors */
1113
23.9k
    put_ushort(s, numTables * 16 - (16 << i)); /* rangeShift */
1114
1115
    /* Write the table directory. */
1116
1117
23.9k
    qsort(tables, numTables, 16, compare_table_tags);
1118
23.9k
    offset = 12 + numTables * 16;
1119
277k
    for (i = 0; i < numTables; ++i) {
1120
253k
        const byte *tab = &tables[i * 16];
1121
253k
        byte entry[16];
1122
1123
253k
        memcpy(entry, tab, 16);
1124
253k
        if (entry[8] < 0x40) {
1125
            /* Not a generated table. */
1126
204k
            uint length = u32(tab + 12);
1127
1128
204k
            put_u32(entry + 8, offset);
1129
204k
            offset += round_up(length, 4);
1130
204k
        } else {
1131
48.7k
            entry[8] -= 0x40;
1132
48.7k
        }
1133
253k
        stream_write(s, entry, 16);
1134
253k
    }
1135
1136
    /* Write tables other than the ones we generate here. */
1137
1138
277k
    for (i = 0; i < numTables; ++i) {
1139
253k
        const byte *tab = &tables[i * 16];
1140
1141
253k
        if (tab[8] < 0x40) {
1142
204k
            ulong start = u32(tab + 8);
1143
204k
            uint length = u32(tab + 12);
1144
1145
204k
            switch (u32(tab)) {
1146
0
            case W('O','S','/','2'):
1147
0
                if (!have_cmap) {
1148
                    /*
1149
                     * Adjust the first and last character indices in the OS/2
1150
                     * table to reflect the values in the generated cmap.
1151
                     */
1152
0
                    byte pos2[OS_2_LENGTH5];
1153
0
                    ttf_OS_2_t os2;
1154
1155
0
                    READ_SFNTS(pfont, OS_2_start, OS_2_length, pos2);
1156
0
                    memcpy(&os2, pos2, min(OS_2_length, sizeof(os2)));
1157
0
                    update_OS_2(&os2, TT_BIAS, 256);
1158
0
                    stream_write(s, &os2, OS_2_length);
1159
0
                    put_pad(s, OS_2_length);
1160
0
                } else {
1161
                    /* Just copy the existing OS/2 table. */
1162
0
                    write_range(s, pfont, OS_2_start, OS_2_length);
1163
0
                    put_pad(s, OS_2_length);
1164
0
                }
1165
0
            break;
1166
23.9k
            case W('m','a','x','p'):
1167
23.9k
                if (enlarged_numGlyphs) {
1168
                    /* Must keep the table size. */
1169
149
                    byte buf[6];
1170
1171
149
                    READ_SFNTS(pfont, maxp_start, sizeof(buf), buf);
1172
149
                    put_u16(buf + 4, enlarged_numGlyphs);
1173
149
                    stream_write(s, buf, min(length, sizeof(buf)));
1174
149
                    if (length > sizeof(buf)) /* Paranoid Safety */
1175
0
                        write_range(s, pfont, start + sizeof(buf), length - sizeof(buf));
1176
149
                } else
1177
23.8k
                    write_range(s, pfont, start, length);
1178
23.9k
                break;
1179
23.9k
            case W('h','h','e','a'):
1180
23.9k
            case W('v','h','e','a'):
1181
23.9k
                if (generate_mtx) {
1182
4.95k
                    write_range(s, pfont, start, length - 2); /* 34 */
1183
4.95k
                    put_ushort(s, mtx[tab[0] == 'v'].numMetrics);
1184
4.95k
                    break;
1185
4.95k
                }
1186
                /* falls through */
1187
176k
            default:
1188
176k
                write_range(s, pfont, start, length);
1189
204k
            }
1190
204k
            put_pad(s, length);
1191
204k
        }
1192
253k
    }
1193
1194
23.9k
    if (!writing_stripped) {
1195
4.95k
        int n = max(numGlyphs, enlarged_numGlyphs) + 1;
1196
1197
        /* Write glyf. */
1198
1199
4.95k
        if (check_position(pfont->memory,
1200
4.95k
                           subtable_positions.glyf + start_position,
1201
4.95k
                           stell(s)))
1202
0
            return_error(gs_error_unregistered);
1203
4.95k
        psf_enumerate_glyphs_reset(penum);
1204
123k
        for (offset = 0; psf_enumerate_glyphs_next(penum, &glyph) != 1; ) {
1205
118k
            gs_glyph_data_t glyph_data;
1206
1207
118k
            glyph_data.memory = pfont->memory;
1208
118k
            if ((code = pfont->data.get_outline(pfont,
1209
118k
                                                glyph & ~GS_GLYPH_TAG,
1210
118k
                                                &glyph_data)) >= 0
1211
118k
                ) {
1212
118k
                uint l = glyph_data.bits.size, zero = 0;
1213
1214
118k
                if (!indexToLocFormat)
1215
118k
                    l = (l + 1) & ~1;
1216
118k
                stream_write(s, glyph_data.bits.data, glyph_data.bits.size);
1217
118k
                if (glyph_data.bits.size < l)
1218
26
                    stream_write(s, &zero, 1);
1219
118k
                offset += l;
1220
118k
                if_debug2m('L', s->memory, "[L]glyf index = %u, size = %u\n",
1221
118k
                          i, glyph_data.bits.size);
1222
118k
                gs_glyph_data_free(&glyph_data, "psf_write_truetype_data");
1223
118k
            }
1224
118k
        }
1225
4.95k
        if_debug1m('l', s->memory, "[l]glyf final offset = %lu\n", offset);
1226
        /* Add a dummy byte if necessary to make glyf non-empty. */
1227
6.04k
        while (offset < glyf_length)
1228
1.08k
            stream_putc(s, 0), ++offset;
1229
4.95k
        put_pad(s, (uint)offset);
1230
1231
        /* Write loca. */
1232
1233
4.95k
        if (check_position(pfont->memory,
1234
4.95k
                           subtable_positions.loca + start_position,
1235
4.95k
                           stell(s)))
1236
0
            return_error(gs_error_unregistered);
1237
4.95k
        psf_enumerate_glyphs_reset(penum);
1238
4.95k
        glyph_prev = 0;
1239
123k
        for (offset = 0; psf_enumerate_glyphs_next(penum, &glyph) != 1; ) {
1240
118k
            gs_glyph_data_t glyph_data;
1241
118k
            uint glyph_index = glyph & ~GS_GLYPH_TAG;
1242
1243
1.72M
            for (; glyph_prev <= glyph_index; ++glyph_prev)
1244
1.60M
                put_loca(s, offset, indexToLocFormat);
1245
118k
            glyph_data.memory = pfont->memory;
1246
118k
            if ((code = pfont->data.get_outline(pfont, glyph_index,
1247
118k
                                                &glyph_data)) >= 0
1248
118k
                ) {
1249
118k
                uint l = glyph_data.bits.size;
1250
1251
118k
                if (!indexToLocFormat)
1252
118k
                    l = (l + 1) & ~1;
1253
118k
                offset += l;
1254
118k
                gs_glyph_data_free(&glyph_data, "psf_write_truetype_data");
1255
118k
            }
1256
1257
118k
        }
1258
        /* Pad to numGlyphs + 1 entries (including the trailing entry). */
1259
10.8M
        for (; glyph_prev < n; ++glyph_prev)
1260
10.8M
            put_loca(s, offset, indexToLocFormat);
1261
4.95k
        put_pad(s, loca_length);
1262
1263
        /* If necessary, write cmap, name, and OS/2. */
1264
1265
4.95k
        if (!have_cmap) {
1266
4.78k
            if (check_position(pfont->memory,
1267
4.78k
                               subtable_positions.cmap + start_position,
1268
4.78k
                               stell(s)))
1269
0
                return_error(gs_error_unregistered);
1270
4.78k
            write_cmap(s, font, TT_BIAS, 256, GS_MIN_GLYPH_INDEX + max_glyph,
1271
4.78k
                       options, cmap_length);
1272
4.78k
        }
1273
4.95k
        if (!have_name) {
1274
16
            if (check_position(pfont->memory,
1275
16
                               subtable_positions.name + start_position,
1276
16
                               stell(s)))
1277
0
                return_error(gs_error_unregistered);
1278
16
            write_name(s, &font_name);
1279
16
        }
1280
4.95k
        if (!have_OS_2) {
1281
4.78k
            if (check_position(pfont->memory,
1282
4.78k
                               subtable_positions.os_2 + start_position,
1283
4.78k
                               stell(s)))
1284
0
                return_error(gs_error_unregistered);
1285
4.78k
            write_OS_2(s, font, TT_BIAS, 256);
1286
4.78k
        }
1287
1288
        /* If necessary, write [hv]mtx. */
1289
1290
4.95k
        if (generate_mtx)
1291
14.8k
            for (i = 0; i < 2; ++i)
1292
9.91k
                if (have_hvhea[i]) {
1293
4.95k
                    if (check_position(pfont->memory,
1294
4.95k
                                       subtable_positions.mtx[i] + start_position,
1295
4.95k
                                       stell(s)))
1296
0
                        return_error(gs_error_unregistered);
1297
4.95k
                    write_mtx(s, pfont, &mtx[i], i);
1298
4.95k
                    put_pad(s, mtx[i].length);
1299
4.95k
                }
1300
1301
        /* If necessary, write post. */
1302
1303
4.95k
        if (!have_post) {
1304
166
            if (check_position(pfont->memory,
1305
166
                               subtable_positions.post + start_position,
1306
166
                               stell(s)))
1307
0
                return_error(gs_error_unregistered);
1308
166
            if (options & WRITE_TRUETYPE_POST) {
1309
0
                code = write_post(s, font, &post);
1310
0
                if (code < 0)
1311
0
                    return code;
1312
166
            } else {
1313
166
                byte post_initial[32 + 2];
1314
1315
166
                memset(post_initial, 0, 32);
1316
166
                put_u32(post_initial, 0x00030000);
1317
166
                stream_write(s, post_initial, 32);
1318
166
            }
1319
166
        }
1320
4.95k
    }
1321
1322
    /* Write head. */
1323
1324
    /****** CHECKSUM WAS NEVER COMPUTED ******/
1325
    /*
1326
     * The following nonsense is to avoid warnings about the constant
1327
     * 0xb1b0afbaL being "unsigned in ANSI C, signed with -traditional".
1328
     */
1329
23.9k
#if ARCH_SIZEOF_LONG > ARCH_SIZEOF_INT
1330
23.9k
#  define HEAD_MAGIC 0xb1b0afbaL
1331
#else
1332
#  define HEAD_MAGIC ((ulong)~0x4e4f5045)
1333
#endif
1334
23.9k
    put_u32(head + 8, HEAD_MAGIC - file_checksum); /* per spec */
1335
23.9k
#undef HEAD_MAGIC
1336
23.9k
    if (check_position(pfont->memory,
1337
23.9k
                       subtable_positions.head + start_position,
1338
23.9k
                       stell(s)))
1339
1.40k
        return_error(gs_error_unregistered);
1340
22.5k
    stream_write(s, head, 56);
1341
1342
22.5k
    return 0;
1343
23.9k
}
1344
1345
/* Write a TrueType font. */
1346
int
1347
psf_write_truetype_font(stream *s, gs_font_type42 *pfont, int options,
1348
                        gs_glyph *orig_subset_glyphs, uint orig_subset_size,
1349
                        const gs_const_string *alt_font_name)
1350
4.78k
{
1351
4.78k
    gs_font *const font = (gs_font *)pfont;
1352
4.78k
    psf_glyph_enum_t genum;
1353
4.78k
    gs_glyph subset_data[256 * MAX_COMPOSITE_PIECES];
1354
4.78k
    gs_glyph *subset_glyphs = orig_subset_glyphs;
1355
4.78k
    uint subset_size = orig_subset_size;
1356
1357
    /* Sort the subset glyphs, if any. */
1358
1359
4.78k
    if (subset_glyphs) {
1360
        /* Add the component glyphs for composites. */
1361
0
        int code;
1362
1363
0
        memcpy(subset_data, orig_subset_glyphs,
1364
0
               sizeof(gs_glyph) * subset_size);
1365
0
        subset_glyphs = subset_data;
1366
0
        code = psf_add_subset_pieces(subset_glyphs, &subset_size,
1367
0
                                     countof(subset_data),
1368
0
                                     countof(subset_data),
1369
0
                                     font);
1370
0
        if (code < 0)
1371
0
            return code;
1372
0
        subset_size = psf_sort_glyphs(subset_glyphs, subset_size);
1373
0
    }
1374
4.78k
    psf_enumerate_glyphs_begin(&genum, font, subset_glyphs,
1375
4.78k
                               (subset_glyphs ? subset_size : 0),
1376
4.78k
                               GLYPH_SPACE_INDEX);
1377
4.78k
    return psf_write_truetype_data(s, pfont, options & ~WRITE_TRUETYPE_CID,
1378
4.78k
                                   &genum, subset_glyphs != 0, alt_font_name);
1379
4.78k
}
1380
/* Write a stripped TrueType font. */
1381
int
1382
psf_write_truetype_stripped(stream *s, gs_font_type42 *pfont)
1383
18.2k
{
1384
18.2k
    psf_glyph_enum_t genum;
1385
18.2k
    byte no_subset = 0;
1386
1387
18.2k
    psf_enumerate_bits_begin(&genum, (gs_font *)pfont, &no_subset, 0,
1388
18.2k
                             GLYPH_SPACE_INDEX);
1389
18.2k
    return psf_write_truetype_data(s, pfont, WRITE_TRUETYPE_STRIPPED,
1390
18.2k
                                   &genum, true, NULL);
1391
18.2k
}
1392
1393
/* Write a CIDFontType 2 font. */
1394
int
1395
psf_write_cid2_font(stream *s, gs_font_cid2 *pfont, int options,
1396
                    const byte *subset_bits, uint subset_size,
1397
                    const gs_const_string *alt_font_name)
1398
170
{
1399
170
    gs_font *const font = (gs_font *)pfont;
1400
170
    psf_glyph_enum_t genum;
1401
1402
170
    psf_enumerate_bits_begin(&genum, font, subset_bits,
1403
170
                             (subset_bits ? subset_size : 0),
1404
170
                             GLYPH_SPACE_INDEX);
1405
170
    return psf_write_truetype_data(s, (gs_font_type42 *)font,
1406
170
                                   options | WRITE_TRUETYPE_CID, &genum,
1407
170
                                   subset_bits != 0, alt_font_name);
1408
170
}
1409
1410
/* Write a stripped CIDFontType 2 font. */
1411
int
1412
psf_write_cid2_stripped(stream *s, gs_font_cid2 *pfont)
1413
774
{
1414
774
    gs_font *const font = (gs_font *)pfont;
1415
774
    psf_glyph_enum_t genum;
1416
774
    byte no_subset = 0;
1417
1418
774
    psf_enumerate_bits_begin(&genum, font, &no_subset, 0,
1419
774
                             GLYPH_SPACE_INDEX);
1420
774
    return psf_write_truetype_data(s, (gs_font_type42 *)font,
1421
774
                                   WRITE_TRUETYPE_STRIPPED |
1422
774
                                     WRITE_TRUETYPE_CID,
1423
774
                                   &genum, true, NULL);
1424
774
}