Coverage Report

Created: 2025-06-10 07:27

/src/ghostpdl/devices/vector/gdevpdtd.c
Line
Count
Source (jump to first uncovered line)
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
/* FontDescriptor implementation for pdfwrite */
18
#include "math_.h"
19
#include "memory_.h"
20
#include "gx.h"
21
#include "gserrors.h"
22
#include "gsrect.h"   /* for rect_merge */
23
#include "gscencs.h"
24
#include "gxfcopy.h"
25
#include "gdevpdfx.h"
26
#include "gdevpdfo.h"   /* for object->written */
27
#include "gdevpdtb.h"
28
#include "gdevpdtd.h"
29
#include "gdevpdtf.h"
30
31
/* ================ Types and structures ================ */
32
33
/*
34
 * There are many different flavors of FontDescriptor.  The first division
35
 * is between FontDescriptors for actual fonts, and character class entries
36
 * in the FD dictionary of a CID-keyed font.  The latter include metrics and
37
 * a FontName but nothing else.  We represent these with a different C
38
 * structure (pdf_sub_font_descriptor_t).
39
 *
40
 * Descriptors for actual fonts have three major orthogonal properties:
41
 *
42
 *  - Whether they represent a CID-keyed font or a name-keyed
43
 *    (non-CID-keyed) font.  We distinguish this by the FontType
44
 *    of the saved font (see below).
45
 *
46
 *  - Whether the font they represent is embedded.
47
 *
48
 *  - Whether the font they represent is a complete font or a subset.
49
 *    We always track which glyphs in a font are used: client code
50
 *    decides whether to treat the font as a subset when the
51
 *    descriptor (and, if embedded, the font) is written.
52
 *
53
 * Note that non-embedded fonts in the base set of 14 do not have
54
 * descriptors, nor do Type 0 or (synthetic bitmap) Type 3 fonts.
55
 */
56
/* Flag bits */
57
/*#define FONT_IS_FIXED_WIDTH (1<<0)*/  /* defined in gxfont.h */
58
3.21k
#define FONT_IS_SERIF (1<<1)
59
633k
#define FONT_IS_SYMBOLIC (1<<2)
60
#define FONT_IS_SCRIPT (1<<3)
61
/*
62
 * There is confusion over the meaning of the 1<<5 bit.  According to the
63
 * published PDF documentation, in PDF 1.1, it meant "font uses
64
 * StandardEncoding", and as of PDF 1.2, it means "font uses (a subset of)
65
 * the Adobe standard Latin character set"; however, Acrobat Reader 3 and 4
66
 * seem to use the former interpretation, even if the font is embedded and
67
 * the file is identified as a PDF 1.2 file.  We have to use the former
68
 * interpretation in order to produce output that Acrobat will handle
69
 * correctly.
70
 */
71
0
#define FONT_USES_STANDARD_ENCODING (1<<5) /* always used */
72
35.4k
#define FONT_IS_ADOBE_ROMAN (1<<5) /* never used */
73
180
#define FONT_IS_ITALIC (1<<6)
74
39.8k
#define FONT_IS_ALL_CAPS (1<<16)
75
4.30k
#define FONT_IS_SMALL_CAPS (1<<17)
76
#define FONT_IS_FORCE_BOLD (1<<18)
77
78
/*
79
 * Define a sub-descriptor for a character class (FD dictionary element).
80
 */
81
typedef struct pdf_sub_font_descriptor_s {
82
    pdf_font_descriptor_common_t common;
83
} pdf_sub_font_descriptor_t;
84
85
/*
86
 * Font descriptors are pseudo-resources, so their GC descriptors
87
 * must be public.
88
 */
89
BASIC_PTRS(pdf_font_descriptor_ptrs) {
90
    GC_STRING_ELT(pdf_font_descriptor_t, common.values.FontName),
91
    GC_OBJ_ELT(pdf_font_descriptor_t, base_font),
92
    GC_OBJ_ELT(pdf_font_descriptor_t, cid.Style),
93
    GC_OBJ_ELT(pdf_font_descriptor_t, cid.FD)
94
};
95
gs_public_st_basic_super(st_pdf_font_descriptor, pdf_font_descriptor_t,
96
  "pdf_font_descriptor_t", pdf_font_descriptor_ptrs,
97
  pdf_font_descriptor_data, &st_pdf_resource, 0);
98
99
/*
100
 * Sub-font descriptors are also pseudo-resources.
101
 */
102
BASIC_PTRS(pdf_sub_font_descriptor_ptrs) {
103
    GC_STRING_ELT(pdf_sub_font_descriptor_t, common.values.FontName)
104
};
105
gs_public_st_basic_super(st_pdf_sub_font_descriptor,
106
  pdf_sub_font_descriptor_t, "pdf_sub_font_descriptor_t",
107
  pdf_sub_font_descriptor_ptrs, pdf_sub_font_descriptor_data,
108
  &st_pdf_resource, 0);
109
110
/* ================ Procedures ================ */
111
112
/* ---------------- Private ---------------- */
113
114
/* Get the ID of font descriptor metrics. */
115
static inline int64_t
116
pdf_font_descriptor_common_id(const pdf_font_descriptor_common_t *pfdc)
117
28.2k
{
118
28.2k
    return pdf_resource_id((const pdf_resource_t *)pfdc);
119
28.2k
}
120
121
/* Write the common part of a FontDescriptor, aside from the final >>. */
122
static int
123
write_FontDescriptor_common(gx_device_pdf *pdev,
124
                            const pdf_font_descriptor_common_t *pfd, bool embed)
