Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/pdf/pdf_font3.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2019-2022 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  1305 Grant Avenue - Suite 200, Novato,
13
   CA 94945, U.S.A., +1(415)492-9861, for further information.
14
*/
15
16
/* code for type 3 font handling */
17
18
#include "pdf_int.h"
19
#include "pdf_stack.h"
20
#include "pdf_array.h"
21
#include "pdf_dict.h"
22
#include "pdf_font_types.h"
23
#include "pdf_gstate.h"
24
#include "pdf_font.h"
25
#include "pdf_font3.h"
26
#include "pdf_deref.h"
27
#include "gscencs.h"
28
#include "gscedata.h"       /* For the encoding arrays */
29
#include "gsccode.h"        /* For the Encoding indices */
30
#include "gsuid.h"          /* For no_UniqueID */
31
#include "gsutil.h"        /* For gs_next_ids() */
32
33
static void pdfi_type3_copy_color(gs_gstate_color *src, gs_gstate_color *dest)
34
22.4k
{
35
22.4k
    *dest->ccolor = *src->ccolor;
36
22.4k
    *dest->dev_color = *src->dev_color;
37
22.4k
    dest->color_space = src->color_space;
38
22.4k
    dest->effective_opm = src->effective_opm;
39
22.4k
}
40
41
static int
42
pdfi_type3_build_char(gs_show_enum * penum, gs_gstate * pgs, gs_font * pfont,
43
                     gs_char chr, gs_glyph glyph)
