Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/devices/vector/gdevpdtd.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2021 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  1305 Grant Avenue - Suite 200, Novato,
13
   CA 94945, U.S.A., +1(415)492-9861, for further information.
14
*/
15
16
17
/* 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
1.42k
#define FONT_IS_SERIF (1<<1)
59
284k
#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
14.8k
#define FONT_IS_ADOBE_ROMAN (1<<5) /* never used */
73
289
#define FONT_IS_ITALIC (1<<6)
74
11.9k
#define FONT_IS_ALL_CAPS (1<<16)
75
1.85k
#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 long
116
pdf_font_descriptor_common_id(const pdf_font_descriptor_common_t *pfdc)
117
10.3k
{
118
10.3k
    return pdf_resource_id((const pdf_resource_t *)pfdc);
119
10.3k
}
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
10.3k
{
126
10.3k
    stream *s;
127
10.3k
    int code;
128
10.3k
    param_printer_params_t params;
129
10.3k
    printer_param_list_t rlist;
130
10.3k
    gs_param_list *const plist = (gs_param_list *)&rlist;
131
10.3k
    char *base14_name = NULL;
132
133
10.3k
    pdf_open_separate(pdev, pdf_font_descriptor_common_id(pfd), resourceFontDescriptor);
134
10.3k
    s = pdev->strm;
135
10.3k
    stream_puts(s, "<</Type/FontDescriptor/FontName");
136
10.3k
    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
10.3k
        pdf_put_name(pdev, pfd->values.FontName.data, pfd->values.FontName.size);
144
145
10.3k
    pdf_write_font_bbox(pdev, &pfd->values.FontBBox);
146
10.3k
    params = param_printer_params_default;
147
10.3k
    code = s_init_param_printer(&rlist, &params, s);
148
10.3k
    if (code >= 0) {
149
10.3k
#define DESC_INT(str, memb)\
150
113k
 {str, gs_param_type_int, offset_of(pdf_font_descriptor_common_t, values.memb)}
151
10.3k
        static const gs_param_item_t required_items[] = {
152
10.3k
            DESC_INT("Ascent", Ascent),
153
10.3k
            DESC_INT("CapHeight", CapHeight),
154
10.3k
            DESC_INT("Descent", Descent),
155
10.3k
            DESC_INT("ItalicAngle", ItalicAngle),
156
10.3k
            DESC_INT("StemV", StemV),
157
10.3k
            gs_param_item_end
158
10.3k
        };
159
10.3k
        static const gs_param_item_t optional_items[] = {
160
10.3k
            DESC_INT("AvgWidth", AvgWidth),
161
10.3k
            DESC_INT("Leading", Leading),
162
10.3k
            DESC_INT("MaxWidth", MaxWidth),
163
10.3k
            DESC_INT("MissingWidth", MissingWidth),
164
10.3k
            DESC_INT("StemH", StemH),
165
10.3k
            DESC_INT("XHeight", XHeight),
166
10.3k
            gs_param_item_end
167
10.3k
        };
168
10.3k
#undef DESC_INT
169
10.3k
        int Flags = pfd->values.Flags;
170
10.3k
        pdf_font_descriptor_t defaults;
171
172
10.3k
        if (base14_name)
173
0
            Flags |=FONT_USES_STANDARD_ENCODING;
174
175
10.3k
        code = param_write_int(plist, "Flags", &Flags);
176
10.3k
        if (code < 0)
177
0
            return code;
178
10.3k
        code = gs_param_write_items(plist, pfd, NULL, required_items);
179
10.3k
        if (code < 0)
180
0
            return code;
181
10.3k
        memset(&defaults, 0, sizeof(defaults));
182
10.3k
        code = gs_param_write_items(plist, pfd, &defaults, optional_items);
183
10.3k
        if (code < 0)
184
0
            return code;
185
10.3k
        s_release_param_printer(&rlist);
186
10.3k
    }
187
10.3k
    return 0;
188
10.3k
}
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
18.5k
{
200
18.5k
    pdf_font_descriptor_t *pfd;
201
18.5k
    pdf_base_font_t *pbfont;
202
18.5k
    int code = pdf_base_font_alloc(pdev, &pbfont, font,
203
18.5k
                (font->orig_FontMatrix.xx == 0 && font->orig_FontMatrix.xy == 0
204
18.5k
                    ? &font->FontMatrix : &font->orig_FontMatrix), false);
205
206
18.5k
    if (code < 0)
207
7.81k
        return code;
208
10.7k
    code = pdf_alloc_resource(pdev, resourceFontDescriptor,
209
10.7k
                              font->id, (pdf_resource_t **)&pfd, -1L);
210
10.7k
    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
10.7k
    memset(&pfd->common.values, 0,
216
10.7k
           sizeof(*pfd) - offset_of(pdf_font_descriptor_t, common.values));
217
10.7k
    pfd->base_font = pbfont;
218
10.7k
    pfd->FontType = font->FontType;
219
10.7k
    pfd->embed = embed;
220
10.7k
    *ppfd = pfd;
221
10.7k
    return 0;
222
10.7k
}
223
224
int pdf_base_font_free(gx_device_pdf *pdev, pdf_base_font_t *pbfont)
225
18.5k
{
226
18.5k
    gs_font *copied = NULL, *complete = NULL;
227
228
18.5k
    if (pbfont) {
229
18.5k
        copied = (gs_font *)pbfont->copied;
230
18.5k
        complete = (gs_font *)pbfont->complete;
231
18.5k
    }
232
233
18.5k
    if (complete && copied != complete)
234
9.87k
        gs_free_copied_font(complete);
235
236
18.5k
    if (copied)
237
10.7k
        gs_free_copied_font(copied);
238
239
18.5k
    if (pbfont) {
240
18.5k
        if (pbfont->CIDSet)
241
421
            gs_free_object(pdev->pdf_memory, pbfont->CIDSet, "Free base font CIDSet from FontDescriptor)");
242
243
18.5k
        if (pbfont->font_name.size) {
244
10.7k
            gs_free_string(pdev->pdf_memory, pbfont->font_name.data, pbfont->font_name.size, "Free BaseFont FontName string");
245
10.7k
            pbfont->font_name.data = (byte *)0L;
246
10.7k
            pbfont->font_name.size = 0;
247
10.7k
        }
248
18.5k
        gs_free_object(pdev->pdf_memory, pbfont, "Free base font from FontDescriptor)");
249
18.5k
    }
250
18.5k
    return 0;
251
18.5k
}
252
253
int pdf_font_descriptor_free(gx_device_pdf *pdev, pdf_resource_t *pres)
254
10.7k
{
255
10.7k
    pdf_font_descriptor_t *pfd = (pdf_font_descriptor_t *)pres;
256
10.7k
    pdf_base_font_t *pbfont = pfd->base_font;
257
258
10.7k
    pdf_base_font_free(pdev, pbfont);
259
10.7k
    pfd->base_font = 0;
260
261
10.7k
    if (pres->object) {
262
10.7k
        gs_free_object(pdev->pdf_memory, pres->object, "free FontDescriptor object");
263
10.7k
        pres->object = NULL;
264
10.7k
    }
265
10.7k
    return 0;
266
10.7k
}
267
268
/* Get the object ID of a FontDescriptor. */
269
long
270
pdf_font_descriptor_id(const pdf_font_descriptor_t *pfd)
271
10.3k
{
272
10.3k
    return pdf_resource_id((const pdf_resource_t *)pfd);
273
10.3k
}
274
275
long pdf_set_font_descriptor_usage(gx_device_pdf *pdev, int parent_id, const pdf_font_descriptor_t *pfd)
276
0
{
277
0
    int id = pdf_resource_id((const pdf_resource_t *)pfd);
278
279
0
    pdf_record_usage_by_parent(pdev, id, parent_id);
280
0
    if (pfd->base_font->FontFile) {
281
0
        id = pfd->base_font->FontFile->id;
282
0
        pdf_record_usage_by_parent(pdev, id, parent_id);
283
0
    }
284
0
    return 0;
285
0
}
286
287
/*
288
 * Get the FontType of a FontDescriptor.
289
 */