125
28.2k
{
126
28.2k
    stream *s;
127
28.2k
    int code;
128
28.2k
    param_printer_params_t params;
129
28.2k
    printer_param_list_t rlist;
130
28.2k
    gs_param_list *const plist = (gs_param_list *)&rlist;
131
28.2k
    char *base14_name = NULL;
132
133
28.2k
    pdf_open_separate(pdev, pdf_font_descriptor_common_id(pfd), resourceFontDescriptor);
134
28.2k
    s = pdev->strm;
135
28.2k
    stream_puts(s, "<</Type/FontDescriptor/FontName");
136
28.2k
    if (!embed) {
137
15
        base14_name = (char *)pdf_find_base14_name(pfd->values.FontName.data, pfd->values.FontName.size);
138
15
        if(base14_name)
139
0
            pdf_put_name(pdev, (byte *)base14_name, strlen(base14_name));
140
15
        else
141
15
            pdf_put_name(pdev, pfd->values.FontName.data, pfd->values.FontName.size);
142
15
    } else
143
28.2k
        pdf_put_name(pdev, pfd->values.FontName.data, pfd->values.FontName.size);
144
145
28.2k
    pdf_write_font_bbox(pdev, &pfd->values.FontBBox);
146
28.2k
    params = param_printer_params_default;
147
28.2k
    code = s_init_param_printer(&rlist, &params, s);
148
28.2k
    if (code >= 0) {
149
28.2k
#define DESC_INT(str, memb)\
150
311k
 {str, gs_param_type_int, offset_of(pdf_font_descriptor_common_t, values.memb)}
151
28.2k
        static const gs_param_item_t required_items[] = {
152
28.2k
            DESC_INT("Ascent", Ascent),
153
28.2k
            DESC_INT("CapHeight", CapHeight),
154
28.2k
            DESC_INT("Descent", Descent),
155
28.2k
            DESC_INT("ItalicAngle", ItalicAngle),
156
28.2k
            DESC_INT("StemV", StemV),
157
28.2k
            gs_param_item_end
158
28.2k
        };
159
28.2k
        static const gs_param_item_t optional_items[] = {
160
28.2k
            DESC_INT("AvgWidth", AvgWidth),
161
28.2k
            DESC_INT("Leading", Leading),
162
28.2k
            DESC_INT("MaxWidth", MaxWidth),
163
28.2k
            DESC_INT("MissingWidth", MissingWidth),
164
28.2k
            DESC_INT("StemH", StemH),
165
28.2k
            DESC_INT("XHeight", XHeight),
166
28.2k
            gs_param_item_end
167
28.2k
        };
168
28.2k
#undef DESC_INT
169
28.2k
        int Flags = pfd->values.Flags;
170
28.2k
        pdf_font_descriptor_t defaults;
171
172
28.2k
        if (base14_name)
173
0
            Flags |=FONT_USES_STANDARD_ENCODING;
174
175
28.2k
        code = param_write_int(plist, "Flags", &Flags);
176
28.2k
        if (code < 0)
177
0
            return code;
178
28.2k
        code = gs_param_write_items(plist, pfd, NULL, required_items);
179
28.2k
        if (code < 0)
180
0
            return code;
181
28.2k
        memset(&defaults, 0, sizeof(defaults));
182
28.2k
        code = gs_param_write_items(plist, pfd, &defaults, optional_items);
183
28.2k
        if (code < 0)
184
0
            return code;
185
28.2k
        s_release_param_printer(&rlist);
186
28.2k
    }
187
28.2k
    return 0;
188
28.2k
}
189
190
/* ---------------- Public ---------------- */
191
192
/*
193
 * Allocate a FontDescriptor, initializing the FontType and rid from the
194
 * gs_font.
195
 */
196
int
197
pdf_font_descriptor_alloc(gx_device_pdf *pdev, pdf_font_descriptor_t **ppfd,
198
                          gs_font_base *font, bool embed)