44
9.06k
{
45
9.06k
    int code = 0;
46
9.06k
    pdf_font_type3 *font;
47
9.06k
    pdf_name *GlyphName = NULL;
48
9.06k
    pdf_stream *CharProc = NULL;
49
9.06k
    int SavedTextBlockDepth = 0;
50
9.06k
    char Notdef[8] = {".notdef"};
51
52
9.06k
    font = (pdf_font_type3 *)pfont->client_data;
53
54
9.06k
    SavedTextBlockDepth = OBJ_CTX(font)->text.BlockDepth;
55
9.06k
    code = pdfi_array_get(OBJ_CTX(font), font->Encoding, (uint64_t)chr, (pdf_obj **)&GlyphName);
56
9.06k
    if (code < 0)
57
0
        return code;
58
59
9.06k
    code = pdfi_dict_get_by_key(OBJ_CTX(font), font->CharProcs, GlyphName, (pdf_obj **)&CharProc);
60
9.06k
    if (code == gs_error_undefined) {
61
1.40k
        byte *Key = NULL;
62
        /* Can't find the named glyph, try to find a /.notdef as a substitute */
63
1.40k
        Key = gs_alloc_bytes(OBJ_MEMORY(font), 8, "working buffer for BuildChar");
64
1.40k
        if (Key == NULL)
65
0
            goto build_char_error;
66
1.40k
        memset(Key, 0x00, 8);
67
1.40k
        memcpy(Key, Notdef, 8);
68
1.40k
        code = pdfi_dict_get(OBJ_CTX(font), font->CharProcs, (const char *)Key, (pdf_obj **)&CharProc);
69
1.40k
        gs_free_object(OBJ_MEMORY(font), Key, "working buffer for BuildChar");
70
1.40k
        if (code == gs_error_undefined) {
71
1.40k
            code = 0;
72
1.40k
            goto build_char_error;
73
1.40k
        }
74
1.40k
    }
75
7.66k
    if (code < 0)
76
167
        goto build_char_error;
77
7.49k
    if (pdfi_type_of(CharProc) != PDF_STREAM) {
78
21
        code = gs_note_error(gs_error_typecheck);
79
21
        goto build_char_error;
80
21
    }
81
82
7.47k
    OBJ_CTX(font)->text.BlockDepth = 0;
83
7.47k
    OBJ_CTX(font)->text.inside_CharProc = true;
84
7.47k
    OBJ_CTX(font)->text.CharProc_d_type = pdf_type3_d_none;
85
86
7.47k
    {
87
        /* It turns out that if a type 3 font uses a stroke to draw, and does not
88
         * acrually set the stroke colour, then we must use the fill colour instead.
89
         * In effect we start a type 3 BuildChar with stroke colour = fill colour.
90
         * That is annoyingly difficult to set up. We need to copy the existing
91
         * colour values from the structures in the gs_gstate_color structures into
92
         * temporary copies and copy the colour space pointer (and keep its reference
93
         * count correct). Then copy the fill colour values and ponter to the stroke
94
         * structures. Finally, after drawing the character, copy the temporary
95
         * saved copies back again.
96
         */
97
7.47k
        gs_gstate_color tmp_color;
98
7.47k
        gs_client_color tmp_cc;
99
7.47k
        gx_device_color tmp_dc;
100
101
        /* Set up the pointers in the gs_gstate_color structure to point to
102
         * the temporary structures we have on the stack.
103
         */
104
7.47k
        tmp_color.ccolor = &tmp_cc;
105
7.47k
        tmp_color.dev_color = &tmp_dc;
106
107
        /* Use the utility routine above to copy the stroke colour to the temporary copy */
108
7.47k
        pdfi_type3_copy_color(&OBJ_CTX(font)->pgs->color[1], &tmp_color);
109
7.47k
        rc_increment_cs(tmp_color.color_space);
110
        /* Use the utility routine above to copy the fill colour to the stroke colour */
111
7.47k
        pdfi_type3_copy_color(&OBJ_CTX(font)->pgs->color[0], &OBJ_CTX(font)->pgs->color[1]);
112
113
7.47k
        code = pdfi_gsave(OBJ_CTX(font));
114
7.47k
        if (code >= 0) {
115
7.47k
            code = pdfi_run_context(OBJ_CTX(font), CharProc, font->PDF_font, true, "CharProc");
116
7.47k
            (void)pdfi_grestore(OBJ_CTX(font));
117
7.47k
        }
118
119
        /* Use the utility routine above to copy the temporary copy to the stroke colour */
120
7.47k
        pdfi_type3_copy_color(&tmp_color, &OBJ_CTX(font)->pgs->color[1]);
121
7.47k
        rc_decrement_cs(tmp_color.color_space, "pdfi_type3_build_char");
122
7.47k
    }
123
124
7.47k
    OBJ_CTX(font)->text.inside_CharProc = false;
125
7.47k
    OBJ_CTX(font)->text.CharProc_d_type = pdf_type3_d_none;
126
7.47k
    OBJ_CTX(font)->text.BlockDepth = SavedTextBlockDepth;
127
128
9.06k
build_char_error:
129
9.06k
    pdfi_countdown(GlyphName);
130
9.06k
    pdfi_countdown(CharProc);
131
9.06k
    return code;
132
7.47k
}
133
134
static int alloc_type3_font(pdf_context *ctx, pdf_font_type3 **font)
135
622
{
136
622
    pdf_font_type3 *t3font = NULL;
137
138
622
    t3font = (pdf_font_type3 *)gs_alloc_bytes(ctx->memory, sizeof(pdf_font_type3), "pdfi_alloc_type3_font");
139
622
    if (t3font == NULL)
140
0
        return_error(gs_error_VMerror);
141
142
622
    memset(t3font, 0x00, sizeof(pdf_font_type3));
143
622
    (t3font)->ctx = ctx;
144
622
    (t3font)->type = PDF_FONT;
145
146
#if REFCNT_DEBUG
147
    (t3font)->UID = ctx->UID++;
148
    dmprintf2(ctx->memory, "Allocated object of type %c with UID %"PRIi64"\n", t3font->type, t3font->UID);
149
#endif
150
151
152
622
    pdfi_countup(t3font);
153
154
622
    t3font->pfont = gs_alloc_struct(ctx->memory, gs_font_base, &st_gs_font_base,
155
622
                            "pdfi (type 3 font)");
156
622
    if (t3font->pfont == NULL) {
157
0
        pdfi_countdown(t3font);
158
0
        return_error(gs_error_VMerror);
159
0
    }
160
161
622
    memset(t3font->pfont, 0x00, sizeof(gs_font_base));
162
622
    t3font->ctx = ctx;
163
622
    t3font->pdfi_font_type = e_pdf_font_type3;
164
165
622
    gs_make_identity(&t3font->pfont->orig_FontMatrix);
166
622
    gs_make_identity(&t3font->pfont->FontMatrix);
167
622
    t3font->pfont->next = t3font->pfont->prev = 0;
168
622
    t3font->pfont->memory = ctx->memory;
169
622
    t3font->pfont->dir = ctx->font_dir;
170
622
    t3font->pfont->is_resource = false;
171
622
    gs_notify_init(&t3font->pfont->notify_list, ctx->memory);
172
622
    t3font->pfont->base = (gs_font *) t3font->pfont;
173
622
    t3font->pfont->client_data = t3font;
174
622
    t3font->pfont->WMode = 0;
175
622
    t3font->pfont->PaintType = 0;
176
622
    t3font->pfont->StrokeWidth = 0;
177
622
    t3font->pfont->is_cached = 0;
178
622
    t3font->pfont->procs.init_fstack = gs_default_init_fstack;
179
622
    t3font->pfont->procs.next_char_glyph = gs_default_next_char_glyph;
180
622
    t3font->pfont->FAPI = NULL;
181
622
    t3font->pfont->FAPI_font_data = NULL;
182
622
    t3font->pfont->procs.glyph_name = ctx->get_glyph_name;
183
622
    t3font->pfont->procs.decode_glyph = pdfi_decode_glyph;
184
622
    t3font->pfont->procs.define_font = gs_no_define_font;
185
622
    t3font->pfont->procs.make_font = gs_no_make_font;
186
622
    t3font->pfont->procs.font_info = gs_default_font_info;
187
622
    t3font->pfont->procs.glyph_info = gs_default_glyph_info;
188
622
    t3font->pfont->procs.glyph_outline = gs_no_glyph_outline;
189
622
    t3font->pfont->procs.encode_char = pdfi_encode_char;
190
622
    t3font->pfont->procs.build_char = pdfi_type3_build_char;
191
622
    t3font->pfont->procs.same_font = gs_default_same_font;
192
622
    t3font->pfont->procs.enumerate_glyph = gs_no_enumerate_glyph;
193
194
622
    t3font->pfont->FontType = ft_PDF_user_defined;
195
    /* outlines ? Bitmaps ? */
196
622
    t3font->pfont->ExactSize = fbit_use_bitmaps;
197
622
    t3font->pfont->InBetweenSize = fbit_use_bitmaps;
198
622
    t3font->pfont->TransformedChar = fbit_transform_bitmaps;
199
200
622
    t3font->pfont->encoding_index = 1;          /****** WRONG ******/
201
622
    t3font->pfont->nearest_encoding_index = 1;          /****** WRONG ******/
202
203
622
    t3font->pfont->client_data = (void *)t3font;
204
622
    t3font->pfont->id = gs_next_ids(ctx->memory, 1);
205
622
    uid_set_UniqueID(&t3font->pfont->UID, no_UniqueID);
206
207
622
    *font = (pdf_font_type3 *)t3font;
208
622
    return 0;
209
622
}
210
211
int pdfi_free_font_type3(pdf_obj *font)
212
622
{
213
622
    pdf_font_type3 *t3font = (pdf_font_type3 *)font;
214
215
622
    if (t3font->pfont)
216
622
        gs_free_object(OBJ_MEMORY(t3font), t3font->pfont, "Free type 3 font");
217
218
622
    if (t3font->Widths)
219
578
        gs_free_object(OBJ_MEMORY(t3font), t3font->Widths, "Free type 3 font Widths array");
220
221
622
    pdfi_countdown(t3font->PDF_font);
222
622
    pdfi_countdown(t3font->FontDescriptor);
223
622
    pdfi_countdown(t3font->CharProcs);
224
622
    pdfi_countdown(t3font->Encoding);
225
622
    pdfi_countdown(t3font->ToUnicode);
226
622
    pdfi_countdown(t3font->filename); /* Should never exist, but just in case */
227
228
622
    gs_free_object(OBJ_MEMORY(font), font, "Free type 3 font");
229
622
    return 0;
230
622
}
231
232
233
int pdfi_read_type3_font(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *stream_dict, pdf_dict *page_dict, pdf_font **ppdffont)
234
622
{
235
622
    int code = 0;
236
622
    pdf_font_type3 *font = NULL;
237
622
    pdf_obj *obj = NULL;
238
622
    pdf_obj *tounicode = NULL;
239
240
622
    *ppdffont = NULL;
241
622
    code = alloc_type3_font(ctx, &font);
242
622
    if (code < 0)
243
0
        return code;
244
245
622
    font->object_num = font_dict->object_num;
246
622
    font->generation_num = font_dict->generation_num;
247
622
    font->indirect_num = font_dict->indirect_num;
248
622
    font->indirect_gen = font_dict->indirect_gen;
249
250
622
    code = pdfi_dict_get_type(ctx, font_dict, "FontBBox", PDF_ARRAY, &obj);
251
622
    if (code < 0)
252
2
        goto font3_error;
253
620
    code = pdfi_array_to_gs_rect(ctx, (pdf_array *)obj, &font->pfont->FontBBox);
254
620
    if (code < 0)
255
2
        goto font3_error;
256
618
    pdfi_countdown(obj);
257
618
    obj = NULL;
258
259
618
    code = pdfi_dict_get_type(ctx, font_dict, "FontMatrix", PDF_ARRAY, &obj);
260
618
    if (code < 0)
261
0
        goto font3_error;
262
618
    code = pdfi_array_to_gs_matrix(ctx, (pdf_array *)obj, &font->pfont->orig_FontMatrix);
263
618
    if (code < 0)
264
4
        goto font3_error;
265
614
    code = pdfi_array_to_gs_matrix(ctx, (pdf_array *)obj, &font->pfont->FontMatrix);
266
614
    if (code < 0)
267
0
        goto font3_error;
268
614
    pdfi_countdown(obj);
269
614
    obj = NULL;
270
271
614
    code = pdfi_dict_get(ctx, font_dict, "CharProcs", (pdf_obj **)&font->CharProcs);
272
614
    if (code < 0)
273
17
        goto font3_error;
274
275
276
597
    code = pdfi_dict_knownget_type(ctx, font_dict, "FontDescriptor", PDF_DICT, (pdf_obj **)&font->FontDescriptor);
277
597
    if (code < 0)
278
6
        goto font3_error;
279
280
591
    pdfi_font_set_first_last_char(ctx, font_dict, (pdf_font *)font);
281
    /* ignore errors with widths... for now */
282
591
    (void)pdfi_font_create_widths(ctx, font_dict, (pdf_font*)font, 1.0);
283
284
285
591
    code = pdfi_dict_get(ctx, font_dict, "Encoding", &obj);
286
591
    if (code < 0)
287
45
        goto font3_error;
288
289
546
    code = pdfi_create_Encoding(ctx, obj, NULL, (pdf_obj **)&font->Encoding);
290
546
    if (code < 0)
291
15
        goto font3_error;
292
531
    pdfi_countdown(obj);
293
294
531
    font->PDF_font = font_dict;
295
531
    pdfi_countup(font_dict);
296
297
531
    if (ctx->args.ignoretounicode != true) {
298
531
        code = pdfi_dict_get(ctx, font_dict, "ToUnicode", (pdf_obj **)&tounicode);
299
531
        if (code >= 0 && pdfi_type_of(tounicode) == PDF_STREAM) {
300
288
            pdf_cmap *tu = NULL;
301
288
            code = pdfi_read_cmap(ctx, tounicode, &tu);
302
288
            pdfi_countdown(tounicode);
303
288
            tounicode = (pdf_obj *)tu;
304
288
        }
305
531
        if (code < 0 || (tounicode != NULL && pdfi_type_of(tounicode) != PDF_CMAP)) {
306
244
            pdfi_countdown(tounicode);
307
244
            tounicode = NULL;
308
244
            code = 0;
309
244
        }
310
531
    }
311
0
    else {
312
0
        tounicode = NULL;
313
0
    }
314
315
531
    font->ToUnicode = tounicode;
316
531
    tounicode = NULL;
317
318
531
    code = replace_cache_entry(ctx, (pdf_obj *)font);
319
531
    if (code < 0)
320
0
        goto font3_error;
321
322
531
    code = gs_definefont(ctx->font_dir, (gs_font *)font->pfont);
323
531
    if (code < 0)
324
0
        goto font3_error;
325
326
531
    *ppdffont = (pdf_font *)font;
327
328
531
    return code;
329
330
91
font3_error:
331
91
    pdfi_countdown(obj);
332
91
    pdfi_countdown(font);
333
91
    return code;
334
531
}