290
font_type
291
pdf_font_descriptor_FontType(const pdf_font_descriptor_t *pfd)
292
10.7k
{
293
10.7k
    return pfd->FontType;
294
10.7k
}
295
296
/*
297
 * Get the embedding status of a FontDescriptor.
298
 */
299
bool
300
pdf_font_descriptor_embedding(const pdf_font_descriptor_t *pfd)
301
21.0k
{
302
21.0k
    return pfd->embed;
303
21.0k
}
304
305
/*
306
 * Check for subset font.
307
 */
308
bool
309
pdf_font_descriptor_is_subset(const pdf_font_descriptor_t *pfd)
310
10.5k
{
311
10.5k
    return pdf_base_font_is_subset(pfd->base_font);
312
10.5k
}
313
314
/*
315
 * Return a reference to the FontName of a FontDescriptor, similar to
316
 * pdf_base_font_name.
317
 */
318
gs_string *pdf_font_descriptor_name(pdf_font_descriptor_t *pfd)
319
21.4k
{
320
21.4k
    return &pfd->common.values.FontName;
321
21.4k
}
322
323
char *pdf_fontfile_hash(void *pfd)
324
10.5k
{
325
10.5k
    pdf_font_descriptor_t *fd = (pdf_font_descriptor_t *)pfd;
326
10.5k
    cos_dict_t *pcd;
327
328
10.5k
    if (fd->base_font && fd->base_font->FontFile) {
329
10.3k
        pcd = (cos_dict_t *)fd->base_font->FontFile;
330
10.3k
        if (pcd->stream_md5_valid)
331
10.3k
            return ((char *)pcd->stream_hash);
332
0
        else
333
0
            return 0;
334
10.3k
    } else
335
150
        return 0;
336
10.5k
}
337
338
/*
339
 * Return the (copied, subset or complete) font associated with a FontDescriptor.
340
 * This procedure probably shouldn't exist....
341
 */