199
59.6k
{
200
59.6k
    pdf_font_descriptor_t *pfd;
201
59.6k
    pdf_base_font_t *pbfont;
202
59.6k
    int code = pdf_base_font_alloc(pdev, &pbfont, font,
203
59.6k
                (font->orig_FontMatrix.xx == 0 && font->orig_FontMatrix.xy == 0
204
59.6k
                    ? &font->FontMatrix : &font->orig_FontMatrix), false);
205
206
59.6k
    if (code < 0)
207
26.3k
        return code;
208
33.3k
    code = pdf_alloc_resource(pdev, resourceFontDescriptor,
209
33.3k
                              font->id, (pdf_resource_t **)&pfd, -1L);
210
33.3k
    if (code < 0) {
211
0
        gs_free_object(pdev->pdf_memory, pbfont,
212
0
                       "pdf_font_descriptor_alloc(base_font)");
213
0
        return code;
214
0
    }
215
33.3k
    pfd->base_font = pbfont;
216
33.3k
    pfd->FontType = font->FontType;
217
33.3k
    pfd->embed = embed;
218
33.3k
    *ppfd = pfd;
219
33.3k
    return 0;
220
33.3k
}
221
222
int pdf_base_font_free(gx_device_pdf *pdev, pdf_base_font_t *pbfont)
223
59.6k
{
224
59.6k
    gs_font *copied = NULL, *complete = NULL;
225
226
59.6k
    if (pbfont) {
227
59.6k
        copied = (gs_font *)pbfont->copied;
228
59.6k
        complete = (gs_font *)pbfont->complete;
229
59.6k
    }
230
231
59.6k
    if (complete && copied != complete)
232
26.2k
        gs_free_copied_font(complete);
233
234
59.6k
    if (copied)
235
33.3k
        gs_free_copied_font(copied);
236
237
59.6k
    if (pbfont) {
238
59.6k
        if (pbfont->CIDSet)
239
2.33k
            gs_free_object(pdev->pdf_memory, pbfont->CIDSet, "Free base font CIDSet from FontDescriptor)");
240
241
59.6k
        if (pbfont->font_name.size) {
242
33.3k
            gs_free_string(pdev->pdf_memory, pbfont->font_name.data, pbfont->font_name.size, "Free BaseFont FontName string");
243
33.3k
            pbfont->font_name.data = (byte *)0L;
244
33.3k
            pbfont->font_name.size = 0;
245
33.3k
        }
246
59.6k
        gs_free_object(pdev->pdf_memory, pbfont, "Free base font from FontDescriptor)");
247
59.6k
    }
248
59.6k
    return 0;
249
59.6k
}
250
251
int pdf_font_descriptor_free(gx_device_pdf *pdev, pdf_resource_t *pres)
252
33.3k
{
253
33.3k
    pdf_font_descriptor_t *pfd = (pdf_font_descriptor_t *)pres;
254
33.3k
    pdf_base_font_t *pbfont = pfd->base_font;
255
256
33.3k
    pdf_base_font_free(pdev, pbfont);
257
33.3k
    pfd->base_font = 0;
258
259
33.3k
    if (pres->object) {
260
33.3k
        gs_free_object(pdev->pdf_memory, pres->object, "free FontDescriptor object");
261
33.3k
        pres->object = NULL;
262
33.3k
    }
263
33.3k
    return 0;
264
33.3k
}
265
266
/* Get the object ID of a FontDescriptor. */
267
int64_t
268
pdf_font_descriptor_id(const pdf_font_descriptor_t *pfd)
269
28.2k
{
270
28.2k
    return pdf_resource_id((const pdf_resource_t *)pfd);
271
28.2k
}
272
273
int64_t pdf_set_font_descriptor_usage(gx_device_pdf *pdev, int parent_id, const pdf_font_descriptor_t *pfd)
274
0
{
275
0
    int id = pdf_resource_id((const pdf_resource_t *)pfd);
276
277
0
    pdf_record_usage_by_parent(pdev, id, parent_id);
278
0
    if (pfd->base_font->FontFile) {
279
0
        id = pfd->base_font->FontFile->id;
280
0
        pdf_record_usage_by_parent(pdev, id, parent_id);
281
0
    }
282
0
    return 0;
283
0
}
284
285
/*
286
 * Get the FontType of a FontDescriptor.
287
 */
288
font_type
289
pdf_font_descriptor_FontType(const pdf_font_descriptor_t *pfd)
290
33.3k
{
291
33.3k
    return pfd->FontType;
292
33.3k
}
293
294
/*
295
 * Get the embedding status of a FontDescriptor.
296
 */
297
bool
298
pdf_font_descriptor_embedding(const pdf_font_descriptor_t *pfd)
299
59.0k
{
300
59.0k
    return pfd->embed;
301
59.0k
}
302
303
/*
304
 * Check for subset font.
305
 */
306
bool
307
pdf_font_descriptor_is_subset(const pdf_font_descriptor_t *pfd)
308
29.6k
{
309
29.6k
    return pdf_base_font_is_subset(pfd->base_font);
310
29.6k
}
311
312
/*
313
 * Return a reference to the FontName of a FontDescriptor, similar to
314
 * pdf_base_font_name.
315
 */
316
gs_string *pdf_font_descriptor_name(pdf_font_descriptor_t *pfd)
317
64.3k
{
318
64.3k
    return &pfd->common.values.FontName;
319
64.3k
}
320
321
char *pdf_fontfile_hash(void *pfd)
322
29.5k
{
323
29.5k
    pdf_font_descriptor_t *fd = (pdf_font_descriptor_t *)pfd;
324
29.5k
    cos_dict_t *pcd;
325
326
29.5k
    if (fd->base_font && fd->base_font->FontFile) {
327
29.4k
        pcd = (cos_dict_t *)fd->base_font->FontFile;
328
29.4k
        if (pcd->stream_md5_valid)
329
29.4k
            return ((char *)pcd->stream_hash);
330
0
        else
331
0
            return 0;
332
29.4k
    } else
333
152
        return 0;
334
29.5k
}
335
336
/*
337
 * Return the (copied, subset or complete) font associated with a FontDescriptor.
338
 * This procedure probably shouldn't exist....
339
 */
340
gs_font_base *
341
pdf_font_descriptor_font(const pdf_font_descriptor_t *pfd, bool complete)
342
52.2M
{
343
52.2M
    return pdf_base_font_font(pfd->base_font, complete);
344
52.2M
}
345
346
/*
347
 * Drop the copied complete font associated with a FontDescriptor.
348
 */
349
void
350
pdf_font_descriptor_drop_complete_font(const pdf_font_descriptor_t *pfd)
351
1.06k
{
352
1.06k
    pdf_base_font_drop_complete(pfd->base_font);
353
1.06k
}
354
355
/*
356
 * Return a reference to the name of a FontDescriptor's base font, per
357
 * pdf_base_font_name.
358
 */
359
gs_string *pdf_font_descriptor_base_name(const pdf_font_descriptor_t *pfd)
360
64.3k
{
361
64.3k
    return pdf_base_font_name(pfd->base_font);
362
64.3k
}
363
364
/*
365
 * Copy a glyph from a font to the stable copy.  Return 0 if this is a
366
 * new glyph, 1 if it was already copied.
367
 */
