Coverage Report

Created: 2025-11-16 07:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/devices/vector/gdevpdtd.c
Line
Count
Source
1
/* Copyright (C) 2001-2024 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
16
17
/* 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.52k
#define FONT_IS_SERIF (1<<1)
59
734k
#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
40.6k
#define FONT_IS_ADOBE_ROMAN (1<<5) /* never used */
73
313
#define FONT_IS_ITALIC (1<<6)
74
43.6k
#define FONT_IS_ALL_CAPS (1<<16)
75
5.25k
#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
31.8k
{
118
31.8k
    return pdf_resource_id((const pdf_resource_t *)pfdc);
119
31.8k
}
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
31.8k
{
126
31.8k
    stream *s;
127
31.8k
    int code;
128
31.8k
    param_printer_params_t params;
129
31.8k
    printer_param_list_t rlist;
130
31.8k
    gs_param_list *const plist = (gs_param_list *)&rlist;
131
31.8k
    char *base14_name = NULL;
132
133
31.8k
    pdf_open_separate(pdev, pdf_font_descriptor_common_id(pfd), resourceFontDescriptor);
134
31.8k
    s = pdev->strm;
135
31.8k
    stream_puts(s, "<</Type/FontDescriptor/FontName");
136
31.8k
    if (!embed) {
137
28
        base14_name = (char *)pdf_find_base14_name(pfd->values.FontName.data, pfd->values.FontName.size);
138
28
        if(base14_name)
139
0
            pdf_put_name(pdev, (byte *)base14_name, strlen(base14_name));
140
28
        else
141
28
            pdf_put_name(pdev, pfd->values.FontName.data, pfd->values.FontName.size);
142
28
    } else
143
31.7k
        pdf_put_name(pdev, pfd->values.FontName.data, pfd->values.FontName.size);
144
145
31.8k
    pdf_write_font_bbox(pdev, &pfd->values.FontBBox);
146
31.8k
    params = param_printer_params_default;
147
31.8k
    code = s_init_param_printer(&rlist, &params, s);
148
31.8k
    if (code >= 0) {
149
31.8k
#define DESC_INT(str, memb)\
150
349k
 {str, gs_param_type_int, offset_of(pdf_font_descriptor_common_t, values.memb)}
151
31.8k
        static const gs_param_item_t required_items[] = {
152
31.8k
            DESC_INT("Ascent", Ascent),
153
31.8k
            DESC_INT("CapHeight", CapHeight),
154
31.8k
            DESC_INT("Descent", Descent),
155
31.8k
            DESC_INT("ItalicAngle", ItalicAngle),
156
31.8k
            DESC_INT("StemV", StemV),
157
31.8k
            gs_param_item_end
158
31.8k
        };
159
31.8k
        static const gs_param_item_t optional_items[] = {
160
31.8k
            DESC_INT("AvgWidth", AvgWidth),
161
31.8k
            DESC_INT("Leading", Leading),
162
31.8k
            DESC_INT("MaxWidth", MaxWidth),
163
31.8k
            DESC_INT("MissingWidth", MissingWidth),
164
31.8k
            DESC_INT("StemH", StemH),
165
31.8k
            DESC_INT("XHeight", XHeight),
166
31.8k
            gs_param_item_end
167
31.8k
        };
168
31.8k
#undef DESC_INT
169
31.8k
        int Flags = pfd->values.Flags;
170
31.8k
        pdf_font_descriptor_t defaults;
171
172
31.8k
        if (base14_name)
173
0
            Flags |=FONT_USES_STANDARD_ENCODING;
174
175
31.8k
        code = param_write_int(plist, "Flags", &Flags);
176
31.8k
        if (code < 0)
177
0
            return code;
178
31.8k
        code = gs_param_write_items(plist, pfd, NULL, required_items);
179
31.8k
        if (code < 0)
180
0
            return code;
181
31.8k
        memset(&defaults, 0, sizeof(defaults));
182
31.8k
        code = gs_param_write_items(plist, pfd, &defaults, optional_items);
183
31.8k
        if (code < 0)
184
0
            return code;
185
31.8k
        s_release_param_printer(&rlist);
186
31.8k
    }
187
31.8k
    return 0;
188
31.8k
}
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
65.8k
{
200
65.8k
    pdf_font_descriptor_t *pfd;
201
65.8k
    pdf_base_font_t *pbfont;
202
65.8k
    int code = pdf_base_font_alloc(pdev, &pbfont, font,
203
65.8k
                (font->orig_FontMatrix.xx == 0 && font->orig_FontMatrix.xy == 0
204
65.8k
                    ? &font->FontMatrix : &font->orig_FontMatrix), false);
205
206
65.8k
    if (code < 0)
207
28.4k
        return code;
208
37.4k
    code = pdf_alloc_resource(pdev, resourceFontDescriptor,
209
37.4k
                              font->id, (pdf_resource_t **)&pfd, -1L);
210
37.4k
    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
37.4k
    pfd->base_font = pbfont;
216
37.4k
    pfd->FontType = font->FontType;
217
37.4k
    pfd->embed = embed;
218
37.4k
    *ppfd = pfd;
219
37.4k
    return 0;
220
37.4k
}
221
222
int pdf_base_font_free(gx_device_pdf *pdev, pdf_base_font_t *pbfont)
223
65.8k
{
224
65.8k
    gs_font *copied = NULL, *complete = NULL;
225
226
65.8k
    if (pbfont) {
227
65.8k
        copied = (gs_font *)pbfont->copied;
228
65.8k
        complete = (gs_font *)pbfont->complete;
229
65.8k
    }
230
231
65.8k
    if (complete && copied != complete)
232
28.4k
        gs_free_copied_font(complete);
233
234
65.8k
    if (copied)
235
37.4k
        gs_free_copied_font(copied);
236
237
65.8k
    if (pbfont) {
238
65.8k
        if (pbfont->CIDSet)
239
3.98k
            gs_free_object(pdev->pdf_memory, pbfont->CIDSet, "Free base font CIDSet from FontDescriptor)");
240
241
65.8k
        if (pbfont->font_name.size) {
242
37.4k
            gs_free_string(pdev->pdf_memory, pbfont->font_name.data, pbfont->font_name.size, "Free BaseFont FontName string");
243
37.4k
            pbfont->font_name.data = (byte *)0L;
244
37.4k
            pbfont->font_name.size = 0;
245
37.4k
        }
246
65.8k
        gs_free_object(pdev->pdf_memory, pbfont, "Free base font from FontDescriptor)");
247
65.8k
    }
248
65.8k
    return 0;
249
65.8k
}
250
251
int pdf_font_descriptor_free(gx_device_pdf *pdev, pdf_resource_t *pres)
252
37.4k
{
253
37.4k
    pdf_font_descriptor_t *pfd = (pdf_font_descriptor_t *)pres;
254
37.4k
    pdf_base_font_t *pbfont = pfd->base_font;
255
256
37.4k
    pdf_base_font_free(pdev, pbfont);
257
37.4k
    pfd->base_font = 0;
258
259
37.4k
    if (pres->object) {
260
37.4k
        gs_free_object(pdev->pdf_memory, pres->object, "free FontDescriptor object");
261
37.4k
        pres->object = NULL;
262
37.4k
    }
263
37.4k
    return 0;
264
37.4k
}
265
266
/* Get the object ID of a FontDescriptor. */
267
int64_t
268
pdf_font_descriptor_id(const pdf_font_descriptor_t *pfd)
269
31.8k
{
270
31.8k
    return pdf_resource_id((const pdf_resource_t *)pfd);
271
31.8k
}
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
37.4k
{
291
37.4k
    return pfd->FontType;
292
37.4k
}
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
66.9k
{
300
66.9k
    return pfd->embed;
301
66.9k
}
302
303
/*
304
 * Check for subset font.
305
 */