342
gs_font_base *
343
pdf_font_descriptor_font(const pdf_font_descriptor_t *pfd, bool complete)
344
11.9M
{
345
11.9M
    return pdf_base_font_font(pfd->base_font, complete);
346
11.9M
}
347
348
/*
349
 * Drop the copied complete font associated with a FontDescriptor.
350
 */
351
void
352
pdf_font_descriptor_drop_complete_font(const pdf_font_descriptor_t *pfd)
353
116
{
354
116
    pdf_base_font_drop_complete(pfd->base_font);
355
116
}
356
357
/*
358
 * Return a reference to the name of a FontDescriptor's base font, per
359
 * pdf_base_font_name.
360
 */
361
gs_string *pdf_font_descriptor_base_name(const pdf_font_descriptor_t *pfd)
362
21.4k
{
363
21.4k
    return pdf_base_font_name(pfd->base_font);
364
21.4k
}
365
366
/*
367
 * Copy a glyph from a font to the stable copy.  Return 0 if this is a
368
 * new glyph, 1 if it was already copied.
369
 */
370
int
371
pdf_font_used_glyph(pdf_font_descriptor_t *pfd, gs_glyph glyph,
372
                    gs_font_base *font)
373
283k
{
374
283k
    return pdf_base_font_copy_glyph(pfd->base_font, glyph, font);
375
283k
}
376
377
/* Compute the FontDescriptor metrics for a font. */
378
int
379
pdf_compute_font_descriptor(gx_device_pdf *pdev, pdf_font_descriptor_t *pfd)
380
10.3k
{
381
10.3k
    gs_font_base *bfont = pdf_base_font_font(pfd->base_font, false);
382
10.3k
    gs_glyph glyph, notdef;
383
10.3k
    int index;
384
10.3k
    int wmode = bfont->WMode;
385
10.3k
    int members = (GLYPH_INFO_WIDTH0 << wmode) |
386
10.3k
        GLYPH_INFO_BBOX | GLYPH_INFO_NUM_PIECES;
387
10.3k
    pdf_font_descriptor_values_t desc;
388
10.3k
    gs_matrix smat;
389
10.3k
    gs_matrix *pmat = NULL;
390
10.3k
    int fixed_width = 0;
391
10.3k
    int small_descent = 0, small_height = 0;
392
10.3k
    bool small_present = false;
393
10.3k
    int x_height = 0;
394
10.3k
    int cap_height = 0;
395
10.3k
    gs_rect bbox_colon, bbox_period, bbox_I;
396
10.3k
    bool is_cid = (bfont->FontType == ft_CID_encrypted ||
397
10.3k
                   bfont->FontType == ft_CID_TrueType);
398
10.3k
    bool have_colon = false, have_period = false, have_I = false;
399
10.3k
    int code;
400
401
10.3k
    memset(&bbox_colon, 0, sizeof(bbox_colon)); /* quiet gcc warnings. */
402
10.3k
    memset(&bbox_period, 0, sizeof(bbox_period)); /* quiet gcc warnings. */
403
10.3k
    memset(&bbox_I, 0, sizeof(bbox_I)); /* quiet gcc warnings. */
404
10.3k
    memset(&desc, 0, sizeof(desc));
405
10.3k
    if (is_cid && bfont->FontBBox.p.x != bfont->FontBBox.q.x &&
406
10.3k
                  bfont->FontBBox.p.y != bfont->FontBBox.q.y) {
407
192
        int scale = (bfont->FontType == ft_TrueType || bfont->FontType == ft_CID_TrueType ? 1000 : 1);
408
409
192
        desc.FontBBox.p.x = (int)(bfont->FontBBox.p.x * scale);
410
192
        desc.FontBBox.p.y = (int)(bfont->FontBBox.p.y * scale);
411
192
        desc.FontBBox.q.x = (int)(bfont->FontBBox.q.x * scale);
412
192
        desc.FontBBox.q.y = (int)(bfont->FontBBox.q.y * scale);
413
192
        desc.Ascent = desc.FontBBox.q.y;
414
192
        members &= ~GLYPH_INFO_BBOX;
415
10.1k
    } else {
416
10.1k
        desc.FontBBox.p.x = desc.FontBBox.p.y = max_int;
417
10.1k
        desc.FontBBox.q.x = desc.FontBBox.q.y = min_int;
418
10.1k
    }
419
    /*
420
     * Embedded TrueType fonts use a 1000-unit character space, but the
421
     * font itself uses a 1-unit space.  Compensate for this here.
422
     */
423
10.3k
    switch (bfont->FontType) {
424
2.48k
    case ft_TrueType:
425
2.65k
    case ft_CID_TrueType:
426
2.65k
        gs_make_scaling(1000.0, 1000.0, &smat);
427
2.65k
        pmat = &smat;
428
        /* Type 3 fonts may use a FontMatrix in PDF, so we don't
429
         * need to deal with non-standard matrices
430
         */
431
2.65k
    case ft_GL2_531:
432
2.65k
    case ft_PCL_user_defined:
433
2.65k
    case ft_GL2_stick_user_defined:
434
2.65k
    case ft_MicroType:
435
2.65k
    case ft_PDF_user_defined:
436
2.65k
    case ft_user_defined:
437
2.65k
        break;
438
        /* Other font types may use a non-standard (not 1000x1000) design grid
439
         * The FontMatrix is used to map to the unit square. However PDF files
440
         * don't allow FontMatrix entries, all fonts are nominally 1000x1000.
441
         * If we have a font with a non-standard matrix we must account for that
442
         * here by scaling the font outline.
443
         */
444
7.68k
    default:
445
7.68k
        gs_matrix_scale(&bfont->FontMatrix, 1000.0, 1000.0, &smat);
446
7.68k
        pmat = &smat;
447
7.68k
        break;
448
10.3k
    }
449
450
    /*
451
     * Scan the entire glyph space to compute Ascent, Descent, FontBBox, and
452
     * the fixed width if any.  For non-symbolic fonts, also note the
453
     * bounding boxes for Latin letters and a couple of other characters,
454
     * for computing the remaining descriptor values (CapHeight,
455
     * ItalicAngle, StemV, XHeight, and flags SERIF, SCRIPT, ITALIC,
456
     * ALL_CAPS, and SMALL_CAPS).  (The algorithms are pretty crude.)
457
     */
458
10.3k
    notdef = GS_NO_GLYPH;
459
10.3k
    for (index = 0;
460
267k
         (bfont->procs.enumerate_glyph((gs_font *)bfont, &index,
461
267k
                (is_cid ? GLYPH_SPACE_INDEX : GLYPH_SPACE_NAME), &glyph)) >= 0 &&
462
267k
             index != 0;
463
257k
         ) {
464
257k
        gs_glyph_info_t info;
465
257k
        gs_const_string gname;
466
257k
        gs_glyph glyph_known_enc;
467
257k
        gs_char position=0;
468
469
257k
        code = bfont->procs.glyph_info((gs_font *)bfont, glyph, pmat, members, &info);
470
257k
        if (code == gs_error_VMerror)
471
0
            return code;
472
257k
        if (code < 0) {
473
            /*
474
             * Since this function may be indirtectly called from gx_device_finalize,
475
             * we are unable to propagate error code to the interpreter.
476
             * Therefore we skip it here hoping that few errors can be
477
             * recovered by the integration through entire glyph set.
478
             */
479
813
            continue;
480
813
        }
481
256k
        if (members & GLYPH_INFO_BBOX) {
482
            /* rect_merge(desc.FontBBox, info.bbox); Expanding due to type cast :*/
483
252k
            if (info.bbox.p.x < desc.FontBBox.p.x) desc.FontBBox.p.x = (int)info.bbox.p.x;
484
252k
            if (info.bbox.q.x > desc.FontBBox.q.x) desc.FontBBox.q.x = (int)info.bbox.q.x;
485
252k
            if (info.bbox.p.y < desc.FontBBox.p.y) desc.FontBBox.p.y = (int)info.bbox.p.y;
486
252k
            if (info.bbox.q.y > desc.FontBBox.q.y) desc.FontBBox.q.y = (int)info.bbox.q.y;
487
252k
            if (!info.num_pieces)
488
252k
                desc.Ascent = max(desc.Ascent, (int)info.bbox.q.y);
489
252k
        }
490
256k
        if (notdef == GS_NO_GLYPH && gs_font_glyph_is_notdef(bfont, glyph)) {
491
10.0k
            notdef = glyph;
492
10.0k
            desc.MissingWidth = (int)info.width[wmode].x;
493
10.0k
        }
494
256k
        if (info.width[wmode].y != 0)
495
0
            fixed_width = min_int;
496
256k
        else if (fixed_width == 0)
497
10.4k
            fixed_width = (int)info.width[wmode].x;
498
245k
        else if (info.width[wmode].x != fixed_width)
499
240k
            fixed_width = min_int;
500
256k
        if (desc.Flags & FONT_IS_SYMBOLIC)
501
4.29k
            continue;    /* skip Roman-only computation */
502
251k
        if (is_cid)
503
3.66k
            continue;
504
248k
        code = bfont->procs.glyph_name((gs_font *)bfont, glyph, &gname);
505
248k
        if (code < 0) {
506
            /* If we fail to get the glyph name, best assume this is a symbolic font */
507
18
            desc.Flags |= FONT_IS_SYMBOLIC;
508
18
            continue;
509
18
        }
510
        /* See if the glyph name is in any of the known encodings */
511
248k
        glyph_known_enc = gs_c_name_glyph(gname.data, gname.size);
512
248k
        if (glyph_known_enc == GS_NO_GLYPH) {
513
183
            desc.Flags |= FONT_IS_SYMBOLIC;
514
183
            continue;
515
183
        }
516
        /* Finally check if the encoded glyph is in Standard Encoding */
517
        /* gs_c_decode always fails to find .notdef, its always present so
518
         * don't worry about it
519
         */
520
248k
        if(strncmp(".notdef", (const char *)gname.data, gname.size)) {
521
238k
            position = gs_c_decode(glyph_known_enc, 0);
522
238k
            if (position == GS_NO_CHAR) {
523
130
                desc.Flags |= FONT_IS_SYMBOLIC;
524
130
                continue;
525
130
            }
526
238k
        }
527
247k
        switch (gname.size) {
528
14.2k
        case 5:
529
14.2k
            if (!memcmp(gname.data, "colon", 5))
530
2.01k
                bbox_colon = info.bbox, have_colon = true;
531
14.2k
            continue;
532
6.32k
        case 6:
533
6.32k
            if (!memcmp(gname.data, "period", 6))
534
2.19k
                bbox_period = info.bbox, have_period = true;
535
6.32k
            continue;
536
200k
        case 1:
537
200k
            break;
538
26.7k
        default:
539
26.7k
            continue;
540
247k
        }
541
542
200k
        if (gname.data[0] >= 'A' && gname.data[0] <= 'Z') {
543
72.9k
            cap_height = max(cap_height, (int)info.bbox.q.y);
544
72.9k
            if (gname.data[0] == 'I')
545
5.06k
                bbox_I = info.bbox, have_I = true;
546
127k
        } else if (gname.data[0] >= 'a' && gname.data[0] <= 'z') {
547
127k
            int y0 = (int)(info.bbox.p.y), y1 = (int)(info.bbox.q.y);
548
549
127k
            small_present = true;
550
127k
            switch (gname.data[0]) {
551
17.4k
            case 'b': case 'd': case 'f': case 'h':
552
35.3k
            case 'k': case 'l': case 't': /* ascender */
553
35.3k
                small_height = max(small_height, y1);
554
41.6k
            case 'i':   /* anomalous ascent */
555
41.6k
                break;
556
346
            case 'j':   /* descender with anomalous ascent */
557
346
                small_descent = min(small_descent, y0);
558
346
                break;
559
15.2k
            case 'g': case 'p': case 'q': case 'y': /* descender */
560
15.2k
                small_descent = min(small_descent, y0);
561
                /* fall through */
562
85.6k
            default:    /* no ascender or descender */
563
85.6k
                x_height = max(x_height, y1);
564
127k
            }
565
127k
        }
566
200k
    }
567
10.3k
    if (!(desc.Flags & FONT_IS_SYMBOLIC)) {
568
10.0k
        desc.Flags |= FONT_IS_ADOBE_ROMAN; /* required if not symbolic */
569
10.0k
        desc.XHeight = (int)x_height;
570
10.0k
        if (!small_present && (pdev->PDFA == 0 || bfont->FontType != ft_TrueType))
571
1.59k
            desc.Flags |= FONT_IS_ALL_CAPS;
572
10.0k
        desc.CapHeight = cap_height;
573
        /*
574
         * Look at various glyphs to determine ItalicAngle, StemV,
575
         * SERIF, SCRIPT, and ITALIC.
576
         */
577
10.0k
        if (have_colon && have_period) {
578
            /* Calculate the dominant angle. */
579
1.91k
            int angle =
580
1.91k
                (int)(atan2((bbox_colon.q.y - bbox_colon.p.y) -
581
1.91k
                              (bbox_period.q.y - bbox_period.p.y),
582
1.91k
                            (bbox_colon.q.x - bbox_colon.p.x) -
583
1.91k
                              (bbox_period.q.x - bbox_period.p.x)) *
584
1.91k
                      radians_to_degrees) - 90;
585
586
            /* Normalize to [-90..90]. */
587
1.91k
            while (angle > 90)
588
0
                angle -= 180;
589
1.91k
            while (angle < -90)
590
0
                angle += 180;
591
1.91k
            if (angle < -30)
592
5
                angle = -30;
593
1.91k
            else if (angle > 30)
594
0
                angle = 30;
595
            /*
596
             * For script or embellished fonts, we can get an angle that is
597
             * slightly off from zero even for non-italic fonts.
598
             * Compensate for this now.
599
             */
600
1.91k
            if (angle <= 2 && angle >= -2)
601
1.62k
                angle = 0;
602
1.91k
            desc.ItalicAngle = angle;
603
1.91k
        }
604
10.0k
        if (desc.ItalicAngle)
605
289
            desc.Flags |= FONT_IS_ITALIC;
606
10.0k
        if (have_I) {
607
5.05k
            double wdot = bbox_period.q.x - bbox_period.p.x;
608
5.05k
            double wcolon = bbox_I.q.x - bbox_I.p.x;
609
5.05k
            double wI = bbox_period.q.x - bbox_period.p.x;
610
611
5.05k
            desc.StemV = (int)wdot;
612
5.05k
            if (wI > wcolon * 2.5 || wI > (bbox_period.q.y - bbox_period.p.y) * 0.25)
613
1.42k
                desc.Flags |= FONT_IS_SERIF;
614
5.05k
        }
615
10.0k
    }
616
10.3k
    if (desc.Ascent == 0)
617
838
        desc.Ascent = desc.FontBBox.q.y;
618
10.3k
    desc.Descent = desc.FontBBox.p.y;
619
10.3k
    if (!(desc.Flags & (FONT_IS_SYMBOLIC | FONT_IS_ALL_CAPS)) &&
620
10.3k
        (small_descent > desc.Descent / 3 || desc.XHeight > small_height * 0.9) &&
621
10.3k
        (pdev->PDFA == 0 || bfont->FontType != ft_TrueType)
622
10.3k
        )
623
1.85k
        desc.Flags |= FONT_IS_SMALL_CAPS;
624
10.3k
    if (fixed_width > 0 && (pdev->PDFA == 0 || bfont->FontType != ft_TrueType)) {
625
826
        desc.Flags |= FONT_IS_FIXED_WIDTH;
626
826
        desc.AvgWidth = desc.MaxWidth = desc.MissingWidth = fixed_width;
627
826
    }
628
10.3k
    if (desc.CapHeight == 0)
629
3.50k
        desc.CapHeight = desc.Ascent;
630
10.3k
    if (desc.StemV == 0)
631
8.92k
        desc.StemV = (int)(desc.FontBBox.q.x * 0.15);
632
10.3k
    pfd->common.values = desc;
633
10.3k
    return 0;
634
10.3k
}
635
636
/*
637
 * Finish a FontDescriptor by computing the metric values, and then
638
 * writing the associated embedded font if any.
639
 */