368
int
369
pdf_font_used_glyph(pdf_font_descriptor_t *pfd, gs_glyph glyph,
370
                    gs_font_base *font)
371
914k
{
372
914k
    return pdf_base_font_copy_glyph(pfd->base_font, glyph, font);
373
914k
}
374
375
/* Compute the FontDescriptor metrics for a font. */
376
int
377
pdf_compute_font_descriptor(gx_device_pdf *pdev, pdf_font_descriptor_t *pfd)
378
28.2k
{
379
28.2k
    gs_font_base *bfont = pdf_base_font_font(pfd->base_font, false);
380
28.2k
    gs_glyph glyph, notdef;
381
28.2k
    int index;
382
28.2k
    int wmode = bfont->WMode;
383
28.2k
    int members = (GLYPH_INFO_WIDTH0 << wmode) |
384
28.2k
        GLYPH_INFO_BBOX | GLYPH_INFO_NUM_PIECES;
385
28.2k
    pdf_font_descriptor_values_t desc;
386
28.2k
    gs_matrix smat;
387
28.2k
    gs_matrix *pmat = NULL;
388
28.2k
    int fixed_width = 0;
389
28.2k
    int small_descent = 0, small_height = 0;
390
28.2k
    bool small_present = false;
391
28.2k
    int x_height = 0;
392
28.2k
    int cap_height = 0;
393
28.2k
    gs_rect bbox_colon, bbox_period, bbox_I;
394
28.2k
    bool is_cid = (bfont->FontType == ft_CID_encrypted ||
395
28.2k
                   bfont->FontType == ft_CID_TrueType);
396
28.2k
    bool have_colon = false, have_period = false, have_I = false;
397
28.2k
    int code;
398
399
28.2k
    memset(&bbox_colon, 0, sizeof(bbox_colon)); /* quiet gcc warnings. */
400
28.2k
    memset(&bbox_period, 0, sizeof(bbox_period)); /* quiet gcc warnings. */
401
28.2k
    memset(&bbox_I, 0, sizeof(bbox_I)); /* quiet gcc warnings. */
402
28.2k
    memset(&desc, 0, sizeof(desc));
403
28.2k
    if (is_cid && bfont->FontBBox.p.x != bfont->FontBBox.q.x &&
404
28.2k
                  bfont->FontBBox.p.y != bfont->FontBBox.q.y) {
405
1.29k
        int scale = (bfont->FontType == ft_TrueType || bfont->FontType == ft_CID_TrueType ? 1000 : 1);
406
407
1.29k
        desc.FontBBox.p.x = (int)(bfont->FontBBox.p.x * scale);
408
1.29k
        desc.FontBBox.p.y = (int)(bfont->FontBBox.p.y * scale);
409
1.29k
        desc.FontBBox.q.x = (int)(bfont->FontBBox.q.x * scale);
410
1.29k
        desc.FontBBox.q.y = (int)(bfont->FontBBox.q.y * scale);
411
1.29k
        desc.Ascent = desc.FontBBox.q.y;
412
1.29k
        members &= ~GLYPH_INFO_BBOX;
413
26.9k
    } else {
414
26.9k
        desc.FontBBox.p.x = desc.FontBBox.p.y = max_int;
415
26.9k
        desc.FontBBox.q.x = desc.FontBBox.q.y = min_int;
416
26.9k
    }
417
    /*
418
     * Embedded TrueType fonts use a 1000-unit character space, but the
419
     * font itself uses a 1-unit space.  Compensate for this here.
420
     */
421
28.2k
    switch (bfont->FontType) {
422
3.29k
    case ft_TrueType:
423
4.45k
    case ft_CID_TrueType:
424
4.45k
        gs_make_scaling(1000.0, 1000.0, &smat);
425
4.45k
        pmat = &smat;
426
        /* Type 3 fonts may use a FontMatrix in PDF, so we don't
427
         * need to deal with non-standard matrices
428
         */
429
4.45k
    case ft_GL2_531:
430
4.45k
    case ft_PCL_user_defined:
431
4.45k
    case ft_GL2_stick_user_defined:
432
4.45k
    case ft_MicroType:
433
4.45k
    case ft_PDF_user_defined:
434
4.45k
    case ft_user_defined:
435
4.45k
        break;
436
        /* Other font types may use a non-standard (not 1000x1000) design grid
437
         * The FontMatrix is used to map to the unit square. However PDF files
438
         * don't allow FontMatrix entries, all fonts are nominally 1000x1000.
439
         * If we have a font with a non-standard matrix we must account for that
440
         * here by scaling the font outline.
441
         */
442
23.8k
    default:
443
23.8k
        gs_matrix_scale(&bfont->FontMatrix, 1000.0, 1000.0, &smat);
444
23.8k
        pmat = &smat;
445
23.8k
        break;
446
28.2k
    }
447
448
    /*
449
     * Scan the entire glyph space to compute Ascent, Descent, FontBBox, and
450
     * the fixed width if any.  For non-symbolic fonts, also note the
451
     * bounding boxes for Latin letters and a couple of other characters,
452
     * for computing the remaining descriptor values (CapHeight,
453
     * ItalicAngle, StemV, XHeight, and flags SERIF, SCRIPT, ITALIC,
454
     * ALL_CAPS, and SMALL_CAPS).  (The algorithms are pretty crude.)
455
     */
456
28.2k
    notdef = GS_NO_GLYPH;
457
28.2k
    for (index = 0;
458
591k
         (bfont->procs.enumerate_glyph((gs_font *)bfont, &index,
459
591k
                (is_cid ? GLYPH_SPACE_INDEX : GLYPH_SPACE_NAME), &glyph)) >= 0 &&
460
591k
             index != 0;
461
563k
         ) {
462
563k
        gs_glyph_info_t info;
463
563k
        gs_const_string gname;
464
563k
        gs_glyph glyph_known_enc;
465
563k
        gs_char position=0;
466
467
563k
        code = bfont->procs.glyph_info((gs_font *)bfont, glyph, pmat, members, &info);
468
563k
        if (code == gs_error_VMerror)
469
0
            return code;
470
563k
        if (code < 0) {
471
            /*
472
             * Since this function may be indirtectly called from gx_device_finalize,
473
             * we are unable to propagate error code to the interpreter.
474
             * Therefore we skip it here hoping that few errors can be
475
             * recovered by the integration through entire glyph set.
476
             */
477
3.00k
            continue;
478
3.00k
        }
479
560k
        if (members & GLYPH_INFO_BBOX) {
480
            /* rect_merge(desc.FontBBox, info.bbox); Expanding due to type cast :*/
481
529k
            if (info.bbox.p.x < desc.FontBBox.p.x) desc.FontBBox.p.x = (int)info.bbox.p.x;
482
529k
            if (info.bbox.q.x > desc.FontBBox.q.x) desc.FontBBox.q.x = (int)info.bbox.q.x;
483
529k
            if (info.bbox.p.y < desc.FontBBox.p.y) desc.FontBBox.p.y = (int)info.bbox.p.y;
484
529k
            if (info.bbox.q.y > desc.FontBBox.q.y) desc.FontBBox.q.y = (int)info.bbox.q.y;
485
529k
            if (!info.num_pieces)
486
528k
                desc.Ascent = max(desc.Ascent, (int)info.bbox.q.y);
487
529k
        }
488
560k
        if (notdef == GS_NO_GLYPH && gs_font_glyph_is_notdef(bfont, glyph)) {
489
25.8k
            notdef = glyph;
490
25.8k
            desc.MissingWidth = (int)info.width[wmode].x;
491
25.8k
        }
492
560k
        if (info.width[wmode].y != 0)
493
0
            fixed_width = min_int;
494
560k
        else if (fixed_width == 0)
495
29.1k
            fixed_width = (int)info.width[wmode].x;
496
531k
        else if (info.width[wmode].x != fixed_width)
497
509k
            fixed_width = min_int;
498
560k
        if (desc.Flags & FONT_IS_SYMBOLIC)
499
29.3k
            continue;    /* skip Roman-only computation */
500
530k
        if (is_cid)
501
30.5k
            continue;
502
500k
        code = bfont->procs.glyph_name((gs_font *)bfont, glyph, &gname);
503
500k
        if (code < 0) {
504
            /* If we fail to get the glyph name, best assume this is a symbolic font */
505
96
            desc.Flags |= FONT_IS_SYMBOLIC;
506
96
            continue;
507
96
        }
508
        /* See if the glyph name is in any of the known encodings */
509
500k
        glyph_known_enc = gs_c_name_glyph(gname.data, gname.size);
510
500k
        if (glyph_known_enc == GS_NO_GLYPH) {
511
1.44k
            desc.Flags |= FONT_IS_SYMBOLIC;
512
1.44k
            continue;
513
1.44k
        }
514
        /* Finally check if the encoded glyph is in Standard Encoding */
515
        /* gs_c_decode always fails to find .notdef, its always present so
516
         * don't worry about it
517
         */
518
498k
        if(pfd->embed == FONT_EMBED_YES && strncmp(".notdef", (const char *)gname.data, gname.size)) {
519
0
            position = gs_c_decode(glyph_known_enc, 0);
520
0
            if (position == GS_NO_CHAR) {
521
0
                desc.Flags |= FONT_IS_SYMBOLIC;
522
0
                continue;
523
0
            }
524
0
        }
525
498k
        switch (gname.size) {
526
37.2k
        case 5:
527
37.2k
            if (!memcmp(gname.data, "colon", 5))
528
3.89k
                bbox_colon = info.bbox, have_colon = true;
529
37.2k
            continue;
530
18.2k
        case 6:
531
18.2k
            if (!memcmp(gname.data, "period", 6))
532
5.84k
                bbox_period = info.bbox, have_period = true;
533
18.2k
            continue;
534
344k
        case 1:
535
344k
            break;
536
99.1k
        default:
537
99.1k
            continue;
538
498k
        }
539
540
344k
        if (gname.data[0] >= 'A' && gname.data[0] <= 'Z') {
541
124k
            cap_height = max(cap_height, (int)info.bbox.q.y);
542
124k
            if (gname.data[0] == 'I')
543
7.09k
                bbox_I = info.bbox, have_I = true;
544
219k
        } else if (gname.data[0] >= 'a' && gname.data[0] <= 'z') {
545
219k
            int y0 = (int)(info.bbox.p.y), y1 = (int)(info.bbox.q.y);
546
547
219k
            small_present = true;
548
219k
            switch (gname.data[0]) {
549
31.7k
            case 'b': case 'd': case 'f': case 'h':
550
59.8k
            case 'k': case 'l': case 't': /* ascender */
551
59.8k
                small_height = max(small_height, y1);
552
71.0k
            case 'i':   /* anomalous ascent */
553
71.0k
                break;
554
3.05k
            case 'j':   /* descender with anomalous ascent */
555
3.05k
                small_descent = min(small_descent, y0);
556
3.05k
                break;
557
28.6k
            case 'g': case 'p': case 'q': case 'y': /* descender */
558
28.6k
                small_descent = min(small_descent, y0);
559
                /* fall through */
560
145k
            default:    /* no ascender or descender */
561
145k
                x_height = max(x_height, y1);
562
219k
            }
563
219k
        }
564
344k
    }
565
28.2k
    if (!(desc.Flags & FONT_IS_SYMBOLIC)) {
566
26.7k
        desc.Flags |= FONT_IS_ADOBE_ROMAN; /* required if not symbolic */
567
26.7k
        desc.XHeight = (int)x_height;
568
26.7k
        if (!small_present && (pdev->PDFA == 0 || bfont->FontType != ft_TrueType))
569
11.6k
            desc.Flags |= FONT_IS_ALL_CAPS;
570
26.7k
        desc.CapHeight = cap_height;
571
        /*
572
         * Look at various glyphs to determine ItalicAngle, StemV,
573
         * SERIF, SCRIPT, and ITALIC.
574
         */
575
26.7k
        if (have_colon && have_period) {
576
            /* Calculate the dominant angle. */
577
2.92k
            int angle =
578
2.92k
                (int)(atan2((bbox_colon.q.y - bbox_colon.p.y) -
579
2.92k
                              (bbox_period.q.y - bbox_period.p.y),
580
2.92k
                            (bbox_colon.q.x - bbox_colon.p.x) -
581
2.92k
                              (bbox_period.q.x - bbox_period.p.x)) *
582
2.92k
                      radians_to_degrees) - 90;
583
584
            /* Normalize to [-90..90]. */
585
2.92k
            while (angle > 90)
586
0
                angle -= 180;
587
2.93k
            while (angle < -90)
588
3
                angle += 180;
589
2.92k
            if (angle < -30)
590
9
                angle = -30;
591
2.92k
            else if (angle > 30)
592
2
                angle = 30;
593
            /*
594
             * For script or embellished fonts, we can get an angle that is
595
             * slightly off from zero even for non-italic fonts.
596
             * Compensate for this now.
597
             */
598
2.92k
            if (angle <= 2 && angle >= -2)
599
2.74k
                angle = 0;
600
2.92k
            desc.ItalicAngle = angle;
601
2.92k
        }
602
26.7k
        if (desc.ItalicAngle)
603
180
            desc.Flags |= FONT_IS_ITALIC;
604
26.7k
        if (have_I) {
605
7.01k
            double wdot = bbox_period.q.x - bbox_period.p.x;
606
7.01k
            double wcolon = bbox_I.q.x - bbox_I.p.x;
607
7.01k
            double wI = bbox_period.q.x - bbox_period.p.x;
608
609
7.01k
            desc.StemV = (int)wdot;
610
7.01k
            if (wI > wcolon * 2.5 || wI > (bbox_period.q.y - bbox_period.p.y) * 0.25)
611
3.21k
                desc.Flags |= FONT_IS_SERIF;
612
7.01k
        }
613
26.7k
    }
614
28.2k
    if (desc.Ascent == 0)
615
2.95k
        desc.Ascent = desc.FontBBox.q.y;
616
28.2k
    desc.Descent = desc.FontBBox.p.y;
617
28.2k
    if (!(desc.Flags & (FONT_IS_SYMBOLIC | FONT_IS_ALL_CAPS)) &&
618
28.2k
        (small_descent > desc.Descent / 3 || desc.XHeight > small_height * 0.9) &&
619
28.2k
        (pdev->PDFA == 0 || bfont->FontType != ft_TrueType)
620
28.2k
        )
621
4.30k
        desc.Flags |= FONT_IS_SMALL_CAPS;
622
28.2k
    if (fixed_width > 0 && (pdev->PDFA == 0 || bfont->FontType != ft_TrueType)) {
623
4.02k
        desc.Flags |= FONT_IS_FIXED_WIDTH;
624
4.02k
        desc.AvgWidth = desc.MaxWidth = desc.MissingWidth = fixed_width;
625
4.02k
    }
626
28.2k
    if (desc.CapHeight == 0)
627
13.5k
        desc.CapHeight = desc.Ascent;
628
28.2k
    if (desc.StemV == 0)
629
25.0k
        desc.StemV = (int)(desc.FontBBox.q.x * 0.15);
630
28.2k
    pfd->common.values = desc;
631
28.2k
    return 0;
632
28.2k
}
633
634
/*
635
 * Finish a FontDescriptor by computing the metric values, and then
636
 * writing the associated embedded font if any.
637
 */
