Coverage Report

Created: 2025-06-24 07:01

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