640
int
641
pdf_finish_FontDescriptor(gx_device_pdf *pdev, pdf_resource_t *pres)
642
10.7k
{
643
10.7k
    pdf_font_descriptor_t *pfd = (pdf_font_descriptor_t *)pres;
644
10.7k
    int code = 0;
645
10.7k
    cos_dict_t *pcd = 0;
646
10.7k
    if (pfd->common.object->id == -1)
647
400
        return 0;
648
10.3k
    if (!pfd->common.object->written &&
649
10.3k
        (code = pdf_compute_font_descriptor(pdev, pfd)) >= 0 &&
650
10.3k
        (!pfd->embed ||
651
10.3k
         (code = pdf_write_embedded_font(pdev, pfd->base_font,
652
10.3k
                                pfd->FontType,
653
10.3k
                                &pfd->common.values.FontBBox,
654
10.3k
                                pfd->common.rid, &pcd)) >= 0)
655
10.3k
        ) {
656
10.1k
        pdf_set_FontFile_object(pfd->base_font, pcd);
657
10.1k
    }
658
10.3k
    return code;
659
10.7k
}
660
661
/* Write a FontDescriptor. */
662
int
663
pdf_write_FontDescriptor(gx_device_pdf *pdev, pdf_resource_t *pres)
664
10.7k
{
665
10.7k
    pdf_font_descriptor_t *pfd = (pdf_font_descriptor_t *)pres;
666
10.7k
    font_type ftype = pfd->FontType;
667
10.7k
    long cidset_id = 0;
668
10.7k
    int code = 0;
669
10.7k
    stream *s;
670
671
10.7k
    if (pfd->common.object->written)
672
0
        return 0;
673
10.7k
    if (pfd->common.object->id == -1)
674
400
        return 0;
675
676
    /* If this is a CIDFont subset, write the CIDSet now. */
677
10.3k
    switch (ftype) {
678
31
    case ft_CID_encrypted:
679
201
    case ft_CID_TrueType:
680
201
        if (pdf_do_subset_font(pdev, pfd->base_font, pfd->common.rid)) {
681
201
            if (pdev->PDFA < 2) {
682
201
                code = pdf_write_CIDSet(pdev, pfd->base_font, &cidset_id);
683
201
                if (code < 0)
684
0
                    return code;
685
201
            }
686
201
        }
687
10.3k
    default:
688
10.3k
        break;
689
10.3k
    }
690
691
10.3k
    {
692
        /*
693
         * Hack: make all embedded TrueType fonts "symbolic" to
694
         * work around undocumented assumptions in Acrobat Reader.
695
         */
696
        /* See the comments in pdf_make_font_resource(). If we are embedding a font, its
697
         * a TrueType font, we are not subsetting it, *and* the original font was not symbolic,
698
         * then force the font to be non-symbolic. Otherwise, yes, force it symbolic.
699
         */
700
10.3k
        pdf_font_descriptor_common_t fd;
701
702
10.3k
        fd = pfd->common;
703
10.3k
        if (pfd->embed && pfd->FontType == ft_TrueType) {
704
2.46k
            fd.values.Flags =
705
2.46k
                (fd.values.Flags & ~(FONT_IS_ADOBE_ROMAN)) | FONT_IS_SYMBOLIC;
706
707
2.46k
            if (pfd->base_font->do_subset == DO_SUBSET_NO && ((const gs_font_base *)(pfd->base_font->copied))->nearest_encoding_index != ENCODING_INDEX_UNKNOWN) {
708
0
                fd.values.Flags =
709
0
                    (fd.values.Flags & ~(FONT_IS_SYMBOLIC)) | FONT_IS_ADOBE_ROMAN;
710
0
            }
711
2.46k
        }
712
10.3k
        code = write_FontDescriptor_common(pdev, &fd, pfd->embed);
713
10.3k
    }
714
10.3k
    if (code < 0)
715
0
        return code;
716
10.3k
    s = pdev->strm;
717
10.3k
    if (cidset_id != 0)
718
201
        pprintld1(s, "/CIDSet %ld 0 R\n", cidset_id);
719
10.1k
    else if (pdf_do_subset_font(pdev, pfd->base_font, pfd->common.rid) &&
720
10.1k
             (ftype == ft_encrypted || ftype == ft_encrypted2) &&
721
10.1k
             pdev->CompatibilityLevel <= 1.7
722
10.1k
             ) {
723
7.65k
        stream_puts(s, "/CharSet");
724
7.65k
        code = pdf_write_CharSet(pdev, pfd->base_font);
725
7.65k
        if (code < 0)
726
0
            return code;
727
7.65k
    }
728
10.3k
    if (pfd->embed && pfd->base_font->FontFile) {
729
10.1k
        code = pdf_write_FontFile_entry(pdev, pfd->base_font);
730
10.1k
        if (code < 0)
731
0
            return code;
732
10.1k
    }
733
10.3k
    if (pfd->cid.Style) {
734
0
        stream_puts(s, "/Style");
735
0
        COS_WRITE(pfd->cid.Style, pdev);
736
0
    }
737
10.3k
    if (pfd->cid.Lang[0]) {
738
0
        pprints1(s, "/Lang(%s)", pfd->cid.Lang);
739
0
    }
740
10.3k
    if (pfd->cid.FD) {
741
0
        stream_puts(s, "/FD");
742
0
        COS_WRITE(pfd->cid.FD, pdev);
743
0
    }
744
10.3k
    stream_puts(s, ">>\n");
745
10.3k
    pdf_end_separate(pdev, resourceFontDescriptor);
746
10.3k
    pfd->common.object->written = true;
747
10.3k
    { const cos_object_t *pco = (const cos_object_t *)pdf_get_FontFile_object(pfd->base_font);
748
10.3k
        if (pco != NULL) {
749
10.1k
            code = COS_WRITE_OBJECT(pco, pdev, resourceFontFile);
750
10.1k
            if (code < 0)
751
0
                return code;
752
10.1k
        }
753
10.3k
    }
754
10.3k
    return 0;
755
10.3k
}
756
757
/*
758
 * Release a FontDescriptor components.
759
 */