638
int
639
pdf_finish_FontDescriptor(gx_device_pdf *pdev, pdf_resource_t *pres)
640
33.3k
{
641
33.3k
    pdf_font_descriptor_t *pfd = (pdf_font_descriptor_t *)pres;
642
33.3k
    int code = 0;
643
33.3k
    cos_dict_t *pcd = 0;
644
33.3k
    if (pfd->common.object->id == -1)
645
5.08k
        return 0;
646
28.2k
    if (!pfd->common.object->written &&
647
28.2k
        (code = pdf_compute_font_descriptor(pdev, pfd)) >= 0 &&
648
28.2k
        (!pfd->embed ||
649
28.2k
         (code = pdf_write_embedded_font(pdev, pfd->base_font,
650
28.2k
                                pfd->FontType,
651
28.2k
                                &pfd->common.values.FontBBox,
652
28.2k
                                pfd->common.rid, &pcd)) >= 0)
653
28.2k
        ) {
654
28.1k
        pdf_set_FontFile_object(pfd->base_font, pcd);
655
28.1k
    }
656
28.2k
    return code;
657
33.3k
}
658
659
/* Write a FontDescriptor. */
660
int
661
pdf_write_FontDescriptor(gx_device_pdf *pdev, pdf_resource_t *pres)
662
33.3k
{
663
33.3k
    pdf_font_descriptor_t *pfd = (pdf_font_descriptor_t *)pres;
664
33.3k
    font_type ftype = pfd->FontType;
665
33.3k
    int64_t cidset_id = 0;
666
33.3k
    int code = 0;
667
33.3k
    stream *s;
668
669
33.3k
    if (pfd->common.object->written)
670
0
        return 0;
671
33.3k
    if (pfd->common.object->id == -1)
672
5.08k
        return 0;
673
674
    /* If this is a CIDFont subset, write the CIDSet now. */
675
28.2k
    switch (ftype) {
676
166
    case ft_CID_encrypted:
677
1.32k
    case ft_CID_TrueType:
678
1.32k
        if (pdf_do_subset_font(pdev, pfd->base_font, pfd->common.rid)) {
679
1.32k
            if (pdev->PDFA < 2) {
680
1.32k
                code = pdf_write_CIDSet(pdev, pfd->base_font, &cidset_id);
681
1.32k
                if (code < 0)
682
0
                    return code;
683
1.32k
            }
684
1.32k
        }
685
28.2k
    default:
686
28.2k
        break;
687
28.2k
    }
688
689
28.2k
    {
690
        /*
691
         * Hack: make all embedded TrueType fonts "symbolic" to
692
         * work around undocumented assumptions in Acrobat Reader.
693
         */
694
        /* See the comments in pdf_make_font_resource(). If we are embedding a font, its
695
         * a TrueType font, we are not subsetting it, *and* the original font was not symbolic,
696
         * then force the font to be non-symbolic. Otherwise, yes, force it symbolic.
697
         */
698
28.2k
        pdf_font_descriptor_common_t fd;
699
700
28.2k
        fd = pfd->common;
701
28.2k
        if (pfd->embed && pfd->FontType == ft_TrueType) {
702
3.28k
            fd.values.Flags =
703
3.28k
                (fd.values.Flags & ~(FONT_IS_ADOBE_ROMAN)) | FONT_IS_SYMBOLIC;
704
705
3.28k
            if (pfd->base_font->do_subset == DO_SUBSET_NO && ((const gs_font_base *)(pfd->base_font->copied))->nearest_encoding_index != ENCODING_INDEX_UNKNOWN) {
706
0
                fd.values.Flags =
707
0
                    (fd.values.Flags & ~(FONT_IS_SYMBOLIC)) | FONT_IS_ADOBE_ROMAN;
708
0
            }
709
3.28k
        }
710
28.2k
        code = write_FontDescriptor_common(pdev, &fd, pfd->embed);
711
28.2k
    }
712
28.2k
    if (code < 0)
713
0
        return code;
714
28.2k
    s = pdev->strm;
715
28.2k
    if (cidset_id != 0)
716
1.32k
        pprinti64d1(s, "/CIDSet %"PRId64" 0 R\n", cidset_id);
717
26.9k
    else if (pdf_do_subset_font(pdev, pfd->base_font, pfd->common.rid) &&
718
26.9k
             (ftype == ft_encrypted || ftype == ft_encrypted2) &&
719
26.9k
             pdev->CompatibilityLevel <= 1.7
720
26.9k
             ) {
721
23.6k
        stream_puts(s, "/CharSet");
722
23.6k
        code = pdf_write_CharSet(pdev, pfd->base_font);
723
23.6k
        if (code < 0)
724
0
            return code;
725
23.6k
    }
726
28.2k
    if (pfd->embed && pfd->base_font->FontFile) {
727
28.1k
        code = pdf_write_FontFile_entry(pdev, pfd->base_font);
728
28.1k
        if (code < 0)
729
0
            return code;
730
28.1k
    }
731
28.2k
    if (pfd->cid.Style) {
732
0
        stream_puts(s, "/Style");
733
0
        COS_WRITE(pfd->cid.Style, pdev);
734
0
    }
735
28.2k
    if (pfd->cid.Lang[0]) {
736
0
        pprints1(s, "/Lang(%s)", pfd->cid.Lang);
737
0
    }
738
28.2k
    if (pfd->cid.FD) {
739
0
        stream_puts(s, "/FD");
740
0
        COS_WRITE(pfd->cid.FD, pdev);
741
0
    }
742
28.2k
    stream_puts(s, ">>\n");
743
28.2k
    pdf_end_separate(pdev, resourceFontDescriptor);
744
28.2k
    pfd->common.object->written = true;
745
28.2k
    { const cos_object_t *pco = (const cos_object_t *)pdf_get_FontFile_object(pfd->base_font);
746
28.2k
        if (pco != NULL) {
747
28.1k
            code = COS_WRITE_OBJECT(pco, pdev, resourceFontFile);
748
28.1k
            if (code < 0)
749
0
                return code;
750
28.1k
        }
751
28.2k
    }
752
28.2k
    return 0;
753
28.2k
}
754
755
/*
756
 * Release a FontDescriptor components.
757
 */