306
bool
307
pdf_font_descriptor_is_subset(const pdf_font_descriptor_t *pfd)
308
33.5k
{
309
33.5k
    return pdf_base_font_is_subset(pfd->base_font);
310
33.5k
}
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
72.8k
{
318
72.8k
    return &pfd->common.values.FontName;
319
72.8k
}
320
321
char *pdf_fontfile_hash(void *pfd)
322
33.5k
{
323
33.5k
    pdf_font_descriptor_t *fd = (pdf_font_descriptor_t *)pfd;
324
33.5k
    cos_dict_t *pcd;
325
326
33.5k
    if (fd->base_font && fd->base_font->FontFile) {
327
33.3k
        pcd = (cos_dict_t *)fd->base_font->FontFile;
328
33.3k
        if (pcd->stream_md5_valid)
329
33.3k
            return ((char *)pcd->stream_hash);
330
0
        else
331
0
            return 0;
332
33.3k
    } else
333
177
        return 0;
334
33.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
55.0M
{
343
55.0M
    return pdf_base_font_font(pfd->base_font, complete);
344
55.0M
}
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.01k
{
352
1.01k
    pdf_base_font_drop_complete(pfd->base_font);
353
1.01k
}
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
72.8k
{
361
72.8k
    return pdf_base_font_name(pfd->base_font);
362
72.8k
}
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
1.12M
{
372
1.12M
    return pdf_base_font_copy_glyph(pfd->base_font, glyph, font);
373
1.12M
}
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
31.8k
{
379
31.8k
    gs_font_base *bfont = pdf_base_font_font(pfd->base_font, false);
380
31.8k
    gs_glyph glyph, notdef;
381
31.8k
    int index;
382
31.8k
    int wmode = bfont->WMode;
383
31.8k
    int members = (GLYPH_INFO_WIDTH0 << wmode) |
384
31.8k
        GLYPH_INFO_BBOX | GLYPH_INFO_NUM_PIECES;
385
31.8k
    pdf_font_descriptor_values_t desc;
386
31.8k
    gs_matrix smat;
387
31.8k
    gs_matrix *pmat = NULL;
388
31.8k
    int fixed_width = 0;
389
31.8k
    int small_descent = 0, small_height = 0;
390
31.8k
    bool small_present = false;
391
31.8k
    int x_height = 0;
392
31.8k
    int cap_height = 0;
393
31.8k
    gs_rect bbox_colon, bbox_period, bbox_I;
394
31.8k
    bool is_cid = (bfont->FontType == ft_CID_encrypted ||
395
31.5k
                   bfont->FontType == ft_CID_TrueType);
396
31.8k
    bool have_colon = false, have_period = false, have_I = false;
397
31.8k
    int code;
398
399
31.8k
    memset(&bbox_colon, 0, sizeof(bbox_colon)); /* quiet gcc warnings. */
400
31.8k
    memset(&bbox_period, 0, sizeof(bbox_period)); /* quiet gcc warnings. */
401
31.8k
    memset(&bbox_I, 0, sizeof(bbox_I)); /* quiet gcc warnings. */
402
31.8k
    memset(&desc, 0, sizeof(desc));
403
31.8k
    if (is_cid && bfont->FontBBox.p.x != bfont->FontBBox.q.x &&
404
1.73k
                  bfont->FontBBox.p.y != bfont->FontBBox.q.y) {
405
1.73k
        int scale = (bfont->FontType == ft_TrueType || bfont->FontType == ft_CID_TrueType ? 1000 : 1);
406
407
1.73k
        desc.FontBBox.p.x = (int)(bfont->FontBBox.p.x * scale);
408
1.73k
        desc.FontBBox.p.y = (int)(bfont->FontBBox.p.y * scale);
409
1.73k
        desc.FontBBox.q.x = (int)(bfont->FontBBox.q.x * scale);
410
1.73k
        desc.FontBBox.q.y = (int)(bfont->FontBBox.q.y * scale);
411
1.73k
        desc.Ascent = desc.FontBBox.q.y;
412
1.73k
        members &= ~GLYPH_INFO_BBOX;
413
30.0k
    } else {
414
30.0k
        desc.FontBBox.p.x = desc.FontBBox.p.y = max_int;
415
30.0k
        desc.FontBBox.q.x = desc.FontBBox.q.y = min_int;
416
30.0k
    }
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
31.8k
    switch (bfont->FontType) {
422
4.18k
    case ft_TrueType:
423
5.73k
    case ft_CID_TrueType:
424
5.73k
        gs_make_scaling(1000.0, 1000.0, &smat);
425
5.73k
        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
5.73k
    case ft_GL2_531:
430
5.73k
    case ft_PCL_user_defined:
431
5.73k
    case ft_GL2_stick_user_defined:
432
5.73k
    case ft_MicroType:
433
5.73k
    case ft_PDF_user_defined:
434
5.73k
    case ft_user_defined:
435
5.73k
        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
26.0k
    default:
443
26.0k
        gs_matrix_scale(&bfont->FontMatrix, 1000.0, 1000.0, &smat);
444
26.0k
        pmat = &smat;
445
26.0k
        break;
446
31.8k
    }
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
31.8k
    notdef = GS_NO_GLYPH;
457
31.8k
    for (index = 0;
458
687k
         (bfont->procs.enumerate_glyph((gs_font *)bfont, &index,
459
687k
                (is_cid ? GLYPH_SPACE_INDEX : GLYPH_SPACE_NAME), &glyph)) >= 0 &&
460
687k
             index != 0;
461
655k
         ) {
462
655k
        gs_glyph_info_t info;
463
655k
        gs_const_string gname;
464
655k
        gs_glyph glyph_known_enc;
465
655k
        gs_char position=0;
466
467
655k
        code = bfont->procs.glyph_info((gs_font *)bfont, glyph, pmat, members, &info);
468
655k
        if (code == gs_error_VMerror)
469
0
            return code;
470
655k
        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
4.27k
            continue;
478
4.27k
        }
479
651k
        if (members & GLYPH_INFO_BBOX) {
480
            /* rect_merge(desc.FontBBox, info.bbox); Expanding due to type cast :*/
481
610k
            if (info.bbox.p.x < desc.FontBBox.p.x) desc.FontBBox.p.x = (int)info.bbox.p.x;
482
610k
            if (info.bbox.q.x > desc.FontBBox.q.x) desc.FontBBox.q.x = (int)info.bbox.q.x;
483
610k
            if (info.bbox.p.y < desc.FontBBox.p.y) desc.FontBBox.p.y = (int)info.bbox.p.y;
484
610k
            if (info.bbox.q.y > desc.FontBBox.q.y) desc.FontBBox.q.y = (int)info.bbox.q.y;
485
610k
            if (!info.num_pieces)
486
609k
                desc.Ascent = max(desc.Ascent, (int)info.bbox.q.y);
487
610k
        }
488
651k
        if (notdef == GS_NO_GLYPH && gs_font_glyph_is_notdef(bfont, glyph)) {
489
28.8k
            notdef = glyph;
490
28.8k
            desc.MissingWidth = (int)info.width[wmode].x;
491
28.8k
        }
492
651k
        if (info.width[wmode].y != 0)
493
0
            fixed_width = min_int;
494
651k
        else if (fixed_width == 0)
495
33.1k
            fixed_width = (int)info.width[wmode].x;
496
618k
        else if (info.width[wmode].x != fixed_width)
497
594k
            fixed_width = min_int;
498
651k
        if (desc.Flags & FONT_IS_SYMBOLIC)
499
29.5k
            continue;    /* skip Roman-only computation */
500
622k
        if (is_cid)
501
42.0k
            continue;
502
580k
        code = bfont->procs.glyph_name((gs_font *)bfont, glyph, &gname);
503
580k
        if (code < 0) {
504
            /* If we fail to get the glyph name, best assume this is a symbolic font */
505
104
            desc.Flags |= FONT_IS_SYMBOLIC;
506
104
            continue;
507
104
        }
508
        /* See if the glyph name is in any of the known encodings */
509
579k
        glyph_known_enc = gs_c_name_glyph(gname.data, gname.size);
510
579k
        if (glyph_known_enc == GS_NO_GLYPH) {
511
1.46k
            desc.Flags |= FONT_IS_SYMBOLIC;
512
1.46k
            continue;
513
1.46k
        }
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
578k
        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
578k
        switch (gname.size) {
526
41.7k
        case 5:
527
41.7k
            if (!memcmp(gname.data, "colon", 5))
528
4.36k
                bbox_colon = info.bbox, have_colon = true;
529
41.7k
            continue;
530
20.4k
        case 6:
531
20.4k
            if (!memcmp(gname.data, "period", 6))
532
6.48k
                bbox_period = info.bbox, have_period = true;
533
20.4k
            continue;
534
408k
        case 1:
535
408k
            break;
536
107k
        default:
537
107k
            continue;
538
578k
        }
539
540
408k
        if (gname.data[0] >= 'A' && gname.data[0] <= 'Z') {
541
146k
            cap_height = max(cap_height, (int)info.bbox.q.y);
542
146k
            if (gname.data[0] == 'I')
543
8.41k
                bbox_I = info.bbox, have_I = true;
544
262k
        } else if (gname.data[0] >= 'a' && gname.data[0] <= 'z') {
545
262k
            int y0 = (int)(info.bbox.p.y), y1 = (int)(info.bbox.q.y);
546
547
262k
            small_present = true;
548
262k
            switch (gname.data[0]) {
549
36.6k
            case 'b': case 'd': case 'f': case 'h':
550
71.1k
            case 'k': case 'l': case 't': /* ascender */
551
71.1k
                small_height = max(small_height, y1);
552
84.3k
            case 'i':   /* anomalous ascent */
553
84.3k
                break;
554
3.16k
            case 'j':   /* descender with anomalous ascent */
555
3.16k
                small_descent = min(small_descent, y0);
556
3.16k
                break;
557
33.5k
            case 'g': case 'p': case 'q': case 'y': /* descender */
558
33.5k
                small_descent = min(small_descent, y0);
559
                /* fall through */
560
175k
            default:    /* no ascender or descender */
561
175k
                x_height = max(x_height, y1);
562
262k
            }
563
262k
        }
564
408k
    }
565
31.8k
    if (!(desc.Flags & FONT_IS_SYMBOLIC)) {
566
30.2k
        desc.Flags |= FONT_IS_ADOBE_ROMAN; /* required if not symbolic */
567
30.2k
        desc.XHeight = (int)x_height;
568
30.2k
        if (!small_present && (pdev->PDFA == 0 || bfont->FontType != ft_TrueType))
569
11.8k
            desc.Flags |= FONT_IS_ALL_CAPS;
570
30.2k
        desc.CapHeight = cap_height;
571
        /*
572
         * Look at various glyphs to determine ItalicAngle, StemV,
573
         * SERIF, SCRIPT, and ITALIC.
574
         */
575
30.2k
        if (have_colon && have_period) {
576
            /* Calculate the dominant angle. */
577
3.51k
            int angle =
578
3.51k
                (int)(atan2((bbox_colon.q.y - bbox_colon.p.y) -
579
3.51k
                              (bbox_period.q.y - bbox_period.p.y),
580
3.51k
                            (bbox_colon.q.x - bbox_colon.p.x) -
581
3.51k
                              (bbox_period.q.x - bbox_period.p.x)) *
582
3.51k
                      radians_to_degrees) - 90;
583
584
            /* Normalize to [-90..90]. */
585
3.51k
            while (angle > 90)
586
0
                angle -= 180;
587
3.51k
            while (angle < -90)
588
5
                angle += 180;
589
3.51k
            if (angle < -30)
590
15
                angle = -30;
591
3.49k
            else if (angle > 30)
592
3
                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
3.51k
            if (angle <= 2 && angle >= -2)
599
3.19k
                angle = 0;
600
3.51k
            desc.ItalicAngle = angle;
601
3.51k
        }
602
30.2k
        if (desc.ItalicAngle)
603
313
            desc.Flags |= FONT_IS_ITALIC;
604
30.2k
        if (have_I) {
605
8.32k
            double wdot = bbox_period.q.x - bbox_period.p.x;
606
8.32k
            double wcolon = bbox_I.q.x - bbox_I.p.x;
607
8.32k
            double wI = bbox_period.q.x - bbox_period.p.x;
608
609
8.32k
            desc.StemV = (int)wdot;
610
8.32k
            if (wI > wcolon * 2.5 || wI > (bbox_period.q.y - bbox_period.p.y) * 0.25)
611
3.52k
                desc.Flags |= FONT_IS_SERIF;
612
8.32k
        }
613
30.2k
    }
614
31.8k
    if (desc.Ascent == 0)
615
2.96k
        desc.Ascent = desc.FontBBox.q.y;
616
31.8k
    desc.Descent = desc.FontBBox.p.y;
617
31.8k
    if (!(desc.Flags & (FONT_IS_SYMBOLIC | FONT_IS_ALL_CAPS)) &&
618
18.3k
        (small_descent > desc.Descent / 3 || desc.XHeight > small_height * 0.9) &&
619
5.25k
        (pdev->PDFA == 0 || bfont->FontType != ft_TrueType)
620
31.8k
        )
621
5.25k
        desc.Flags |= FONT_IS_SMALL_CAPS;
622
31.8k
    if (fixed_width > 0 && (pdev->PDFA == 0 || bfont->FontType != ft_TrueType)) {
623
3.97k
        desc.Flags |= FONT_IS_FIXED_WIDTH;
624
3.97k
        desc.AvgWidth = desc.MaxWidth = desc.MissingWidth = fixed_width;
625
3.97k
    }
626
31.8k
    if (desc.CapHeight == 0)
627
14.9k
        desc.CapHeight = desc.Ascent;
628
31.8k
    if (desc.StemV == 0)
629
28.2k
        desc.StemV = (int)(desc.FontBBox.q.x * 0.15);
630
31.8k
    pfd->common.values = desc;
631
31.8k
    return 0;
632
31.8k
}
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
37.4k
{
641
37.4k
    pdf_font_descriptor_t *pfd = (pdf_font_descriptor_t *)pres;
642
37.4k
    int code = 0;
643
37.4k
    cos_dict_t *pcd = 0;
644
37.4k
    if (pfd->common.object->id == -1)
645
5.60k
        return 0;
646
31.8k
    if (!pfd->common.object->written &&
647
31.8k
        (code = pdf_compute_font_descriptor(pdev, pfd)) >= 0 &&
648
31.8k
        (!pfd->embed ||
649
31.7k
         (code = pdf_write_embedded_font(pdev, pfd->base_font,
650
31.7k
                                pfd->FontType,
651
31.7k
                                &pfd->common.values.FontBBox,
652
31.7k
                                pfd->common.rid, &pcd)) >= 0)
653
31.8k
        ) {
654
31.6k
        pdf_set_FontFile_object(pfd->base_font, pcd);
655
31.6k
    }
656
31.8k
    return code;
657
37.4k
}
658
659
/* Write a FontDescriptor. */
660
int
661
pdf_write_FontDescriptor(gx_device_pdf *pdev, pdf_resource_t *pres)
662
37.4k
{
663
37.4k
    pdf_font_descriptor_t *pfd = (pdf_font_descriptor_t *)pres;
664
37.4k
    font_type ftype = pfd->FontType;
665
37.4k
    int64_t cidset_id = 0;
666
37.4k
    int code = 0;
667
37.4k
    stream *s;
668
669
37.4k
    if (pfd->common.object->written)
670
0
        return 0;
671
37.4k
    if (pfd->common.object->id == -1)
672
5.60k
        return 0;
673
674
    /* If this is a CIDFont subset, write the CIDSet now. */
675
31.8k
    switch (ftype) {
676
237
    case ft_CID_encrypted:
677
1.78k
    case ft_CID_TrueType:
678
1.78k
        if (pdf_do_subset_font(pdev, pfd->base_font, pfd->common.rid)) {
679
1.78k
            if (pdev->PDFA < 2) {
680
1.78k
                code = pdf_write_CIDSet(pdev, pfd->base_font, &cidset_id);
681
1.78k
                if (code < 0)
682
0
                    return code;
683
1.78k
            }
684
1.78k
        }
685
31.8k
    default:
686
31.8k
        break;
687
31.8k
    }
688
689
31.8k
    {
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
31.8k
        pdf_font_descriptor_common_t fd;
699
700
31.8k
        fd = pfd->common;
701
31.8k
        if (pfd->embed && pfd->FontType == ft_TrueType) {
702
4.16k
            fd.values.Flags =
703
4.16k
                (fd.values.Flags & ~(FONT_IS_ADOBE_ROMAN)) | FONT_IS_SYMBOLIC;
704
705
4.16k
            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
4.16k
        }
710
31.8k
        code = write_FontDescriptor_common(pdev, &fd, pfd->embed);
711
31.8k
    }
712
31.8k
    if (code < 0)
713
0
        return code;
714
31.8k
    s = pdev->strm;
715
31.8k
    if (cidset_id != 0)
716
1.78k
        pprinti64d1(s, "/CIDSet %"PRId64" 0 R\n", cidset_id);
717
30.0k
    else if (pdf_do_subset_font(pdev, pfd->base_font, pfd->common.rid) &&
718
30.0k
             (ftype == ft_encrypted || ftype == ft_encrypted2) &&
719
25.8k
             pdev->CompatibilityLevel <= 1.7
720
30.0k
             ) {
721
25.8k
        stream_puts(s, "/CharSet");
722
25.8k
        code = pdf_write_CharSet(pdev, pfd->base_font);
723
25.8k
        if (code < 0)
724
0
            return code;
725
25.8k
    }
726
31.8k
    if (pfd->embed && pfd->base_font->FontFile) {
727
31.6k
        code = pdf_write_FontFile_entry(pdev, pfd->base_font);
728
31.6k
        if (code < 0)
729
0
            return code;
730
31.6k
    }
731
31.8k
    if (pfd->cid.Style) {
732
0
        stream_puts(s, "/Style");
733
0
        COS_WRITE(pfd->cid.Style, pdev);
734
0
    }
735
31.8k
    if (pfd->cid.Lang[0]) {
736
0
        pprints1(s, "/Lang(%s)", pfd->cid.Lang);
737
0
    }
738
31.8k
    if (pfd->cid.FD) {
739
0
        stream_puts(s, "/FD");
740
0
        COS_WRITE(pfd->cid.FD, pdev);
741
0
    }
742
31.8k
    stream_puts(s, ">>\n");
743
31.8k
    pdf_end_separate(pdev, resourceFontDescriptor);
744
31.8k
    pfd->common.object->written = true;
745
31.8k
    { const cos_object_t *pco = (const cos_object_t *)pdf_get_FontFile_object(pfd->base_font);
746
31.8k
        if (pco != NULL) {
747
31.6k
            code = COS_WRITE_OBJECT(pco, pdev, resourceFontFile);
748
31.6k
            if (code < 0)
749
0
                return code;
750
31.6k
        }
751
31.8k
    }
752
31.8k
    return 0;
753
31.8k
}
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
41.2k
{
775
41.2k
    if (pfd != NULL && pfd->common.object->id == -1)
776
31.8k
        pdf_reserve_object_id(pdev, (pdf_resource_t *)&pfd->common, 0);
777
41.2k
    return 0;
778
41.2k
}
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
8.32k
{
837
8.32k
    pdf_font_descriptor_values_t *desc;
838
839
8.32k
    if(!pdfont || !pdfont->FontDescriptor)
840
1.24k
        return 0;
841
842
7.08k
    desc = &pdfont->FontDescriptor->common.values;
843
844
7.08k
    if (!(desc->Flags & FONT_IS_SYMBOLIC)) {
845
6.20k
        desc->Flags |= FONT_IS_SYMBOLIC;
846
6.20k
        desc->Flags &= ~FONT_IS_ADOBE_ROMAN;
847
6.20k
    }
848
7.08k
    return 1;
849
8.32k
}