760
int
761
pdf_release_FontDescriptor_components(gx_device_pdf *pdev, pdf_resource_t *pres)
762
0
{
763
0
    pdf_font_descriptor_t *pfd = (pdf_font_descriptor_t *) pres;
764
765
0
    gs_free_object(pdev->pdf_memory, pfd->base_font, "pdf_release_FontDescriptor_components");
766
0
    pfd->base_font = NULL;
767
    /* fixme: underimplemented. */
768
0
    return 0;
769
0
}
770
771
/*
772
 * Mark a FontDescriptor used in a text.
773
 */
774
int
775
pdf_mark_font_descriptor_used(gx_device_pdf *pdev, pdf_font_descriptor_t *pfd)
776
13.8k
{
777
13.8k
    if (pfd != NULL && pfd->common.object->id == -1)
778
10.3k
        pdf_reserve_object_id(pdev, (pdf_resource_t *)&pfd->common, 0);
779
13.8k
    return 0;
780
13.8k
}
781
782
/*
783
 * Convert True Type font descriptor into CID font descriptor for PDF/A.
784
 */
785
int
786
pdf_convert_truetype_font_descriptor(gx_device_pdf *pdev, pdf_font_resource_t *pdfont)
787
0
{
788
0
    pdf_font_descriptor_t *pfd = pdfont->FontDescriptor;
789
0
    pdf_base_font_t *pbfont = pfd->base_font;
790
0
    gs_font *pfont = (gs_font *)pbfont->copied;
791
0
    gs_char ch;
792
    /* Save the simple font descriptor data because CID font data overlap them. */
793
0
    int FirstChar = pdfont->u.simple.FirstChar, LastChar = pdfont->u.simple.LastChar;
794
0
    pdf_encoding_element_t *Encoding = pdfont->u.simple.Encoding;
795
0
    int length_CIDSet = (pbfont->num_glyphs > LastChar ? (pbfont->num_glyphs + 7) / 8 : ((LastChar + 1) + 7 / 8));
796
0
    int length_CIDToGIDMap = (pbfont->num_glyphs > LastChar ? (pbfont->num_glyphs + 1) * sizeof(ushort) : (LastChar + 1) * sizeof(ushort));
797
798
0
    pfd->FontType = ft_CID_TrueType;
799
0
    pdfont->u.simple.Encoding = NULL; /* Drop due to overlapping against a garbager problem. */
800
0
    pbfont->CIDSet = gs_alloc_bytes(pdev->pdf_memory, length_CIDSet,
801
0
                        "pdf_convert_truetype_font_descriptor");
802
0
    if (pbfont->CIDSet == NULL)
803
0
        return_error(gs_error_VMerror);
804
0
    memset(pbfont->CIDSet, 0, length_CIDSet);
805
0
    pdfont->u.cidfont.CIDToGIDMap = (ushort *)gs_alloc_bytes(pdev->pdf_memory,
806
0
                        length_CIDToGIDMap, "pdf_convert_truetype_font_descriptor");
807
0
    if (pdfont->u.cidfont.CIDToGIDMap == NULL)
808
0
        return_error(gs_error_VMerror);
809
0
    memset(pdfont->u.cidfont.CIDToGIDMap, 0, length_CIDToGIDMap);
810
0
    if(pdev->PDFA) {
811
0
        for (ch = FirstChar; ch <= LastChar; ch++) {
812
0
            if (Encoding[ch].glyph != GS_NO_GLYPH) {
813
0
                gs_glyph glyph = pfont->procs.encode_char(pfont, ch, GLYPH_SPACE_INDEX);
814
815
0
                pbfont->CIDSet[ch / 8] |= 0x80 >> (ch % 8);
816
0
                pdfont->u.cidfont.CIDToGIDMap[ch] = glyph - GS_MIN_GLYPH_INDEX;
817
0
            }
818
0
        }
819
        /* Set the CIDSet bit for CID 0 (the /.notdef) which must always be present */
820
0
        pbfont->CIDSet[0] |= 0x80;
821
0
    } else {
822
0
        for (ch = 0; ch <= pbfont->num_glyphs; ch++) {
823
0
            gs_glyph glyph = pfont->procs.encode_char(pfont, ch, GLYPH_SPACE_INDEX);
824
825
0
            pbfont->CIDSet[ch / 8] |= 0x80 >> (ch % 8);
826
0
            pdfont->u.cidfont.CIDToGIDMap[ch] = glyph - GS_MIN_GLYPH_INDEX;
827
0
        }
828
0
    }
829
0
    pbfont->CIDSetLength = length_CIDSet;
830
0
    pdfont->u.cidfont.CIDToGIDMapLength = length_CIDToGIDMap / sizeof(ushort);
831
0
    pdfont->u.cidfont.Widths2 = NULL;
832
0
    pdfont->u.cidfont.used2 = NULL;
833
0
    pdfont->u.cidfont.v = NULL;
834
0
    return 0;
835
0
}
836
837
int mark_font_descriptor_symbolic(const pdf_font_resource_t *pdfont)
838
3.80k
{
839
3.80k
    pdf_font_descriptor_values_t *desc;
840
841
3.80k
    if(!pdfont || !pdfont->FontDescriptor)
842
1.20k
        return 0;
843
844
2.59k
    desc = &pdfont->FontDescriptor->common.values;
845
846
2.59k
    if (!(desc->Flags & FONT_IS_SYMBOLIC)) {
847
2.36k
        desc->Flags |= FONT_IS_SYMBOLIC;
848
2.36k
        desc->Flags &= ~FONT_IS_ADOBE_ROMAN;
849
2.36k
    }
850
2.59k
    return 1;
851
3.80k
}