758
int
759
pdf_release_FontDescriptor_components(gx_device_pdf *pdev, pdf_resource_t *pres)
760
0
{
761
0
    pdf_font_descriptor_t *pfd = (pdf_font_descriptor_t *) pres;
762
763
0
    gs_free_object(pdev->pdf_memory, pfd->base_font, "pdf_release_FontDescriptor_components");
764
0
    pfd->base_font = NULL;
765
    /* fixme: underimplemented. */
766
0
    return 0;
767
0
}
768
769
/*
770
 * Mark a FontDescriptor used in a text.
771
 */
772
int
773
pdf_mark_font_descriptor_used(gx_device_pdf *pdev, pdf_font_descriptor_t *pfd)
774
36.6k
{
775
36.6k
    if (pfd != NULL && pfd->common.object->id == -1)
776
28.2k
        pdf_reserve_object_id(pdev, (pdf_resource_t *)&pfd->common, 0);
777
36.6k
    return 0;
778
36.6k
}
779
780
/*
781
 * Convert True Type font descriptor into CID font descriptor for PDF/A.
782
 */
783
int
784
pdf_convert_truetype_font_descriptor(gx_device_pdf *pdev, pdf_font_resource_t *pdfont)
785
0
{
786
0
    pdf_font_descriptor_t *pfd = pdfont->FontDescriptor;
787
0
    pdf_base_font_t *pbfont = pfd->base_font;
788
0
    gs_font *pfont = (gs_font *)pbfont->copied;
789
0
    gs_char ch;
790
    /* Save the simple font descriptor data because CID font data overlap them. */
791
0
    int FirstChar = pdfont->u.simple.FirstChar, LastChar = pdfont->u.simple.LastChar;
792
0
    pdf_encoding_element_t *Encoding = pdfont->u.simple.Encoding;
793
0
    int length_CIDSet = (pbfont->num_glyphs > LastChar ? (pbfont->num_glyphs + 7) / 8 : ((LastChar + 1) + 7 / 8));
794
0
    int length_CIDToGIDMap = (pbfont->num_glyphs > LastChar ? (pbfont->num_glyphs + 1) * sizeof(ushort) : (LastChar + 1) * sizeof(ushort));
795
796
0
    pfd->FontType = ft_CID_TrueType;
797
0
    pdfont->u.simple.Encoding = NULL; /* Drop due to overlapping against a garbager problem. */
798
0
    pbfont->CIDSet = gs_alloc_bytes(pdev->pdf_memory, length_CIDSet,
799
0
                        "pdf_convert_truetype_font_descriptor");
800
0
    if (pbfont->CIDSet == NULL)
801
0
        return_error(gs_error_VMerror);
802
0
    memset(pbfont->CIDSet, 0, length_CIDSet);
803
0
    pdfont->u.cidfont.CIDToGIDMap = (ushort *)gs_alloc_bytes(pdev->pdf_memory,
804
0
                        length_CIDToGIDMap, "pdf_convert_truetype_font_descriptor");
805
0
    if (pdfont->u.cidfont.CIDToGIDMap == NULL)
806
0
        return_error(gs_error_VMerror);
807
0
    memset(pdfont->u.cidfont.CIDToGIDMap, 0, length_CIDToGIDMap);
808
0
    if(pdev->PDFA) {
809
0
        for (ch = FirstChar; ch <= LastChar; ch++) {
810
0
            if (Encoding[ch].glyph != GS_NO_GLYPH) {
811
0
                gs_glyph glyph = pfont->procs.encode_char(pfont, ch, GLYPH_SPACE_INDEX);
812
813
0
                pbfont->CIDSet[ch / 8] |= 0x80 >> (ch % 8);
814
0
                pdfont->u.cidfont.CIDToGIDMap[ch] = glyph - GS_MIN_GLYPH_INDEX;
815
0
            }
816
0
        }
817
        /* Set the CIDSet bit for CID 0 (the /.notdef) which must always be present */
818
0
        pbfont->CIDSet[0] |= 0x80;
819
0
    } else {
820
0
        for (ch = 0; ch <= pbfont->num_glyphs; ch++) {
821
0
            gs_glyph glyph = pfont->procs.encode_char(pfont, ch, GLYPH_SPACE_INDEX);
822
823
0
            pbfont->CIDSet[ch / 8] |= 0x80 >> (ch % 8);
824
0
            pdfont->u.cidfont.CIDToGIDMap[ch] = glyph - GS_MIN_GLYPH_INDEX;
825
0
        }
826
0
    }
827
0
    pbfont->CIDSetLength = length_CIDSet;
828
0
    pdfont->u.cidfont.CIDToGIDMapLength = length_CIDToGIDMap / sizeof(ushort);
829
0
    pdfont->u.cidfont.Widths2 = NULL;
830
0
    pdfont->u.cidfont.used2 = NULL;
831
0
    pdfont->u.cidfont.v = NULL;
832
0
    return 0;
833
0
}
834
835
int mark_font_descriptor_symbolic(const pdf_font_resource_t *pdfont)
836
7.39k
{
837
7.39k
    pdf_font_descriptor_values_t *desc;
838
839
7.39k
    if(!pdfont || !pdfont->FontDescriptor)
840
986
        return 0;
841
842
6.40k
    desc = &pdfont->FontDescriptor->common.values;
843
844
6.40k
    if (!(desc->Flags & FONT_IS_SYMBOLIC)) {
845
5.43k
        desc->Flags |= FONT_IS_SYMBOLIC;
846
5.43k
        desc->Flags &= ~FONT_IS_ADOBE_ROMAN;
847
5.43k
    }
848
6.40k
    return 1;
849
7.39k
}